学习内容

Struts 2国际化

Struts 2的异常处理

Struts 2的文件上传与下载

能力目标

熟练使用Struts 2实现国际化

能通过Struts 2的异常处理增强WEB应用的健壮性

使用Struts2实现文件上传与下载

本章简介

本章主要介绍Struts 2的常见应用,主要包括Struts 2国际化、Struts 2异常处理和文件上传与下载。Internet把全世界联系在了一起,WEB应用可以通过浏览器被全世界的人们所使用,所以开发人员需要考虑WEB应用系统在不同地区和语言环境中的使用情况,使WEB

应用系统能在不同的地区和语言环境中以当地的语言进行显示,这个过程就称之为国际化。

任何成熟的MVC类框架都应该提供成熟完善的异常处理机制,Struts 2采用了一种声明式的异常处理机制,从而避免了在程序中编写大量的try-catch块,使异常处理和业务代码不再耦合。

文件的上传与下载也是WEB应用常见的功能,例如上传图片,本章最后会学习使用Struts 2实现文件的上传与下载。

核心技能部分

9.1 sStruts 2国际化

国际化主要是指语言的国际化,目的是使应用程序能提供一个语言自适应、显示更友好的用户界面,扫除语言障碍,使不同地区和使用不同语言的用户都能方便的使用我们开发的WEB应用系统。Struts 2国际化建立在Java国际化的基础上,只是对Java国际化进行了进一步的优化和封装,从而简化了国际化的实现过程。

9.1.1 Struts 2国际化机制

Struts 2实现国际化的过程需要三个步骤:

(1) 创建中英文资源文件。

(2) 在struts.xml文件中配置资源文件。

(3) 在JSP页面中使用<s:text />标签或OGNL显示国际化信息。

示例9.1

下面我们以添加学生为例来演示Struts 2实现国际化的详细过程。

(1) 在工程的src根目录下创建两个国际化资源文件,分别是英文的资源文件: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一样,国际化资源文件是以properties为扩展名的文本文件,该文本文件以key=value的形式存储了国际化消息资源。国际化资源文件的命名规则是resourceName_language.properties。其中,resourceName是自定义的资源文件基本名,language是不能自定义的,Java中规定了不同的字符代表不同的国家和地区的语言,zh表示简体中文,en表示英语。

中文的资源文件因为包含了非西欧字符,所以必须把这个文件通过native2ascii命令进行转码,转码之后的中文资源文件才能使用,语法如下所示:

语法

native2ascii -encoding UTF-8 原中文资源文件名转码后的资源文件名

高版本的MyEclipse会自动对中文资源文件转码,因此可以直接编辑。

(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文件中通过<constant>元素把国际化资源文件的名字告知Struts 2框架,其中name属性的值必须是"struts.custom.i18n.resources",value属性的值就是项目中国际化资源文件的名字,注意只写基本名即可。

(3) 在JSP页面中显示国际化信息,参考代码如下所示。

<%@ 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页面中显示国际化信息的方式有两种:

Ø 如果是页面上单独的文本,可以使用<s:text/>标签读取国际化信息,name属性的值是资

源文件中的key。

Ø 如果是标签中的某个属性值,例如上述代码中的提交按钮,这时可以使用%{getText(' key ')}读取国际化信息,其中key指的就是资源文件中的key。

运行该JSP页面,效果如图9.1.1和9.1.2所示。

图9.1.1 中文界面

图9.1.2 英文界面

问了方便用户自由选择语言,我们在页面上放置了两个超链接,单击【英文】超链接后就显示英文界面,单击【Chinese】超链接后就显示中文界面,这两个超链接的代码如下所示。

<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>

在上述代码中,超链接请求了changeLang.action并传递了参数“request_locale”,那么changeLang.action对应的Action类是如何实现中英文界面切换的呢?我们看下面该Action类的代码。

public class LanguageAction extends ActionSupport {

public String execute()

{

return SUCCESS;

}

}

我们发现该Action类没有做任何处理,为什么能够实现中英文界面切换呢?事实上,这个功能是由Struts 2内置的名字是“i18n”的拦截器实现的,该拦截器被添加到了默认的拦截器栈中(defaultStack),具体实现过程如下:

Ø 当客户端请求发送到服务器端后,Struts 2的i18n拦截器会对客户端请求进行拦截并获得参数request_locale的值(zh或cn),该值存储了客户端浏览器的地区语言环境,获得该值后i18n拦截器将它实例化成一个Locale对象并存储在用户session中一个名字为WW_TRANS_I18N_LOCALE的属性中,该属性的值将会作为浏览器默认的Locale。

Ø 在获得了客户端地区语言环境后,Struts 2会查找struts.xml配置文件来加载国际化资源文件。

Ø 加载好国际化资源文件后,Struts 2的视图文件会通过Struts 2标签把国际化消息显示出来。

9.1.2 校验配置文件的国际化

上一章我们学习了使用Struts 2内置校验器进行输入校验,这时需要提供一个校验配置文件,例如下面是登录案例的校验配置文件。

<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>密码长度必须大于等于${minLength}</message>

</field-validator>

</field>

</validators>

在校验配置文件中可以通过<message>元素设置提示信息,但是如果现在需要对这些提示信息进行国际化处理该怎么办呢?

示例9.2

假如现在我们要添加学生,要求学生姓名非空,学生身高必须在120cm和220cm之间,考虑到国际化,校验配置文件可以这样写:

<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>元素不再直接设置提示信息了,而是通过key属性从国际化资源文件中取出信息,key属性的值就是国际化资源文件中的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}

