首页 > 代码库 > Struts2学习三

Struts2学习三

一,自定义拦截器:

1>,实现Interceptor接口:

com.opensymphony.xwork2.interceptor.Interceptor接口的 Java:

?init: 该方法将在拦截器被创建后立即被调用, 它在拦截器的生命周期内只被调用一次. 可以在该方法中对相关资源进行必要的初始化 

?interecept: 每拦截一个动作请求, 该方法就会被调用一次

?destroy: 该方法将在拦截器被销毁之前被调用, 它在拦截器的生命周期内也只被调用一次.


Struts 会依次调用程序员为某个 Action 而注册的每一个拦截器的 interecept 方法. 

每次调用 interecept 方法时, Struts 会传递一个 ActionInvocation 接口的实例.

ActionInvocation: 代表一个给定动作的执行状态, 拦截器可以从该类的对象里获得与该动作相关联的 Action 对象和 Result 对象. 在完成拦截器自己的任务之后, 拦截器将调用 ActionInvocation 对象的 invoke 方法前进到 Action 处理流程的下一个环节

还可以调用 ActionInvocation 对象的 addPreResultListener 方法给 ActionInvocation 对象 “挂” 上一个或多个 PreResultListener 监听器. 该监听器对象可以在动作执行完毕之后, 开始执行动作结果之前做些事情 

AbstractInterceptor 类实现了 Interceptor 接口. 并为 init, destroy 提供了一个空白的实现

自定义拦截器代码:

import java.util.Map;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

/**
 * 自定义拦截器,需要实现Interceptor接口
 */
@SuppressWarnings("serial")
public class PerssionInterceptor implements Interceptor {
	public PerssionInterceptor(){
	   System.out.println("PerssionInterceptor的构造方法");
	}
	
	/**
	 * 在拦截器的生命周期中,调用1次
	 */
	public void init() {
       System.out.println("PerssionInterceptor init方法");
	}
	/**
	 * 在拦截器的生命周期中,调用n次
	 * ActionInvocation:保存struts2运行时的上下文信息,有struts2运行自动注入
	 */
	public String intercept(ActionInvocation invocation) throws Exception {
		System.out.println("PerssionInterceptor intercept方法");
		
		System.out.println(" invocation.getAction()   "+invocation.getAction());
		System.out.println(" invocation.getProxy()   "+invocation.getProxy());
		System.out.println(" invocation.getProxy().getActionName()   "+invocation.getProxy().getActionName());
		System.out.println(" invocation.getProxy().getMethod()   "+invocation.getProxy().getMethod());
		System.out.println(" invocation.getProxy().getNamespace()  "+invocation.getProxy().getNamespace());
	
		//获取session
		Map sessionMap=invocation.getInvocationContext().getSession();
		Object obj=sessionMap.get("user");
		if(obj==null){
			// <result name="error">/aop/error.jsp</result>
			return "error";
		}
		
		
		//调用action中的方法
		String returnvalue=http://www.mamicode.com/invocation.invoke();"returnvalue  "+returnvalue);
		
		//<result name="success">/aop/success.jsp</result>
		return returnvalue;
	}
	/**
	 * 在拦截器的生命周期中,调用1次
	 */
	public void destroy() {
		 System.out.println("PerssionInterceptor destroy方法");
	}
}


在struts.xml中配置自定义拦截器:

