Struts 2常见应用
學(xué)習(xí)內(nèi)容
?Struts 2國(guó)際化
?Struts 2的異常處理
?Struts 2的文件上傳與下載
能力目標(biāo)
?熟練使用Struts 2實(shí)現(xiàn)國(guó)際化
?能通過(guò)Struts 2的異常處理增強(qiáng)WEB應(yīng)用的健壯性
?使用Struts2實(shí)現(xiàn)文件上傳與下載
?
?
本章簡(jiǎn)介
本章主要介紹Struts 2的常見(jiàn)應(yīng)用,主要包括Struts 2國(guó)際化、Struts 2異常處理和文件上傳與下載。Internet把全世界聯(lián)系在了一起,WEB應(yīng)用可以通過(guò)瀏覽器被全世界的人們所使用,所以開(kāi)發(fā)人員需要考慮WEB應(yīng)用系統(tǒng)在不同地區(qū)和語(yǔ)言環(huán)境中的使用情況,使WEB
應(yīng)用系統(tǒng)能在不同的地區(qū)和語(yǔ)言環(huán)境中以當(dāng)?shù)氐恼Z(yǔ)言進(jìn)行顯示,這個(gè)過(guò)程就稱(chēng)之為國(guó)際化。
任何成熟的MVC類(lèi)框架都應(yīng)該提供成熟完善的異常處理機(jī)制,Struts 2采用了一種聲明式的異常處理機(jī)制,從而避免了在程序中編寫(xiě)大量的try-catch塊,使異常處理和業(yè)務(wù)代碼不再耦合。
文件的上傳與下載也是WEB應(yīng)用常見(jiàn)的功能,例如上傳圖片,本章最后會(huì)學(xué)習(xí)使用Struts 2實(shí)現(xiàn)文件的上傳與下載。
核心技能部分
9.1?sStruts 2國(guó)際化
國(guó)際化主要是指語(yǔ)言的國(guó)際化,目的是使應(yīng)用程序能提供一個(gè)語(yǔ)言自適應(yīng)、顯示更友好的用戶(hù)界面,掃除語(yǔ)言障礙,使不同地區(qū)和使用不同語(yǔ)言的用戶(hù)都能方便的使用我們開(kāi)發(fā)的WEB應(yīng)用系統(tǒng)。Struts 2國(guó)際化建立在Java國(guó)際化的基礎(chǔ)上,只是對(duì)Java國(guó)際化進(jìn)行了進(jìn)一步的優(yōu)化和封裝,從而簡(jiǎn)化了國(guó)際化的實(shí)現(xiàn)過(guò)程。
9.1.1?Struts 2國(guó)際化機(jī)制
Struts 2實(shí)現(xiàn)國(guó)際化的過(guò)程需要三個(gè)步驟:
(1)?創(chuàng)建中英文資源文件。
(2)?在struts.xml文件中配置資源文件。
(3)?在JSP頁(yè)面中使用<s:text />標(biāo)簽或OGNL顯示國(guó)際化信息。
示例9.1
下面我們以添加學(xué)生為例來(lái)演示Struts 2實(shí)現(xiàn)國(guó)際化的詳細(xì)過(guò)程。
(1)?在工程的src根目錄下創(chuàng)建兩個(gè)國(guó)際化資源文件,分別是英文的資源文件:ApplicationResources_en.properties和中文的資源文件:ApplicationResources_zh.properties,參考代碼如下所示。
文件名:ApplicationResources_en.properties
addstu.title=\u6DFB\u52A0\u5B66\u751F
addstu.name=\u5B66\u751F\u59D3\u540D
addstu.birthday=\u5B66\u751F\u751F\u65E5
addstu.height=\u5B66\u751F\u8EAB\u9AD8
addstu.weight=\u5B66\u751F\u4F53\u91CD
addstu.btn=\u6DFB\u52A0
addstu.exception=\u4E0D\u597D\u610F\u601D\uFF0C\u7A0B\u5E8F\u6682\u65F6\u 51FA\u73B0\u5F02\u5E38\u3002
addstu.en=\u82F1\u6587
addstu.zh=\u4E2D\u6587
文件名:ApplicationResources_zh.properties
addstu.title=add a new Student
addstu.name=student'name
addstu.birthday=student'birthday
addstu.height=student'height
addstu.weight=student'weight
addstu.btn=Add
addstu.exception=Sorry,Program temporarily appear unusual.
addstu.zh=Chinese
addstu.en=EngLish
和Struts 1一樣,國(guó)際化資源文件是以properties為擴(kuò)展名的文本文件,該文本文件以key=value的形式存儲(chǔ)了國(guó)際化消息資源。國(guó)際化資源文件的命名規(guī)則是resourceName_language.properties。其中,resourceName是自定義的資源文件基本名,language是不能自定義的,Java中規(guī)定了不同的字符代表不同的國(guó)家和地區(qū)的語(yǔ)言,zh表示簡(jiǎn)體中文,en表示英語(yǔ)。
中文的資源文件因?yàn)榘朔俏鳉W字符,所以必須把這個(gè)文件通過(guò)native2ascii命令進(jìn)行轉(zhuǎn)碼,轉(zhuǎn)碼之后的中文資源文件才能使用,語(yǔ)法如下所示:
語(yǔ)法
native2ascii -encoding UTF-8 原中文資源文件名轉(zhuǎn)碼后的資源文件名
高版本的MyEclipse會(huì)自動(dòng)對(duì)中文資源文件轉(zhuǎn)碼,因此可以直接編輯。
(2)?在struts.xml文件中配置資源文件,參考代碼如下所示。
<struts>
<constant name="struts.custom.i18n.resources" value="ApplicationResources" />
<package name="student" extends="struts-default">
<action name="add" class="com.zy.StudentAction"></action>
<action name="changeLang" class="com.zy.LanguageAction">
<result name="success">/addStu.jsp</result>
</action>
</package>
</struts>
在struts.xml文件中通過(guò)<constant>元素把國(guó)際化資源文件的名字告知Struts 2框架,其中name屬性的值必須是"struts.custom.i18n.resources",value屬性的值就是項(xiàng)目中國(guó)際化資源文件的名字,注意只寫(xiě)基本名即可。
(3)?在JSP頁(yè)面中顯示國(guó)際化信息,參考代碼如下所示。
<%@ page language="java" pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title><s:text name="addstu.title"/></title>
</head>
<body>
<center>
<a href="changeLang.action?request_locale=zh_CN">
<s:text name="addstu.zh"/></a>?
<a href="changeLang.action?request_locale=en">
<s:text name="addstu.en"/></a>
</center>
<s:form action="add.action" method="post">
<table>
<tr><td><s:text name="addstu.name"/></td>
<td><s:textfield name="name" /></td></tr>
<tr><td><s:text name="addstu.birthday"/></td>
<td><s:textfield name="birthday" /></td></tr>
<tr><td><s:text name="addstu.height"/></td>
<td><s:textfield name="height" /></td></tr>
<tr><td><s:text name="addstu.weight"/></td>
<td><s:textfield name="weight" /></td></tr>
<tr><td colspan="2">
<s:submit value="%{getText('addstu.btn')}"/>
</td></tr>
</table>
</s:form>
</body>
</html>
在JSP頁(yè)面中顯示國(guó)際化信息的方式有兩種:
??如果是頁(yè)面上單獨(dú)的文本,可以使用<s:text/>標(biāo)簽讀取國(guó)際化信息,name屬性的值是資
源文件中的key。
??如果是標(biāo)簽中的某個(gè)屬性值,例如上述代碼中的提交按鈕,這時(shí)可以使用%{getText(' key ')}讀取國(guó)際化信息,其中key指的就是資源文件中的key。
運(yùn)行該JSP頁(yè)面,效果如圖9.1.1和9.1.2所示。
?
圖9.1.1 中文界面
?
圖9.1.2 英文界面
問(wèn)了方便用戶(hù)自由選擇語(yǔ)言,我們?cè)陧?yè)面上放置了兩個(gè)超鏈接,單擊【英文】超鏈接后就顯示英文界面,單擊【Chinese】超鏈接后就顯示中文界面,這兩個(gè)超鏈接的代碼如下所示。
<a href="changeLang.action?request_locale=zh_CN">
<s:text name="addstu.zh"/></a>
<a href="changeLang.action?request_locale=en">
<s:text name="addstu.en"/></a>
在上述代碼中,超鏈接請(qǐng)求了changeLang.action并傳遞了參數(shù)“request_locale”,那么changeLang.action對(duì)應(yīng)的Action類(lèi)是如何實(shí)現(xiàn)中英文界面切換的呢?我們看下面該Action類(lèi)的代碼。
public class LanguageAction extends ActionSupport {
public String execute()
{
return SUCCESS;
}
}
我們發(fā)現(xiàn)該Action類(lèi)沒(méi)有做任何處理,為什么能夠?qū)崿F(xiàn)中英文界面切換呢?事實(shí)上,這個(gè)功能是由Struts 2內(nèi)置的名字是“i18n”的攔截器實(shí)現(xiàn)的,該攔截器被添加到了默認(rèn)的攔截器棧中(defaultStack),具體實(shí)現(xiàn)過(guò)程如下:
??當(dāng)客戶(hù)端請(qǐng)求發(fā)送到服務(wù)器端后,Struts 2的i18n攔截器會(huì)對(duì)客戶(hù)端請(qǐng)求進(jìn)行攔截并獲得參數(shù)request_locale的值(zh或cn),該值存儲(chǔ)了客戶(hù)端瀏覽器的地區(qū)語(yǔ)言環(huán)境,獲得該值后i18n攔截器將它實(shí)例化成一個(gè)Locale對(duì)象并存儲(chǔ)在用戶(hù)session中一個(gè)名字為WW_TRANS_I18N_LOCALE的屬性中,該屬性的值將會(huì)作為瀏覽器默認(rèn)的Locale。
??在獲得了客戶(hù)端地區(qū)語(yǔ)言環(huán)境后,Struts 2會(huì)查找struts.xml配置文件來(lái)加載國(guó)際化資源文件。
??加載好國(guó)際化資源文件后,Struts 2的視圖文件會(huì)通過(guò)Struts 2標(biāo)簽把國(guó)際化消息顯示出來(lái)。
9.1.2?校驗(yàn)配置文件的國(guó)際化
上一章我們學(xué)習(xí)了使用Struts 2內(nèi)置校驗(yàn)器進(jìn)行輸入校驗(yàn),這時(shí)需要提供一個(gè)校驗(yàn)配置文件,例如下面是登錄案例的校驗(yàn)配置文件。
<validators>
<field name="name">
<field-validator type="requiredstring">
<message>登錄不能為空!</message>
</field-validator>
</field>
<field name="pwd">
<field-validator type="requiredstring">
<message>登錄密碼不能為空!</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">6</param>
<message>密碼長(zhǎng)度必須大于等于${minLength}</message>
</field-validator>
</field>
</validators>
在校驗(yàn)配置文件中可以通過(guò)<message>元素設(shè)置提示信息,但是如果現(xiàn)在需要對(duì)這些提示信息進(jìn)行國(guó)際化處理該怎么辦呢?
示例9.2
假如現(xiàn)在我們要添加學(xué)生,要求學(xué)生姓名非空,學(xué)生身高必須在120cm和220cm之間,考慮到國(guó)際化,校驗(yàn)配置文件可以這樣寫(xiě):
<validators>
<field name="name">
<field-validator type="requiredstring">
<message key="addStu.validate.name"/>
</field-validator>
</field>
<field name="height">
<field-validator type="int">
<param name="min">120</param>
<param name="max">220</param>
<message ?key="addStu.validate.height"/>
</field-validator>
</field>
</validators>
<message>元素不再直接設(shè)置提示信息了,而是通過(guò)key屬性從國(guó)際化資源文件中取出信息,key屬性的值就是國(guó)際化資源文件中的key。下面是本示例中的資源文件:
中文資源文件:
addstu.title=\u6DFB\u52A0\u5B66\u751F
addstu.name=\u5B66\u751F\u59D3\u540D
addstu.birthday=\u5B66\u751F\u751F\u65E5
addstu.height=\u5B66\u751F\u8EAB\u9AD8
addstu.weight=\u5B66\u751F\u4F53\u91CD
addstu.btn=\u6DFB\u52A0
addstu.exception=\u4E0D\u597D51FA\u73B0\u5F02\u5E38\u3002
addstu.en=\u82F1\u6587
addstu.zh=\u4E2D\u6587
addstu.validate.name=\u5B66\u759D3\u540D\u5FC5\u987B\u586B\u5199\uFF01
addStu.validate.height=\u5B66\u751F\u8E5\u987B\u5728${min}\u548C${max}
英文資源文件:
addstu.title=add a new Student
addstu.name=student'name
addstu.birthday=student'birthday
addstu.height=student'height
addstu.weight=student'weight
addstu.btn=Add
addstu.exception=Sorry,Program temporarily appear unusual.
addstu.zh=Chinese
addstu.en=EngLish
addstu.validate.name=student name is required
addStu.validate.height=student height is must between ${min} and ${max}
其他文件的代碼不變,運(yùn)行效果如圖9.1.3和圖9.1.4所示。
?
圖9.1.3 中文提示信息
?
圖9.1.4 英文提示信息
9.2?Struts 2異常處理
異常是程序運(yùn)行時(shí)不可避免的情況,所以我們?cè)谶M(jìn)行程序開(kāi)發(fā)時(shí)必須對(duì)異常進(jìn)行處理。傳統(tǒng)的異常處理方式就是使用try-catch語(yǔ)句,這種處理機(jī)制采用的是硬編碼的方式,需要編寫(xiě)很多重復(fù)的代碼,并且不利于維護(hù)。而Struts 2作為成熟的MVC框架提供了完善的異常處理機(jī)制,采用的是聲明式的異常處理方式,這種方式便于管理和維護(hù)。
9.2.1?Struts 2異常處理機(jī)制
客戶(hù)端發(fā)送一個(gè)請(qǐng)求后,Struts 2框架會(huì)把這個(gè)請(qǐng)求交給Action進(jìn)行處理,在Action進(jìn)行業(yè)務(wù)處理的過(guò)程中,如果出現(xiàn)異常了,Struts 2中名字為exception的攔截器就會(huì)自動(dòng)攔截該異常并進(jìn)行處理,然后再轉(zhuǎn)到相應(yīng)的視圖頁(yè)面反饋給用戶(hù)。由于Struts 2把異常交給了exception攔截器進(jìn)行處理,所以我們無(wú)須在Action中編寫(xiě)try-catch語(yǔ)句塊,只需要在struts.xml中對(duì)Action進(jìn)行異常配置就行了。
struts.xml文件通過(guò)使用<exception-mapping />元素來(lái)進(jìn)行異常映射配置,在使用該元素時(shí)需要指定兩個(gè)屬性:
??exception屬性:該屬性用來(lái)指定異常的類(lèi)型。
??result屬性:該屬性值是一個(gè)url地址,用來(lái)指定出現(xiàn)異常時(shí)Struts 2跳轉(zhuǎn)到哪個(gè)視圖。
根據(jù)異常映射起作用的范圍可以把異常映射配置分為全局異常映射和局部異常映射。
??全局異常映射:這種映射使用<global-exception-mapping />元素進(jìn)行配置,在該元素中嵌套<exception-mapping />作為子元素,這種映射的作用范圍是package中的所有Action。
??局部異常映射:這種映射直接在Action內(nèi)部使用<exception-mapping />元素配置就行了,當(dāng)然它的作用范圍為它所在的Action。
這兩種異常映射的優(yōu)先級(jí)不同,如果對(duì)一個(gè)Action既配置了全局映射又配置了局部映射,那么Struts 2會(huì)采用“就進(jìn)原則”,即使用局部映射進(jìn)行異常處理。
9.2.2?異常處理示例
示例9.3
下面通過(guò)一個(gè)示例來(lái)具體介紹Struts 2如何進(jìn)行異常處理。在程序中如果出現(xiàn)除數(shù)為0的情況就會(huì)出現(xiàn)java.lang.ArithmeticException異常,這個(gè)大家都非常熟悉了。本示例就模擬除數(shù)為0的情況,如圖9.1.5所示。
?
圖9.1.5 運(yùn)行效果
JSP頁(yè)面的參考代碼如下所示。
<body>
<h3><center>除法計(jì)算</center></h3>
<center>
<s:form action="jisuan.action" method="post" theme="simple">
<s:textfield name="a" cssStyle="width:60"></s:textfield>
除以
<s:textfield name="b" cssStyle="width:60"></s:textfield>
等于
<s:textfield name="c" cssStyle="width:60"></s:textfield>
<s:submit value="計(jì)算"/>
</s:form></center>
</body>
Action的代碼如下所示。
public class jisuanAction ?extends ActionSupport{
private int a; ???//被除數(shù)
private int b; ??//除數(shù)
private int c; ??//結(jié)果
//省略getter和setter方法
public String jisuan()
{
this.c=this.a/this.b;
return SUCCESS;
}
}
異常提示頁(yè)面error.jsp的代碼如下所示。
<body>
<center><h2>出現(xiàn)除0異常</h2></center>
</body>
重點(diǎn)是下面的配置文件,代碼如下所示。
<package name="struts2_math" extends="struts-default">
<global-results>
<result name="error">/error.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping result="error"
?exception="java.lang.ArithmeticException">
</exception-mapping>
</global-exception-mappings>
<action name="jisuan" class="com.zy.jisuanAction" method="jisuan">
</action>
</package>
我們?cè)谂渲梦募?lt;global-exception-mappings>元素中配置了一個(gè)異常映射用來(lái)處理除0異常,如果有除0異常發(fā)生就跳轉(zhuǎn)到error.jsp頁(yè)面,如圖9.1.6所示。
?
圖9.1.6 異常提示
9.3?Struts 2文件上傳
文件上傳是WEB應(yīng)用中經(jīng)常遇到的問(wèn)題,Struts 2默認(rèn)使用Jakarta的Common-FileUpload文件上傳框架,并對(duì)其進(jìn)行了優(yōu)化和封裝。在實(shí)際應(yīng)用中,需要把commons-io-xxx.jar和commons-fileupload-xxx.jar(xxx是版本號(hào))導(dǎo)入到WEB項(xiàng)目中。我們通過(guò)MyEclipse 添加Struts支持時(shí)會(huì)默認(rèn)導(dǎo)入這兩個(gè)Jar文件,如圖9.1.7所示。
?
圖9.1.7 導(dǎo)入Jar
9.3.1?單文件上傳
示例9.4
文件上傳中最簡(jiǎn)單的是上傳一個(gè)文件,下面我們通過(guò)一個(gè)示例介紹如何使用Struts 2實(shí)現(xiàn)單文件上傳。
(1)?創(chuàng)建表單提供上傳文件的操作入口,代碼如下所示。
<body>
<s:form action="up.action" method="post" enctype="multipart/form-data">
<s:file name="upload" label="請(qǐng)選擇上傳文件"/>
<s:submit value="上傳"/>
</s:form>
</body>
需要注意:<s:form>標(biāo)簽必須指定enctype屬性并且該屬性的值必須是“multipart/form-data”,這表示表單的數(shù)據(jù)不再以字符串的形式提交,而是以二進(jìn)制編碼的形式來(lái)提交數(shù)據(jù)。
(2)?創(chuàng)建實(shí)現(xiàn)在服務(wù)器端接收上傳文件并保存到指定位置功能的Action,代碼如下所示。
public class MyUpAction extends ActionSupport{
??private File upload; ??//對(duì)應(yīng)表單中文件域的名字
??private String uploadContentType; ???//文件類(lèi)型
??private String uploadFileName; ??????//文件名字
//省略getter和setter方法
??public String execute() throws Exception
??{
//獲取服務(wù)器上保存文件的路徑和上傳文件的名字,本示例的路徑是/upfile
??????String fileName=ServletActionContext.getServletContext().
getRealPath("/upfile")+"\\"+getUploadFileName();
//文件輸出流
??????FileOutputStream fos=new FileOutputStream(fileName);
//文件上傳流
??????FileInputStream fis=new FileInputStream(getUpload()); ?
//下面的代碼把上傳到服務(wù)器的文件保存(寫(xiě)入)到指定文件夾中
??????byte[] b=new byte[1024];
??????int len=0;
//通過(guò)循環(huán)把文件二進(jìn)制數(shù)據(jù)寫(xiě)入到服務(wù)器
??????while((len=fis.read(b))>0)
??????{
????????fos.write(b,0,len);
??????}
??????return this.SUCCESS;
??}
}
該Action與普通Action的差別不大,upload屬性封裝了表單中的文件域;uploadContentType封裝上傳文件的類(lèi)型;uploadFileName封裝上傳文件的名字。以上三個(gè)屬性是必須的并且Struts 2會(huì)從文件域中解析出來(lái)自動(dòng)賦值給Action。一般情況下,如果表單中包含一個(gè)name屬性為xxx的文件域,那么就需要在Action中使用如下的三個(gè)屬性來(lái)封裝文件域信息:
private File xxx:封裝文件域?qū)?yīng)的文件內(nèi)容。
?private String xxxFileName:封裝上傳文件的文件名。
?private String xxxContentType:封裝上傳文件的文件類(lèi)型。
通過(guò)封裝上述三個(gè)屬性之后就可以在execute方法中實(shí)現(xiàn)文件上傳功能了。在execute方法中主要通過(guò)文件輸入輸出流實(shí)現(xiàn)文件的上傳。
(3)?上傳成功后跳轉(zhuǎn)到另外一個(gè)頁(yè)面顯示文件的名字,如果是圖片就把圖片顯示到頁(yè)面上,參考代碼如下所示。
<body>
<h3>文件上傳成功</h3>
<s:property value="uploadFileName"/><br>
<img src="upfile/<s:property value="uploadFileName"/>"/>
</body>
(4)?在struts.xml文件中進(jìn)行配置,參考代碼如下所示。
<package name="upfile" extends="struts-default">
<action name="up" class="com.zy.MyUpAction">
<interceptor-ref name="fileUpload">
<param name="allowedExtensions">.bmp,.gif,.jpg</param>
<param name="maximumSize">1000000</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
<result name="success" type="dispatcher">/up_success.jsp</result>
<result name="input" >/up_success.jsp</result>
</action>
</package>
為了對(duì)上傳文件的類(lèi)型和大小進(jìn)行限制,我們?yōu)锳ction配置了名字是“fileUpload”的攔截器,該攔截器由Struts 2框架提供,專(zhuān)門(mén)用來(lái)限制上傳文件的類(lèi)型和大小。在使用的時(shí)候需要指定兩個(gè)參數(shù):
??allowedExtensions:該參數(shù)用來(lái)限制文件類(lèi)型,需要給出擴(kuò)展名,多個(gè)擴(kuò)展名之間用逗
號(hào)隔開(kāi)。
??maximumSize:該參數(shù)用來(lái)限制文件大小,單位是字節(jié)。
如果上傳文件失敗了,Struts 2會(huì)自動(dòng)轉(zhuǎn)入到input結(jié)果視圖,所以必須為Action配置input結(jié)果視圖。另外,我們必須配置defaultStack默認(rèn)攔截器棧,并且必須放在fileUpload攔截器的后面。
Struts 2默認(rèn)情況下最大只能上傳2M的文件,超過(guò)2M的話(huà)maximumSize參數(shù)也不起作用,會(huì)直接出現(xiàn)異常。為了解決這個(gè)問(wèn)題,我們可以在struts.xml文件中配置struts.multipart.maxSize常量,參考代碼如下所示。
<constant name="struts.multipart.maxSize" value="1000000000"/>
我們上傳一張圖片,運(yùn)行效果如圖9.1.8和10.1.9所示。
?
圖9.1.8 上傳圖片
?
圖9.1.9 上傳成功
?
9.3.2?多文件上傳
示例9.5
在WEB應(yīng)用中,一次上傳多個(gè)文件也是很常見(jiàn)的情況,這時(shí)我們只需在上述實(shí)現(xiàn)單文件上傳的代碼的基礎(chǔ)上稍作修改即可,與單文件上傳的本質(zhì)是一樣的。
(1)?修改表單,增加幾個(gè)文件域,參考代碼如下所示。
<body>
<s:form action="up_m.action" method="post" enctype="multipart/form-data">
請(qǐng)選擇您要上傳的文件:<br>
<s:file name="upload" label="圖片1"/>
<s:file name="upload" label="圖片2"/>
<s:file name="upload" label="圖片3"/>
<s:submit value="上傳" />
</s:form>
</body>
多個(gè)文件域的name屬性值保持一致。
(2)?修改實(shí)現(xiàn)上傳的Action,參考代碼如下所示。
public class MyUpAction_m extends ActionSupport {
//由于是多文件上傳,所以下面三個(gè)屬性都改成了數(shù)組
??private File[] upload;
??private String[] uploadContentType;
??private String[] uploadFileName;
//省略getter和setter方法
??public String execute() throws Exception
??{
??????File[] files=getUpload();
//由于是多文件上傳,所以在源代碼的基礎(chǔ)上增加了for循環(huán)
??????for(int i=0;i<files.length;i++)
??????{
????????String fileName=ServletActionContext.getServletContext().
getRealPath("/upfile")+"\\"+getUploadFileName()[i];
????????FileOutputStream fos=new FileOutputStream(fileName);
????????FileInputStream fis=new FileInputStream(files[i]); ?????
????????byte[] b=new byte[1024];
????????int len=0;
????????while((len=fis.read(b))>0)
????????{
??????????fos.write(b,0,len);
????????}
??????}
??????return this.SUCCESS;
??}
}
(3)?修改上傳成功后的頁(yè)面,參考代碼如下所示。
<s:iterator value="uploadFileName" id="name">
<s:property value="name"/>
<img src="upfile/<s:property value="name"/>"/>
</s:iterator>
由于要顯示多個(gè)文件,所以這里使用了<s:iterator>迭代器來(lái)進(jìn)行循環(huán)顯示。
struts.xml無(wú)需修改,運(yùn)行效果如圖9.1.10和圖9.1.11所示。
?
圖9.1.10 多文件上傳
?
圖9.1.11上傳成功
本章總結(jié)
??國(guó)際化主要是指語(yǔ)言的國(guó)際化,目的是使應(yīng)用程序能提供一個(gè)語(yǔ)言自適應(yīng)、顯示更友好的用戶(hù)界面,掃除語(yǔ)言障礙,使不同地區(qū)和使用不同語(yǔ)言的用戶(hù)都能方便的使用我們開(kāi)發(fā)的WEB應(yīng)用系統(tǒng)。
(1)創(chuàng)建中英文資源文件。
(2)在struts.xml文件中配置資源文件。
(3)在JSP頁(yè)面中使用<s:text />標(biāo)簽或OGNL顯示國(guó)際化信息。
??Struts 2作為成熟的MVC框架提供了完善的異常處理機(jī)制,采用的是聲明式的異常處理方式,這種方式便于管理和維護(hù),struts.xml文件通過(guò)使用<exception-mapping />元素來(lái)進(jìn)行異常映射配置。
(1)exception屬性:該屬性用來(lái)指定異常的類(lèi)型。
(2)result屬性:該屬性值是一個(gè)url地址,用來(lái)指定出現(xiàn)異常時(shí)Struts 2跳轉(zhuǎn)到哪個(gè)視圖。
(3)全局異常映射:這種映射使用<global-exception-mapping />元素進(jìn)行配置,在該元素中嵌套<exception-mapping />作為子元素,這種映射的作用范圍是package中的所有Action。
(4)局部異常映射:這種映射直接在Action內(nèi)部使用<exception-mapping />元素配置就行了,當(dāng)然它的作用范圍為它所在的Action。
??文件上傳是WEB應(yīng)用中經(jīng)常遇到的問(wèn)題,Struts 2默認(rèn)使用Jakarta的Common-FileUpload文件上傳框架,并對(duì)其進(jìn)行了優(yōu)化和封裝。
(1)<s:form>標(biāo)簽必須指定enctype屬性并且該屬性的值必須是“multipart/form-data”,這表示表單的數(shù)據(jù)不再以字符串的形式提交,而是以二進(jìn)制編碼的形式來(lái)提交數(shù)據(jù)。
(2)實(shí)現(xiàn)在服務(wù)器端接收上傳文件并保存到指定位置功能的Action。
(3)fileUpload攔截器,該攔截器由Struts 2框架提供,專(zhuān)門(mén)用來(lái)限制上傳文件的類(lèi)型和大小。
任務(wù)實(shí)訓(xùn)部分
1:添加管理員功能?chē)?guó)際化
訓(xùn)練技能點(diǎn)
??國(guó)際化
??<s:text>和OGNL顯示國(guó)際化消息
需求說(shuō)明
在上一章的任務(wù)實(shí)訓(xùn)部分我們實(shí)現(xiàn)了對(duì)添加管理員的輸入驗(yàn)證,現(xiàn)在要求對(duì)該案例進(jìn)行國(guó)際化處理,支持中文、英文的切換。
實(shí)現(xiàn)步驟
(1)?創(chuàng)建中英文國(guó)際化資源文件,參考代碼如下所示
英文資源文件:
addadmin.title=add a new Administrator
addadmin.name=name
addadmin.pwd=password
addadmin.submit=submit
addadmin.validate.name.null=name is required!
addadmin.validate.pwd.null=password is required!
addadmin.validate.pwd.length=password'length must be more than 6
addadmin.validate.pwd2=Two of the input password must be equal
addadmin.lang=ChooseLanguage
addadmin.zh=Chinese
addadmin.en=EngLish
中文資源文件:
addadmin.title=\u6DFB\u52A0\u7BA1\u7406\u5458
addadmin.name=\u767B\u5F55\u540D\u79F0
addadmin.pwd=\u767B\u5F55\u5BC6\u7801
addadmin.submit=\u63D0\u4EA4
addadmin.validate.name.null=\u767B\u5F55\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A\uFF01
addadmin.validate.pwd.null=\u767B\u5F55\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF01
addadmin.validate.pwd.length=\u5BC6\u7801\u957F\u5EA6\u5FC5\u987B\u5927\u4E8E6\uFF01
addadmin.validate.pwd2=\u4E24\u6B21\u8F93\u5165\u7684\u5BC6\u7801\u5FC5\u987B\u4E00\u81F4\uFF01
addadmin.lang=\u8BED\u8A00\u9009\u62E9
addadmin.zh=\u4E2D\u6587
addadmin.en=\u82F1\u6587
(2)?下面是實(shí)現(xiàn)輸入驗(yàn)證的Action,參考代碼如下所示。
public class AddAction extends ActionSupport {
private String logName;
private String logPwd1;
private String logPwd2;
public String execute() {
AdminDao ad=new AdminDao();
if(ad.addAdmin(logName, logPwd1))
return SUCCESS;
else
return ERROR;
}
public void validate()
{
if(logName==null||logName.equals(""))
this.addFieldError("logName",
getText("addadmin.validate.name.null"));
if(logPwd1==null||logPwd1.equals(""))
this.addFieldError("logPwd1",
getText("addadmin.validate.pwd.null"));
if(logPwd1.length()<6||logPwd2.length()>10)
this.addFieldError("logPwd1", )
getText("addadmin.validate.pwd.length"));
if(!logPwd1.equals(logPwd2))
this.addFieldError("logPwd2", getText("addadmin.validate.pwd2"));
}
//省略getter和setter方法
}
在通過(guò)addFieldError方法添加提示信息時(shí),請(qǐng)注意這里使用了getText。
(3)?下面是添加管理員的表單,代碼如下所示。
<body>
<h3><s:text name="addadmin.title"/></h3>
<s:text name="addadmin.lang"/>:<select οnchange="changeLocal(this.value)" id="lang">
<option value="zh"><s:text name="addadmin.zh"/></option>
<option value="en"><s:text name="addadmin.en"/></option>
</select>
<s:form action="add.action" method="post">
<s:textfield name="logName" label="%{getText('addadmin.name')}"/>
<s:password name="logPwd1" label="%{getText('addadmin.pwd')}"/>
<s:password name="logPwd2" label="%{getText('addadmin.pwd')}"/>
<s:submit value="%{getText('addadmin.submit')}"/>
</s:form>
</body>
<script>
??if(location.search=="")
location="changeLang.action?request_locale=zh";
??else if(location.search=="?request_locale=zh")
document.getElementById("lang").selectedIndex=0;
??else
document.getElementById("lang").selectedIndex=1;
function changeLocal(val)
{
location="changeLang.action?request_locale="+val;
}
</script>
這里我們要求用戶(hù)可以自由選擇語(yǔ)言環(huán)境,但不是通過(guò)超鏈接實(shí)現(xiàn)的,而是通過(guò)下拉列表框,如圖9.2.1所示,所以必須通過(guò)JavaScript代碼進(jìn)行控制。
?
圖9.2.1 中文界面
?
圖9.2.2 英文界面
2:國(guó)際化校驗(yàn)配置文件
訓(xùn)練技能點(diǎn)
??Struts 2內(nèi)置校驗(yàn)器
??國(guó)際化校驗(yàn)配置文件
需求說(shuō)明
上個(gè)實(shí)訓(xùn)任務(wù)是通過(guò)重寫(xiě)ActionSupport類(lèi)的valudate方法來(lái)實(shí)現(xiàn)輸入校驗(yàn)的,現(xiàn)在要求使用Struts 2的內(nèi)置校驗(yàn)器實(shí)現(xiàn)輸入校驗(yàn)并實(shí)現(xiàn)校驗(yàn)配置文件的國(guó)際化。
3:數(shù)據(jù)庫(kù)操作異常處理
訓(xùn)練技能點(diǎn)
??Struts 2異常處理
需求說(shuō)明
在使用JDBC進(jìn)行數(shù)據(jù)庫(kù)操作時(shí)很容易出現(xiàn)異常,所以通常我們都需要對(duì)進(jìn)行數(shù)據(jù)庫(kù)操作的代碼使用try-catch語(yǔ)句,但是這也不能滿(mǎn)足復(fù)雜項(xiàng)目的需求,現(xiàn)在要求為添加管理員的示例使用Struts 2完善異常處理,為Action配置全局異常映射。
4:添加學(xué)生照片
訓(xùn)練技能點(diǎn)
??Struts 2文件上傳
需求說(shuō)明
前面我們實(shí)現(xiàn)過(guò)一個(gè)添加學(xué)生的示例,現(xiàn)在要求在添加學(xué)生信息的時(shí)候必須保存學(xué)生的照片,請(qǐng)使用Struts 2文件上傳實(shí)現(xiàn)該功能。
實(shí)現(xiàn)步驟
(1)?在表單中增加文件域,代碼如下所示:
<body>
<s:form action="addStu.action" method="post"
?enctype="multipart/form-data">
<s:textfield name="name" label="學(xué)生姓名"/>
<s:textfield name="birthday" label="學(xué)生生日"/>
<s:textfield name="height" label="學(xué)生身高"/>
<s:textfield name="weight" label="學(xué)生體重"/>
<s:file name="upload" label="學(xué)生照片"/>
<s:submit value="添加"/>
</s:form>
</body>
注意為表單增加enctype="multipart/form-data"。
(2)創(chuàng)建實(shí)現(xiàn)上傳的Action,參考代碼如下所示:
public class MyUpAction extends ActionSupport{
private String name; ??//學(xué)生姓名
private String birthday; ??//學(xué)生生日
private int height; ???????//學(xué)生身高
private int weight; ??????//學(xué)生體重
?//封裝上傳文件域的屬性
private File upload;
//封裝上傳文件的類(lèi)型
private String uploadContentType;
//封裝上傳文件名
private String uploadFileName;
//方法省略
}
(3)上傳成功后,把學(xué)生的相關(guān)信息顯示到頁(yè)面上,運(yùn)行效果如圖9.2.3和圖9.2.4所示。
?
圖9.2.3 添加學(xué)生
?
圖9.2.4 顯示學(xué)生信息
?
鞏固練習(xí)
一、選擇題
1. 用來(lái)讀取國(guó)際化資源文件的Struts 2標(biāo)簽是()。
A.?<s:textfield>
B.?<s:text>
C.?<s:message>
D.?<s:resource>
2.以下關(guān)于Struts 2的國(guó)際化資源文件說(shuō)法正確的是()。
A.?資源文件的名字可以自定義,沒(méi)有任何規(guī)定
B.?資源文件只要放在正確的路徑下,Struts就能找到了,無(wú)需在struts-config.xml中進(jìn)行任何配置
C.?資源文件只能放在WEB-INF/classes的根目錄下
D.?中文資源文件需要轉(zhuǎn)碼
3.以下關(guān)于Struts 2異常處理說(shuō)法正確的是()。
A.?通過(guò)Struts 2的異常處理機(jī)制可以避免異常的發(fā)生
B.?Struts 2的異常處理需要名字為exception的攔截器
C.?全局異常映射的作用范圍是struts.xml中的所有Action
D.?全局異常映射的優(yōu)先級(jí)高于局部異常映射
4.以下關(guān)于Struts 2異常處理說(shuō)法正確的是()。
A.?通過(guò)Struts 2的異常處理機(jī)制可以避免異常的發(fā)生
E.?Struts 2的異常處理需要名字為exception的攔截器
F.?全局異常映射的作用范圍是struts.xml中的所有Action
G.?全局異常映射的優(yōu)先級(jí)高于局部異常映射
5.以下關(guān)于Struts 2文件上傳說(shuō)法錯(cuò)誤的是()。
A.?表單必須設(shè)置enctype屬性
B.?通過(guò)名字是“fileUpload”的攔截器可以限制文件類(lèi)型和大小
C.?Struts 2對(duì)上傳文件的大小沒(méi)有任何限制
D.?Struts 2支持多文件上傳?
二、上機(jī)練習(xí)
上一章的鞏固練習(xí)部分要求大家實(shí)現(xiàn)了一個(gè)注冊(cè)功能,現(xiàn)在在此基礎(chǔ)上使用Struts 2實(shí)現(xiàn)國(guó)際化和照片上傳功能。
總結(jié)
以上是生活随笔為你收集整理的Struts 2常见应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Struts2 类型转换和数据校验
- 下一篇: Spring常见面试题