其他文件的代码不变,运行效果如图9.1.3和图9.1.4所示。

图9.1.3 中文提示信息

图9.1.4 英文提示信息

9.2 Struts 2异常处理

异常是程序运行时不可避免的情况,所以我们在进行程序开发时必须对异常进行处理。传统的异常处理方式就是使用try-catch语句,这种处理机制采用的是硬编码的方式,需要编写很多重复的代码,并且不利于维护。而Struts 2作为成熟的MVC框架提供了完善的异常处理机制,采用的是声明式的异常处理方式,这种方式便于管理和维护。

9.2.1 Struts 2异常处理机制

客户端发送一个请求后,Struts 2框架会把这个请求交给Action进行处理,在Action进行业务处理的过程中,如果出现异常了,Struts 2中名字为exception的拦截器就会自动拦截该异常并进行处理,然后再转到相应的视图页面反馈给用户。由于Struts 2把异常交给了exception拦截器进行处理,所以我们无须在Action中编写try-catch语句块,只需要在struts.xml中对Action进行异常配置就行了。

struts.xml文件通过使用<exception-mapping />元素来进行异常映射配置,在使用该元素时需要指定两个属性:

Ø exception属性:该属性用来指定异常的类型。

Ø result属性:该属性值是一个url地址,用来指定出现异常时Struts 2跳转到哪个视图。

根据异常映射起作用的范围可以把异常映射配置分为全局异常映射和局部异常映射。

Ø 全局异常映射:这种映射使用<global-exception-mapping />元素进行配置,在该元素中嵌套<exception-mapping />作为子元素,这种映射的作用范围是package中的所有Action。

Ø 局部异常映射:这种映射直接在Action内部使用<exception-mapping />元素配置就行了,当然它的作用范围为它所在的Action。

这两种异常映射的优先级不同,如果对一个Action既配置了全局映射又配置了局部映射,那么Struts 2会采用“就进原则”,即使用局部映射进行异常处理。

9.2.2 异常处理示例

示例9.3

下面通过一个示例来具体介绍Struts 2如何进行异常处理。在程序中如果出现除数为0的情况就会出现java.lang.ArithmeticException异常,这个大家都非常熟悉了。本示例就模拟除数为0的情况,如图9.1.5所示。

图9.1.5 运行效果

JSP页面的参考代码如下所示。

<body>

<h3><center>除法计算</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="计算"/>

</s:form></center>

</body>

Action的代码如下所示。

public class jisuanAction  extends ActionSupport{

private int a;    //被除数

private int b;   //除数

private int c;   //结果

//省略getter和setter方法

public String jisuan()

{

this.c=this.a/this.b;

return SUCCESS;

}

}

异常提示页面error.jsp的代码如下所示。

<body>