<?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
	"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>  
  <package name="aop" namespace="/aop" extends="struts-default">
     
     <interceptors>
            <!-- 声明自定义的拦截器 -->
            <interceptor name="perssionInterceptor" class="cn.yujian.aop.PerssionInterceptor" />
            <!-- 声明新的拦截器栈 -->
            <interceptor-stack name="perssionStack">
            
                <!--因为struts2中如文件上传,数据验证,封装请求参数到action等
                    功能都是由系统默认的defaultStack中的拦截器实现的,所以
                    我们定义的拦截器需要引用系统默认的defaultStack,这样应用才
                    可以使用struts2框架提供的众多功能。 
                    如果希望包下的所有action都使用自定义的拦截器,
                    可以通过<default-interceptor-ref name=“perssionStack”/>
                    把拦截器定义为默认拦截器。注意:每个包只能指定一个默认拦截器。
                    另外,一旦我们为该包中的某个action显式指定了某个拦截器,
                    则默认拦截器不会起作用。-->
                <interceptor-ref name="defaultStack"/>
                <!-- 在拦截器栈中加入自定义的拦截器 -->
                <interceptor-ref name="perssionInterceptor"/>
            </interceptor-stack>
     </interceptors>
     
     <!-- 配置struts2框架运行时,真正要执行的拦截器栈 -->
     <default-interceptor-ref name="perssionStack"/>
     
     <action name="userAction_*" class="cn.yujian.aop.UserAction" method="{1}">
     
         <!—只对当前的action有效-->       
        <interceptor-ref name="perssionStack"></interceptor-ref>   
             
        <result name="success">/aop/success.jsp</result>
        <result name="error">/aop/error.jsp</result>
     </action>
  </package>
</struts>


二,struts2验证:

struts2校验有两种实现方法:

1,手工编写代码实现(基本验证)

2,基于XML配置方式实现(验证框架)


1>手工验证: 

jsp代码:

<%@ page language="java"  pageEncoding="UTF-8" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<html>
  <head>    
    <title>My JSP ‘login.jsp‘ starting page</title>
  </head>
  <body>
  <br>
      <s:form  id="loginForm"  name="loginForm" method="post"  namespace="/validate"  
               action="validateAction_login.action" theme="simple">
         <table border="1">
           <tr>
              <td>用户名</td>
              <td> <s:textfield name="username" /><s:fielderror fieldName="username" /></td>
           </tr>
           <tr>
              <td>密码</td>
              <td><s:password name="psw" /><s:fielderror fieldName="psw" /></td>
           </tr>
           <tr>
              <td>&nbsp;</td>
              <td><s:submit value="http://www.mamicode.com/登陆"/></td>
           </tr>
         </table>
     </s:form>
  </body>
  
  <a href="http://www.mamicode.com/${pageContext.request.contextPath}/validate/validateAction_test.action">test其他的方法</a>
  
</html>


2>,在Action中重写Validateable接口中的validate()方法 ;

validate()方法在其他业务之前 执行,

java代码:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class ValidateAction extends ActionSupport {
	
	private String username;//和form表单中的字段name想对应
	private String psw;

	public void setUsername(String username) {//设置属性值的操作都是struts2来完成的
		System.out.println("1 setUsername方法 "+username);
		this.username = username;
	}
	
	@Override
	public void validate() {
	   System.out.println("2 执行validate方法");
	   if(username==null||"".equals(this.username.trim())){
	       this.addFieldError("username","用户名不能为空");
	   }
	   
	   if(psw==null||"".equals(this.psw.trim())){
	       this.addFieldError("psw","密码不能为空");
	   }else{
		   
		   //编译正则  
		   Pattern p = Pattern.compile("^[a-zA-Z0-9]{6,12}$");
		   Matcher m = p.matcher(this.psw);
		   boolean b = m.matches();
		   if(!b){
			   this.addFieldError("psw","密码的长度6-12之间");
		   }
	   }
	}
	
	public String login(){
        System.out.println("3 执行login方法");		
		return "success";
	}
	
	public void validateTest(){
        System.out.println("3 执行test方法");		
	}
	
	public String test(){
        System.out.println("3 执行test方法");		
		return "success";
	}
	public void setPsw(String psw) {
		this.psw = psw;
	}
	
	public String getPsw() {
		return psw;
	}
	public String getUsername() {
		return username;
	}

}

方法执行顺序:

1 setUsername方法 5dd

2 执行validate方法

3 执行login方法

