Struts2相关知识整合
2014-01-14 16:18
459 查看
网站
Apache Struts 2 http://struts.apache.org/2.x/index.html
Opensymphony XWork http://www.opensymphony.com/xwork
Opensymphony WebWork http://www.opensymphony.com/webwork
Struts2是使用Filter作为控制器
Struts2AndStruts1
Struts2和Struts1对比
Struts2,
Struts
Struts 2 = WebWork 2.2
对比:
1.配置文件:Struts1配置文件放在WEB-INF/struts-config.xml(可定制)目录下;Struts2的配置文件要放在WEB-INF/classes目录下
2.控制器:Struts1的控制器是一个ActionServlet类;Struts2的控制器是一个过滤器。
3.动作表单:Struts1的HTML表单对应一个ActionForm类的实例,动作类可访问对应配置的ActionForm,操作ActionForm进行填充数据传输对象;Struts2的HTML表单直接映射成POJO,动作类中可直接访问POJO,操作对POJO的验证。
4.动作类:Struts1的动作类继承org.apache.struts.action.Action类;Struts2的动作类可以是任何一个POJO,但是最好是继承ActionSupport类?。
5.显示对象:在JSP中Struts2使用OGNL来显示各种对象模型,JSP自带的JSTL和EL中EL常用来补充使用。
6.标签库:Struts1常用HTML标签库、Bean标签库和Logic标签库;Struts2有通用标签库、表单标签库? 。
为什么最好是继承ActionSupport类 ?Struts2的标签具体有哪些
Action 跟 Actionsupport 的区别
当我们在写action的时候,可以实现Action接口,也可以继承Actionsupport这个类.到底这两个有什么区别呢?
Action接口有:
public static final java.lang.String SUCCESS = "success";
public static final java.lang.String NONE = "none";
public static final java.lang.String ERROR = "error";
public static final java.lang.String INPUT = "input";
public static final java.lang.String LOGIN = "login";
public abstract java.lang.String execute() throws java.lang.Exception;
而Actionsupport这个工具类在实现了Action接口的基础上还定义了一个validate()方法,重写该方法,它会在execute()方法之前执行,如校验失败,会转入input处,必须在配置该Action时配置input属性。
另外,Actionsupport还提供了一个getText(String key)方法还实现国际化,该方法从资源文件上获取国际化信息.
这样在自定义标签时可以定义一个变量为new actionsupport对象实现国际化。
ActionSupport类的作用
struts2不要求我们自己设计的action类继承任何的struts基类或struts接口,但是我们为了方便实现我们自己的action,大多数情况下都会继承com.opensymphony.xwork2.ActionSupport类,并重写此类里的public String execute() throws Exception方法。因为此类中实现了很多的实用借口,提供了很多默认方法,这些默认方法包括国际化信息的方法、默认的处理用户请求的方法等,这样可以大大的简化Acion的开发。
Struts2中通常直接使用Action来封装HTTP请求参数,因此,Action类里还应该包含与请求参数对应的属性,并且为属性提供对应的getter和setter方法。
2.8 增加数据校验
在上面应用中,即使浏览者输入任何用户名、密码,系统也会处理用户请求。在我们整个HelloWorld应用中,这种空用户名、空密码的情况不会引起太大的问题。但如果数据需要保存到数据库,或者需要根据用户输入的用户名、密码查询数据,这些空输入可能引起异常。
为了避免用户的输入引起底层异常,通常我们会在进行业务逻辑操作之前,先执行基本的数据校验。
2.8.1 继承ActionSupport
ActionSupport类是一个工具类,它已经实现了Action接口。除此之外,它还实现了Validateable接口,提供了数据校验功能。通过继承该ActionSupport类,可以简化Struts 2的Action开发。
在Validatable接口中定义了一个validate()方法,重写该方法,如果校验表单输入域出现错误,则将错误添加到ActionSupport类的fieldErrors域中,然后通过OGNL表达式负责输出。
为了让Struts 2增加输入数据校验的功能,改写程序中的LoginAction,增加重写validate方法。修改后的LoginAction类代码如下:
上面的Action类重写了validate方法,该方法会在执行系统的execute方法之前执行,如果执行该方法之后,Action类的fieldErrors中已经包含了数据校验错误,请求将被转发到input逻辑视图处。
为了在校验失败后,系统能将视图转入input处,必须在配置该Action时配置input属性。下面是修改后login Action的配置片段:
对比上面的Action配置与前面的Action配置,我们发现该Action配置片段中增加了input逻辑视图的配置,该逻辑视图映射到login.jsp页面。
前面已经提到:当用户提交请求时,请求得到execute方法处理之前,先会被validate方法处理,如果该方法处理结束后,Action的fieldErrors里的校验错误不为空,请求将被转发给input逻辑视图。如果我们不输入用户名、密码而直接提交表单,将看到如图2.13所示的界面。
看到这里也许读者觉得非常神奇:我们仅仅在Action添加了数据校验错误,并未在输入页面输出这些校验错误信息,但图2.13所示的页面,却可以看到页面已经输出了这些校验信息——这是因为Struts 2的标签,上面的JSP页面中表单使用的并不是HTML表单,而是用了<s:form .../>标签,Struts 2的<s:form ... />标签已经具备了输出校验错误的能力。
提示 Struts 2的<s:form .../>默认已经提供了输出校验错误的能力。
但上面的程序还存在一个问题:校验信息的国际化。查看上面的Action类代码发现:重写validate方法时,如果发生校验失败的问题,校验错误的提示信息是以硬编码方式写死了——这就失去了国际化的能力。
实际上,ActionSupport类已经提供了国际化信息的能力,它提供了一个getText(String key)方法,该方法用于从资源文件中获取国际化信息。为了让校验信息支持国际化,再次改写Action里的validate方法,改写后的validate方法代码如下:
在上面的validate方法中,添加校验错误提示时,并不是直接给出了错误提示的字符串,而是调用了getText方法来获取错误提示。因为在Action中,使用getText方法来获取了两个国际化提示:user.required和pass.required,因此应该在国际化资源文件中添加这两条提示信息。
提示 ActionSupport增加了让提示信息国际化的能力,ActionSupport提供的getText方法可以根据资源文件加载获得国际化提示信息。
此时,如果没有任何输出,直接提交登录表单,将看到如图2.14所示的界面。
Struts2Request
Struts2在Action 中访问request,session,application
Struts2ActionMethod
Struts2Action中方法的访问
Updated
May 10, 2010 by
cm2...@gmail.com
Struts2OGNL
Struts2_OGNL表达式
Updated
May 10, 2010 by
cm2...@gmail.com
Struts2标签不支持el表达式,只能使用OGNL.
Struts2ResultType
Struts2返回类型
Updated
May 10, 2010 by
cm2...@gmail.com
Struts2Staglib
Struts2的S标签
Updated
May 10, 2010 by
cm2...@gmail.com
Struts2FormTaglib
Struts2表单标签
Updated
May 10, 2010 by
cm2...@gmail.com
Struts2FileUpload
Struts2文件上传下载
Struts2
Updated
Apr 26, 2010 by
coderro...@gmail.com
2.Action
3.配置上传文件临时文件夹(在struts.xml中配置)
2.struts.xml配置
3.Action
Struts2JSON
Struts2返回JSON
Updated
May 10, 2010 by
cm2...@gmail.com
Struts2.18导入struts2-json-plugin-2.1.8.1.jar(Struts2 lib下有)
Struts2返回XML
Updated
May 10, 2010 by
cm2...@gmail.com
Struts2CRUD
Struts2增删改查例子
Updated
May 10, 2010 by
cm2...@gmail.com
2.info.jsp(添加和修改页面)
Struts2I18n
Struts2国际化
Updated
May 10, 2010 by
cm2...@gmail.com
1.如果配置文件是en_US结尾,传入en,en_US都可以找到
2.如果配置文件是en结尾,只能传入en,传入en_US会找不到,从而找默认的配置文件(en的范围>en_US,使用英语的国家不止美国一个)
Struts2Validator
Struts2验证框架
Updated
Jun 18, 2010 by
cm2...@gmail.com
Action配置中一定要设置input返回页面
添加验证只要创建验证的xml文件
如:ValidateAction创建ValidateAction-validation.xml
param:trim(boolean) ->true->去除前后空格
param: min(int);max(int)
param:max(date);min(date)
email
给定的String值是否是一个电子邮件地址
区别:expression 不是一个字段验证程序,失败时将生成一个动作错误.(JSP中调用
才显示出错信息)
fieldexpression 是一个字段验证程序,失败时将抛出一个字段错误.(对字段验证)
param:expression(String)OGNL表达式
expression:
fieldexpression:
如果另一个Action对UserBean使用另一个标准的验证,可以创建新的验证文件
param:minLength(int);maxLength(int);trim(boolean)
param:expression(String)正则表达式;caseSensitive(boolean)是否区别大小写,默认为true;trim(boolean)是否去除前后空格
ActionSupport类已经实现了这个接口
要创建一个字段验证程序,扩展FieldValidatorSupport类.验证失败要从validate方法调用addFieldError方法.
如果要能接受参数,要在类中定义一个相应的属性,并生成get,set.
Apache Struts 2 http://struts.apache.org/2.x/index.html
Opensymphony XWork http://www.opensymphony.com/xwork
Opensymphony WebWork http://www.opensymphony.com/webwork
Struts2是使用Filter作为控制器
Struts2AndStruts1
Struts2和Struts1对比
Struts2,
Struts
Struts 2 = WebWork 2.2
对比:
1.配置文件:Struts1配置文件放在WEB-INF/struts-config.xml(可定制)目录下;Struts2的配置文件要放在WEB-INF/classes目录下
2.控制器:Struts1的控制器是一个ActionServlet类;Struts2的控制器是一个过滤器。
3.动作表单:Struts1的HTML表单对应一个ActionForm类的实例,动作类可访问对应配置的ActionForm,操作ActionForm进行填充数据传输对象;Struts2的HTML表单直接映射成POJO,动作类中可直接访问POJO,操作对POJO的验证。
4.动作类:Struts1的动作类继承org.apache.struts.action.Action类;Struts2的动作类可以是任何一个POJO,但是最好是继承ActionSupport类?。
5.显示对象:在JSP中Struts2使用OGNL来显示各种对象模型,JSP自带的JSTL和EL中EL常用来补充使用。
6.标签库:Struts1常用HTML标签库、Bean标签库和Logic标签库;Struts2有通用标签库、表单标签库? 。
为什么最好是继承ActionSupport类 ?Struts2的标签具体有哪些
Action 跟 Actionsupport 的区别
当我们在写action的时候,可以实现Action接口,也可以继承Actionsupport这个类.到底这两个有什么区别呢?
Action接口有:
public static final java.lang.String SUCCESS = "success";
public static final java.lang.String NONE = "none";
public static final java.lang.String ERROR = "error";
public static final java.lang.String INPUT = "input";
public static final java.lang.String LOGIN = "login";
public abstract java.lang.String execute() throws java.lang.Exception;
而Actionsupport这个工具类在实现了Action接口的基础上还定义了一个validate()方法,重写该方法,它会在execute()方法之前执行,如校验失败,会转入input处,必须在配置该Action时配置input属性。
另外,Actionsupport还提供了一个getText(String key)方法还实现国际化,该方法从资源文件上获取国际化信息.
这样在自定义标签时可以定义一个变量为new actionsupport对象实现国际化。
ActionSupport类的作用
struts2不要求我们自己设计的action类继承任何的struts基类或struts接口,但是我们为了方便实现我们自己的action,大多数情况下都会继承com.opensymphony.xwork2.ActionSupport类,并重写此类里的public String execute() throws Exception方法。因为此类中实现了很多的实用借口,提供了很多默认方法,这些默认方法包括国际化信息的方法、默认的处理用户请求的方法等,这样可以大大的简化Acion的开发。
Struts2中通常直接使用Action来封装HTTP请求参数,因此,Action类里还应该包含与请求参数对应的属性,并且为属性提供对应的getter和setter方法。
2.8 增加数据校验
在上面应用中,即使浏览者输入任何用户名、密码,系统也会处理用户请求。在我们整个HelloWorld应用中,这种空用户名、空密码的情况不会引起太大的问题。但如果数据需要保存到数据库,或者需要根据用户输入的用户名、密码查询数据,这些空输入可能引起异常。
为了避免用户的输入引起底层异常,通常我们会在进行业务逻辑操作之前,先执行基本的数据校验。
2.8.1 继承ActionSupport
ActionSupport类是一个工具类,它已经实现了Action接口。除此之外,它还实现了Validateable接口,提供了数据校验功能。通过继承该ActionSupport类,可以简化Struts 2的Action开发。
在Validatable接口中定义了一个validate()方法,重写该方法,如果校验表单输入域出现错误,则将错误添加到ActionSupport类的fieldErrors域中,然后通过OGNL表达式负责输出。
为了让Struts 2增加输入数据校验的功能,改写程序中的LoginAction,增加重写validate方法。修改后的LoginAction类代码如下:
//Struts 2的Action类就是一个普通的Java类 public class LoginAction { //下面是Action内用于封装用户请求参数的两个属性 private String username; private String password; //username属性对应的getter方法 public String getUsername() { return username; } //username属性对应的setter方法 public void setUsername(String username) { this.username = username; } //password属性对应的getter方法 public String getPassword() { return password; } //password属性对应的setter方法 public void setPassword(String password) { this.password = password; } //处理用户请求的execute方法 public String execute() throws Exception { //当用户请求参数的username等于scott,密码请求参数为tiger时,返回success 字符串 //否则返回error的字符串 if (getUsername().equals("scott") && getPassword().equals("tiger") ) { return "success"; } else { return "error"; } } //完成输入校验需要重写的validate方法 public void validate() { //如果用户名为空,或者用户名为空字符串 if (getUsername() == null || getUsername().trim().equals("")) { //添加表单校验错误 addFieldError("username", "user.required"); } //当密码为空,或者密码为空字符串时,添加表单校验错误 if (getPassword() == null || getPassword().trim().equals("")) { addFieldError("password", "pass.required"); } } } |
为了在校验失败后,系统能将视图转入input处,必须在配置该Action时配置input属性。下面是修改后login Action的配置片段:
<!-- 定义login的Action --> <action name="Login" class="lee.LoginAction"> <!-- 定义input的逻辑视图名,对应login.jsp页面 --> <result name="input">/login.jsp</result> <!-- 定义error的逻辑视图名,对应error.jsp页面 --> <result name=" success ">/error.jsp</result> <!-- 定义welcome的逻辑视图名,对应welcome.jsp页面 --> <result name="success">/welcome.jsp</result> </action> |
前面已经提到:当用户提交请求时,请求得到execute方法处理之前,先会被validate方法处理,如果该方法处理结束后,Action的fieldErrors里的校验错误不为空,请求将被转发给input逻辑视图。如果我们不输入用户名、密码而直接提交表单,将看到如图2.13所示的界面。
图2.13 输入校验的界面 |
提示 Struts 2的<s:form .../>默认已经提供了输出校验错误的能力。
但上面的程序还存在一个问题:校验信息的国际化。查看上面的Action类代码发现:重写validate方法时,如果发生校验失败的问题,校验错误的提示信息是以硬编码方式写死了——这就失去了国际化的能力。
实际上,ActionSupport类已经提供了国际化信息的能力,它提供了一个getText(String key)方法,该方法用于从资源文件中获取国际化信息。为了让校验信息支持国际化,再次改写Action里的validate方法,改写后的validate方法代码如下:
//执行数据校验的validate方法 public void validate() { //如果用户名为空,或者为空字符串 if (getUsername() == null || getUsername().trim().equals("")) { //添加校验错误提示,使用getText方法来使提示信息国际化 addFieldError("username", getText("user.required")); } if (getPassword() == null || getPassword().trim().equals("")) { addFieldError("password", getText("pass.required")); } } |
提示 ActionSupport增加了让提示信息国际化的能力,ActionSupport提供的getText方法可以根据资源文件加载获得国际化提示信息。
此时,如果没有任何输出,直接提交登录表单,将看到如图2.14所示的界面。
图2.14 国际化数据校验的错误提示 |
Struts2在Action 中访问request,session,application
只需用到attribute
//获取request ActionContext ctx = ActionContext.getContext(); ctx.put("request", "request"); //获取Session Map<String,Object> session = ctx.getSession(); session.put("session", "session"); //获取ServletContext Map<String,Object> appliction = ctx.getApplication(); appliction.put("appliction", "appliction");
获得HttpServletRequest
代码获得
HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse(); HttpSession session = request.getSession(); //不要在Action构造器里调用,可能还没初始化好 ServletContext servletContext = ServletActionContext.getServletContext();
接口获得
如果有多个Action需要用到request,可以写个Action继承接口,使用request的Action继承再它./*继承ServletRequestAware(获得request),ServletResponseAware(获得response), ServletContextAware(获得ServletContext),SessionAware(获得Session)接口*/ public class FormAction implements ServletRequestAware,ServletResponseAware{ private HttpServletRequest request; private HttpServletResponse response; //拦截器会把request注入到变量中 public void setServletRequest(HttpServletRequest req) { this.request = req; } public void setServletResponse(HttpServletResponse res) { this.response = res; } }
Struts2ActionMethod
Struts2Action中方法的访问
Updated
May 10, 2010 by
cm2...@gmail.com
默认方法
//Struts2中默认访问的是Action中execute方法 //url:http://127.0.0.1:8080/Struts2Pro/hello.action(访问hello指定的Action中的execute方法) public String execute() { return "success"; }
访问Action中多个方法
动态方法调用
只要在url中指定方法名称就可以了. 如:要访问HelloAction中的add()方法 url:http://127.0.0.1:8080/Struts2Pro/hello!add.action (加!和方法名字)<!-- 在struts.xml中配置可以关闭动态方法(默认是激活,可能会让用户方法没有公开的方法,最好不用) --> <constant name="struts.enable.DynamicMethodInvocation" value="false" />
配置文件中多个方法
配置多个方法
<!-- url:http://127.0.0.1:8080/Struts2Pro/userActionAdd.action 访问FormAction中的add方法 --> <action name="userActionAdd" class="com.struts2.form.FormAction" method="add"> <!-- url:http://127.0.0.1:8080/Struts2Pro/userActionUpdate.action 访问FormAction中的update方法 --> <action name="userActionUpdate" class="com.struts2.form.FormAction" method="update">
使用通配符调用多个方法
<!-- name="*_*" class="com.struts2.form.{1}Action" method="{2}" url:user_list.action 就是调用userAction中list方法. name="*_*_*" url:user_list_abd.action method="{1}"->user(第一个*对应的字符串) method="{2}"->list(第二个*对应的字符串) method="{3}"->abd(第三个*对应的字符串) --> <action name="userAction_*" class="com.struts2.form.FormAction" method="{1}">
Struts2OGNL
Struts2_OGNL表达式
Updated
May 10, 2010 by
cm2...@gmail.com
Struts2标签不支持el表达式,只能使用OGNL.
1.OGNL分为Object Stack和Context Map. 把动作和相关对象压入Object Stack. 把各种映射关系(一些Map类型的对象)压入Context Map.(parameters,request,session,application,attr) OGNL表达式加上一个前缀"#",访问Context Map. 没加访问Object Stack. 2.OGNL访问数组 //String[] colors = {"blue","green","red"}; colors[0]//访问第一个元素 colors.length//访问长度 3.OGNL访问List countries[0]//访问第一个元素 countries.size//访问countries.size() countries.isEmpty//访问countries.isEmpty() 创建List {"a","b","c"}//创建一个由3个String构成的List 4.OGNL访问Map cities["CA"]或者cities['CA']//访问cities中key为CA的元素 cities.size//访问cities.size() cities.isEmpty//访问cities.isEmpty() 创建Map {"CA":"S","WA":"O","UT":"ST"} %{}里面的表达式会被求值(%{#request.user.age>40}->true or false,%{1+6}->7)
Struts2ResultType
Struts2返回类型
Updated
May 10, 2010 by
cm2...@gmail.com
类型对应的类
Chain(chain) 构成一条动作链 Dispatcher(dispatcher) 默认类型,转发 FreeMarker(freemarker) 用于与FreeMarker的集成 HttpHeader(httpheader) 把HTTP标头发送回用户 Redirect(redurect) 重定向到另一个URL RedirectAction(redirectAction) 重定向到另一个Action Stream(stream) 把一个InputStream流发送给浏览器(下载用) Velocity(Velocity) 用于与Velocity技术的集成 XSLT(xslt) 用于与XML/XSLT技术的集成 PlainText(plaintext) 发送普通文本,通常用来显示JSP页面的源代码
Chain
<!-- Chain用途是构成一条动作链:前一个动作把控制权转交给后一个动作,而前一个动作的状态在后一个动作里仍保持着. 动作链能不用就不用, 有可能把一套连续动作弄成一团乱. --> <package name="package1" extends="struts-default"> <action name="action1" class="..."> <result type="chain">action2</result> </action> <action name="action2" class="..."> <result type="chain"> <param name="actionName">action3</param> <param name="namespace">/namespace2</param> </result> </action> </package> <package name="package2" namespace="/namespace2" extends="struts-default"> <action name="action3" class="..."> <result>/view.jsp</result> </action> </package>
Dispatcher
<!-- 转发到JSP,result默认类型 --> <result name="...">/view.jsp</result> <!--或者--> <result name="..."> <param name="location">/view.jsp</param> </result>
HttpHeader
<!-- 把一个HTTP状态发送给浏览器 --> <action name="CatchAll"> <result type="httpheader"> <param name="status">404</param> </result> </action>
Redirect
<!-- 重定向 参数:location:重定向的目的地 parse: 表明是否把location参数的值视为一个OGNL表达式来解释,默认值为true --> <action name="..." class="..."> <result name="success" type="redirect"> <!-- 内部资源 --> /jsp/Product.jsp <!-- Action带动态参数(${userName}值为本Action中的userName属性值) --> UserAction.action?userName=${userName} <!-- 外部资源(如果需要使用&和+之类的特殊字符必须使用转义序列.如:&改成&) http://www.google.com?user=1&site=4 转成:http://www.google.com?user=1&site=4 --> http://www.google.com </result> </action>
RedirectAction
<!-- 重定向到一个Action 参数:actionName:指定重定向Action的名字 namespace: 指定重定向Action的命名空间(没有此参数,与本action同一个命名空间) --> <result type="redirectAction">UserAction</result> <!-- 或者 --> <result type="redirectAction"> <param name="actionName">UserAction</param> <!-- 参数 --> <param name="userId">xyz</param> <param name="area">ga</param> <result> <!-- 生成URL:UserAction.action?userId=xyz&area=ga -->
PlainText
<!-- 通常被用来发送JSP页面的源代码 --> <action name="source_show" class="..."> <result name="success" type="plaintext">/jsp/Menu.jsp</result> </action>
Struts2Staglib
Struts2的S标签
Updated
May 10, 2010 by
cm2...@gmail.com
<!-- 访问request必须要加# --> <p>赋值,取值</p> <!-- 页面定义变量(本页赋值用name要加#取值),default默认值.--> <!-- 赋值字符串要加'',不然是去Action中找对应的变量.value="test"->在Action中找test变量 --> <s:set id="test1" value="'test1'"></s:set> <!-- #request.get('javax.servlet.forward.context_path')必须经过Action转发到jsp才有值,直接访问jsp无值 --> <s:set id="msg" value="#request.get('javax.servlet.forward.context_path')"/> s:<s:property value="#msg" default="Struts2"/><br/> el:${msg}<br/> <!-- 取Action中变量的值不用加# --> <s:property value="user.name"/><br/> <!-- Action中的变量放在request中 --> --${requestScope.user}||<br/> <p><b>if标签:</b> If标签用来控制基本的条件处理流程,通常和else标签或者elseif标签连用。(%{}可加可不加)</p> <!-- test必须,支持表达式(不支持el表达式) --> <s:if test="#request.user!=null"> <div>user!=null</div> <s:if test="%{#request.user.age>40}"> <div>中年人</div> </s:if> <s:elseif test="%{#request.user.age>20}"> <div>年轻人</div> </s:elseif> <s:else> <div>小孩</div> </s:else> </s:if> <s:else> <div>user==null</div> </s:else> <p><b>iterator标签:</b> 对集合迭代 </p> 迭代List<br/> <!-- 判断是否为空 --> <s:if test="(userList!=null)&&(!userList.isEmpty())"> <div>userList</div> <s:iterator value="#request.userList" id="u" status="st"> index:<s:property value="#st.index+1"/> 是否第一个:<s:property value="#st.first"/> 是否最后一个:<s:property value="#st.last"/> 是否偶数:<s:property value="#st.even"/> 是否奇数:<s:property value="#st.odd"/> <br/> <s:property value="#u.name"/> <s:property value="#u.age"/> <!-- 格式化日期 --> <s:date name="#u.birthday" format="yyyy-MM-dd HH:mm:ss" /> <br/> </s:iterator> </s:if> <s:else> <div>null</div> </s:else> 迭代Map<br/> <s:if test="(userMap!=null)&&(!userMap.isEmpty())"> <div>userMap</div> <s:iterator value="#request.userMap" id="map" status="st"> index:<s:property value="#st.index+1"/> 是否第一个:<s:property value="#st.first"/> 是否最后一个:<s:property value="#st.last"/> 是否偶数:<s:property value="#st.even"/> 是否奇数:<s:property value="#st.odd"/> <br/> <s:property value="#map.key"/> <s:property value="#map.value.name"/> <s:property value="#map.value.age"/> <!-- 格式化日期 --> <s:date name="#map.value.birthday" format="yyyy-MM-dd HH:mm:ss" /> <br/> </s:iterator> </s:if> <s:else> <div>null</div> </s:else> <p><b>append标签:</b> 对多个集合进行合并 </p> <br/> 合并List <br/> <s:append id="newList"> <s:param value="#request.userList"></s:param> <s:param value="#request.userList"></s:param> </s:append> <s:iterator value="#newList" id="u" status="st"> index:<s:property value="#st.index+1"/> 是否第一个:<s:property value="#st.first"/> 是否最后一个:<s:property value="#st.last"/> 是否偶数:<s:property value="#st.even"/> 是否奇数:<s:property value="#st.odd"/> <br/> <s:property value="#u.name"/> <s:property value="#u.age"/> <!-- 格式化日期 --> <s:date name="#u.birthday" format="yyyy-MM-dd HH:mm:ss" /> <br/> </s:iterator> <br/> List和Map合并,结果为Map <br/> <s:append id="newListMap"> <s:param value="#request.userList"></s:param> <s:param value="#request.userMap"></s:param> </s:append> <s:iterator value="#newListMap" id="map" status="st"> index:<s:property value="#st.index+1"/> 是否第一个:<s:property value="#st.first"/> 是否最后一个:<s:property value="#st.last"/> 是否偶数:<s:property value="#st.even"/> 是否奇数:<s:property value="#st.odd"/> <br/> <s:property value="#map.key"/> <s:property value="#map.value.name"/> <s:property value="#map.value.age"/> <!-- 格式化日期 --> <s:date name="#map.value.birthday" format="yyyy-MM-dd HH:mm:ss" /> <br/> </s:iterator> <!-- 显示栈里的参数信息 --> <s:debug></s:debug>
Struts2FormTaglib
Struts2表单标签
Updated
May 10, 2010 by
cm2...@gmail.com
<!-- action="userAction!%{tip}"动态方法tip为Action中的变量 submit不加method --> <s:form action="userAction" namespace="/form" method="POST"> <!-- userBean.id为Action中属性userBean中id的值 --> <s:hidden name="userBean.id"></s:hidden> <s:textfield name="userBean.name" label="用户名" ></s:textfield> <s:textfield name="userBean.age" label="年龄" ></s:textfield> <s:textfield name="userBean.birthday" label="生日" > <!-- 格式化日期 --> <s:param name="value"> <s:date name="userBean.birthday" format="yyyy-MM-dd" /> </s:param> </s:textfield> <!-- 密码不能回填 --> <s:password name="userBean.password" label="密码" ></s:password> <s:textarea name="userBean.des" label="描述" cols="35" rows="8"></s:textarea> <!-- 这种checkbox显示出来是一行只有一个checkbox <s:iterator value="likeList"> <s:checkbox name="userBean.likes" label="%{name}" fieldValue="%{id}"></s:checkbox> </s:iterator> --> <!-- 这种是一行多个 --> <s:checkboxlist list="likeList" name="userBean.likes" listKey="id" listValue="name" label="爱好"></s:checkboxlist> <!-- 下拉框 <s:select list="likeList" listKey="id" listValue="name" headerKey="-1" headerValue="请选择爱好"></s:select> --> <!-- value="1" 设置默认,但是好像设置了不能回填 --> <s:radio list="#{'1':'男','2':'女'}" label="性别" name="userBean.sex"></s:radio> <!-- value显示值,method调用方法 --> <s:submit value="%{tip}" id="submitBut" method="%{tip}"></s:submit> </s:form>
Struts2FileUpload
Struts2文件上传下载
Struts2
Updated
Apr 26, 2010 by
coderro...@gmail.com
文件上传
1.jsp页面<s:form action="fileAction" namespace="/file" method="POST" enctype="multipart/form-data"> <!-- name为后台对应的参数名称 --> <s:file name="files" label="file1"></s:file> <s:file name="files" label="file2"></s:file> <s:file name="files" label="file3"></s:file> <s:submit value="提交" id="submitBut"></s:submit> </s:form>
2.Action
//单个文件上传可以用 File files,String filesFileName,String filesContentType //名称要与jsp中的name相同(三个变量都要生成get,set) private File[] files; // 要以File[]变量名开头 private String[] filesFileName; // 要以File[]变量名开头 private String[] filesContentType; private ServletContext servletContext; //Action调用的上传文件方法 public String execute() { ServletContext servletContext = ServletActionContext.getServletContext(); String dataDir = servletContext.getRealPath("/file/upload"); System.out.println(dataDir); for (int i = 0; i < files.length; i++) { File saveFile = new File(dataDir, filesFileName[i]); files[i].renameTo(saveFile); } return "success"; }
3.配置上传文件临时文件夹(在struts.xml中配置)
<constant name="struts.multipart.saveDir" value="c:/temp"/>
文件下载
1.下载的url(到Action)<a href="${pageContext.request.contextPath}/file/fileAction!down.action">下载</a>
2.struts.xml配置
<package name="file" namespace="/file" extends="struts-default"> <action name="fileAction" class="com.struts2.file.FileAction"> <!-- 下载文件配置 --> <!--type 为 stream 应用 StreamResult 处理--> <result name="down" type="stream"> <!-- 不管实际类型,待下载文件 ContentType 统一指定为 application/octet-stream 默认为 text/plain --> <param name="contentType">application/octet-stream</param> <!-- 默认就是 inputStream,它将会指示 StreamResult 通过 inputName 属性值的 getter 方法, 比如这里就是 getInputStream() 来获取下载文件的内容,意味着你的 Action 要有这个方法 --> <param name="inputName">inputStream</param> <!-- 默认为 inline(在线打开),设置为 attachment 将会告诉浏览器下载该文件,filename 指定下载文 件保有存时的文件名,若未指定将会是以浏览的页面名作为文件名,如以 download.action 作为文件名, 这里使用的是动态文件名,${fileName}, 它将通过 Action 的 getFileName() 获得文件名 --> <param name="contentDisposition">attachment;filename="${fileName}"</param> <!-- 输出时缓冲区的大小 --> <param name="bufferSize">4096</param> </result> </action> </package>
3.Action
//Action调用的下载文件方法 public String down() { return "down"; } //获得下载文件的内容,可以直接读入一个物理文件或从数据库中获取内容 public InputStream getInputStream() throws Exception { String dir = servletContext.getRealPath("/file/upload"); File file = new File(dir, "icon.png"); if (file.exists()) { //下载文件 return new FileInputStream(file); //和 Servlet 中不一样,这里我们不需对输出的中文转码为 ISO8859-1 //将内容(Struts2 文件下载测试)直接写入文件,下载的文件名必须是文本(txt)类型 //return new ByteArrayInputStream("Struts2 文件下载测试".getBytes()); } return null; } // 对于配置中的 ${fileName}, 获得下载保存时的文件名 public String getFileName() { String fileName ="图标.png"; try { // 中文文件名也是需要转码为 ISO8859-1,否则乱码 return new String(fileName.getBytes(), "ISO8859-1"); } catch (UnsupportedEncodingException e) { return "icon.png"; } }
Struts2JSON
Struts2返回JSON
Updated
May 10, 2010 by
cm2...@gmail.com
1.导入jsonplugin包
Struts2.16:导入jsonplugin-0.34.jar包(下载包)和commons-logging-1.0.4.jar(Struts2 lib下有)Struts2.18导入struts2-json-plugin-2.1.8.1.jar(Struts2 lib下有)
2.struts.xml中package 中extends="json-default"
<package name="json" namespace="/json" extends="json-default">
3.result 中type="json"
<!-- 封装所以的get开头的方法 --> <result type="json" name="user"> </result> <!-- 只包含user.id属性 --> <result type="json" name="user"> <param name="includeProperties"> user\.id </param> </result> <!-- 不包含user属性 --> <result type="json" name="list"> <param name="excludeProperties"> user </param> </result> <!-- 根对象只包含user --> <result type="json"> <param name="root"> user </param> </result> <!-- "root"对象中父类的field(属性)不会(会?) 默认存放到 JSON数据中,如果不想这样做,需要在配置时指定 ignoreHierarchy 为 false: --> <result type="json"> <param name="ignoreHierarchy">false</param> </result>
4.避免使用get开头的action方法
在属性get方法上面加 @JSON(name="newName")json中的名称 @JSON(serialize=false) 属性不被加入json @JSON(format="yyyy-MM-dd") 格式化日期
5.在action中赋值,返回对应的result字符串
Struts2XMLStruts2返回XML
Updated
May 10, 2010 by
cm2...@gmail.com
使用response
//直接调用responseOut方法 public void responseOut() throws Exception { StringBuilder sb = new StringBuilder(); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); sb.append("<users>"); sb.append(" <user id=\"50\">"); sb.append(" <userName>abc</userName>"); sb.append(" </user>"); sb.append("</users>"); //得到response HttpServletResponse response = ServletActionContext.getResponse(); //设置编码 response.setCharacterEncoding("UTF-8"); response.setContentType("text/xml;charset=utf-8"); response.setHeader("Cache-Control", "no-cache"); PrintWriter out = response.getWriter(); out.write(sb.toString()); out.flush(); out.close(); }
Struts2CRUD
Struts2增删改查例子
Updated
May 10, 2010 by
cm2...@gmail.com
UserBean
//要添加set,get public class UserBean { private Long id; private String name; private String password; private int age; private Date birthday; private Long sex; private Set<Long> likes; private String des;//描述 } public class LikeBean { private Long id; private String name; }
FormAction
public class FormAction{ //属性要生成get,set //标记(添加,修改) private String tip; private UserBean userBean; private List<LikeBean> likeList; private List<UserBean> userList; //到列表页面 public String list(){ userList = new ArrayList<UserBean>(); userList.add(new UserBean("abc",19,new Date())); userList.add(new UserBean("def",70,new Date())); userList.add(new UserBean("ghi",40,new Date())); return "list"; } //到添加页面 public String toAdd(){ likeList = new ArrayList<LikeBean>(); likeList.add(new LikeBean(new Long(1),"上网")); likeList.add(new LikeBean(new Long(2),"读书")); likeList.add(new LikeBean(new Long(3),"游戏")); tip = "add"; return "info"; } //添加方法,Struts2会自动把对应的值赋值给userBean public String add(){ System.out.println(userBean); return "toList"; } //到更新页面,取出值,设置标记 public String toUpdate(){ likeList = new ArrayList<LikeBean>(); likeList.add(new LikeBean(new Long(1),"上网")); likeList.add(new LikeBean(new Long(2),"读书")); likeList.add(new LikeBean(new Long(3),"游戏")); tip = "update"; System.out.println("update name:"+userBean.getName()); userBean = new UserBean("update",100,new Date()); userBean.setId(new Long(101)); userBean.setSex(new Long(2)); userBean.setDes("Struts2用户"); Set<Long> likes = new HashSet<Long>(); likes.add(new Long(2)); likes.add(new Long(3)); userBean.setLikes(likes); return "info"; } //更新方法 public String update(){ System.out.println(userBean); return "toList"; } //删除方法 public String delete(){ System.out.println("del name:"+userBean.getName()); return "toList"; } }
struts.xml配置
<struts> <package name="form" namespace="/form" extends="struts-default"> <!-- 使用通配符调用多个方法,method为*对应的字符串 --> <action name="userAction_*" class="com.struts2.form.FormAction" method="{1}"> <!-- 方法返回的字符串对应name,再转发到页面 --> <result name="list">/form/list.jsp</result> <result name="info">/form/info.jsp</result> <!-- 重定向Action,可以有Action名字和空间,参数 --> <result name="toList" type="redirectAction"> <!-- 空间参数,不写代表和当前Action同一个空间 <param name="namespace">form</param> --> <!-- 重定向Action的名称 --> <param name="actionName">userAction_list</param> <!-- url带的参数,${userBean.name}是动态参数,值为Action的属性userBean中name的值 --> <param name="userName">${userBean.name}</param> <param name="userAge">${userBean.age}</param> </result> </action> </package> </struts>
jsp页面
1.list(列表页面)<!-- 添加标签 --> <%@ taglib prefix="s" uri="/struts-tags" %> <div><a href="${pageContext.request.contextPath}/form/userAction_toAdd.action">添加</a></div> <div> <!-- 判断用户是否为空 --> <s:if test="(userList!=null)&&(!userList.isEmpty())"> <div>用户列表</div> <!-- 遍历用户 --> <s:iterator value="#request.userList" id="u" status="st"> <s:property value="#st.index+1"/> <s:property value="#u.name"/> <s:property value="#u.age"/> <!-- 格式化日期 --> <s:date name="#u.birthday" format="yyyy-MM-dd HH:mm:ss" /> <a href="${pageContext.request.contextPath}/form/userAction_toUpdate.action?userBean.name=${u.name}">修改</a> <a href="${pageContext.request.contextPath}/form/userAction_delete.action?userBean.name=${u.name}">删除</a> <br/> </s:iterator> </s:if> <s:else> <div>无用户</div> </s:else> </div>
2.info.jsp(添加和修改页面)
<!-- 添加标签 --> <%@ taglib prefix="s" uri="/struts-tags" %> <!-- 显示标记(添加/修改) --> <s:property value="tip"/> <!-- action="userAction_%{tip}"tip为Action中的标记变量 submit不加method --> <s:form action="userAction" namespace="/form" method="POST"> <!-- userBean.id为Action中属性userBean中id的值 --> <s:hidden name="userBean.id"></s:hidden> <s:textfield name="userBean.name" label="用户名" ></s:textfield> <s:textfield name="userBean.age" label="年龄" ></s:textfield> <s:textfield name="userBean.birthday" label="生日" > <!-- 格式化日期 --> <s:param name="value"><s:date name="userBean.birthday" format="yyyy-MM-dd" /></s:param> </s:textfield> <!-- 密码不能回填 --> <s:password name="userBean.password" label="密码" ></s:password> <s:textarea name="userBean.des" label="描述" cols="35" rows="8"></s:textarea> <!-- 这种checkbox显示出来是一行只有一个checkbox <s:iterator value="likeList"> <s:checkbox name="userBean.likes" label="%{name}" fieldValue="%{id}"></s:checkbox> </s:iterator> --> <!-- 这种是一行多个 --> <s:checkboxlist list="likeList" name="userBean.likes" listKey="id" listValue="name" label="爱好"></s:checkboxlist> <!-- 下拉框 <s:select list="likeList" listKey="id" listValue="name" headerKey="-1" headerValue="请选择爱好"></s:select> --> <!-- value="1" 设置默认,但是好像设置了不能回填 --> <s:radio list="#{'1':'男','2':'女'}" label="性别" name="userBean.sex"></s:radio> <s:submit value="%{tip}" id="submitBut" method="%{tip}"></s:submit> </s:form>
Struts2I18n
Struts2国际化
Updated
May 10, 2010 by
cm2...@gmail.com
1.定义properties文件
资源文件查找顺序
JAVA国际化 如果系统同时存在资源文件、类文件,系统将以类文件为主,而不会调用资源文件。 对于简体中文的Locale,ResourceBundle搜索资源的顺序是: (1)baseName_zh_CN.class (2)baseName_zh_CN.properties (3)baseName_zh.class (4)baseName_zh.properties (5)baseName.class (6)baseName.properties /* Struts2找不到对应语言的配置文件时,会先找系统语言对应的配置文件,再找不到才使用baseName.properties */
国际化分为三类:全局的,包级别的,类级别的
全局的: 1.在struts.xml中的<constant name="struts.custom.i18n.resources" value="message"></constant>指定baseName 国际化文件名为:baseName_语言名_国家名.properties(如:message_zh_CN.properties) 2.全局的国际化资源文件放在src下面 包级别的: 1.包级别的国际化资源文件放在该包下面 2.命名规则为:package_语言名_国家名.properties(如:package_zh_CN.properties) 其中package不变,不是指的是包名,每个包的国际化文件命名都这样 类级别的: 1.与该类放在同一目录中 2.命名规则为:类名_语言名_国家名.properties(如:RegisterAction_zh_CN.properties) 若同一key 在上面三个国际化文件中都为value值则:(优先级)类级别的>包级别的>全局的
2.在jsp中访问国际化资源文件
<!-- 输出国际化 --> <!-- name为国际化文件中的key --> <s:text name="hello"> <!-- 若该国际化文件的value中有{0}则可用下面的标签把参数传进去 --> <s:param>mengya</s:param> <s:param><s:property value="firstName"/></s:param> </s:text> <s:property value="%{getText('customer.contact')}"/> 传参数 <s:property value="%{getText('customer.contact','sh')}"/> 定义变量,加var属性 <s:text name="greetings" var="msg"/> <s:property value="#msg"/> <!-- 指定特定的国际化文件,name为全局国际化文件的baseName --> <s:i18n name="temp"> <!-- 下面的<s:text>标签与上面的用法一样 --> <s:text name="hello"> <s:param>mengya</s:param> </s:text> </s:i18n> 表单国际化: 1.theme不能为simple如:<s:form action="register">(默认的theme不是simple) 2.使用key如:<s:textfield name="username" key="" id="usernameId"></s:textfield> 3.或者使用getText方法<s:textfield name="username" label="%{getText('customer.name')}"/>
3.在Action中访问国际化资源文件,该Action继承了ActionSupport类
this.getText("username.invalid") 若该key对应的value需要参数则: this.getText("username.invalid",new String[]{username}) 或 List list = new ArrayList(); list.add(username); this.getText("username.invalid",list) 如: if (null == username || username.length() < 6 || username.length() > 10) { List list = new ArrayList(); list.add(username); this.addActionError(this.getText("username.invalid",new String[]{username})); } 该国际化资源文件中的key和value为: username.invalid = \u7528\u6237\u540d "{0}" \u586b\u5199\u4e0d\u6b63\u786e
4.在输入验证框架访问国际化资源文件
<!-- 使用<message key="..."></message> -> <field-validator type="requiredstring"> <param name="trim">true</param> <message key="username.invalid"></message> </field-validator>
5.动态改变语言
只有在url传入request_locale=en_US就可以指定为en_US的语言1.如果配置文件是en_US结尾,传入en,en_US都可以找到
2.如果配置文件是en结尾,只能传入en,传入en_US会找不到,从而找默认的配置文件(en的范围>en_US,使用英语的国家不止美国一个)
<a href="${pageContext.request.contextPath}/i18n/i18nAction?request_locale=en_US">English</a>
6.使用类来代替properties文件
//继承ListResourceBundle实现getContents方法 public class MyCustomResourceBundle extends ListResourceBundle { public Object[][] getContents() { if (Calendar.getInstance().get(Calendar.HOUR_OF_DAY) < 12) { return contents1; } else { return contents2; } } static final Object[][] contents1 = { { "greetings", "中午好 {0}" }, { "farewell", "再见" } }; static final Object[][] contents2 = { { "greetings", "你好 {0}" }, { "farewell", "再见" } }; } //en对应的字符串 public class MyCustomResourceBundle_en extends ListResourceBundle { public Object[][] getContents() { if (Calendar.getInstance().get(Calendar.HOUR_OF_DAY) < 12) { return contents1; } else { return contents2; } } static final Object[][] contents1 = { { "greetings", "Good morning {0}" }, { "farewell", "Good bye" } }; static final Object[][] contents2 = { { "greetings", "Hello {0}" }, { "farewell", "Good bye" } }; } //jsp中使用 <s:i18n name="com.resourcebundle.MyCustomResourceBundle"> <s:text name="greetings"> <s:param>Jon</s:param> </s:text>. <s:text name="farewell"/> </s:i18n>
Struts2Validator
Struts2验证框架
Updated
Jun 18, 2010 by
cm2...@gmail.com
Action配置中一定要设置input返回页面
添加验证只要创建验证的xml文件
1.创建xml文件名
验证Action中全部方法
在Action同包下,创建:Action类名-validation.xml如:ValidateAction创建ValidateAction-validation.xml
验证Action中单个方法
<!-- 每个方法单独配置一个Action --> <!-- 在Action同包下,创建:Action类名-action方法配置名称-validation.xml --> <action name="validateAdd" class="com.struts2.validator.ValidateAction" method="add"> <!-- 要创建ValidateAction-validateAdd-validation.xml --> <!-- 使用通配符配置 --> <!-- 在Action同包下,创建:Action类名-action方法对应的名称-validation.xml --> <action name="validate_*" class="com.struts2.validator.ValidateAction" method="{1}"> <!-- 要创建ValidateAction-validate_add-validation.xml,validate_add为访问这个action方法的路径 -->
注意事项
注意: 1.要验证的方法不能叫input. 2.这样配置在form表单中要在<s:form action="validate_add">中action写好名称, 不能写action="validate_",然后<s:submit value="提交"method="add" /> 这样会找不到对应的配置文件,跳过验证. 3.如果验证出错,返回input页面时,那些存在ValueStack中的值会丢失,可以将Action实现Preparable接口, 然后prepare()方法里初始化添加页面需要的值. 4.如果使用Preparable接口,必须在action配置中添加<interceptor-ref name="paramsPrepareParamsStack" />. 这样prepare()才能得到form提交的参数.
2.创建xml内容
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <validators> <!-- 要验证的字段名称 --> <!-- 要验证Action中UserBean的id字段,name="userBean.id"(userBean为Action中的变量名) --> <field name="mail"> <!-- type要验证的类型,short-circuit(默认false),true含义,如果当前验证失败了,下面的验证就不执行了.如requiredstring失败了,email就不验证了. --> <!-- field-validator下面可以有多个param元素,但是最多只能有一个message --> <field-validator type="requiredstring"> <param name="trim">true</param> <message>Please enter a mail</message> </field-validator> <field-validator type="email"> <message> Invalid MAIL </message> </field-validator> </field> </validators>
Struts内建验证程序(type的值)
required
保证字段的值不是空值null.空字符串不是空值null.<field name="userName"> <field-validator type="required"> <message>Please enter a user name</message> </field-validator> </field>
requiredstring
保证字段不是空值null,也不是空白(empty).param:trim(boolean) ->true->去除前后空格
<field name="userName"> <field-validator type="requiredstring"> <param name="trim">true</param> <message>Please enter a user name</message> </field-validator> </field> <field name="password"> <field-validator type="requiredstring"> <param name="trim">false</param> <message>Please enter a password</message> </field-validator> </field>
int
验证字段值是否可以转换为一个整数.param: min(int);max(int)
<field name="yeaar"> <field-validator type="int"> <param name="min">1999</param> <param name="max">2010</param> <message>year:1999-2010</message> </field-validator> </field>
date
验证给定日期字段的值是否在一个给定的范围内.param:max(date);min(date)
<field name="borthday"> <field-validator type="int"> <!-- 格式取决于当前地理时区 --> <param name="min">1999-01-01</param> <param name="max">2010-01-01</param> <message>birthday:1999-2010</message> </field-validator> </field>
<field name="email"> <field-validator type="email"> <message>Invalid email</message> </field-validator> </field>
url
给定的String值是否是一个合法的URL(要有前缀)<field name="url"> <field-validator type="url"> <message>Invalid URL</message> </field-validator> </field>
expression,fieldexpression
验证给定字段是否满足一个OGNL表达式.区别:expression 不是一个字段验证程序,失败时将生成一个动作错误.(JSP中调用
<actionerror>
</actionerror>
才显示出错信息)
fieldexpression 是一个字段验证程序,失败时将抛出一个字段错误.(对字段验证)
param:expression(String)OGNL表达式
expression:
public class ExpressionTestAction { //属性生成get,set private int min; private int max; } <validator type="expression"> <param name="expression"> max > min </param> <message> Maximum temperature must be greater than Minimum temperature </message> </validator> <!-- jsp --> <s:actionerror/>
fieldexpression:
public class FieldExpressionTestAction { //属性生成get,set private int min; private int max; } <!-- 对字段验证 --> <field name="max"> <field-validator type="fieldexpression"> <param name="expression"> max > min </param> <message> Maximum temperature must be greater than Minimum temperature </message> </field-validator> </field>
visitor
把同一个验证程序配置文件用于多个动作(对一个Bean写验证文件,每个使用的Action只要引用)//UserBean public class UserBean { //属性get,set private String name; private int age; } //UserBean-validation.xml(和UserBean放在同一个包中) <field name="name"> <field-validator type="requiredstring"> <message>用户名必须</message> </field-validator> </field> <field name="age"> <field-validator type="int"> <param name="min">18</param> <param name="max">99</param> <message>Age must be between 18 and 99</message> </field-validator> </field> //Action的validation.xml <!-- userBean变量名 --> <field name="userBean"> <field-validator type="visitor"> <!-- message会和UserBean验证中的message一起显示 --> <message>用户: </message> </field-validator> </field>
如果另一个Action对UserBean使用另一个标准的验证,可以创建新的验证文件
//UserBean-specific-validation.xml <!-- 和之前的验证不同 --> <field name="age"> <field-validator type="int"> <param name="min">30</param> <param name="max">50</param> <message>Age must be between 30 and 50</message> </field-validator> </field> //另一个Action的validation.xml <field name="userBean"> <field-validator type="visitor"> <!-- xml中扩展的名字,执行UserBean-specific-validation.xml的验证 --> <param name="context">specific</param> <message>用户1: </message> </field-validator> </field>
conversion
检查对某个属性进行类型转换是否会导致一个转换错误<field name="age"> <field-validator type="conversion"> <message> An age must be an integer. </message> </field-validator> </field>
stringlength
验证一个非空的字段值是不是足够的长度param:minLength(int);maxLength(int);trim(boolean)
<field name="password"> <field-validator type="requiredstring"> <param name="minLength">6</param> <param name="maxLength">14</param> <message>length:6-14</message> </field-validator> </field>
regex
给定的值是否与一个给定的正则表达式匹配param:expression(String)正则表达式;caseSensitive(boolean)是否区别大小写,默认为true;trim(boolean)是否去除前后空格
<field name="phone"> <field-validator type="regex"> <param name="expression"> <![CDATA[\d\d\d\-\d\d\d\-\d\d\d\d]]> </param> <message> Invalid phone number or invalid format </message> </field-validator> </field>
3.在action中验证
利用Validateable接口实现验证,实现void validate()方法.ActionSupport类已经实现了这个接口
//继承ActionSupport public class User extends ActionSupport { //属性get,set private String userName; private String password; private static List<String> userNames = new ArrayList<String>(); static { userNames.add("harry"); userNames.add("sally"); } //验证方法 public void validate() { if (userNames.contains(userName)) { //添加出错信息 addFieldError("userName", "'" + userName + "' has been taken."); } } }
4.自定义验证类
要创建一个普通的验证程序(非字段验证程序),扩展ValidatorSupport类.验证失败要从validate方法调用addActionError方法.要创建一个字段验证程序,扩展FieldValidatorSupport类.验证失败要从validate方法调用addFieldError方法.
如果要能接受参数,要在类中定义一个相应的属性,并生成get,set.
编写类
public class StrongPasswordValidator extends FieldValidatorSupport { //属性 private int minLength = -1; public void setMinLength(int minLength) { this.minLength = minLength; } public int getMinLength() { return minLength; } //验证方法 public void validate(Object object) throws ValidationException { String fieldName = getFieldName(); String value = (String) getFieldValue(fieldName, object); if (value == null || value.length() <= 0) { // use a required validator for these return; } if ((minLength > -1) && (value.length() < minLength)) { addFieldError(fieldName, object); } else if (!isPasswordStrong(value)) { addFieldError(fieldName, object); } } private static final String GROUP_1 = "abcdefghijklmnopqrstuvwxyz"; private static final String GROUP_2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final String GROUP_3 = "0123456789"; protected boolean isPasswordStrong(String password) { boolean ok1 = false; boolean ok2 = false; boolean ok3 = false; int length = password.length(); for (int i = 0; i < length; i++) { if (ok1 && ok2 && ok3) { break; } String character = password.substring(i, i + 1); System.out.println("character:" + character); if (GROUP_1.contains(character)) { ok1 = true; continue; } if (GROUP_2.contains(character)) { ok2 = true; continue; } if (GROUP_3.contains(character)) { ok3 = true; } } return (ok1 && ok2 && ok3); } }
注册xml
在src下创建validators.xml<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator Config 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd"> <validators> <!-- 名称(type对应值),类路径 --> <validator name="strongpassword" class="com.validator.StrongPasswordValidator"/> </validators>
使用验证
<field name="password"> <field-validator type="strongpassword"> <param name="minLength">8</param> <message> Password must be at least 8 characters long and contains at least one lower case character, one upper case character, and a digit. </message> </field-validator> </field>
相关文章推荐
- 重新整理struts2与spring整合相关知识
- 【JavaWeb-25】事务管理相关知识、手动/半自动/自动管理事务案例、整合Junit、整合Web、spring和hibernate整合、struts2和spring整合
- struts2相关知识
- struts2文件上传相关资料收集整合
- 分享知识-快乐自己:SpringMvc中的四种数据源及相关配置(整合快速集成开发)
- Struts2相关知识(一)
- 细说struts2中一些相关的知识
- struts2 相关知识
- 相关知识整合
- Hibernate和Struts2的整合(相关问题的说明)
- Spring Boot相关知识(三) Spring Boot项目整合MyBatis
- Struts2 Spring3 Mybatis 3 整合 相关配置文件
- struts2的流程和一系列相关知识
- SSH框架整合开发(struts2 spring hibernate 三大框架知识总结)
- Struts2 Hibernate Spring 整合的基本流程和步骤及其相关配置细节
- struts2的流程和一系列相关知识代码解析
- 电商之梳理struts2相关知识---开发基础框架
- struts2 相关知识
- struts2--(3)--一些小的知识----访问web相关元素
- struts2-ValueStack相关知识(OGNL)