<center><h2>出现除0异常</h2></center>

</body>

重点是下面的配置文件,代码如下所示。

<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>

我们在配置文件的<global-exception-mappings>元素中配置了一个异常映射用来处理除0异常,如果有除0异常发生就跳转到error.jsp页面,如图9.1.6所示。

图9.1.6 异常提示

9.3 Struts 2文件上传

文件上传是WEB应用中经常遇到的问题,Struts 2默认使用Jakarta的Common-FileUpload文件上传框架,并对其进行了优化和封装。在实际应用中,需要把commons-io-xxx.jar和commons-fileupload-xxx.jar(xxx是版本号)导入到WEB项目中。我们通过MyEclipse 添加Struts支持时会默认导入这两个Jar文件,如图9.1.7所示。

图9.1.7 导入Jar

9.3.1 单文件上传

示例9.4

文件上传中最简单的是上传一个文件,下面我们通过一个示例介绍如何使用Struts 2实现单文件上传。

(1) 创建表单提供上传文件的操作入口,代码如下所示。

<body>

<s:form action="up.action" method="post" enctype="multipart/form-data">

<s:file name="upload" label="请选择上传文件"/>

<s:submit value="上传"/>

</s:form>

</body>

需要注意:<s:form>标签必须指定enctype属性并且该属性的值必须是“multipart/form-data”,这表示表单的数据不再以字符串的形式提交,而是以二进制编码的形式来提交数据。

(2) 创建实现在服务器端接收上传文件并保存到指定位置功能的Action,代码如下所示。

public class MyUpAction extends ActionSupport{

private File upload;   //对应表单中文件域的名字

private String uploadContentType;    //文件类型

private String uploadFileName;       //文件名字

//省略getter和setter方法

public String execute() throws Exception

{

//获取服务器上保存文件的路径和上传文件的名字,本示例的路径是/upfile

String fileName=ServletActionContext.getServletContext().

getRealPath("/upfile")+"\\"+getUploadFileName();

//文件输出流

FileOutputStream fos=new FileOutputStream(fileName);

//文件上传流

FileInputStream fis=new FileInputStream(getUpload());

//下面的代码把上传到服务器的文件保存(写入)到指定文件夹中

byte[] b=new byte[1024];

int len=0;

//通过循环把文件二进制数据写入到服务器

while((len=fis.read(b))>0)

{

fos.write(b,0,len);

}

return this.SUCCESS;

}

}

该Action与普通Action的差别不大,upload属性封装了表单中的文件域;uploadContentType封装上传文件的类型;uploadFileName封装上传文件的名字。以上三个属性是必须的并且Struts 2会从文件域中解析出来自动赋值给Action。一般情况下,如果表单中包含一个name属性为xxx的文件域,那么就需要在Action中使用如下的三个属性来封装文件域信息:

private File xxx:封装文件域对应的文件内容。

private String xxxFileName:封装上传文件的文件名。

private String xxxContentType:封装上传文件的文件类型。

通过封装上述三个属性之后就可以在execute方法中实现文件上传功能了。在execute方法中主要通过文件输入输出流实现文件的上传。

(3) 上传成功后跳转到另外一个页面显示文件的名字,如果是图片就把图片显示到页面上,参考代码如下所示。

<body>

<h3>文件上传成功</h3>

<s:property value="uploadFileName"/><br>

<img src="upfile/<s:property value="uploadFileName"/>"/>

</body>

(4) 在struts.xml文件中进行配置,参考代码如下所示。

<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>

为了对上传文件的类型和大小进行限制,我们为Action配置了名字是“fileUpload”的拦截器,该拦截器由Struts 2框架提供,专门用来限制上传文件的类型和大小。在使用的时候需要指定两个参数:

Ø allowedExtensions:该参数用来限制文件类型,需要给出扩展名,多个扩展名之间用逗

号隔开。

Ø maximumSize:该参数用来限制文件大小,单位是字节。

如果上传文件失败了,Struts 2会自动转入到input结果视图,所以必须为Action配置input结果视图。另外,我们必须配置defaultStack默认拦截器栈,并且必须放在fileUpload拦截器的后面。

