1.strust简介(发展):
大概的流行时间:2010前后各3年
※有两个版本:Struts1,Struts2
Struts1: 采用servlet机制,JSP+Action(Servlet+JavaBean)+BaseServlet
Struts2: 采用拦截器机制, JSP+Action(Servlet+JavaBean)+拦截器(动态代理Action)+Filter
Struts中的Action(本质上是EJB) 和 拦截器都是通过xml配置的方式创建
Struts框架帮我们做的功能:
1)帮我们把页面传过来的数据(参数)封装成JavaBean(Action对象)Struts1:所有“*.do”的请求都会被它拦截
2)帮我们把结果信息存放到request中
3)实现可配置的转发路径(即结果页面的url地址可配置)
4)除了上面3个核心功能之外,还帮我们实现了一些辅助:国际化、表单可配置、上传下载组件、表单页面的标签库。Struts2还提供了校验框架,对ajax的支持,数据库连接和事务等
Struts2:早期版本所有“*.action”的请求都会被它拦截,后来所有的都会被拦截
struts框架是apache公司,官网:http://struts.apache.org
2.Struts2概念
Struts2是Struts的第二代产品,以WebWork为核心,采用拦截器的机制处理用户请求,使业务逻辑控制器能与ServletAPI完全脱离。Struts1采用Servlet的机制处理用户请求。
Struts 2框架的所有类都基于接口,核心接口独立于HTTP。Struts 2配置文件中的大多数配置元素都会有默认值,有助于减少在XML文件中需要进行的配置。
Struts2框架主要由三部分组成:
核心控制器(StrutsPrepareAndExecuteFilter)、业务控制器和用户定义的业务逻辑组件。
(也有核心控制器使用FilterDispatcher)
1 、核心控制器
FilterDispatcher 是早期 struts2 的过滤器,可以对客户端 URL 请求进行过滤,负责处理用户所有以 .action 结尾的请求。 2.1.3 版后,官方推荐使用 StrutsPrepareAndExecuteFilter
2 、业务控制器
是用户实现的 Action 类实例 。 Action 类通常包含一个 execute 方法 ,返回一个字符串作为逻辑视图名。创建了 Action 类之后,还需要 在 struts.xml 文件中配置 此 Action 的相关信息
3、业务逻辑组件
通常是指用户自己针对系统功能开发的功能模块组件。被业务控制器组件所调用来处理业务逻辑的。
3.Struts2框架的处理流程
第 1 步: 客户端 浏览器 发送一个请求 。
第2步:web服务器如Tomcat收到该请求,读取配置文件,将请求 导向Struts2的StrutsPrepareAndExecuteFilter(核心控制器), 后者根据请求决定调用合适Action。
第3步:StrutsPrepareAndExecuteFilter在调用Action之前被Struts2的拦截器拦截,拦截器自动对请求应用通用功能,如数据转换,校验等。
第4步:调用Action的execute方法,该方法根据请求的参数来执行一定的操作。
第5步:依据Action的execute方法处理结果,导向不同的URL。如在execute中验证用户,验证成功可以导向成功的页面。否则重新登录
4.Struts2入门示例
第1步:新建一个web工程,向工程中导入struts核心包
第2步:编写一个登陆界面inex.jsp。注意使用Struts2的标签
第3步:编写一个登陆成功后导向的页面succ.jsp。
第4步:在src目录中添加一个配置文件struts.xml。在web服务器启动时读取该文件。
第5步:改写网站配置文件web.xml,添加Struts2过滤器。
第6步:建立控制器类LoginAction,页面输入后导向该Action。文件名为LoginAction.java。
第7步:将项目部署到web服务器中
第8步:测试
5.Struts2运行流程
①首先客户端输入url:http://localhost:8080/strutsHello②提交按钮按下后向服务器端发出请求,请求/index了③该url被struts过滤器拦截④过滤器根据url中的路径名struts2读取配置文件,该action对应Action类是LoginAction⑤则Struts2控制器创建一个LoginAction实例,调用该实例的setUsername以及setPassword函数实际参数值来源于客户端页面用户输入的username,password两个变量。⑥然后调用LoginAction中的execute函数,根据该函数返回值导向不同的页面。如果是success导向成功页面succ.jsp。如果是input导向输入页面login.jsp。
6.Struts2的配置文件
(1)Struts2框架配置文件中的包就是由多个Action、多个拦截器、多个拦截器引用构成。包的作用和java中的类包是非常类似的,它主要用于管理一组业务功能相关的action,在实际应用中,我们应该把一组业务功能相关的action放在同一个包下。
<struts> <!-- Struts2的action必须放在一个指定的包空间下定义--> <package name="default"extends="struts-default"> <!-- 定义处理请求URL为login.action的Action --> <action name="login" class=action.LoginAction"> <!-- 定义处理结果字符串和URL之间的映射关系--> <result name="success">/success.jsp</result> <result name="input">/login.jsp</result> </action> </package> </struts>
(2)、namespace命名空间配置
考虑到同一个Web应用中需要同名的Action,Struts2以命名空间的方式来管理Action,同一个命名空间不能有同名的Action。
Struts2通过为包指定namespace属性来为包下面的所有Action指定共同的命名空间。把上示例的配置改为如下形式:
包student:没有指定namespace属性。默认的命名空间是"",访问的时候不需要加命名空间。
包admin:指定了命名空间/admin。则如上名为adminaction.LoginAction的Action,它处理的URL为:
http://localhost:8080/chapter10web/admin/adminLogin.action
(3)、include包含配置
在Struts2中可以将一个配置文件分解成多个配置文件,那么我们必须在struts.xml中包含其他配置文件。
<struts>
<includefile="struts-default.xml"/>
<includefile="struts-student.xml"/>
<includefile="struts-admin.xml"/>
<includefile="struts-user.xml"/>
......
</struts>
7.Action类
在Struts2中,Action不同于struts1.x中的Action。Struts2中Action并不需要继承任何控制器类型或实现相应接口。比如struts1.x中的Action需要继承Action或者DispatcherAction。
同时Struts2中的Action并不需要借助于象struts1中的ActionForm获取表单的数据。可以直接通过与表单元素相同名称的数据成员(setter-getter函数)获取页面表单数据。
虽然Struts2中的Action原则上不用继承任何类。但是一般需要实现Action接口或者继承ActionSupport类,重写execute方法。如果继承ActionSupport类,我们可以在的控制器中增加更多的功能。
定义Action类的两种形式:
1、基本形式:从ActionSupport类继承
public class LoginAction extendsActionSupport{ private String username; private String password; /*getter-setter代码略*/ public void validate(){…} public String execute()throwsException {….} }
2、普通JavaBean
package com.bean; public class User { private String username; private String password; /*getter-setter代码略*/ public String execute()throwsException {...} }
Action动态处理函数
1、Action默认的execute函数
一般客户端请求url被Struts2的拦截后,根据url指定action名称,查找相应的action,默认调用Action类的execute函数。如:
<packagename="struts2" extends="struts-default">
<!-- 通过Action类处理才导航的Action定义-->
<action name="Login"class="com.action.LoginAction">
<result name="input">/login.jsp</result>
<result name="success">/success.jsp</result>
</action>
</package>
2、如果不用调用默认execute()。要求调用指定函数fun()函数。
第1种方法是修改配置文件,修改action标记的method属性值
<actionname="userLogin"class="com.action.LoginAction" method="fun">
<result name="input">/login.jsp</result>
<result name="success">/success.jsp</result>
</action>
第2种方法是在页面form标记action属性中指定调用处理方法名,如Action类编写如下:
publicclass LoginAction{
public String fun1() throws Exception{ ..... }
public String fun2() throwsException{ ...... }
}
在页面form标记的action属性中指定调用处理方法名。
<formaction="/login!fun1.action"method="post">
<formaction="/login!fun2.action"method="post">
3、使用通配符映射方式
配置文件admin_* :定义一系列请求URL是admin_*.action模式的逻辑Action
<action name="admin_*"
class="action.UserAction"method="{1}">
<result name="input">/login.jsp</result>
<resultname="success">/success.jsp</result>
</action>
如上,<action name=“admin_*”>定义一系列请求URL是admin_*.action模式的逻辑Action。同时method属性值为一个表达式{1},表示它的值是name属性值中第一个*的值。
例如:用户请求URL为admin_login.action时,将调用AdminAction类的login方法;用户请求URL为admin_regist.action时,将调用到AdminAction类的regist方法。
8.Action访问ServletAPI
在进行Web编程时,很多时候需要使用Servlet相关对象,例如:HttpServletRequest、HttpServletResponse、HttpSession、ServletContext。我们可以将一些信息存放到session中,然后在需要的时候取出。
Struts2中提供了一个ActionContext类(当前Action的上下文对象),此类的getContext方法可以得到当前Action的上下文,也就是当前Action所处的容器环境,进而得到相关对象。下面是该类中提供的几个常用方法:
public static ActionContext getContext () :获得当前 ActionActionContext 实例。publicObject get(Object key) :此方法类似于调用 HttpServletRequest 的 getAttribute (Stringname) 方法。publicvoid put(Object key, Object value) :此方法类似于调用 HttpServletRequest 的 setAttribute (Stringname, Object o) 。
publicMap getParameters () :获取所有的请求参数。类似于调用 HttpServletRequest 对象的 getParameterMap () 方法。
publicMap getSession () :返回一个 Map 对象,该 Map 对象模拟了 HttpSession 实例。
publicvoid setSession (Map session) : 直接传入一个 Map 实例,将该 Map 实例的 key-value 对转换成 session 的属性名-属性值对。
publicMap getApplication () :返回一个 Map 对象,该对象模拟了该应用的 ServletContext 实例。
publicvoid setApplication (Map application) :直接传入一个 Map 实例,将该 Map 实例里的 key-value 对转换成 application 的属性名-属性值对。
9.Struts2校验框架
输入校验几乎是任何一个系统都需要开发的功能模块,我们无法预料用户如何输入,但是必须全面考虑用户输入的各种情况,尤其需要注意那些非正常输入。Struts2提供了功能强大的输入校验机制,通过Struts2内建的输入校验器,在应用程序中无需书写任何代码,即可完成大部分的校验功能,并可以同时完成客户端和服务器端的校验。
如果应用的输入校验规则特别,Struts2也允许通过重写validate方法来完成自定义校验,另外Struts2的开放性还允许开发者提供自定义的校验器。
Struts2中可以通过重写validate方法来完成输入校验。如果我们重写了validate方法,则该方法会应用于此Action中的所有提供服务的业务方法。
Struts2的输入校验流程如下:
1、类型转换器负责对字符串的请求参数执行类型转换,并将这此值设置成Action的属性值。
2、在执行类型转换过程中可能出现异常,如果出现异常,将异常信息保存到ActionContext中,conversionError拦截器 负责将其封装到fieldError里,然后执行第3步;如果转换过程没有异常信息,则直接进入第3步。
3、通过反射调用validateXxx()方法,其中Xxx是即将处理用户请求的处理逻辑所对应的方法名。
4、调用Action类里的validate()方法。
5、如果经过上面4步都没有出现fieldError,将调用Action里处理用户请求的处理方法;如果出现了fieldError,系统将转入input逻辑视图所指定的视图资源。
校验示例:
第1步:编写一个User2Action类,该Action接受页面提交过来的参数
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-size:12px;color:#330033;">package cn.hncu.user.login; import com.opensymphony.xwork2.ActionSupport; public class User2Action extends ActionSupport{ private String name; private String pwd; private String email; private String other; public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String execute() throws Exception { return SUCCESS; } }</span> </span>
第2步:在该Action相同的目录下建一个xml文件,该文件的命名为ActionName-validation.xml,其中ActionName为该Action的类名,例如LoginValidateAction-validation.xml。然后在xml配置文件中配置需要验证的字段。
<span style="font-family:Microsoft YaHei;font-size:12px;color:#330033;"><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd"> <validators> <field name="name"> <field-validator type="requiredstring"> <message key="用户名不能为空" /> </field-validator> </field> <field name="pwd"> <field-validator type="requiredstring"> <message key="密码不能为空" /> </field-validator> <field-validator type="stringlength"> <param name="minLength">6</param> <param name="maxLength">16</param> <message>密码长度应在6~16个字符之间</message> </field-validator> </field> <field name="age"> <field-validator type="int"> <param name="min">1</param> <param name="max">10</param> <message key="validate.integerValidatorField" >年龄不正确</message> </field-validator> </field> <field name="email"> <field-validator type="email"> <message key="validate.emailValidatorField" >邮箱不正确</message> </field-validator> </field> <field name="other"> <field-validator type="regex"> <param name="expression">.*\.txt</param> <message key="正则表达式" /> </field-validator> </field> </validators></span><span style="font-family:Microsoft YaHei;"> </span>
第3步:在struts.xml文件中配置Action,在Action配置中必须有input视图(input视图是验证失败的进入的页面,默认的result是成功的页面)
第 4 步:添加一个 jsp 页面 loginvalidate.jsp ,放入一个 struts 标签(导入s标签)<span style="color:#330033;"><action name="validate" class="cn.hncu.user.login.User2Action"> <span style="color:#FF6600;"><result name="input">/index.jsp</result><!-- 这个是转向失败的页面 --> <result>/succ.jsp</result><!-- 这个是登陆成功失败的页面 --></span> </action> </span>
<span style="font-size:12px;color:#330099;"> <span style="font-family:Microsoft YaHei;color:#330033;"><form action="validate"> <s:fielderror /> Name<input type="text" name="name"><br/> Pwd<input type="text" name="pwd"><br/> age<input type="text" name="age"><br/> email<input type="text" name="email"><br/> other<input type="text" name="other"><br/> <input type="submit" value="登录"><br/> </form></span></span>
基础的Struts2输入校验规则:
<validators> 对必填校验 <field name="name"> <field-validator type="required"> <message>必填内容</message> </field-validator> </field> 必填字符串校验 <field name="name"> <field-validator type="requiredstring"> <param name="trim">true</param> <message>字符串必填校验</message> </field-validator> </field> 对int类型的校验 <fieldname = age "> <field-validator type="int"> <paramname = min "> 1 </param> <paramname = max "> 100 </param> <message key="年龄不正确" /> </field-validator> </field> 对日期的校验 <field name="dta"> <field-validator type="date"> <param name="min">01/01/1990</param> <param name="max">01/01/2000</param> <message key="日期不正确" /> </field-validator> </field> 对email的校验 <field name="email"> <field-validator type="email"> <message key="email不正确" /> </field-validator> </field> 对URL的校验 <field name="url"> <field-validator type="url"> <message key="ulr不正确" /> </field-validator> </field> 对字符串长度的校验 <field name="stringLengthValidatorField"> <field-validator type="stringlength"> <param name="maxLength">4</param> <param name="minLength">2</param> <paramname = trim "> true </param> <message key="validate.stringLengthValidatorField" /> </field-validator> </field> 对正则表达式的校验 <field name="regexValidatorField"> <field-validator type="regex"> <paramname = expression "> .*\.txt </param> <message key="validate.regexValidatorField" /> </field-validator> </field> </validators>
10.Struts2拦截器
拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
Struts 2拦截器是动态拦截Action调用的对象。它提供了一种机制,使开发者可以定义一个特定的功能模块,这个模块可以在Action执行之前或者之后运行,也可以在一个Action执行之前阻止Action执行。同时也提供了一种可以提取Action中可重用的部分的方式。
拦截器(Interceptor)是Struts 2的核心组成部分。很多功能都是构建在拦截器基础之上的,例如文件的上传和下载、国际化、转换器和数据校验等,Struts 2利用内建的拦截器,完成了框架内的大部分操作。
Struts2的拦截器和Servlet过滤器类似。在执行Action的execute方法之前,Struts2会首先执行在struts.xml中引用的拦截器,在执行完所有引用的拦截器的intercept方法后,会执行Action的execute方法。
Struts2拦截器类必须实现Interceptor接口或继承AbstractInterceptor类。
在Struts2中称为拦截器栈InterceptorStack。拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序依次被调用。
使用:
第1步:创建一个拦截器的触发页面test_interceptor.jsp
<%@page language="java" pageEncoding="UTF-8"%>
<%@taglibprefix="s"uri="/struts-tags"%>
<html>
<head></head>
<body>
<s:formaction="test_interceptor">
<s:textfield name="username"label="username"></s:textfield>
<s:submit name="submit"></s:submit>
</s:form>
</body>
</html>
第2步:定义拦截器类MyInterceptor1.java
<span style="color:#330033;">package com.interceptor; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; public class MyInterceptor1 implements Interceptor { public void init() {// 覆盖Interceptor接口中的init函数 System.out.println("拦截器已经被加载"); } public void destroy() {// 覆盖Interceptor接口中的destroy函数 System.out.println("destroy"); } /* 覆盖Interceptor接口中的intercept函数 */ public String intercept(ActionInvocation invocation) throws Exception { System.out.println("调用intercept方法"); /* invocation.invoke()方法检查是否还有拦截器 有的话继续调用余下的拦截器 没有了则执行action的业务逻辑 */ String result = invocation.invoke(); return result; } }</span>
第3步:Struts2配置文件,拦截器的映射
<span style="color:#330033;"> <package name="myinterceptor" extends="struts-default"> <!-- 定义拦截器 --> <interceptors> <interceptor name="myInterceptor" class="com.interceptor.MyInterceptor1"/> </interceptors> <!-- 配置action --> <action name="test_interceptor" class="com.action.InterceptorTest"> <result name="success">/interceptorsuccess.jsp</result> <result name="input">/test_interceptor.jsp</result> <!-- 将声明好的拦截器插入action中 --> <interceptor-ref name="myInterceptor" /> <interceptor-ref name="defaultStack" /> </action> </package></span>
第4步:通过拦截器后进入Action
package com.action; import com.opensymphony.xwork2.ActionSupport; public class InterceptorTest extends ActionSupport { private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String execute() throws Exception { System.out.println("come"); return SUCCESS; } }
在Struts2中配置自定义的拦截器
1、扩展拦截器接口的自定义拦截器配置(实现接口)
2、继承抽象拦截器的自定义拦截器配置(继承抽象类)
注:
struts.xml配置文件中缺省拦截器栈<default-interceptor-ref >定义。如果定义则所有Action都会执行的缺省拦截器栈拦截器,并按照循序从上到下执行。如果哪个拦截器没有通过则下面拦截器不会执行。
如果没有定义缺省拦截器栈,则缺省拦截器栈不起作用。
11.Struts2转换器
在B/S中,将字符串请求参数转换为相应的数据类型,应该是MVC框架提供的基本功能。Struts2也提供了类型转换功能。
在Struts2中分两种转换,一种是局部转换,另一种是全局类型转换。具体转换的实施需要一个转换类和一个自定义类。
1、局部类型转换
对于int,long,double,char,float等基本类型,Struts2会自动完成类型转换,像age年龄,在输入页面是String型的,到Action后会自动转换成int型。而如果是转换成其它类类型的话,就需要自定义类型转换。这样就需要一个自定义类。要定义一个转换类,需要继承ognl.DefaultTypeConverter这个类 ,这是个类型转换的类。
使用:
第1步: 编写转换类UserConverter.java
package cn.hncu.domain; import java.lang.reflect.Member; import java.util.Map; import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter; public class UserConverter extends DefaultTypeConverter{ @Override public Object convertValue(Map<String, Object> context, Object value, Class toType) { if (User.class == toType) { User user = new User(); String[] str = (String[]) value; String[] values = str[0].split(","); user.setName(values[0]); user.setAge(Integer.valueOf(values[1])); return user; } if (String.class == toType) { User User = (User) value; return User.toString(); } return null; } }
第 2 步: 编写 User 类
package cn.hncu.domain; public class User { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return name +","+ age ; } }
第3步: 编写Action类。TypeConverterAction.java
package cn.hncu.domain; import com.opensymphony.xwork2.ActionSupport; public class TypeConverterAction extends ActionSupport{ User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public String execute() throws Exception { System.out.println(user); return SUCCESS; } }
第4步:编写转换属性文件。TypeConverterAction-conversion.properties
内容为:user=com.converter.UserConverter
自定义类、转换类、action都创建好之后,要创建一个属性文件,放置在与action在同一包。该属性文件名为:action文件名-conversion.properties。文件中的内容如下:
user=转换类名 即user=cn.hncu.domain.UserConverter
注意:
(1) user是Action的一个属性,转换类指明所使用哪个转换类对此属性进行转换。
(2)有两种类型的转换器:一是局部类型转换器。仅仅对某个Action的属性起作用。属性文件名:ActionName-conversion.properties。内容:属性名=类型转换器类,如date=com.DateConverter。存放位置与ActionName类相同路径。二是全局类型转换器。对所有Action的特定类型的属性都会生效。属性文件名:xwork-conversion.properties。内容如java.util.Date=com.DateConverter.存放位置为WEB-INF/classes/目录下。
第5步:编写JSP页面。
<form action="converter" method="post"> user<input type="text" name="user"><br/> <input type="submit" value="登录"><br/> </form>
类型转换的流程:
1、用户进行请求,根据请求名在struts.xml中寻找Action。
2、在Action中,根据请求域中的名字去寻找对应的set方法。找到后在赋值之前会检查这个属性有没有自定义的类型转换。没有的话,按照默认进行转换;如果某个属性已经定义好了类型转换,则会去检查在Action同一目录下的action文件名-conversion.properties文件。
3、从文件中找到要转换的属性及其转换类。
4、然后进入转换类中,在此类中判断转换的方向。我们是先从用户请求开始的,所以这时先进入从字符串到类的转换。返回转换后的对象。流程返回Action。
5、将返回的对象赋值给Action中的属性,执行Action中的execute()。
6、执行完execute()方法,根据struts.xml的配置转向页面。
7、在jsp中显示内容时,根据页面中的属性名去调用相应的get方法,以便输出。
8、在调用get方法之前,会检查有没有此属性的自定义类型转换。如果有,再次跳转到转换类当中。
9、在转换类中再次判断转换方向,进入由类到字符串的转换,完成转换后返回字符串。
10、将返回的值直接带出到要展示的页面当中去显示。
12.Struts2国际化(1)
所谓国际化是指你的web系统,在不同国家或地区被访问,其中的一些主要信息,如注册信息中字段,错误信息提示等显示结果应该与该地区或国家语言相同。这样用户很好理解你的网页。
Web系统国际化通过两步来完成。第一通过将文字内容以特定的方式存放在特定的文件中。第二,在运行时根据当前的语言环境决定从哪个文件中读取文字内容。
Java中国际化的概念是将不同国家的语言描述的相同的东西放在各自对应的属性文件中,如果这个文件的名字叫做Message,那么对应语言的文件分别为:
中文中国 message_zh_CN.properties
日文日本message_ja_JP.properties
英文美国message_en_US.properties
1、JSP页面上的国际化
<s:i18n name="message">
< !-- key="hello"依据读取资源文件中的hello关键字对应的内容,{0}表示第一个参数输出位置即${username}在这里输出-->
<s:text key="hello">
<s:param>${username}</s:param>
</s:text>
</s:i18n>
中英文资源如下:
message_en_US.properties文件配置:
hello=hello world,{0}
message_zh_CN.properties文件配置:
hello=你好,{0}
2、表单元素的Label国际化
未国际化:
<s:textfieldname="username" label="username"></s:textfield>
<s:textfieldname="password" label="password"></s:textfield>
国际化后:
<s:textfieldname="username" key="uname"></s:textfield>
<s:textfieldname="password" key="pword"></s:textfield>
中英文资源如下:
message_en_US.properties文件,配置:
uname=username
pword=password
message_zh_CN.properties文件,配置:
uname=用户名
pword=密码
3、Action中的国际化
未国际化:
this.addFieldError("username","the username error!");
this.addFieldError("password","the password error!");
国际化后:
this.addFieldError("username","username.error");
this.addFieldError("password","password.error");
中英文资源如下:
message_en_US.properties文件配置:
username.error = the username error !
password.error = the password error!
message_zh_CN.properties文件配置:
username.error=用户名错误!
username.error=密码错误!
4、配置文件中的国际化。以输入校验的LoginAction-validation.xml为例:
<fieldname="username">
<field-validator type="requiredstring">
<paramname="trim">true</param>
<messagekey="username.empty"></message>
</field-validator>
<field-validator type="stringlength">
<paramname="minLength">6</param>
<paramname="maxLength">12</param>
<message key="username.size"></message>
</field-validator>
</field>
13.Struts2上传下载
Struts2并未提供自己的请求解析器,也就是就Struts2不会自己去处理multipart/form-data的请求,它需要调用其他请求解析器,将HTTP请求中的表单域解析出来。但Struts2在原有的上传解析器基础上做了进一步封装,更进一步简化了文件上传。
Struts2默认使用的是Jakarta的Common-FileUpload框架来上传文件,因此,要在web应用中增加两个Jar文件:commons-fileupload-1.2.jar和commons-io-1.3.1.jar。
文件上传:
1.写一个Action类
FileUploadAction.java
<span style="font-size:14px;">package cn.hncu.file; import java.io.*; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; public class FileUploadAction extends ActionSupport { private static final int BUFFER_SIZE = 16 * 1024; private String title; // 文件标题 private File upload; // 上传文件域对象 private String uploadFileName; // 上传文件名 private String uploadContentType; // 上传文件类型 private String savePath; // 保存文件的目录路径(通过依赖注入) /* 省略getter和setter... */ private static void copy(File src, File dst) { InputStream in = null; OutputStream out = null; try { in = new BufferedInputStream(new FileInputStream(src), BUFFER_SIZE); out = new BufferedOutputStream(new FileOutputStream(dst), BUFFER_SIZE); byte[] buffer = new byte[BUFFER_SIZE]; int len = 0; while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } in.close(); out.close(); } catch (Exception e) { e.printStackTrace(); } } public String execute() throws Exception { // 根据服务器的文件保存地址和原文件名创建目录文件全路径 String dstPath = ServletActionContext.getServletContext().getRealPath( this.getSavePath()) + "/" + this.getUploadFileName(); System.out.println("上传的文件的类型:" + this.getUploadContentType()); File dstFile = new File(dstPath); copy(this.upload, dstFile); return SUCCESS; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public File getUpload() { return upload; } public void setUpload(File upload) { this.upload = upload; } public String getUploadFileName() { return uploadFileName; } public void setUploadFileName(String uploadFileName) { this.uploadFileName = uploadFileName; } public String getUploadContentType() { return uploadContentType; } public void setUploadContentType(String uploadContentType) { this.uploadContentType = uploadContentType; } public String getSavePath() { return savePath; } public void setSavePath(String savePath) { this.savePath = savePath; } }</span>
2.在页面上写jsp代码
<form action="fileUpload " method="POST" enctype="multipart/form-data"> 文件标题:<input type="text" name="title" size="50"/><br/> 选择文件:<input type="file" name="upload" size="50"/><br/> <input type="submit" value=" 上传 "/> </form>
3.写入struts.xml中
</action> <action name ="fileUpload" class ="cn.hncu.file.FileUploadAction"> <!-- 动态设置Action中的savePath属性的值 --> <param name="savePath">/upload</param> <result name ="success">/index.jsp</result> </action>
文件下载:
1.写一个Action类
FileDownAction.java在类中写getDownloadFile方法
package cn.hncu.file; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import com.opensymphony.xwork2.ActionSupport; public class FileDownloadAction extends ActionSupport{ public InputStream getDownloadFile(){ File file=new File("G:/a/a.xls"); FileInputStream fis=null; try { fis=new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } return fis; } @Override public String execute() throws Exception { return super.execute(); } }
2.在页面写入jsp代码
<a href="<c:url value='fileDown'/>">下载</a>
3.在struts中配置
<action name="fileDown" class ="cn.hncu.file.FileDownloadAction"> <result name ="success" type="stream"> <param name="contentType"> application/vnd.ms-excel</param> <param name="contentDisposition"> attachment;filename="aa.xls"; </param> <param name="inputName">downloadFile</param> </result> </action>