一、需求
利用struts2实现中文验证并对错误消息的抽离。
详细需求:用户登录--》不填写用户名--》页面跳转到用户登录页面,提示用户名必填(以英文和中文两种方式提示)--》填写英文用户名--》页面提示用户名必须填写为英文---》填写中文用户名---》页面跳转到登录成功页面。
二、效果图
1、英文提示
2、中文提示
三、代码分析
result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<s:form action="ResultAction" enctype="multipart/form-data" method="POST">
<s:textfield label="用户名" name="username"/>
<s:submit value="提交"/>
</s:form>
</body>
</html>
result_success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> 恭喜,登录成功! <hr> 用户名:<s:property value="username"/> </body> </html>
ResultAction.java
package result; import com.opensymphony.xwork2.ActionSupport; public class ResultAction extends ActionSupport { private static final long serialVersionUID = 7340087601249007671L; private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public void validate() { if (username != null && username.trim().length() > 0) { if (username.matches("[\u4e00-\ufa29]+")) { } else { // this.addFieldError("username", "用户名必须为中文"); this.addFieldError("username", this.getText("result.username.mustchinese")); } } else { this.addFieldError("username", this.getText("result.username.required")); // this.addFieldError("username", "用户名必填!"); } } public String execute() throws Exception { return SUCCESS; } }
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!--<include file="config/upload.xml"></include>-->
<!-- 加载其他配置文件 -->
<!-- <include file="config/upload-interceptor.xml"></include> -->
<!-- 加载属性文件-国际化 -->
<constant name="struts.custom.i18n.resources" value="message"></constant>
<!-- 结果集 -->
<include file="config/result_struts.xml"></include>
</struts>
result_struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="result" extends="struts-default"> <action name="ResultAction" class="result.ResultAction" method="execute"> <result name="success" type="dispatcher"> /WEB-INF/result_success.jsp </result> <result name="input" type="dispatcher"> result.jsp </result> </action> </package> </struts>
message_zh_CN.properties
login.username=\u7528\u6237\u540D login.submit=\u767B\u5F55 login.hello=\u4F60\u597D{0},\u6211\u662F{1} login.tom=\u6C64\u59C6 login.amos=\u963F\u83AB\u65AF result.username.required=\u7528\u6237\u540D\u5FC5\u586B result.username.mustchinese=\u5FC5\u987B\u4E3A\u4E2D\u6587
message_en_US.properties
login.username=USERNAME login.submit=LOGIN login.hello=hello {0},I am {1} login.tom=TOM login.amos=AMOS result.username.required=username cannot be empty result.username.mustchinese=username must be chinese
首先,项目运行时,通过struts.xml将配置文件加载到内存中,其中strutx.xml加载了result_struts.xml,message_zh_CN.properties,message_en_US.properties三个配置文件。
两个properties文件分别对应的是中英文提示信息,这里在项目启动时已经加载到内存中去了。
其次,result.jsp页面是程序入口==>调用了ResultAction==>ResultAction是在result_struts.xml中配置的ResultAction.java中的execute方法==>
调用validate()验证方法==>validate()验证方法主要作用是对username进行验证,必须是非空和中文,否则会使用getText()方法调用properties中配置的提示信息,将错误提示信息添加到addFieldError()方法中。
最后,通过struts的标签<s:textfield>将错误提示信息显示输出到浏览器中。
总结,对中文的验证主要是采用正则表达式,即使用unicode编码汉字的范围;对错误信息的分离抽取主要使用properties文件进行配置,然后再通过struts标签进行错误信息的输出,这里同时也用到了上篇文章的国际化的知识.
四、结果(result)类型
一般情况下,当Action中的execute方法的返回值为null时不需要配置<action>下的<result>标签,但如果有返回值时则需要将result标签进行配置.
在struts2-core.jar包里有struts-default.xml默认配置文件,其中有这样一段:
<result-types> <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/> <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/> <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/> <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/> <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/> <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" /> <result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" /> </result-types>
关于result-types,即结果类型,其中经常用到的有dispatcher,redirect,然后class有其对应的类来实现所配置的功能.这里来简单介绍下redirectAction:
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
选中类路径,eclipse中ctrl+shift+t能跳转到对应的实现类,查看一下源码,其中可选属性有actionName,namespace,method,下面以实例来说明其使用方法.
redirectAction从名字上理解为重定向action,重定向时浏览器中的路径是会发生变化的.这里要实现的需求为:从一个FromAction重定向到另一个ToAction
1.具体代码为:
FromAction.java
package result; import com.opensymphony.xwork2.ActionSupport; public class FromAction extends ActionSupport{ private static final long serialVersionUID = -3310226638999302819L; public String execute() throws Exception { return "gotoAction"; } }
ToAction.java
package result; import com.opensymphony.xwork2.ActionSupport; public class ToAction extends ActionSupport{ private static final long serialVersionUID = 6648927017489122451L; public String execute() throws Exception { return null; } }
result_struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="result" extends="struts-default"> <action name="ResultAction" class="result.ResultAction" method="execute"> <result name="success" type="dispatcher"> /WEB-INF/result_success.jsp </result> <result name="input" type="dispatcher"> result.jsp </result> </action> <action name="FromAction" class="result.FromAction" method="execute"> <result name="gotoAction" type="redirectAction"> <param name="actionName">ToAction</param> <!-- <param name="namespace">/</param> <param name="method">execute</param> --> </result> </action> <action name="ToAction" class="result.ToAction" method="execute"></action> </package> </struts>
2.代码分析
其中result中的主要实现代码为:
<result name="gotoAction" type="redirectAction"> <param name="actionName">ToAction</param> </result>
gotoAction为FromAction中execute方法的return value值.
redirectAction为result的类型值
actionName为参数名称,这里与源码中定义的参数名称一致
ToAction为将要重定向到另外一个Action的名称.
还可以配置namespace,method等,这里就不再介绍.
3.效果
1)输入FromAction,回车
2)url跳转到ToAction
4.result配置提高
1).如果一个package中多个action标签出现同样的return value="success",如果每个都配置一遍就太过麻烦,这里以上面例子为基础将ToAction的return null 改为 return SUCCESS后,配置文件也跟着改,配置一个返回值为success的全局result:
<global-results> <result name="success" type="dispatcher"> /WEB-INF/success.jsp </result> </global-results>
将全局result转发到success.jsp中.
2).相对应的还有局部的result:
<action name="ToAction" class="result.ToAction" method="execute"> <result name="success" type="dispatcher"> /WEB-INF/part_success.jsp </result> </action>
3)如果局部和全局result共存时以哪个为准???
这里经过测验得出以局部的为准.
全部的result_struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="result" extends="struts-default"> <global-results> <result name="success" type="dispatcher"> /WEB-INF/success.jsp </result> </global-results> <action name="ResultAction" class="result.ResultAction" method="execute"> <!-- <result name="success" type="dispatcher"> /WEB-INF/result_success.jsp </result> --> <result name="input" type="dispatcher"> result.jsp </result> </action> <action name="FromAction" class="result.FromAction" method="execute"> <result name="gotoAction" type="redirectAction"> <param name="actionName">ToAction</param> <!-- <param name="namespace">/</param> <param name="method">execute</param> --> </result> </action> <action name="ToAction" class="result.ToAction" method="execute"> <!-- <result name="success" type="dispatcher"> /WEB-INF/part_success.jsp </result> --> </action> </package> </struts>