Struts 2默认情况下最大只能上传2M的文件,超过2M的话maximumSize参数也不起作用,会直接出现异常。为了解决这个问题,我们可以在struts.xml文件中配置struts.multipart.maxSize常量,参考代码如下所示。

<constant name="struts.multipart.maxSize" value="1000000000"/>

我们上传一张图片,运行效果如图9.1.8和10.1.9所示。

图9.1.8 上传图片

图9.1.9 上传成功

9.3.2 多文件上传

示例9.5

在WEB应用中,一次上传多个文件也是很常见的情况,这时我们只需在上述实现单文件上传的代码的基础上稍作修改即可,与单文件上传的本质是一样的。

(1) 修改表单,增加几个文件域,参考代码如下所示。

<body>

<s:form action="up_m.action" method="post" enctype="multipart/form-data">

请选择您要上传的文件:<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>

多个文件域的name属性值保持一致。

(2) 修改实现上传的Action,参考代码如下所示。

public class MyUpAction_m extends ActionSupport {

//由于是多文件上传,所以下面三个属性都改成了数组

private File[] upload;

private String[] uploadContentType;

private String[] uploadFileName;

//省略getter和setter方法

public String execute() throws Exception

{

File[] files=getUpload();

//由于是多文件上传,所以在源代码的基础上增加了for循环

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) 修改上传成功后的页面,参考代码如下所示。

<s:iterator value="uploadFileName" id="name">

<s:property value="name"/>

<img src="upfile/<s:property value="name"/>"/>

</s:iterator>

由于要显示多个文件,所以这里使用了<s:iterator>迭代器来进行循环显示。

struts.xml无需修改,运行效果如图9.1.10和图9.1.11所示。

图9.1.10 多文件上传

图9.1.11上传成功


本章总结

Ø 国际化主要是指语言的国际化,目的是使应用程序能提供一个语言自适应、显示更友好的用户界面,扫除语言障碍,使不同地区和使用不同语言的用户都能方便的使用我们开发的WEB应用系统。

(1)创建中英文资源文件。

(2)在struts.xml文件中配置资源文件。

(3)在JSP页面中使用<s:text />标签或OGNL显示国际化信息。

Ø Struts 2作为成熟的MVC框架提供了完善的异常处理机制,采用的是声明式的异常处理方式,这种方式便于管理和维护,struts.xml文件通过使用<exception-mapping />元素来进行异常映射配置。

(1)exception属性:该属性用来指定异常的类型。

(2)result属性:该属性值是一个url地址,用来指定出现异常时Struts 2跳转到哪个视图。

(3)全局异常映射:这种映射使用<global-exception-mapping />元素进行配置,在该元素中嵌套<exception-mapping />作为子元素,这种映射的作用范围是package中的所有Action。

(4)局部异常映射:这种映射直接在Action内部使用<exception-mapping />元素配置就行了,当然它的作用范围为它所在的Action。

Ø 文件上传是WEB应用中经常遇到的问题,Struts 2默认使用Jakarta的Common-FileUpload文件上传框架,并对其进行了优化和封装。

(1)<s:form>标签必须指定enctype属性并且该属性的值必须是“multipart/form-data”,这表示表单的数据不再以字符串的形式提交,而是以二进制编码的形式来提交数据。

(2)实现在服务器端接收上传文件并保存到指定位置功能的Action。

(3)fileUpload拦截器,该拦截器由Struts 2框架提供,专门用来限制上传文件的类型和大小。

任务实训部分

1:添加管理员功能国际化

训练技能点

Ø 国际化

Ø <s:text>和OGNL显示国际化消息

需求说明

在上一章的任务实训部分我们实现了对添加管理员的输入验证,现在要求对该案例进行国际化处理,支持中文、英文的切换。

实现步骤

(1) 创建中英文国际化资源文件,参考代码如下所示

英文资源文件:

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) 下面是实现输入验证的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方法

}

在通过addFieldError方法添加提示信息时,请注意这里使用了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>

这里我们要求用户可以自由选择语言环境,但不是通过超链接实现的,而是通过下拉列表框,如图9.2.1所示,所以必须通过JavaScript代码进行控制。

图9.2.1 中文界面

图9.2.2 英文界面

