拦截器笔记

http://struts.apache.org/2.0.11/docs/interceptors.html

AOP通过拦截来实现关注点织入(Weaving),一般拦截一个方法可以采用回调方法或者动态代理。动态代理至少需要实现两个类:一个代理,一个被代理(都要实现共有接口)。代理类是通过java.lang.reflect.Proxy来的到的。

  Action的调用都是通过拦截器来实现的。

HelloWorld拦截器

配置

<interceptors>
   <interceptor name="Myinterceptor"
    class="Myintercepor">
   </interceptor>

>

<action name="Reg" class="Reg">
   <result name="success/success.jsp</result>
   <result name="input">/reg.jsp</result>
   <interceptor-ref name="defaultStack"></interceptor-ref>
   <interceptor-ref name="MyInterceptor"></interceptor-ref>
  </action>

 

拦截器类

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

public class Myintercepor extends AbstractInterceptor {

 public String intercept(ActionInvocation arg0) throws Exception {
  // TODO Auto-generated method stub
  Reg reg = (Reg) arg0.getAction();
  System.out.println("拦截器信息:HelloWorld拦截器!");
  // 执行Action或者执行下一个拦截器
  String result = arg0.invoke();
  // 提示Action执行完毕
  System.out.println("拦截器信息:Action执行完毕!");
  return result;
 }

}

业务控制器Reg

import java.util.Date;

import com.opensymphony.xwork2.ActionSupport;

public class Reg extends ActionSupport {

 // 定义用户名属性
 private String username;
 // 定义处理信息:注意同http中的msg不同名称
 private String mymsg;
 // 定义密码属性
 private String password1;
 // 定义确认密码
 private String password2;
 // 定义生日属性
 private Date birthday;

 public String execute() throws Exception {

  if (username != null && getPassword1().equals(getPassword2())
    && !getUsername().trim().equals("")) {
   System.out.println("Action信息:正在执行Actiion... ...");
   return SUCCESS;
  } else {
   System.out.println("Action信息:没有用户参数,返回input");
   return INPUT;
  }

 }

 public String getUsername() {
  return username;
 }

 public void setUsername(String username) {
  this.username = username;
 }

 public String getMymsg() {
  return mymsg;
 }

 public void setMymsg(String mymsg) {
  this.mymsg = mymsg;
 }

 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;
 }

}

reg.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>用户注册</title>
<s:head />
</head>
<body>
<table>
<s:form id="id" action="Reg">
    <s:textfield name="username" label="用户名:"/>
    <s:password name="password1" label="密码:"/>
    <s:password name="password2" label="确认密码:"/>
    <s:datetimepicker name="birthday" label="生日:"/>
    <s:submit value="注册"/>
</s:form>
</table>
</body>
</html>

 

  自定义拦截器

 

Struts 2 框架提供import com.opensymphony.xwork2.interceptor.AbstractInterceptor类,继承该类,就可以定义自己的拦截器,该类定义了init(),destory(),intercept(ActionInvocation invocation),如果不需要加在一些特殊的系统资源,可以不用实现init(),destory().

<!--自定义拦截器-->

 

<interceptors>
     <interceptor name="simpleInterceptor"
    class="simpleInterceptor">
   </interceptor>

</interceptors>

   <action name="Reg" class="Reg">
   <result name="success">/success.jsp</result>
   <result name="input">/reg.jsp</result>
   <interceptor-ref name="defaultStack"></interceptor-ref><!--不能少-->
   <interceptor-ref name="simpleInterceptor"></interceptor-ref>
  </action>

自定义拦截器实现类

import java.util.Date;

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

public class simpleInterceptor extends AbstractInterceptor {

 //重写intercept方法
 public String intercept(ActionInvocation arg0) throws Exception {
  //获得被拦截的Action引用
  Reg reg = (Reg) arg0.getAction();
  System.out.println("拦截器信息:启动拦截器,拦截Action时间:"+new Date());
  // 执行Action或者执行下一个拦截器
  String result = arg0.invoke();//如果在控制中不调用invoke()方法,则Action不会被执行,拦截器直接返回一个"success"字符串。
  // 提示Action执行完毕
  System.out.println("拦截器信息:Action执行完毕时间:!"+new Date());
  return result;
 }

}

   </interceptor>

