深入分析JavaWeb 46 -- Struts2数据校验与国际化
2016-06-08 10:02
531 查看
1、用户输入数据的校验
1、校验方式
a:客户端校验。(防君子防不了小人)在页面中写js脚本。 这样做的好处是:输入错误的话提醒比较及时;
减轻服务器的压力
b、服务器端校验。
数据安全 ,整个应用阻止非法数据的最后防线
而在实际开发中通常选择:a+b
2、服务器端数据校验:
1、编程式校验:自己Action中编写一个校验代码(缺点:验证规则都写在了代码中)前提:动作类继承ActionSupport,重写Validateable接口中的validate()方法 ,在该方法中完成验证。
步骤如下:
* validate()方法在其他的业务方法之前执行
验证出错转向的页面
struts.xml配置
<result name="input">/validate/login.jsp</result>
其中input转向是在action中已经定义好的.
public static final String INPUT = "input";
什么时候表示验证出错(转向input所指向的页面)
this.addFieldError("sss", "错误信息");方法指向的是一个集合
当集合不为空时,转向错误页面.显示错误Jsp页面: 使用
<s:fielderror/>显示错误消息
1、针对动作类中的所有动作进行校验
编写UserAction继承 ActionSupport,并validate()方法。
package com.itheima.actions; import java.util.Arrays; import org.apache.commons.lang3.StringUtils; import org.apache.struts2.interceptor.validation.SkipValidation; import com.opensymphony.xwork2.ActionSupport; public class UserAction extends ActionSupport { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String add(){ //调用Service try{ System.out.println("保存成功:"+this); return SUCCESS; }catch(Exception e){ e.printStackTrace(); return ERROR; } } //在此处编写校验规则:针对所有的动作方法进行验证 public void validate() { //用户名不能为null或“” if(StringUtils.isEmpty(username)){ addFieldError("username", "用户名不能为空");// Map<String,String>key:字段名,value错误提示 } } @Override public String toString() { return "UserAction [username=" + username + ", password=" + password + ", age=" + age + ", birthday=" + birthday + ", hobby=" + Arrays.toString(hobby) + "]"; } }
在struts.xml中配置action
<package name="p1" extends="struts-default"> <action name="UserAdd" class="com.itheima.actions.UserAction" method="add"> <result>/success.jsp</result> <result name="error">/error.jsp</result> <result name="input">/regist.jsp</result> </action> </package>
分别编写三个简单的页面success.jsp–error.jsp—register.jsp
register.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>用户注册</title> </head> <body> <s:fielderror></s:fielderror> <form action="${pageContext.request.contextPath}/UserAdd.action" method="post"> 姓名:<input type="text" name="username"/><br/> 密码:<input type="text" name="password"/><br/> 年龄:<input type="text" name="age"/><br/> </form> </body> </html>
error.jsp
<body> 服务器忙 </body>
success.jsp
<body> 保存成功 </body>
上述的校验方法对action的所有方法进行校验,如果要校验指定的方法,则要
2、针对指定的动作进行校验
方式一:写了一个validate方法,可以在不需要验证的动作方法前,使用@SkipValidation。比如动作方法add,可以表示为
//@SkipValidation//忽略验证 public String add(){ //调用Service try{ System.out.println("保存成功:"+this); return SUCCESS; }catch(Exception e){ e.printStackTrace(); return ERROR; } }
方式二:validate方法有一定的书写规范。public void validate动作方法名(首字母大写),比如动作方法edit
public String edit(){ return SUCCESS; }
对应的验证方法
//只针对edit动作方法进行验证 public void validateEdit() { //用户名不能为null或“” if(StringUtils.isEmpty(username)){ addFieldError("username", "用户名不能为空,咋不听话呢");// } }
validateXxx()只会校验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写。
底层代码(ValidationInterceptor拦截器)
总结:所有验证不通过或转换不同的过的,框架都会转向
name=”input”的结果视图。要显示错误提示,
使用
<s:fieldError/>,显示字段有关的错误提示
上述的校验的流程:
类型转换器对请求参数执行类型转换,并把转换后的值赋给action中的属性。
如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器将异常信息封装到fieldErrors里,然后执行第3步。如果类型转换没有出现异常,则直接进入第3步。
系统通过反射技术调用action中的validateXxx()方法,Xxx为方法名。
调用action中的validate()方法。
经过上面4步,如果系统中的fieldErrors存在错误信息(即存放错误信息的集合的size大于0),系统自动将请求转发至名称为input的视图。如果系统中的fieldErrors没有任何错误信息,系统将执行action中的处理方法。
2、 声明式校验:通过xml配置文件(方便)
1、针对动作类中的所有动作进行校验在这个校验文件中,对UserAction中字符串类型的username属性进行验证,首先要求调用trim()方法去掉空格,然后判断用户名是否为空。
该文件需要和action类放在同一个包下,文件的取名应遵守ActionClassName-validation.xml规则,其中ActionClassName为action 的简单类名,-validation为固定写法。 例如:如果Action类为cn.msg.validate.UserAction. 那么该文件 的取名应为:UserAction-validation.xml
UserAction-validation.xml为文件的配置如下
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> <validators> <validate> <!-- 写法形式一:可以给一个字段添加好多的验证规则 --> <field name="username"><!-- 验证的字段名 --> <field-validator type="requiredstring"><!-- 不能为空 --> <param name="trim">false</param> <message>用户名不能为空哦</message> </field-validator> <field-validator type="stringlength"><!-- 验证字符串长度的 --> <param name="minLength">3</param> <param name="maxLength">9</param> <message>用户名必须介于${minLength}~${maxLength}之间哦</message> </field-validator> </field> <field name="email"> <field-validator type="email"> <message>请输入正确的邮箱</message> </field-validator> </field> <validator type="expression"> <param name="expression"> password==repassword </param> <message>两次密码必须一致</message> </validator> <!-- 写法形式二:用于非字段性的验证 <validator type="requiredstring"> <param name="fieldName">username</param> <message>用户名不能为空</message> </validator> --> </validators>
**说明:
<validators>: 根元素
<field>:指定action中要校验的属性,name属性指定将被验证的表单字段的名字
<field-validator>:指定校验器, type 指定验证规则
上面指定的校验器requiredstring是由系统提供的,系统提供了能满足大部分验证需求
的校验器,这些校验器的定义可以在xwork-2.x.jar中的
com.opensymphony.xwork2.validator.validators下的default.xml中找到。
<param>:子元素可以向验证程序传递参数
<message>:子元素为校验失败后的提示信息,如果需要国际化,可以为message
指定key属性,key的值为属性文件中的key。
2、针对指定的动作进行校验
方式一:使用@SkipValidation
方式二:声明文件遵循一定的书写规范:
如果你只需要对UserAction中的某个add方法实施校验,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,其中ActionName为struts.xml中action的名称。
UserAction-UserAdd-validation.xml
基于XML校验的一些特点
当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件时,系统按下面顺序寻找校验文件:
1。AconClassName-validation.xml
2。ActionClassName-ActionName-validation.xml
系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于处理方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。
编写校验文件时,不能出现提示信息
在编写ActionClassName-validation.xml校验文件时,如果出现不了帮助信息,可以按下面方式解决:
windwos->preferences->myeclipse->files and editors->xml->xmlcatalog
点“add”,在出现的窗口中的location中选“File system”,然后在xwork-2.1.2解压目录的src\java目录中选择xwork-validator-1.0.3.dtd,回到设置窗口的时候不要急着关闭窗口,应把窗口中的Key Type改为URI 。Key改为http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd
校验器介绍
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>
int:整数校验器
<field-validator type="int"> <param name="min">1</param> <param name="max">150</param> <message>年龄必须在1-150之间</message> </field-validator>
date: 日期校验器
<field-validator type="date"> <param name="min">1900-01-01</param> <param name="max">2050-02-21</param> <message>生日必须在${min}到${max}之间</message> </field-validator>
url: 网络路径校验器
<field-validator type="url"> <message>传智播客的主页地址必须是一个有效网址</message> </field-validator>
email:邮件地址校验器
<field-validator type="email"> <message>电子邮件地址无效</message> </field-validator>
regex:正则表达式校验器
<field-validator type="regex"> <param name="expression"><![CDATA[^13\d{9}$]]></param> <message>手机号格式不正确!</message> </field-validator>
fieldexpression : 字段表达式校验
<field-validator type="fieldexpression"> <param name="expression"><![CDATA[(password==repassword)]]></param> <message>两次密码输入不一致</message> </field-validator>
3、自定义声明式校验
自定义验证程序必须实现 Validator 接口.Validation 拦截器负责加载和执行各种验证程序. 在加载了一个验证程序之后, 这个拦截器将调用那个验证程序的 setValidatorContext 方法, 把当前的 ValidatorContext 对象传递给它, 这使程序员可以访问当前 Action. 接下来, Validation 拦截器将调用 validate 方法并把需要验证的对象传递给它. validate 方法是编写一个自定义的验证程序时需要覆盖的方法.
ValidatorSupport 和 FieldValidatorSupport 实现了 Validator 接口
若需要普通的验证程序, 可以继承 ValidatorSupport 类
若需要字段验证程序, 可以继承 FieldValidatorSupport 类
若验证程序需要接受一个输入参数, 需要为这个参数增加一个相应的属性
案例:验证密码的强度
开发步骤:
1、编写一个StrongPasswordValidator类:实现Validator接口或者继承ValidatorSupport。如果是验证表单字段有关,建议继承FieldValidatorSupport。
package com.itheima.actions; import com.opensymphony.xwork2.validator.ValidationException; import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport; public class StrongPasswordValidator extends FieldValidatorSupport { private int minLength = -1; public int getMinLength() { return minLength; } public void setMinLength(int minLength) { this.minLength = minLength; } //验证方法:针对不符合要求的内容进行判断,向Map中添加信息即可 //参数:object就是当前的动作对象 public void validate(Object object) throws ValidationException { //获取要验证的字段名称 String fieldName = getFieldName(); Object fieldValue = getFieldValue(fieldName, object); if(fieldValue==null) return; if(!isStrong((String)fieldValue)){ addFieldError(fieldName, object); } if((minLength>-1)&&((String)fieldValue).length()<minLength){ // 添加一个消息 addFieldError(fieldName, object); } } //判断s是否强大 private static final String GROUP1 = "abcdefghijklmnopqrstuvwxyz"; private static final String GROUP2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final String GROUP3 = "0123456789"; //判断密码是否强壮:至少一个大写字母、一个小写字母、一个数字 private boolean isStrong(String s) { boolean ok1 = false; boolean ok2 = false; boolean ok3 = false; int length = s.length(); for(int i=0;i<length;i++){ if(ok1&&ok2&&ok3) break; String character = s.substring(i,i+1); if(GROUP1.contains(character)){ ok1 = true; continue; } if(GROUP2.contains(character)){ ok2 = true; continue; } if(GROUP3.contains(character)){ ok3 = true; continue; } } return ok1&&ok2&&ok3; } }
2、要注册校验器
在WEB-INF\classes目录下,建立一个固定名称为validators.xml的配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator Definition 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-definition-1.0.dtd"> <!-- START SNIPPET: validators-default --> <validators> <validator name="strongpassword" class="com.itheima.actions.StrongPasswordValidator"/> </validators>
3、可以像使用requiredstring这样的验证器来使用了
2、Struts2的国际化
之前讲到过国际化ResourceBundle rb = ResourceBundle.getBunle(“message”,Locale);
这里讲在struts2中,先准备资源文件,资源文件的命名格式如下:
baseName_language_country.properties
baseName_language.properties
baseName.properties
其中baseName是资源文件的基本名,我们可以自定义,但language和country必须是java支持的语言和国家。如:
中国大陆:
baseName_zh_CN.properties
美国:
baseName_en_US.properties
现在为应用添加两个资源文件:
第一个存放中文:
msg_zh_CN.properties
hello=\u60A8\u5403\u4E86\u5417\u554A\u6CA1\u5403 username=\u7528\u6237\u540D
第二个存放英语(美国):
msg_en_US.properties
内容为:
hello=good morning username=Username
对于中文的属性文件,我们编写好后,应该使用jdk提供的native2ascii命令把文件转换为unicode编码的文件。命令的使用方式如下:
native2ascii 源文件.properties 目标文件.properties
1、配置全局国际化消息资源包
a、配置全局消息资源包当准备好资源文件之后,我们可以在struts.xml中通过struts.custom.i18n.resources常量把资源文件定义为全局资源文件,如下:
<constant name="struts.custom.i18n.resources" value="msg" />
msg为资源文件的基名。
b、如何访问
在动作类中:
前提,动作类继承ActionSupport
package com.itheima.actions; import com.opensymphony.xwork2.ActionSupport; //在动作类中访问国际化消息 public class I18nAction extends ActionSupport { public String execute(){ String value = getText("hello");// TextProvider System.out.println(value); return SUCCESS; } }
在页面中:
<!-- 取不到,就显示key值 --> <s:text name="hello"></s:text><br/>
或者
<s:textfield key="username"></s:textfield><br/>
自由指定消息资源包,借助struts2的有关国际化的标签:
<s:i18n name="message"><!-- 指定消息资源包的位置 --> <s:text name="hello"></s:text> </s:i18n>
如果消息资源包在
com.itheima.resources.msg_zh_CN.properties
<s:i18n name="com/itheima/resources/message"><!-- 指定消息资源包的位置 --> <s:text name="hello"></s:text> </s:i18n>
2、配置局部消息资源包
一定要经过Action才行:书写规范:在动作类所在包中,建立名字”
动作类名-zh-CN.properties”的配置文件。动作类中访问,发现局部的比全局的优先级高。
3、包范围的消息资源包
也得经过action访问书写有规范的,名称为
package_zh_CN.properties,放在类的包中。可以被包中及子包的所有动作类来访问。
当查找指定key的消息时,系统会先从ActionClassName_language_country.properties资源文件查找,如果没有找到对应的key,然后沿着当前包往上查找基本名为package 的资源文件,一直找到最顶层包。如果还没有找到对应的key,最后会从常量
struts.custom.i18n.resources指定的资源文件中寻找。
顺序如下
相关文章推荐
- 根据Java对象获取里面的方法,属性
- 图解用tree命令研究Windows目录、.net目录、项目目录、JDK目录
- Java编程体验:线程的7种状态及相互转换(图)
- Java-线程
- Spring学习之路
- 深入分析JavaWeb 45 -- Struts2封装请求参数与类型转换
- Java设计模式透析之 —— 单例(Singleton)
- Java for循环写法效率
- 深入分析JavaWeb 44 -- Struts2开发核心之动作类Action
- spring+hibernate进行线程操作时异常:save is not valid without active transaction
- eclipse shift+ctrl +f 格式化失败
- rxJava Schedulers Use Cases
- 深入分析JavaWeb 43 -- Struts2开发入门
- 一张图让你看懂JAVA线程间的状态转换
- java线程之中断线程Interrupted用法
- MyEclipse快捷键大全
- struts2复习1
- Key Components and Internals of Spring Boot Framework--转
- Spring2.5中使用注解装配属性
- 成为Java高手的25个学习要点