2:国际化校验配置文件

训练技能点

Ø Struts 2内置校验器

Ø 国际化校验配置文件

需求说明

上个实训任务是通过重写ActionSupport类的valudate方法来实现输入校验的,现在要求使用Struts 2的内置校验器实现输入校验并实现校验配置文件的国际化。

3:数据库操作异常处理

训练技能点

Ø Struts 2异常处理

需求说明

在使用JDBC进行数据库操作时很容易出现异常,所以通常我们都需要对进行数据库操作的代码使用try-catch语句,但是这也不能满足复杂项目的需求,现在要求为添加管理员的示例使用Struts 2完善异常处理,为Action配置全局异常映射。

4:添加学生照片

训练技能点

Ø Struts 2文件上传

需求说明

前面我们实现过一个添加学生的示例,现在要求在添加学生信息的时候必须保存学生的照片,请使用Struts 2文件上传实现该功能。

实现步骤

(1) 在表单中增加文件域,代码如下所示:

<body>

<s:form action="addStu.action" method="post"

enctype="multipart/form-data">

<s:textfield name="name" label="学生姓名"/>

<s:textfield name="birthday" label="学生生日"/>

<s:textfield name="height" label="学生身高"/>

<s:textfield name="weight" label="学生体重"/>

<s:file name="upload" label="学生照片"/>

<s:submit value="添加"/>

</s:form>

</body>

注意为表单增加enctype="multipart/form-data"。

(2)创建实现上传的Action,参考代码如下所示:

public class MyUpAction extends ActionSupport{

private String name;   //学生姓名

private String birthday;   //学生生日

private int height;        //学生身高

private int weight;       //学生体重

//封装上传文件域的属性

private File upload;

//封装上传文件的类型

private String uploadContentType;

//封装上传文件名

private String uploadFileName;

//方法省略

}

(3)上传成功后,把学生的相关信息显示到页面上,运行效果如图9.2.3和图9.2.4所示。

图9.2.3 添加学生

图9.2.4 显示学生信息

巩固练习

一、选择题

1. 用来读取国际化资源文件的Struts 2标签是()。

A. <s:textfield>

B. <s:text>

C. <s:message>

D. <s:resource>

2.以下关于Struts 2的国际化资源文件说法正确的是()。

A. 资源文件的名字可以自定义,没有任何规定

B. 资源文件只要放在正确的路径下,Struts就能找到了,无需在struts-config.xml中进行任何配置

C. 资源文件只能放在WEB-INF/classes的根目录下

D. 中文资源文件需要转码

3.以下关于Struts 2异常处理说法正确的是()。

A. 通过Struts 2的异常处理机制可以避免异常的发生

B. Struts 2的异常处理需要名字为exception的拦截器

C. 全局异常映射的作用范围是struts.xml中的所有Action

D. 全局异常映射的优先级高于局部异常映射

4.以下关于Struts 2异常处理说法正确的是()。

A. 通过Struts 2的异常处理机制可以避免异常的发生

E. Struts 2的异常处理需要名字为exception的拦截器

F. 全局异常映射的作用范围是struts.xml中的所有Action

G. 全局异常映射的优先级高于局部异常映射

5.以下关于Struts 2文件上传说法错误的是()。

A. 表单必须设置enctype属性

B. 通过名字是“fileUpload”的拦截器可以限制文件类型和大小

C. Struts 2对上传文件的大小没有任何限制

D. Struts 2支持多文件上传

二、上机练习

上一章的巩固练习部分要求大家实现了一个注册功能,现在在此基础上使用Struts 2实现国际化和照片上传功能。