struts.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
	"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>  
  <package name="validate" namespace="/validate" extends="struts-default">
     <action name="validateAction_*" class="cn.yujian.validate.ValidateAction" method="{1}">
        <result name="success">/validate/success.jsp</result>
        <result name="error">/validate/error.jsp</result>
        <!-- input表示表单验证出错要转向的页面 -->
        <result name="input">/validate/login.jsp</result>
     </action>
  </package>
</struts>

默认请求下validate()方法对所有方法进行验证。

如果想要对action中的指定方法进行校验,需要在validate后面加上需要校验的方法名称,方法名第一个字母大写,例如:validateLogin()  对上面的login方法进行校验

代码:

public void validateLogin() {
	   System.out.println("2 执行validate方法");
	   if(username==null||"".equals(this.username.trim())){
	       this.addFieldError("username","用户名不能为空");
	   }
	   
	   if(psw==null||"".equals(this.psw.trim())){
	       this.addFieldError("psw","密码不能为空");
	   }else{
		   
		   //编译正则  
		   Pattern p = Pattern.compile("^[a-zA-Z0-9]{6,12}$");
		   Matcher m = p.matcher(this.psw);
		   boolean b = m.matches();
		   if(!b){
			   this.addFieldError("psw","密码的长度6-12之间");
		   }
	   }
	}


2>XML框架验证 :

验证文件的规范在xwork-core-2.1.6.jar/xwork-validator-1.0.3.dtd文件;

验证规则的配置文件 xwork-core-2.1.6.jar\com\opensymphony\xwork2\validator\validators\default.xml;

在校验的Action包下创建一个xml文件,命名必须遵守规则:Action-validation.xml 文件,本例中是:ValidateXmlAction-validation.xml,其中-validation为固定写法

xml代码如下:

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE validators PUBLIC
  		"-//OpenSymphony Group//XWork Validator 1.0.3//EN"
  		"http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
 <validators>
    <!--
        field表示验证的action中的属性  
        field-validator:声明校验器
           * type:表示校验规则 requiredstring对应的是
                  com.opensymphony.xwork2.validator.validators.RequiredStringValidator
           * <param name="trim">true</param> 去掉username两端的空格
                    调用RequiredStringValidator类中的setTrim(true)方法
           * message:验证出错的提示信息.
    -->
    <field name="username">
       <field-validator type="requiredstring">
         <param name="trim">true</param>
         <message>用户名不能为空</message>
       </field-validator>
    </field>
    
    <field name="psw">
       <field-validator type="requiredstring">
         <param name="trim">true</param>
         <message>密码不能为空</message>
       </field-validator>
       
       <field-validator type="regex">
         <param name="expression"><![CDATA[^[a-zA-Z0-9]{6,12}$]]></param>
         <message><![CDATA[密码的长度应该在6-12为之间]]></message>
       </field-validator>
    </field>
 </validators>

先用<field>标签描述要校验的字段,里面定义校验器使用<field-vaidator>标签,这个标签中有个type 属性,这个属性指是就是校验规则,比如:requiredstring  就代表必填表的字符串,表明这个信息是用户必须输入的。需要注意的是type属性不是随便写的,这个名字会对应struts2 提供的各样校验器类。我们查找strust2 原代码会在xwork jar包中的com.opensymphony.xwork2.validator.validators包下面找到一个default.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">
<!-- START SNIPPET: validators-default -->
<validators>
    <validator name="required"class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
    <validator name="requiredstring"class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>
    <validator name="int"class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>
    <validator name="double"class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>
    <validator name="date"class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>
    <validator name="expression"class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>
    <validator name="fieldexpression"class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>
    <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>
    <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>
    <validator name="visitor"class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>
    <validator name="conversion"class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>
    <validator name="stringlength"class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>
    <validator name="regex"class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>
</validators>


struts.xml代码:

<?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
	"http://struts.apache.org/dtds/struts-2.1.7.dtd">
