Struts 2 讲义(5)
--Struts2特性
一、国际化
国际化的步骤:
1)建立一个中文资源文件,globalMessages.properties。用文本编辑器输入,内容如下:
#定义国际化资源文件
HelloWorld=你好,世界!
name=用户名称
pass=用户密码
username=用户名
password1=密码
password2=确认密码
birthday=生日
2)在Dos中执行下面命令:
native2ascii globalMessages.properties
globalMessages_zh_CN.properties
3)中文资源文件名:globalMessages_zh_CN.properties。转换内容为:
#\u5b9a\u4e49\u56fd\u9645\u5316\u8d44\u6e90\u6587\u4ef6
HelloWorld=\u4f60\u597d\uff0c\u4e16\u754c\uff01
name=\u7528\u6237\u540d\u79f0
pass=\u7528\u6237\u5bc6\u7801
username=\u7528\u6237\u540d
password1=\u5bc6\u7801
password2=\u786e\u8ba4\u5bc6\u7801
birthday=\u751f\u65e5
4)建立一个英文资源文件内容为:globalMessages_en_US.properties HelloWorld=Hell World!
name=username
pass=password
username=Your Name
password1=Password
password2=confirm Password
birthday=Birthday
5)上述两个文件保存到WEB-INF\classes目录中
6)创建struts.properties 中,保存到WEB-INF\classes目录下,内容如下:
struts.custom.i18n.resources=globalMessages
7)创建reg.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
8)创建reg_ok_local.jsp代码如下所示:
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
欢迎
9)创建Reg.java
p ackage com.my.inter;
import java.util.Date;
import com.opensymphony.xwork2.Action;
public class Reg implements Action {
private String username;
private String password1;
private String password2;
private Date birthday;
public Reg(){
}
public String getUsername() {
return username;
}
public void setUsername(String username) { https://www.doczj.com/doc/a13203606.html,ername = username;
}
public String getPassword1() {
return password1;
}
public void setPassword1(String password1) { this.password1 = password1;
}
public String getPassword2() {
return password2;
}
public void setPassword2(String password2) { this.password2 = password2;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) { this.birthday = birthday;
}
public String execute() throws Exception {
return SUCCESS;
}
}
9)配置struts.xml
执行结果如下:
改进reg_tag.jsp
Struts2 可以在label值中访问国际化资源文件。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %>
运行结果如下图所示:
二、数据校验
1.输入校验简介
在Web 系统项目中有大量的视图页面需要用户自行输入很多数据。这些数据的类型有很多种。为了防止某些客户的恶意输入以及对Web 项目的恶意破坏。必须引入输入校验像Windows 操作系统中的防火墙一样把一些“垃圾”数据过滤,挡在Web 系统之外。Struts2 的输入校验是以类型转换为基础。而且输入校验一般和Web 系统的业务逻辑息息相关。
1.使用validate方法进行校验
Struts2 对输入校验这方面采用的最基本方法是在每个Action 里继承ActionSupport 类,并且重写它的输入校验方法validate()。在注册页面中输入各种校验将所有不符合输入校验规则的错误信息都由ActionSupport 类中另一个方法addFieldError 方法将错误信息加入到表单错误信息,并且在输入数据的页面显示,而不会再由Action 导航到注册成功页面。【例3-4】使用validate方法进行校验实例。
⑴注册页面:register.jsp
<%@ page language="java" pageEncoding="gb2312"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
⑵注册控制类:RegisterAction.java
package https://www.doczj.com/doc/a13203606.html,it;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Date;
public class RegisterAction extends ActionSupport {
// Action类公用私有变量,用来做页面导航标志
private static String FORWARD = null;
private String username; // 用户名属性
private String password; // 密码属性
private String repassword; // 确认密码属性
private Date birthday; // 生日属性
private String mobile; // 手机号码属性
private int age; // 年龄属性
public String getUsername() { // 取得用户名值
return username;
}
public void setUsername(String username) { // 设置用户名值
https://www.doczj.com/doc/a13203606.html,ername = username;
}
public String getPassword() { // 取得密码值
return password;
}
public void setPassword(String password) { // 设置密码值
this.password = password;
}
public String getRepassword() { // 取得确认密码值
return repassword;
}
public void setRepassword(String repassword) { // 设置确认密码值this.repassword = repassword;
}
public Date getBirthday() { // 取得生日值
return birthday;
}
public void setBirthday(Date birthday) { // 设置生日值
this.birthday = birthday;
}
public String getMobile() { // 取得手机号码值
return mobile;
}
public void setMobile(String mobile) { // 设置手机号码值
this.mobile = mobile;
}
public int getAge() { // 取得年龄值
return age;
}
public void setAge(int age) { // 设置年龄值
this.age = age;
}
public String execute() throws Exception { // 执行注册方法FORWARD = "success";
return FORWARD;
}
public void validate() { // 校验方法,用来输入校验
// 校验是否输入用户名
if (getUsername() == null || getUsername().trim().equals("")) { addFieldError("username", "请输入用户名");
}
// 校验是否输入生日
if(getBirthday()==null){
addFieldError("birthday", "请输入生日日期");
}else
// 校验是否输入正确的生日日期
if(getBirthday().after(new Date())){
addFieldError("birthday", "请不要输入未来日期");
}
// 校验是否输入密码
if (getPassword() == null || getPassword().trim().equals("")) { addFieldError("password", "请输入密码");
}
// 校验是否输入确认密码
if (getRepassword() == null || getRepassword().trim().equals("")) { addFieldError("repassword", "请输入确认密码");
}
// 校验输入的密码和确认密码是否一致
if (!getPassword().equals(getRepassword())) {
addFieldError("repassword", "确认密码和密码输入不一致");
}
// 校验输入的手机号码长度是否正确
if (getMobile().length()!=11) {
addFieldError("mobile", "请输入正确的手机号码");
}
// 校验输入的年龄是否正确
if (getAge()<1||getAge()>99) {
addFieldError("age", "请输入您的真实年龄");
}
}
}
⑶注册成功页面:register1.jsp
<%@ page language="java" pageEncoding="gb2312"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
运行结果如图3-8、3-9所示。
图3-8没有输入数据校验
图3-9 校验输入密码不一致
2.使用validateXXX方法进行校验
Struts2 中除了validate 方法之外它还有一种validateXXX 方法针对Action 中某一特定方法进行各种字段的输入校验。其中XXX 就是该特定方法名。
【注】:如果使用validateRegister 方法,那最好不要再使用validate 方法。validate 方法是对所有Action 中方法的输入校验都进行校验,validateRegister 方法只对Register 方法进行校验。因此两者不能重复使用,都使用会造成两个方法都进行了校验的结果。执行顺序是先
validateRegister后validate。如果validateRegister 方法有特殊的输入校验则就会被validate 方法“覆盖”,因此达不到预期的输入校验目的。
【例3-5】使用validateXXX方法进行校验实例。
⑴注册页面:register1.jsp
<%@ page language="java" pageEncoding="gb2312"%>
<%@taglib prefix="s" uri="/struts-tags"%>
⑵注册控制类:RegisterAction1.java
package https://www.doczj.com/doc/a13203606.html,it;
import java.util.Date;
import com.opensymphony.xwork2.ActionSupport;
public class RegisterAction1 extends ActionSupport {
private static String FORWARD = null;
private String username; // 用户名属性
private String password; // 密码属性
private String repassword; // 确认密码属性
private Date birthday; // 生日属性
private String mobile; // 手机号码属性
private int age; // 年龄属性
public String getUsername() { // 取得用户名值
return username;
}
public void setUsername(String username) { // 设置用户名值
https://www.doczj.com/doc/a13203606.html,ername = username;
}
public String getPassword() { // 取得密码值
return password;
}
public void setPassword(String password) { // 设置密码值this.password = password;
}
public String getRepassword() { // 取得确认密码值
return repassword;
}
public void setRepassword(String repassword) { // 设置确认密码值this.repassword = repassword;
}
public Date getBirthday() { // 取得生日值
return birthday;
}
public void setBirthday(Date birthday) { // 设置生日值
this.birthday = birthday;
}
public String getMobile() { // 取得手机号码值
return mobile;
}
public void setMobile(String mobile) { // 设置手机号码值this.mobile = mobile;
}
public int getAge() { // 取得年龄值
return age;
}
public void setAge(int age) { // 设置年龄值
this.age = age;
}
// 执行注册方法
public String Register() throws Exception {
FORWARD = "success";
return FORWARD;
}
public void validateRegister() { // 校验方法,用来输入校验// 校验是否输入用户名
if (getUsername() == null || getUsername().trim().equals("")) { addFieldError("username", "请输入用户名");
}
// 校验是否输入生日
if (getBirthday() == null) {
addFieldError("birthday", "请输入生日日期");
} else
// 校验是否输入正确的生日日期
if (getBirthday().after(new Date())) {
addFieldError("birthday", "请不要输入未来日期");
}
// 校验是否输入密码
if (getPassword() == null || getPassword().trim().equals("")) { addFieldError("password", "请输入密码");
}
// 校验是否输入确认密码
if (getRepassword() == null || getRepassword().trim().equals("")) { addFieldError("repassword", "请输入确认密码");
}
// 校验输入的密码和确认密码是否一致
if (!getPassword().equals(getRepassword())) {
addFieldError("repassword", "确认密码和密码输入不一致");
}
if (getMobile().length() != 11) { // 校验输入的手机号码长度是否正确
addFieldError("mobile", "请输入正确的手机号码");
}
if (getAge() < 1 || getAge() > 99) { // 校验输入的年龄是否正确
addFieldError("age", "请输入您的真实年龄");
}
}
}
运行结果如图3-10所示。
图3-10 validateXXX方法校验没有输入数据
2.使用Struts2框架校验
Struts2框架提供了一种基于框架文件的输入校验方式,将校验规则保存在特定的框架
文件中,这样就使输入校验同Action实现分离,提高了系统的维护性。
Struts2使用配置文件来完成输入校验方式步骤:首先在Action 代码中去除所有validate与validateXXX 方法的代码。然后在和Action 类文件同一级目录下增加XXX-validation.xml 配置文件。这里“XXX ”是Action 类文件名字,表示该XML 文件中所有输入校验的规则定义和错误信息显示方式都只针对该Action 有效。
1.Struts2 字段校验
Struts2字段校验是在
【例3-6】使用Struts2字段校验实例。
(1)注册页面:register2.jsp
<%@ page language="java" pageEncoding="gb2312"%>
<%@taglib prefix="s" uri="/struts-tags"%>
(2)注册控制类:RegisterAction2.java
package https://www.doczj.com/doc/a13203606.html,it;
import java.util.Date;
import com.opensymphony.xwork2.ActionSupport;
public class RegisterAction2 extends ActionSupport {
private static String FORWARD = null;
private String username; // 用户名属性
private String password; // 密码属性
private String repassword; // 确认密码属性
private Date birthday; // 生日属性
private String mobile; // 手机号码属性
private int age; // 年龄属性
public String getUsername() { // 取得用户名值
return username;
}
public void setUsername(String username) { // 设置用户名值https://www.doczj.com/doc/a13203606.html,ername = username;
}
public String getPassword() { // 取得密码值
return password;
}
public void setPassword(String password) { // 设置密码值
this.password = password;
}
public String getRepassword() { // 取得确认密码值
return repassword;
}
public void setRepassword(String repassword) { // 设置确认密码值this.repassword = repassword;
}
public Date getBirthday() { // 取得生日值
return birthday;
}
public void setBirthday(Date birthday) { // 设置生日值
this.birthday = birthday;
}
public String getMobile() { // 取得手机号码值
return mobile;
}
public void setMobile(String mobile) { // 设置手机号码值
this.mobile = mobile;
}
public int getAge() { // 取得年龄值
return age;
}
public void setAge(int age) { // 设置年龄值
this.age = age;
}
// 执行注册方法
public String Register() throws Exception {
FORWARD = "success";
return FORWARD;
}
}
(3)字段校验配置文件:RegisterAction2-validation.xml
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"https://www.doczj.com/doc/a13203606.html,/xwork/xwork-validator-1.0.2.dtd">
6
8
6
8
6
8
password==repassword
1928-01-01
2004-01-01
11
1
80
运行结果与例3-5相似。
2. Struts2 非字段校验
非字段格式的输入校验方式与上字段校验相比主要是它的书写格式不是像之前在
在
【例3-7】使用Struts2非字段校验实例。
⑴注册页面与注册控制类与例3-5一致。
⑵非字段校验配置文件:RegisterAction3-validation.xml
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"https://www.doczj.com/doc/a13203606.html,/xwork/xwork-validator-1.0.2.dtd">
username
6
8
username
password
6
8
password
repassword
6
8
repassword
password
repassword
password==repassword
birthday
birthday
1928-01-01
2004-01-01
mobile
mobile
age
age
1
80
三、拦截器
1.1.1拦截器简介
拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
拦截器(Interceptor)是动态拦截Action调用的对象,类似于Servlet中的过滤器。在执行Action的业务逻辑处理方法(execute())之前,Struts2会首先执行在struts.xml中引用的拦截器。拦截器是struts2的一个重要特性。Struts2框架的大多数核心功能都是通过拦截器来实现的,如避免表单重复提交、类型转换、对象组装、验证、文件上传等,都是在拦截器的帮助下实现的。
拦截器之所以称为“拦截器”,是因为它可以在Action执行之前和执行之后拦截调用。Struts2将它的核心功能放到拦截器中实现,而不是分散到Action中实现,有利于系统的解耦,使得功能的实现类似于个人电脑的组装,变成了可插拔的,需要某个功能就“插入”一个拦截器,不需要某个功能就“拔出”一个拦截器。你可以任意组合拦截器来为Action提供附加的功能,而不需要修改Action的代码。拦截器围绕着Action和Result的执行,其工作方式如图3-1所示。
图3-1 Struts2拦截器工作方式
从图中可以看到,在Action和Result执行之前,为Action配置的拦截器将首先被执行,在Action和Result执行之后,拦截器将重新获得控制权,然后按照与先前调用相反的顺序依次执行。在整个执行过程中,任何一个拦截器都可以选择直接返回,从而终止余下的拦截器、Action和Result的执行。例如:当一个未授权的用户访问受保护的资源时,执行身份验证的拦截器可以直接返回。
1.1.2Struts2拦截器
Struts2内置了大量的拦截器,这些拦截器以name-class对的形式配置在struts-default.xml 文件中,其中name是拦截器的名字,就是以后使用该拦截器的唯一标识;class则指定了该拦截器的实现类,如果定义的package继承了Struts2的struts-default包,则可以自由使用下面定义的拦截器,否则必须自己定义这些拦截器。
表3-1 Struts2内置拦截器
大部分时候,开发者无需手动控制这些拦截器,因为struts-default.xml文件中已经配置了这些拦截器,只要我们定义的包继承了系统的struts-default包,就可以直接使用这些拦截器。
1.定义拦截器
Struts2 拦截器定义格式为:
参数A初始化值
参数B初始化值
……
2.拦截器栈
拦截器栈:就是由多个拦截器组成的一个拦截器组,来实现一个特定的拦截功能。例如,可以可以将用户安全认证拦截器、日志拦截器、密码加密组成一个拦截器栈,在一个业务控制Action执行之前使用,比如用户注册Action,在执行该Action前来执行该拦截器栈,进行一系列公共功能方面的处理。
拦截器栈的定义:
在拦截器栈定义的
3.编写拦截器类
在struts2中要编写拦截器类,必须实现com.opensymphony.xwork2.interceptor.Interceptor 接口,该接口定义了如下的三个方法:
●void init():该方法在拦截器实例创建后、intercept()方法被调用之前调用,用于初始
化拦截器所需要的资源,例如数据库连接的初始化。该方法只执行一次。
●void destroy():该方法在拦截器实例被销毁之前调用,用于释放在init()方法中分配
的资源。该方法只执行一次。
●String intercept(ActionInvocation invocation) throws Exception:该方法在Action执行
之前被调用,拦截器为Action提供的附加功能在该方法中实现。利用invocation参
数,可以获取action执行的状态。在intercept()方法中,如果要继续执行后续的部分(包
括余下的应用于Action的拦截器、Action和Result),可以调用invocation.invoke()。
如果要终止后续的执行,可以直接返回一个结果码,框架将根据这个结果码来呈现
对应的结果视图。
【例3-1】HelloWorld拦截器实例。
⑴建立一个业务控制器Reg
Reg.java
package https://www.doczj.com/doc/a13203606.html,it;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Date;
public class Reg extends ActionSupport{
private String username; //用户名
private String password1; //密码
private String password2; //确认密码
private Date birthday; //生日
public Date getBirthday() {