Struts 2常见应用相关推荐

  1. 渗透测试 面试笔试题

    Powered By 行云博客(https://www.xy586.top)原创文章,转载请附上原文出处链接和本声明. 原文链接:https://blog.csdn.net/qq_41679358/a ...

  2. 渗透测试面试问题集合(转载自己看,链接在开头)

    红蓝对抗一些经验 文章的原链接 一.思路流程 1.信息收集 a.服务器的相关信息(真实ip,系统类型,版本,开放端口,WAF等) b.网站指纹识别(包括,cms,cdn,证书等),dns记录 c.wh ...

  3. 信息安全学习----渗透测试知识点

    信息安全学习----渗透测试知识点 信息收集 服务器的相关信息(真实ip,系统类型,版本,开放端口,WAF等) 网站指纹识别(包括,cms,cdn,证书等),dns记录 whois信息,姓名,备案,邮 ...

  4. 干货|2020渗透测试面试问题大全 建议收藏

    转自HACK之道 乌雲安全 2020-12-28 渗透篇 0.渗透测试知识体系结构 1.介绍一下自认为有趣的挖洞经历 挖洞也有分很多种类型,一种是以渗透.一种是以找漏洞为主,如果是前者会想各种办法获取 ...

  5. 2020渗透测试面试问题大全

    转自HACK之道 乌雲安全 目录 渗透篇 前端篇 一.思路流程 二.问题 三.深信服一面 四.SQL注入防护 五.为什么参数化查询可以防止SQL注入 六.SQL头注入点 七.盲注是什么?怎么盲注? 八 ...

  6. 渗透测试面试问题2021版,内含大量渗透技巧

    目录 思路流程 信息收集 漏洞挖掘 漏洞利用&权限提升 清除测试数据&输出报告 复测 问题 1.拿到一个待检测的站,你觉得应该先做什么? 2.判断出网站的CMS对渗透有什么意义? 3. ...

  7. 渗透测试面试、渗透技巧

    一.思路流程 1.信息收集 a.服务器的相关信息(真实ip,系统类型,版本,开放端口,WAF等) b.网站指纹识别(包括,cms,cdn,证书等),dns记录 c.whois信息,姓名,备案,邮箱,电 ...

  8. 渗透测试面试问题合集

    一.思路流程 1.信息收集 a.服务器的相关信息(真实ip,系统类型,版本,开放端口,WAF等) b.网站指纹识别(包括,cms,cdn,证书等),dns记录 c.whois信息,姓名,备案,邮箱,电 ...

  9. 详细的渗透思路(转Mr-xn)

    信息收集 服务器的相关信息(真实ip,系统类型,版本,开放端口,WAF等) 网站指纹识别(包括,cms,cdn,证书等),dns记录 whois信息,姓名,备案,邮箱,电话反查(邮箱丢社工库,社工准备 ...

最新文章

  1. android开发4:Android布局管理器1(线性布局,相对布局RelativeLayout-案例)
  2. 360下载的mysql_MySQL数据库5.7
  3. django mysql内存泄漏_Django的:使内存的关系,而不保存到数据库
  4. java 日历类_JAVA 的日历类型
  5. [MicroPython]stm32f407控制DS18B20检测温度
  6. c语言statistics函数,Logistic回归中C-Statistics计算方法
  7. discuz中写一个表单,数据存入到数据库中,再从数据库读出来显示在列表中
  8. 配置Spring.NET
  9. Paip.语义分析----情绪情感词汇表总结
  10. 禅道下载与安装教程(完整版)
  11. 服务器与mysql数据库服务器_数据库与服务器的关系
  12. 【ClearCase 学习笔记 】之(1/4)CC四大功能概述
  13. 手把手教你理解SURF算法的全部过程
  14. 全国宏观经济指标(图表以及相应的大致注释)
  15. Java——哈希值是什么?
  16. coffeescript java 执行_CoffeeScript—面向对象
  17. 解释程序和编译程序的区别
  18. 火狐浏览器 Error: Incorrect contents fetched, please reload.
  19. 半年内连发6篇CNS!又一顶级学者全职回国,加盟浙大!
  20. Excel的公式:公式基本使用、单元格地址引用、错误值利用、追踪公式利用与追踪错误

热门文章

  1. java安全编码指南之:对象构建
  2. 自定义spring boot的自动配置
  3. Scala的Higher-Kinded类型
  4. 操作系统-信号量的使用
  5. leetcode-剑指 Offer 44. 数字序列中某一位的数字
  6. 【解析】UVA-548 Tree
  7. @Cacheable原理
  8. Java 折半查询,java之折半查询
  9. 子网划分以及子网掩码
  10. python的out模式_如何用python中的DataFrame列的模式替换NA值?