<struts>  
  <package name="validate" namespace="/validate" extends="struts-default">
     <action name="validateXmlAction_*" class="cn.yujian.validate.ValidateXmlAction" method="{1}">
        <result name="success">/validate/success.jsp</result>
        <result name="error">/validate/error.jsp</result>
        <!-- input表示表单验证出错要转向的页面 -->
        <result name="input">/validate/loginxml.jsp</result>
     </action>
     
  </package>
</struts>


Action代码:

import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class ValidateXmlAction extends ActionSupport {
	
	private String username;
	private String psw;

	public void setUsername(String username) {
		this.username = username;
	}
	
	public String login(){
        System.out.println("执行login方法");		
		return "success";
	}
	
	public String test(){
        System.out.println("执行test方法");		
		return "success";
	}
	
	public void setPsw(String psw) {
		this.psw = psw;
	}
	
	public String getPsw() {
		return psw;
	}
	public String getUsername() {
		return username;
	}

}

当校验文件的取名为ActionClassName-validation.xml时,会对 action中的所有处理方法实施输入验证。 如果你只需要对action中的某个action方法实施校验,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,其中ActionName为struts.xml中action的名称。

ActionClassName:action的类名

ActionName:当前请求的action的名称

 -validation.xml:固定写法

本例:如果是登陆

ValidateXmlAction-validateXmlAction_login-validation.xml,其他都一样;


当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件时,系统按下面顺序寻找校验文件:

1。AconClassName-validation.xml

2。ActionClassName-ActionName-validation.xml

系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于处理方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。


当action继承了另一个action,父类action的校验文件会先被搜索到。假设UserAction继承BaseAction, UserAction在struts.xml的配置如下:

<action name="user" class="cn.itcast.action.UserAction" method="{1}">

.....

</action>

访问上面名为user的action,系统先搜索到BaseAction-validation.xml, BaseAction-user-validation.xml,接着搜索到UserAction-validation.xml, UserAction-user-validation.xml。校验规则是这四个文件的总和。    


下面对校验器进行说明:

required: 确保某给定字段的值不是空值 null 

requiredstring: 确保某给定字段的值既不是空值 null, 也不是空白.

    ?trim 参数. 默认为 true, 表示 struts 在验证该字段值之前先剔除前后空格

stringlength: 验证一个非空的字段值是不是有足够的长度

    ?minLength: 相关字段的最小长度. 若没有给出这个参数, 该字段将没有最小长度限制                      ?maxLength:相关字段的最大长度. 若没有给出这个参数, 该字段将没有最大长度限制 

     ?trim: 在验证之前是否去除前后空格 

int: 检查给定字段的值是否可以被转换为一个整数 

    ?min: 相关字段的最小值. 若没给出这个参数, 该字段将没有最小值限制 

    ?max: 相关字段的最大值. 若没给出这个参数, 该字段将没有最大值限制

date: 确保某给定日期字段的值落在一个给定的范围内 

    ?max:相关字段的最大值. 若没给出这个参数, 该字段将没有最大值限制

    ?min:相关字段的最小值. 若没给出这个参数, 该字段将没有最小值限制 

email: 检查给定 String 值是否是一个合法的 email 

url: 检查给定 String 值是否是一个合法的 url 

regex: 检查某给定字段的值是否与一个给定的正则表达式模式相匹配

    ?expresssion*: 用来匹配的正则表达式 

    ?caseSensitive: 是否区分字母的大小写. 默认为 true         

    ?trim: 是否去除前后空格. 默认为 true

conversion(转换校验器,指定在类型转换失败时,提示的错误信息)

visitor(用于校验action中的复合属性,它指定一个校验文件用于校验复合属性中的属性) expression(OGNL表达式校验器,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过,该校验器不可用在字段校验器风格的配置中) 

double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)


校验器示例:

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>


字段OGNL表达式校验器

<field name="imagefile">

  <field-validator type="fieldexpression">

  <param name="expression"><![CDATA[imagefile.length() <= 0]]></param>

  <message>文件不能为空</message>

  </field-validator>

</field>


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>





Struts2学习三