<interceptors>

 

拦截器的方法过滤

继承MethodFilterInterceptor雷,就可以使用拦截器的方法过滤功能,来拦截Action中特定的方法。

。excludeMethods:该参数指定拦截器拒绝的方法列表,如:"method1,method2"

。includeMethods:该参数指定拦截器需要拦截的方法列表。

下面给出该类的主要方法:

.protected abstract String doIntercept(ActionInvocation invocation):继承该类的子类必须重写该方法,并实现拦截逻辑。

.String intercept(ActionInvocation invocation):继承自com.opensyphony.xwork2.interceptor.AbstractInterceptor雷,该方法不需要强制重写。

 

.void setExcludeMethods(String excludeMethods):设置黑名单,该方法参数为一个字符串,即对应的Action方法名称。

。void setIncludeMethods(String includeMethods):设置拦截器的白名单,该方法参数为一个字符串,即对应的Action方法名称。

.set getExcludeMethodsSet():获得该拦截器的黑名单。

.set getIncludeMethodsSet():获得该拦截器的白名单。

如果使用MethodFilterInterceptor类的子类来实现,不需要重写intercept(ActionInvocationinvocation)方法,只要重写doIntercept(ActionInvocation invocation)方法即可。

 

实现方法过滤的拦截器与普通拦截器并没有大的差别,只是继承了com.opensymphony.xwork2.interceptor.AbstractInterceptor类的子类MethodFilterInterceptor,并重写doIntercept(ActionInvocationinvocation)方法。

实现方法过滤的拦截器实现类FilterInterceptor

import java.util.Date;

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

public class FilterInterceptor extends MethodFilterInterceptor {
 //拦截器名称参数,可以在配置文件中指定
 private String name;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }


 protected String doIntercept(ActionInvocation arg0) throws Exception {
  // 引用被拦截Action对象
  FilterAction fa = (FilterAction) arg0.getAction();
  // 打印拦截信息
  System.out.println(name+"拦截器在Action执行前拦截:" + new Date());
  // 执行Action或者下一个拦截器
  String res = arg0.invoke();
  // 打印Action执行完毕信息
  System.out.println(name+"拦截器在Action执行后拦截:" + new Date());
  // 返回逻辑视图
  return res;
 }

}

动态调用业务控制器FilterAction

import com.opensymphony.xwork2.ActionSupport;

public class FilterAction extends ActionSupport {
 private String msg;

 public String getMsg() {
  return msg;
 }

 public void setMsg(String msg) {
  this.msg = msg;
 }

 // 模拟方法1
 public String method1() throws Exception {
  System.out.println("Action执行方法:method1()");
  return SUCCESS;
 }
 
 // 模拟方法2
 public String method2() throws Exception {
  System.out.println("Action执行方法:method2()");
  return SUCCESS;
 }

 // 模拟方法3
 public String method3() throws Exception {
  System.out.println("Action执行方法:method3()");
  return SUCCESS;
 }
}

配置

<interceptors>
     <interceptor name="FilterInterceptor"
    class="ch5.FilterInterceptor">
   </interceptor>

     </interceptors>

<action name="FilterAction" class="FilterAction">
   <result name="success">/MethodFilter.jsp</result>
   <interceptor-ref name="defaultStack"></interceptor-ref>
   <interceptor-ref name="FilterInterceptor">

<!--使用方法过滤,设置白名单或者黑名单-->
    <param name="includeMethods">method1</param>
    <param name="excludeMethods">method2</param>
    <param name="name">方法过滤拦截器</param>
   </interceptor-ref>
  </action>

 

一些重要的拦截器
  <interceptor-stack name="defaultStack">
                
<interceptor-ref name="exception"/><!--将异常定位到一个页面-->
                
<interceptor-ref name="alias"/><!--在不同请求之间将请求参数在不同名字间转换,请求内容不变-->

                
<interceptor-ref name="servletConfig"/>
                
