随笔-15  评论-79  文章-0  trackbacks-0

最近发现很多朋友连拦截器都不知道,于是想写个BLOG总结一下。
java拦截器的基本原理其实非常简单,说白了就是动态代理类。
下面来看一个简单的例子
首先,我建立一个拦截器的类InterceptorClass,这里的before()和after()方法是以后拦截器会执行的方法
CODE清单一:

public class InterceptorClass {
 
public void before()
  System.out.println(
"拦截器InterceptorClass方法调用:before()!"); 
 }
 
 
public void after()
     System.out.println(
"拦截器InterceptorClass方法调用:after()!"); 
 }

}

 

我们模拟一个业务组件接口BusinessInterface,和一个业务组件实现类BusinessClass
CODE清单二:

public interface BusinessInterface {
 
public void doSomething();
}

 

CODE清单三:

public class BusinessClass implements BusinessInterface {
 
public void doSomething() {
   System.out.println(
"业务组件BusinessClass方法调用:doSomething()"); 
 }

}

 

然后,创建一个动态代理类DynamicProxyHandler,这个类是集成InvocationHandler接口的,动态类的原理实际上是使得当你执行一个动态方

法的时候,他可以把这个动态方法dispatch到这个动态类上来。这样,你就可以在这个方法的前后嵌入自己的一些方法。
CODE清单四:
//包含了业务对象绑定动态代理类的处理,并实现了InvocationHandler接口的invoke方法

public class DynamicProxyHandler implements InvocationHandler {
 
private Object business;//被代理对象
 private InterceptorClass inceptor = new InterceptorClass();//拦截器
 
 
// 动态生成一个代理类对象,并绑定被代理类和代理处理器
 public Object bind(Object business) {
   
this.business = business;
   
return Proxy.newProxyInstance(
     
//被代理类的ClassLoader
     business.getClass().getClassLoader(),
     
//要被代理的接口,本方法返回对象会自动声称实现了这些接口
     business.getClass().getInterfaces(), 
     
//代理处理器对象
     this);
 }


 
 // 代理要调用的方法,并在方法调用前后调用连接器的方法

 /**
  * 
@param proxy  代理类对象
  * 
@param method 被代理的接口方法
  * 
@param args   被代理接口方法的参数
  * 
@throws Throwable
  
*/

 
public Object invoke(Object proxy, Method method, Object[] args)
   
throws Throwable {
  Object result 
= null;
  inceptor.before();
  result
=method.invoke(business,args);
  inceptor.after();
  
return result;
 }


OK,我们来写个类测试一下
CODE清单五:

public static void main(String[] args) {
  
//生成动态代理类实例
  DynamicProxyHandler handler = new DynamicProxyHandler();
  
//生成待测试的业务组件对象
        BusinessInterface business = new BusinessClass();
        
//将业务组件对象和动态代理类实例绑定
        BusinessInterface businessProxy = (BusinessInterface) handler.bind(business);
        
//用动态代理类调用方法
        businessProxy.doSomething();
 }


来看看结果:


近期struts2很流行,而且拦截器是struts2里面一个比较好的功能,下面举个例子说明一下拦截器在struts2中的用法。
struts2对拦截器实现做了一个封装,使得我们在实现的时候比较简单。
首先我们要建一个拦截器类
CODE清单六:

public class AuthorizationInterceptor extends AbstractInterceptor {
 @Override
 
public String intercept(ActionInvocation invocation) throws Exception {
  Map session 
= invocation.getInvocationContext().getSession();
  String userName 
= (String) session.get("userName");
  
if ( userName != null && userName.equals("test")) {
   System.out.println(
"拦截器:合法用户登录---");
   
return invocation.invoke();
  }

  
else
  
{
   System.out.println(
"拦截器:用户未登录---");
   
return Action.LOGIN;
  }

 }

}


这个类是必须要继承struts2包中提供的AbstractInterceptor类,这个类有一个抽象方法intercept,这个方法是必须要实现的。
那么经理在这个拦截器里面写了一个简单的实现,对url用户合法性做了一个限制。

接下来比较关键的是过滤器在struts2中的配置,先看看代码
CODE清单七:

<package name="system" extends="struts-default">
  
<interceptors>
   
<!--  定义权限控制拦截器  -->
   
<interceptor name="authority" 

class
="com.sharesin.biz.common.intercepts.struts2.AuthorizationInterceptor"/>
   
<!-- 定义一个包含权限控制的拦截器栈   -->
   
<interceptor-stack name="mystack">
    
<interceptor-ref name="defaultStack"></interceptor-ref>
    
<interceptor-ref name="authority"></interceptor-ref>
   
</interceptor-stack>
  
</interceptors>
   
<!--定义默认拦截器   -->
        
<default-interceptor-ref name="mystack" />
   
<!--定义全局处理结果   -->
  
<global-results>
   
<result name="login">index.jsp</result>
  
</global-results>
  
<action name="login_*" class="com.sharesin.biz.web.system.LoginAction" method="{1}">
   
<result name="success">system/homepage.jsp</result>
  
</action>
 
</package>


在interceptors节点里,我们可以定义多个拦截器,这里的名为authority的只是其中的一个。struts2的拦截器栈我是先执行struts2默认的拦

截器defaultStack,然后再执行我的。然后只需要用default-interceptor-ref标签设置好这个system包中的默认拦截器为这个拦截器就OK了。

struts2中引入了package这个概念,我觉得十分实用,当然这对struts2拦截器也是个实惠,我们可以根据不同的action来分包和不同的拦截器


ok,来运行测试一下。


结果..


 

 

 

 

 

posted on 2010-09-06 17:21 张元Won 阅读(4487) 评论(3)  编辑  收藏 所属分类: Java

评论:
# re: JAVA拦截器原理及Struts2扩展 2011-05-16 13:46 | lixiujuan
以上代码中struts的运行还是在测试类里运行吧?怎么执行不了啊,,,???  回复  更多评论
  
# re: JAVA拦截器原理及Struts2扩展 2011-05-27 08:54 | え经理え
确实在测试类里的,不过绝对运行的了的..不然不会截图...你报的什么错?..@lixiujuan
  回复  更多评论
  
# re: JAVA拦截器原理及Struts2扩展 2014-08-04 00:15 | 打破沙锅问到底
拦截器一直拦截 根本过不去啊 一直在登录页面 不管你怎么填
Map session = invocation.getInvocationContext().getSession();
String userName = (String) session.get("userName");

这个userName 就是null值啊 另外这个get里的“userName” 随意给的吗  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: