输入校验
在Structs2中,我们可以实现对action的所有方法进行校验或者对action的指定方法进行校验。
校验示例1-在action中验证
对一个form表单进行数据校验,运用action中的validate 方法判断,是否为空,通过
<s:fielderror/>
进行提示,涉及input的处理结果类型,接收form表单的数据则用ModelDriver,动态方法调用则是用通配符的方式
执行结果:
<s:fielderror/>
显示错误信息,通过this.addFieldError("username", "用户名不能为空");
的格式添加错误信息,类似一个list集合姓名下方的
<s:fielderror fieldName="username"/>
只会显示姓名栏的校验信息update方法不会进行校验
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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:fielderror ></s:fielderror>
<form action="user_login.action" method="post">
姓名:<input type="text" name="username"/><s:fielderror fieldName="username"></s:fielderror><br/>
密码:<input type="password" name="password"/><br/>
mobile:<input type="text" name="mobile"/><br/>
<input type="submit"value="登录">
</form>
<a href="user_update.action">update</a>
</body>
</html>
User.java
//package model;
/**
* Title: User
* Description: 对应form表单的数据实体类
* @author Peng
* @date 下午6:34:50
*/
public class User {
private String username;
private String password;
private String mobile;
//getter and setter
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", mobile=" + mobile + "]";
}
}
UserAction.java
//package action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import model.User;
@SuppressWarnings("serial")
public class UserAction extends ActionSupport implements ModelDriven<User>{
private User user = new User();//这里需要实例化
public String login(){
System.out.println(user.toString());
System.out.println("执行了login");
return SUCCESS;
}
public String update(){
System.out.println("执行了update");
return "update";
}
/*//全部方法执行前,都会执行此验证方法
@Override
public void validate() {
if(user.getUsername()==null||"".equals(user.getUsername())){
this.addFieldError("username", "用户名不能为空");
}
if(user.getPassword()==null||"".equals(user.getPassword())){
this.addFieldError("password", "密码不能为空");
}
if(user.getMobile()==null||"".equals(user.getMobile())){
this.addFieldError("mobile", "手机号不能为空");
}
}*/
//只做login()方法的验证
public void validateLogin() {
if(user.getUsername()==null||"".equals(user.getUsername())){
this.addFieldError("username", "用户名不能为空");
}
if(user.getPassword()==null||"".equals(user.getPassword())){
this.addFieldError("password", "密码不能为空");
}
if(user.getMobile()==null||"".equals(user.getMobile())){
this.addFieldError("mobile", "手机号不能为空");
}
}
@Override
public User getModel() {
return user;
}
}
如果用注释的 validate() 方法,则会对所有的 action 中的方法进行校验,包括 update 方法,如果错误,会返回 input 处理结果类型。
如果只想对 action 中某个特定的方法进行校验,则可以使用 validate+需要校验的方法名(首字母大写)()的方式,如:
public void validateLogin(){}
只对 login() 方法进行校验
public void validateUpdate(){}
只对 update() 方法进行校验
structs.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="default" namespace="/" extends="struts-default">
<action name="user_*" method="{1}" class="action.UserAction">
<result>/index.jsp</result>
<result name="update">/index.jsp</result>
<result name="input">/login.jsp</result>
</action>
</package>
</struts>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>structs2Validator</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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>
index.jsp
</body>
</html>
校验示例2-在xml中验证
在上例基础上更新
UserAction.java
//package action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import model.User;
@SuppressWarnings("serial")
public class UserAction extends ActionSupport implements ModelDriven<User>{
private User user = new User();//这里需要实例化
public String login(){
System.out.println(user.toString());
System.out.println("执行了login");
return "login";
}
public String update(){
System.out.println("执行了update");
return "update";
}
@Override
public User getModel() {
return user;
}
}
校验文件的命名规则是
ActionName-validation.xml
,需放在action类的同一包下
UserAction-validation.xml
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="username">
<!-- 首先调用trim()方法去掉空格,然后判断用户名是否为空 -->
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>密码不能为空!</message>
</field-validator>
<field-validator type="stringlength">
<param name="trim">true</param>
<param name="minLength">4</param>
<param name="maxLength">10</param>
<message>密码长度要4-10之间!</message>
</field-validator>
</field>
</validators>
上面的xml校验配置文件会对所有的action方法进行拦截
xml配置方式对指定的action方法实现输入校验
校验文件的取名应为
ActionClassName-ActionName-validation.xml
例如:
在下面的action配置中
<action name="user_*" method="{1}" class="action.UserAction">
<result name="login">/index.jsp</result>
<result name="update">/index.jsp</result>
<result name="input">/login.jsp</result>
</action>
public class UserAction extends ActionSupport{
public String login(){
return "login";
}
public String login(){
return "update";
}
}
校验文件名
UserAction-validation.xml 对UserAction中所有方法校验
UserAction-user_login-validation.xml 只对login方法校验
UserAction-user_update-validation.xml 只对update方法校验
系统提供的校验器如下
required (必填校验器,要求field的值不能为null)
requiredstring (必填字符串校验器,要求field的值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)
stringlength (字符串长度校验器,要求field的值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)
regex (正则表达式校验器,检查被校验的field是否匹配一个正则表达式.expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)
int (整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)
double (双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)
fieldexpression (字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定
ognl 表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)
email (邮件地址校验器,要求如果field的值非空,则必须是合法的邮件地址)
url (网址校验器,要求如果field的值非空,则必须是合法的url地址)
date (日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)
conversion (转换校验器,指定在类型转换失败时,提示的错误信息)
visitor (用于校验action中的复合属性,它指定一个校验文件用于校验复合属性中的属性)
expression (OGNL表达式校验器,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过,该校验器不可用在字段校验器风格的配置中)
校验器的使用示例
required 必填校验器
<field-validator type="required">
<message>性别不能为空!</message>
</field-validator>
requiredstring 必填字符串校验器
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
stringlength:字符串长度校验器
<field-validator type="stringlength">
<param name="maxLength">10</param>
<param name="minLength">2</param>
<param name="trim">true</param>
<message><![CDATA[产品名称应在2-10个字符之间]]></message>
</field-validator>
email:邮件地址校验器
<field-validator type="email">
<message>电子邮件地址无效</message>
</field-validator>
regex:正则表达式校验器
<field-validator type="regex">
<param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
<message>手机号格式不正确!</message>
</field-validator>
int:整数校验器
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年龄必须在1-150之间</message>
</field-validator>
字段OGNL表达式校验器
<field name="imagefile">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[imagefile.length() <= 0]]></param>
<message>文件不能为空</message>
</field-validator>
</field>
XML校验的特点
当为某个action提供了ActionClassName-validation.xml
和ActionClassName-ActionName-validation.xml
两种规则的校验文件时,系统按下面顺序寻找校验文件:
1。AconClassName-validation.xml
2。ActionClassName-ActionName-validation.xml
系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于action方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。
当action继承了另一个action,父类action的校验文件会先被搜索到。
假设UserAction继承BaseAction:
<action name="user" class="cn.itcast.action.UserAction" method="{1}">
</action>
访问上面 action,系统先搜索父类的校验文件:BaseAction-validation.xml
, BaseAction-user-validation.xml
,接着搜索子类的校验文件: UserAction-validation.xml
, UserAction-user-validation.xml
。应用于上面 action 的校验规则为这四个文件的总和。
国际化
火狐浏览器的选项,内容,设置语言
servlet通过读取不同的properties文件显示文字,实现国际化
I18NServlet.java
//package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Locale;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Title: I18NServlet
* Description: 读取不同的properties文件,测试国际化
* @author Peng
* @date 下午10:07:42
*/
@WebServlet("/I18NServlet")
public class I18NServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public I18NServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Locale local = Locale.getDefault();//读取本地机器语言编码zh_CN
//System.out.println(local);
Locale local1 = request.getLocale();//读取浏览器页面语言编码zh_CN
System.out.println(local1);
response.setContentType("text/html;charset=utf-8");
PrintWriter out =response.getWriter();
Properties prop = new Properties();
prop.load(this.getClass().getResourceAsStream(
"/aa_"+local1.toString()+".properties"));
out.println(prop.getProperty("aa"));
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
两个properties文件
aa_en_US.properties
aa=Hello
aa_zh_CN.properties
aa=\u4F60\u597D
把IE浏览器的语言格式改变为en_US,输出的将是Hello
资源文件的命名格式如下:
baseName_language_country.properties
baseName_language.properties
baseName.properties
其中baseName是资源文件的基本名,我们可以自定义,但language和country必须是java支持的语言和国家。
中国大陆: baseName_zh_CN.properties
美国: baseName_en_US.properties
对于中文的属性文件,我们编写好后,应该使用jdk提供的native2ascii 命令把文件转换为unicode编码的文件。命令的使用方式如下:
native2ascii 源文件.properties 目标文件.properties
配置全局资源与输出国际化信息
当准备好资源文件之后,我们可以在struts.xml中通过struts.custom.i18n.resources常量把资源文件定义为全局资源文件,如下:
<constant name="struts.custom.i18n.resources" value="aa"></constant>
value 为资源文件的基本名
aa_zh_CN.properties
,aa_en_US.properties
等,对应读取aa开头的资源文件
在 JSP 页面中使用<s:text name=""/>
标签输出国际化信息
<s:text name="user"/>
在表单标签中,通过key属性指定资源文件中的key,value显示
<s:textfield name="realname" key="user"/>
在Action类中,可以继承 ActionSupport,使用getText()方法得到国际化信息,该方法的第一个参数用于指定资源文件中的key。
System.out.println(this.getText("aa"));
System.out.println(this.getText("user"));
示例
I18NAction.java
//package action;
import com.opensymphony.xwork2.ActionSupport;
public class I18NAction extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println(this.getText("aa"));
System.out.println(this.getText("user"));
return SUCCESS;
}
}
aa_en_US.properties
aa=Hello
user=json
aa_zh_CN.properties
aa=你好
user=杰森
structs.xml
<constant name="struts.custom.i18n.resources" value="aa"></constant>
<package name="i18n" namespace="/" extends="struts-default">
<action name="i18n" class="action.I18NAction">
<result >/1.jsp</result>
</action>
</package>
1.jsp
<body>
这里是1.jsp <br/>
<s:text name="user"/><br/>
<s:textfield name="realname" key="user"/>
</body>
国际化—输出带占位符的国际化信息
资源文件中的内容如下:
aa_en_US.properties
aa=Hello
user=json
welcome=hello{0},{1}
aa_zh_CN.properties
aa=你好
user=杰森
welcome=hello{0},{1}
在jsp页面中输出带占位符的国际化信息
<s:text name="welcome">
<s:param>德玛西亚</s:param>
<s:param>勇士长存</s:param>
</s:text>
在Action类中获取带占位符的国际化信息,可以使用getText(String key, String[] args)
或getText(String aTextName, List args)
方法。
示例:
aa_en_US.properties
aa=Hello
user=json
welcome=hello{0},{1}
aa_zh_CN.properties
aa=你好
user=杰森
welcome=hello{0},{1}
1.jsp
<body>
这里是1.jsp <br/>
标签输出:<s:text name="user"/><br/>
表单标签:<s:textfield name="realname" key="user"/><br/>
自定义输出占位符的文字,下面输入什么,就输出什么,与资源文件无关<br/>
<s:text name="welcome">
<s:param>德玛西亚</s:param>
<s:param>勇士长存</s:param>
</s:text>
</body>
I18NAction.java
public class I18NAction extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println(this.getText("aa"));
System.out.println(this.getText("user"));
System.out.println(this.getText("welcome", new String[]{"呆萌","有毒"}));
return SUCCESS;
}
}
控制台输出,由I18NAction输出的内容:
十一月 16, 2016 11:25:52 上午 org.apache.catalina.core.StandardContext reload
信息: Reloading Context with name [/structsi18n] is completed
你好
杰森
hello呆萌,有毒
1.jsp 输出的内容:
国际化—包范围资源文件
在一个大型应用中,整个应用有大量的内容需要实现国际化,如果我们把国际化的内容都放置在全局资源属性文件中,显然会导致资源文件变的过于庞大、臃肿,不便于维护,这个时候我们可以针对不同模块,使用包范围来组织国际化文件。
方法如下:
在java的包下放置package_language_country.properties
资源文件,package为固定 写法,处于该包及子包下的 action 都可以访问该资源。
当查找指定 key 的消息时,系统会先从 package 资源文件查找,当找不到对应的key时,才 会从常量struts.custom.i18n.resources
指定的资源文件中寻找。
例如:
在 action 包下有
package_zh_CN.properties
文件,则action包及其子包下,都可以使用这个资源文件。
国际化—Action范围资源文件
我们也可以为某个 action 单独指定资源文件,方法如下:
在Action类所在的路径,放置
ActionClassName_language_country.properties
资源文件,ActionClassName 为 action 类的简单名称。当查找指定key的消息时,系统会先从
ActionClassName_language_country.properties
资源文件查找,如 果没有找到对应的key,然后沿着当前包往上查找基本名为 package 的资源文件,一直找到最顶层包。如果还没有找到对应的key,最后会从常量struts.custom.i18n.resources
指定的资源文件中寻 找
国际化—JSP中直接访问某个资源文件
struts2为我们提供了<s:i18n>
标签,使用<s:i18n>
标签我们可以在类路径下直接从某个资源文件中获取国际化数据,而无需任何配置:
<s:i18n name="jxust">
<s:text name=“welcome”/>
</s:i18n>
jxust为类路径下资源文件的基本名。
如果要访问的资源文件在类路径的某个包下,可以这样访问:
<s:i18n name=“cn/jxust/action/package">
<s:text name="welcome">
<s:param>江西理工大学</s:param>
</s:text>
</s:i18n>
上面访问cn.jxust.action包下基本名为package的资源文件。
xml中校验配置全局资源与输出国际化信息
接着上面的xml中校验的例子
UserAction-validation.xml
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="username">
<!-- 首先调用trim()方法去掉空格,然后判断用户名是否为空 -->
<field-validator type="requiredstring">
<param name="trim">true</param>
<message key="errors.username"></message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message key="errors.password1"></message>
</field-validator>
<field-validator type="stringlength">
<param name="trim">true</param>
<param name="minLength">4</param>
<param name="maxLength">10</param>
<message key="errors.password2"></message>
</field-validator>
</field>
</validators>
errors_en_US.properties
errors.username=name is null!
errors.password1=password is null!
errors.password2=password length is error!
errors_zh_CN.properties
errors.username=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A\uFF01
errors.password1=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A\uFF01
errors.password2=\u5BC6\u7801\u957F\u5EA6\u89814-10\u4E4B\u95F4\uFF01
structs.xml
需要这个常量
<constant name="struts.custom.i18n.resources" value="errors"></constant>
login.jsp
<body>
<%-- 读取errors.username:<s:text name="errors.username"/><br/> --%>
<%-- 表单标签读取value值<s:textfield name="realname" key="errors.username"/> --%>
<s:fielderror ></s:fielderror>
<form action="user_login.action" method="post">
姓名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
mobile:<input type="text" name="mobile"/><br/>
<input type="submit"value="登录">
</form>
<a href="user_update.action">update</a>
</body>
执行结果:
浏览器为英文的前提下
浏览器为中文