<interceptor-ref name="prepare"/>
                
<interceptor-ref name="i18n"/>
                
<interceptor-ref name="chain"/><!--让前一个Action的属性可以被后一个Action访问,和chain类型的result(resulttype="chain"结合使用-->

                
<interceptor-ref name="debugging"/>
                
<interceptor-ref name="profiling"/>
                
<interceptor-ref name="scopedModelDriven"/>
                
<interceptor-ref name="modelDriven"/>
                
<interceptor-ref name="fileUpload"/><!--提供文件上传-->

                
<interceptor-ref name="checkbox"/>
                
<interceptor-ref name="staticParams"/>
                
<interceptor-ref name="params"><!--将请求中的参数设置到Action中去-->

                  
<param name="excludeParams">dojo..*</param>
                
</interceptor-ref>
                
<interceptor-ref name="conversionError"/>
                
<interceptor-ref name="validation">
                    
<param name="excludeMethods">input,back,cancel,browse</param>
                
</interceptor-ref>
                
<interceptor-ref name="workflow">
                    
<param name="excludeMethods">input,back,cancel,browse</param>
                
</interceptor-ref>
            
</interceptor-stack>

 

首先,第一个是exception    用法如下,如果不用这个功能可以去掉

          < action  name ="test" >
             
< interceptor-ref  name ="exception" />
             
< interceptor-ref  name ="basicStack" />
             
< exception-mapping  exception ="com.acme.CustomException"  result ="custom_error" />
             
< result  name ="custom_error" > custom_error.ftl </ result >
         </action>

 

第二个,是取别名的功能,也可以基本不用

 

 <action name="someAction" class="com.examples.SomeAction">
     
<!– The value for the foo parameter will be applied as if it were named bar –>
     
<param name="aliases">#{ ’foo’ : ’bar’ }</param>

     
<interceptor-ref name="alias"/>
     
<interceptor-ref name="basicStack"/>
     
<result name="success">good_result.ftl</result>
 
</action>

第三个,看一下代码就明白了,这个有时还是能用到的,暂且保留好了(我们可以用 ServletActionContext代替)

 

 

        if (action instanceof ServletRequestAware) {
            HttpServletRequest request 
= (HttpServletRequest) context.get(HTTP_REQUEST);
            ((ServletRequestAware) action).setServletRequest(request);
        }


        
if (action instanceof ServletResponseAware) {
            HttpServletResponse response 
= (HttpServletResponse) context.get(HTTP_RESPONSE);
            ((ServletResponseAware) action).setServletResponse(response);
        }


        
if (action instanceof ParameterAware) {
            ((ParameterAware) action).setParameters(context.getParameters());
        }


        
if (action instanceof RequestAware) {
            ((RequestAware) action).setRequest((Map) context.get(
"request"));
        }


        
if (action instanceof SessionAware) {
            ((SessionAware) action).setSession(context.getSession());
        }


        
if (action instanceof ApplicationAware) {
            ((ApplicationAware) action).setApplication(context.getApplication());
        }

第四个 prepare  这个拦截器的控制粒度在方法级别,常用在一些方法的执行必须基于某某方法先执行

     public  String doIntercept(ActionInvocation invocation)  throws  Exception  {
        Object action 
= invocation.getAction();

        
if (action instanceof Preparable) {
            
try {
                PrefixMethodInvocationUtil.invokePrefixMethod(invocation,
                    
new String[] { PREPARE_PREFIX, ALT_PREPARE_PREFIX });
            }

            
catch(Exception e) {
                
// just in case there’s an exception while doing reflection,
                
// we still want prepare() to be able to get called.
                LOG.warn("an exception occured while trying to execute prefixed method", e);
            }

            
if (alwaysInvokePrepare) {
                ((Preparable) action).prepare(); 先执行
            }

        }


        
return invocation.invoke(); 后执行
    }

另外这个拦截器要设置

 

  • excludeMethods - methods name to be excluded
  • includeMethods - methods name to be included

这2个属性 因为它是继承自 MethodFilterInterceptorfoo.action?request_locale=en_US 

如果看不惯request_locale,可以设置掉 提供了
    public void setParameterName(String parameterName) {
        this.parameterName = parameterName;
    }
  

第五个,就不用说了,非常重要 

 

在项目应用中,尽量减少不需要的拦截器的饮用。拦截器重要的是可以通过拦截器来实现AOP的设计思想。通过对项目的分析,找出“横切关注点“,可以使用拦截器来实现分离。

应用如权限拦截器

原理:在特定的包含范围内,定义一个权限拦截器,该拦截器的作用是验证当前用户的请求种Session中的权限标识。为了使包中所有的Action都应用该拦截器,将该拦截器定义为包默认拦截器。

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class checkInterceptor extends AbstractInterceptor {

 public String intercept(ActionInvocation arg0) throws Exception {
  // 获得Action上下文
  ActionContext ctx = arg0.getInvocationContext();
  // 获得Session
  Map session = ctx.getSession();
  // 获得Session中的user标识
  String user = (String) session.get("user");
  // 如果标识合法,则执行Action非法
  if (user != null && user.equals("pla")) {
   return arg0.invoke();
  } else {
   // 如果不合法,则拦截Action执行,跳转到登录界面
   return "login";
  }
 }

}
这样使用的好处是避免了在每个Action或者JSP视图中判断当前用户是否为合法用户。

 

配置拦截器

如要配置上权限拦截器

.定义拦截器:使用<interceptor.../>

.定义一个全局result:对应拦截器验证不合法的逻辑视图"login"。

.定义一个默认拦截器zai:为了使包内所有的Action都能使用拦截器,最好的方式就是将其定义为默认拦截器。

 

<!--定义权限拦截器-->

<interceptors>
   <interceptor name="checkInterceptor"
    class="ch5.checkInterceptor"></interceptor>
   <!--定义一个自定义拦截器栈,包含系统默认拦截器和权限拦截器-->
   <interceptor-stack name="mydefaultstack">
    <interceptor-ref name="defaultStack"></interceptor-ref>
    <interceptor-ref name="checkInterceptor"></interceptor-ref>
   </interceptor-stack>
  </interceptors>

<!--将自定义拦截器栈设置为包默认拦截器-->
  <default-interceptor-ref name="mydefaultstack"></default-interceptor-ref>
  <global-results>
   <result name="login">/login.jsp</result>
  </global-results>

 

权限拦截器loginAction

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {
 private String username;
 private String password;
 private String msg;
  
 public String execute() throws Exception {
  //检查用户名密码是否合法
  if (username.equals("pla")&&password.equals("pla")){
   //合法,则设置msg消息内容
   setMsg("欢迎"+username);
   //将用户名存入session中
   ActionContext ctx=ActionContext.getContext();
   Map session=ctx.getSession();
   session.put("user", username);
   return SUCCESS;
  }else{
   //将用户名存入session中
   ActionContext ctx=ActionContext.getContext();
   Map session=ctx.getSession();
   session.put("user", null);
   return LOGIN;
  }
 }
 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public String getMsg() {
  return msg;
 }
 public void setMsg(String msg) {
  this.msg = msg;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
}

 

import com.opensymphony.xwork2.ActionSupport;

public class ViewBankAction extends ActionSupport {
 public String execute() throws Exception {
  // 没有任何逻辑,直接返回SUCCESS
  return SUCCESS;
 }
}

 

JSP:login.jsp

 

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>用户登录</title>
<s:head />
</head>
<body>
<table>
 <h2><s:property value="msg" /></h2>
 <s:form id="id" action="login">
  <s:textfield name="username" label="用户名:" />
  <s:password name="password" label="密码:" />
  <s:submit value="登录" />
 </s:form>
 <ul>
  <s:url id="url" action="ViewBankAction"></s:url>
  <s:a href="%{url}">查看银行账户</s:a>
 </ul>
</table>
</body>
</html>

 

viewbank.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>登录成功界面</title>
<s:head />
</head>
<body>
<table>
<h2>你好<s:property  value="username" />,登录成功!!</h2>
<h2>欢迎您查看您的银行账户。</h2>
</table>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值