基于spring security及spring aop的权限控制

一 首先,获取spring security的当前用户:

Spring security获取当前用户

http://blog.csdn.net/tomcat_2014/article/details/50725723

.Java代码中使用

[java]  view plain  copy
  1. UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication() .getPrincipal();  

 但我在实际运用中发现获得的Authentication为null。仔细看了下源代码发现,如果想用上面的代码获得当前用户,必须在spring    

     security过滤器执行中执行,否则在过滤链执行完时org.springframework.security.web.context.SecurityContextPersistenceFilter类会

     调用SecurityContextHolder.clearContext();而把SecurityContextHolder清空,所以会得到null。    经过spring security认证后,     

     security会把一个SecurityContextImpl对象存储到session中,此对象中有当前用户的各种资料

[java]  view plain  copy
  1. SecurityContextImpl securityContextImpl = (SecurityContextImpl) request  
  2.  .getSession().getAttribute("SPRING_SECURITY_CONTEXT");  
  3. // 登录名  
  4. System.out.println("Username:"  
  5.  + securityContextImpl.getAuthentication().getName());  
  6. // 登录密码,未加密的  
  7. System.out.println("Credentials:"  
  8.  + securityContextImpl.getAuthentication().getCredentials());  
  9. WebAuthenticationDetails details = (WebAuthenticationDetails) securityContextImpl  
  10.  .getAuthentication().getDetails();  
  11. // 获得访问地址  
  12. System.out.println("RemoteAddress" + details.getRemoteAddress());  
  13. // 获得sessionid  
  14. System.out.println("SessionId" + details.getSessionId());  
  15. // 获得当前用户所拥有的权限  
  16. List<GrantedAuthority> authorities = (List<GrantedAuthority>) securityContextImpl  
  17.  .getAuthentication().getAuthorities();  
  18. for (GrantedAuthority grantedAuthority : authorities) {  
  19.  System.out.println("Authority" + grantedAuthority.getAuthority());  
  20. }  

二 然后,需要在Controller层建立切面拦截,参考:

使用Spring的注解方式实现AOP

http://blog.csdn.net/a352193394/article/details/7345860


spring对AOP的实现提供了很好的支持。下面我们就使用Spring的注解来完成AOP做一个例子。

首先,为了使用Spring的AOP注解功能,必须导入如下几个包。aspectjrt.jar,aspectjweaver.jar,cglib-nodep.jar.

然后我们写一个接口

[java]  view plain  copy
 print ?
  1. package com.bird.service;  
  2.   
  3. public interface PersonServer {  
  4.   
  5.     public void save(String name);  
  6.     public void update(String name, Integer id);  
  7.     public String getPersonName(Integer id);  
  8.       
  9. }  

和一个接口实现类

[java]  view plain  copy
 print ?
  1. package com.bird.service.impl;  
  2.   
  3. import com.bird.service.PersonServer;  
  4.   
  5. public class PersonServiceBean implements PersonServer{  
  6.       
  7.     @Override  
  8.     public void save(String name) {  
  9.           
  10.         System.out.println("我是save方法");  
  11.     //  throw new RuntimeException();  
  12.     }  
  13.   
  14.     @Override  
  15.     public void update(String name, Integer id) {  
  16.           
  17.         System.out.println("我是update()方法");  
  18.     }  
  19.   
  20.     @Override  
  21.     public String getPersonName(Integer id) {  
  22.           
  23.         System.out.println("我是getPersonName()方法");  
  24.         return "xxx";  
  25.     }  
  26.   
  27. }  

下面使用Spring注解方式对这个Bean进行方法拦截

[java]  view plain  copy
 print ?
  1. package com.bird.service;  
  2.   
  3. import org.aspectj.lang.ProceedingJoinPoint;  
  4. import org.aspectj.lang.annotation.After;  
  5. import org.aspectj.lang.annotation.AfterReturning;  
  6. import org.aspectj.lang.annotation.AfterThrowing;  
  7. import org.aspectj.lang.annotation.Around;  
  8. import org.aspectj.lang.annotation.Aspect;  
  9. import org.aspectj.lang.annotation.Before;  
  10. import org.aspectj.lang.annotation.Pointcut;  
  11.   
  12. /** 
  13.  * 切面 
  14.  * @author Bird 
  15.  * 
  16.  */  
  17. @Aspect  
  18. public class MyInterceptor {  
  19.     @Pointcut("execution(* com.bird.service.impl.PersonServiceBean.*(..))")  
  20.     private void anyMethod(){}//定义一个切入点  
  21.       
  22.     @Before("anyMethod() && args(name)")  
  23.     public void doAccessCheck(String name){  
  24.         System.out.println(name);  
  25.         System.out.println("前置通知");  
  26.     }  
  27.       
  28.     @AfterReturning("anyMethod()")  
  29.     public void doAfter(){  
  30.         System.out.println("后置通知");  
  31.     }  
  32.       
  33.     @After("anyMethod()")  
  34.     public void after(){  
  35.         System.out.println("最终通知");  
  36.     }  
  37.       
  38.     @AfterThrowing("anyMethod()")  
  39.     public void doAfterThrow(){  
  40.         System.out.println("例外通知");  
  41.     }  
  42.       
  43.     @Around("anyMethod()")  
  44.     public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{  
  45.         System.out.println("进入环绕通知");  
  46.         Object object = pjp.proceed();//执行该方法  
  47.         System.out.println("退出方法");  
  48.         return object;  
  49.     }  
  50. }  
[java]  view plain  copy
 print ?
  1. @Pointcut("execution(* com.bird.service.impl.PersonServiceBean.*(..))")  
这句话是方法切入点,execution为执行的意思,*代表任意返回值,然后是包名,.*意思是包下面的所有子包。(..)代

表各种方法.

然后下面的注解就比较简单了,就是在使用方法前和中,还有环绕拦截/

然后在Spring的配置文件中继续配置Bean,需要打开AOP命名空间

[java]  view plain  copy
 print ?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:aop="http://www.springframework.org/schema/aop"  
  5.        xsi:schemaLocation="  
  6.        http://www.springframework.org/schema/beans   
  7.        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  8.        http://www.springframework.org/schema/aop   
  9.        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">  
  10.           
  11.         <aop:aspectj-autoproxy/>  
  12.     <bean id="personServiceBean" class="com.bird.service.impl.PersonServiceBean"/>  
  13.     <bean id="myInterceptor" class="com.bird.service.MyInterceptor"/>  
  14.      
  15. </beans>  

然后建立一个Junit测试

[java]  view plain  copy
 print ?
  1. package junit.test;  
  2.   
  3. import org.junit.Test;  
  4. import org.springframework.context.ApplicationContext;  
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  6.   
  7. import com.bird.service.PersonServer;  
  8.   
  9. public class SpringAOPTest {  
  10.       
  11.     @Test  
  12.     public void inteceptorTest(){  
  13.         ApplicationContext ctx = new ClassPathXmlApplicationContext("beanAop.xml");  
  14.         PersonServer bean = (PersonServer)ctx.getBean("personServiceBean");  
  15.         bean.save(null);  
  16.     }  
  17.       
  18.   
  19. }  

测试结果为

[java]  view plain  copy
 print ?
  1. 2012-3-12 18:08:39 org.springframework.context.support.AbstractApplicationContext prepareRefresh  
  2. 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@dd20f6: display name [org.springframework.context.support.ClassPathXmlApplicationContext@dd20f6]; startup date [Mon Mar 12 18:08:39 CST 2012]; root of context hierarchy  
  3. 2012-3-12 18:08:40 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions  
  4. 信息: Loading XML bean definitions from class path resource [beanAop.xml]  
  5. 2012-3-12 18:08:40 org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory  
  6. 信息: Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@dd20f6]: org.springframework.beans.factory.support.DefaultListableBeanFactory@b0bad7  
  7. 2012-3-12 18:08:40 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons  
  8. 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@b0bad7: defining beans [org.springframework.aop.config.internalAutoProxyCreator,personServiceBean,myInterceptor]; root of factory hierarchy  
  9. null  
  10. 前置通知  
  11. 进入环绕通知  
  12. 我是save方法  
  13. 后置通知  
  14. 退出方法  
  15. 最终通知  
注意:

1.本博客中的 && args(name),我测下来这个before只能拦截到有一个参数的函数,如果要拦截所有签名的函数,则

//    @Before("anyMethod()")
//    public void doAccessCheck(){
//        System.out.println("前置通知");
//    }

2.本案采用spring aop而不是spring mvc拦截器,这之间的区别,在本博客底部转载

3.另有一篇参考博客:spring boot 使用spring AOP实现拦截器

http://blog.csdn.net/clementad/article/details/52035199,其中的

/** 
     * 定义拦截规则:拦截com.xjj.web.controller包下面的所有类中,有@RequestMapping注解的方法。 
     */  
    @Pointcut("execution(* com.xjj.web.controller..*(..)) and @annotation(org.springframework.web.bind.annotation.RequestMapping)")  
    public void controllerMethodPointcut(){}  

4.另有一篇博客,解释了spring mvc中使用aop失效的问题: SpringMVC中使用aop注解无效的问题

先备案:http://blog.csdn.net/u010483289/article/details/52725796



三 最后,有两个小问题:

1.业务要求,不同的Controller对应于不同的模块,这就要求在切面中跟踪是调用哪个类;


2.有些请求返回页面,有些请求返回对象,这就要求在切面中跟踪被切方法的返回类型。

参考:http://blog.csdn.net/meiyang1990/article/details/50562046 (ProceedingJoinPoint获取当前方法

aspectJ切面通过ProceedingJoinPoint想要获取当前执行的方法:

错误方法:


     Signature s = pjp.getSignature();
    MethodSignature ms = (MethodSignature)s;
    Method m = ms.getMethod();

这种方式获取到的方法是接口的方法而不是具体的实现类的方法,因此是错误的。


正确方法:

        Signature sig = pjp.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Object target = pjp.getTarget();
        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());


唉,就因为这个摔了好大一跤


由于我这边是基于类而不是接口的,所以不考虑其中的正确方法,直接使用:

获取类:

pjp.getTarget().getClass()

获取返回类型

Class returnType =  ((MethodSignature) pjp.getSignature()).getReturnType();


if(returnType.equals(String.class)) {
                object = "common/noauth";
            } else {
                object = Result.genFail("没有权限");
            }

切面图:

xxxController——xxx业务模块

xxxControler下属restful接口函数  xxdeletexx,xxsavexx函数,专门定义两个切面来拦截删除操作和更新操作,所以这就对代码命名有所要求


    @Pointcut("execution(* com.ilex.jiutou.web..*delete*(..))")
    private void deleteMethod(){}//定义一个切入点

    @Pointcut("execution(* com.ilex.jiutou.web..*save*(..)) || execution(* com.ilex.jiutou.web..*update*(..))")
    private void updateMethod(){}//定义一个切入点

我这边就是更新操作的命名没统一,有save和update两种,所以以 || 来建立或逻辑,(这里用 or 我测下来不行,只能截到 *save*的函数

以这种方式来控制在一个业务模块(xxxController)中不同的读写、删除权限。


完。


两个疑问:

@EnableAspectJAutoProxy我没加

spring.aop.proxy-target-class=true我没加


附件:spring aop与spring mvc拦截器的区别

http://www.lai18.com/content/2471799.html

谈谈spring中的拦截器interceptor

谈谈spring中的拦截器

在web开发中,拦截器是经常用到的功能。它可以帮我们验证是否登陆、预先设置数据以及统计方法的执行效率等等。今天就来详细的谈一下spring中的拦截器。spring中拦截器主要分两种,一个是HandlerInterceptor,一个是MethodInterceptor。

一,HandlerInterceptor拦截器

HandlerInterceptor是springMVC项目中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行。实现一个HandlerInterceptor拦截器可以直接实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类。这两种方法殊途同归,其实HandlerInterceptorAdapter也就是声明了HandlerInterceptor接口中所有方法的默认实现,而我们在继承他之后只需要重写必要的方法。下面就是HandlerInterceptorAdapter的代码,可以看到一个方法只是默认返回true,另外两个是空方法:
[java]  view plain copy
  1. public abstract class HandlerInterceptorAdapter implements HandlerInterceptor {  
  2.   
  3.     /** 
  4.      * This implementation always returns <code>true</code>. 
  5.      */  
  6.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  
  7.         throws Exception {  
  8.         return true;  
  9.     }  
  10.   
  11.     /** 
  12.      * This implementation is empty. 
  13.      */  
  14.     public void postHandle(  
  15.             HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)  
  16.             throws Exception {  
  17.     }  
  18.   
  19.     /** 
  20.      * This implementation is empty. 
  21.      */  
  22.     public void afterCompletion(  
  23.             HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)  
  24.             throws Exception {  
  25.     }  
  26.   
  27. }  
这三个方法都是干什么的,有什么作用,什么时候调用,不同的拦截器之间是怎样的调用顺序呢?这还得参考一下DispatcherServlet的doDispatch方法:
[java]  view plain copy
  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  2.         HttpServletRequest processedRequest = request;  
  3.         HandlerExecutionChain mappedHandler = null;  
  4.         int interceptorIndex = -1;  
  5.   
  6.         try {  
  7.             ModelAndView mv;  
  8.             boolean errorView = false;  
  9.   
  10.             try {  
  11.                 processedRequest = checkMultipart(request);  
  12.   
  13.                 // Determine handler for the current request.  
  14.                 mappedHandler = getHandler(processedRequest, false);  
  15.                 if (mappedHandler == null || mappedHandler.getHandler() == null) {  
  16.                     noHandlerFound(processedRequest, response);  
  17.                     return;  
  18.                 }  
  19.   
  20.                 // Determine handler adapter for the current request.  
  21.                 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());  
  22.   
  23.                 // Process last-modified header, if supported by the handler.  
  24.                 String method = request.getMethod();  
  25.                 boolean isGet = "GET".equals(method);  
  26.                 if (isGet || "HEAD".equals(method)) {  
  27.                     long lastModified = ha.getLastModified(request, mappedHandler.getHandler());  
  28.                     if (logger.isDebugEnabled()) {  
  29.                         String requestUri = urlPathHelper.getRequestUri(request);  
  30.                         logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);  
  31.                     }  
  32.                     if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {  
  33.                         return;  
  34.                     }  
  35.                 }  
  36.   
  37.                 // Apply preHandle methods of registered interceptors.  
  38.                 HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();  
  39.                 if (interceptors != null) {  
  40.                     for (int i = 0; i < interceptors.length; i++) {  
  41.                         HandlerInterceptor interceptor = interceptors[i];  
  42.                         if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {  
  43.                             triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);  
  44.                             return;  
  45.                         }  
  46.                         interceptorIndex = i;  
  47.                     }  
  48.                 }  
  49.   
  50.                 // Actually invoke the handler.  
  51.                 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
  52.   
  53.                 // Do we need view name translation?  
  54.                 if (mv != null && !mv.hasView()) {  
  55.                     mv.setViewName(getDefaultViewName(request));  
  56.                 }  
  57.   
  58.                 // Apply postHandle methods of registered interceptors.  
  59.                 if (interceptors != null) {  
  60.                     for (int i = interceptors.length - 1; i >= 0; i--) {  
  61.                         HandlerInterceptor interceptor = interceptors[i];  
  62.                         interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);  
  63.                     }  
  64.                 }  
  65.             }  
  66.             catch (ModelAndViewDefiningException ex) {  
  67.                 logger.debug("ModelAndViewDefiningException encountered", ex);  
  68.                 mv = ex.getModelAndView();  
  69.             }  
  70.             catch (Exception ex) {  
  71.                 Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);  
  72.                 mv = processHandlerException(processedRequest, response, handler, ex);  
  73.                 errorView = (mv != null);  
  74.             }  
  75.   
  76.             // Did the handler return a view to render?  
  77.             if (mv != null && !mv.wasCleared()) {  
  78.                 render(mv, processedRequest, response);  
  79.                 if (errorView) {  
  80.                     WebUtils.clearErrorRequestAttributes(request);  
  81.                 }  
  82.             }  
  83.             else {  
  84.                 if (logger.isDebugEnabled()) {  
  85.                     logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +  
  86.                             "': assuming HandlerAdapter completed request handling");  
  87.                 }  
  88.             }  
  89.   
  90.             // Trigger after-completion for successful outcome.  
  91.             triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);  
  92.         }  
  93.   
  94.         catch (Exception ex) {  
  95.             // Trigger after-completion for thrown exception.  
  96.             triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);  
  97.             throw ex;  
  98.         }  
  99.         catch (Error err) {  
  100.             ServletException ex = new NestedServletException("Handler processing failed", err);  
  101.             // Trigger after-completion for thrown exception.  
  102.             triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);  
  103.             throw ex;  
  104.         }  
  105.   
  106.         finally {  
  107.             // Clean up any resources used by a multipart request.  
  108.             if (processedRequest != request) {  
  109.                 cleanupMultipart(processedRequest);  
  110.             }  
  111.         }  
  112.     }  


代码有点长,但是它封装了springMVC处理请求的整个过程。首先根据请求找到对应的HandlerExecutionChain,它包含了处理请求的handler和所有的HandlerInterceptor拦截器;然后在调用hander之前分别调用每个HandlerInterceptor拦截器的preHandle方法,若有一个拦截器返回false,则会调用triggerAfterCompletion方法,并且立即返回不再往下执行;若所有的拦截器全部返回true并且没有出现异常,则调用handler返回ModelAndView对象;再然后分别调用每个拦截器的postHandle方法;最后,即使是之前的步骤抛出了异常,也会执行triggerAfterCompletion方法。关于拦截器的处理到此为止,接下来看看triggerAfterCompletion做了什么
[java]  view plain copy
  1. private void triggerAfterCompletion(HandlerExecutionChain mappedHandler,  
  2.             int interceptorIndex,  
  3.             HttpServletRequest request,  
  4.             HttpServletResponse response,  
  5.             Exception ex) throws Exception {  
  6.   
  7.         // Apply afterCompletion methods of registered interceptors.  
  8.         if (mappedHandler != null) {  
  9.             HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();  
  10.             if (interceptors != null) {  
  11.                 for (int i = interceptorIndex; i >= 0; i--) {  
  12.                     HandlerInterceptor interceptor = interceptors[i];  
  13.                     try {  
  14.                         interceptor.afterCompletion(request, response, mappedHandler.getHandler(), ex);  
  15.                     }  
  16.                     catch (Throwable ex2) {  
  17.                         logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);  
  18.                     }  
  19.                 }  
  20.             }  
  21.         }  
  22.     }  
triggerAfterCompletion做的事情就是从当前的拦截器开始逆向调用每个拦截器的afterCompletion方法,并且捕获它的异常,也就是说每个拦截器的afterCompletion方法都会调用。
根据以上的代码,分析一下不同拦截器及其方法的执行顺序。假设有5个拦截器编号分别为12345,若一切正常则方法的执行顺序是12345的preHandle,54321的postHandle,54321的afterCompletion。若编号3的拦截器的preHandle方法返回false或者抛出了异常,接下来会执行的是21的afterCompletion方法。这里要注意的地方是,我们在写一个拦截器的时候要谨慎的处理preHandle中的异常,因为这里一旦有异常抛出就不会再受到这个拦截器的控制。12345的preHandle的方法执行过之后,若handler出现了异常或者某个拦截器的postHandle方法出现了异常,则接下来都会执行54321的afterCompletion方法,因为只要12345的preHandle方法执行完,当前拦截器的拦截器就会记录成编号5的拦截器,而afterCompletion总是从当前的拦截器逆向的向前执行。
另外,实现HandlerInterceptor拦截器还有一个方法,就是实现WebRequestInterceptor接口。其实它和刚才的两种方法也是殊途同归,最终还是被spring适配成HandlerInterceptor。有一点不同,它的preHandle方法最终只会返回true。

二,MethodInterceptor拦截器

MethodInterceptor是AOP项目中的拦截器,它拦截的目标是方法,即使不是controller中的方法。实现MethodInterceptor拦截器大致也分为两种,一种是实现MethodInterceptor接口,另一种利用AspectJ的注解或配置。
下面是第一种方法的示例
[java]  view plain copy
  1. public class MethodInvokeInterceptor implements MethodInterceptor {  
  2.     @Override  
  3.     public Object invoke(MethodInvocation methodInvocation) throws Throwable {  
  4.         System.out.println("before method invoke");  
  5.         Object object = methodInvocation.proceed();  
  6.         System.out.println("after method invoke");  
  7.         return object;  
  8.     }  
  9. }  
下面是基于注解的AspectJ方式

[java]  view plain copy
  1. @Component  
  2. @Aspect  
  3. public class AutoAspectJInterceptor {  
  4.   
  5.     @Around("execution (* com.test.controller..*.*(..))")  
  6.     public Object around(ProceedingJoinPoint point) throws Throwable{  
  7.         System.out.println("AutoAspectJInterceptor begin around");  
  8.         Object object = point.proceed();  
  9.         System.out.println("AutoAspectJInterceptor end around");  
  10.         return object;  
  11.     }  
  12.      
  13. }  
下面是一个用于支持AspectJ方式拦截的普通的bean,当然你也可以在配置文件中声明这个bean
[java]  view plain copy
  1. @Component  
  2.  public class AspectJInterceptor {  
  3.     public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {  
  4.         System.out.println("AspectJInterceptor around before");  
  5.         Object object = proceedingJoinPoint.proceed();  
  6.         System.out.println("AspectJInterceptor around after");  
  7.         return object;  
  8.     }  
  9. }  
当然,这一切都离不开配置,具体看配置中的注释

[java]  view plain copy
  1. <!-- 自定义拦截器 ,先过mvc:interceptors-->  
  2.     <bean id="methodInvokeInterceptor" class="com.test.interceptor.MethodInvokeInterceptor"/>  
  3.     <bean id="aspectInterceptor" class="com.test.interceptor.AspectJInterceptor"/>  
  4.   
  5.     <aop:config>  
  6.         <!--切入点,controlller -->  
  7.         <aop:pointcut id="pointcut_test"   expression="execution(* com.test.controller..*.*(..))" />  
  8.         <!--在该切入点使用自定义拦截器 ,按照先后顺序执行 -->  
  9.         <aop:advisor pointcut-ref="pointcut_test" advice-ref="methodInvokeInterceptor" />  
  10.   
  11.         <aop:aspect ref="aspectInterceptor">  
  12.             <aop:around method="around" pointcut="execution(* com.test.controller..*.*(..))"/>  
  13.         </aop:aspect>  
  14.     </aop:config>  
  15.     <!-- 自动扫描使用了aspectj注解的类 -->  
  16.     <aop:aspectj-autoproxy/>  


通过上面的配置三个MethodInterceptor就能正常工作了。其实,这两种实现方式。。。。。最终。。。。。。没错,还是殊途同归。aspectj的拦截器会被解析成AOP中的advice,最终被适配成MethodInterceptor,详细的过程请参考springAOP的实现。

三,谈一谈区别

上面的两种拦截器都能起到拦截的效果,但是他们拦截的目标不一样,实现的机制不同,所以有的时候适用不同的场景。HandlerInterceptoer拦截的是请求地址,所以针对请求地址做一些验证、预处理等操作比较合适。当你需要统计请求的响应时间时MethodInterceptor将不太容易做到,因为它可能跨越很多方法或者只涉及到已经定义好的方法中一部分代码。MethodInterceptor利用的是AOP的实现机制,在本文中只说明了使用方式,关于原理和机制方面介绍的比较少,因为要说清楚这些需要讲出AOP的相当一部分内容。在对一些普通的方法上的拦截HandlerInterceptoer就无能为力了,这时候只能利用AOP的MethodInterceptor。
另外,还有一个跟拦截器类似的东西----Filter。Filter是Servlet规范规定的,不属于spring框架,也是用于请求的拦截。但是它适合更粗粒度的拦截,在请求前后做一些编解码处理、日志记录等。而拦截器则可以提供更细粒度的,更加灵活的,针对某些请求、某些方法的组合的解决方案。
另外的另外,用过人人网的ROSE框架的人都会非常喜欢它的拦截器功能。因为它实现了全注解的方式,只要在类的名字上加上拦截器的注解即表示这是一个拦截器。而使用这个拦截器的方法或者controller也只需在方法或controller的上面加上这个拦截器的注解。其实这是一个关注点的转变,spring的切面控制在配置文件中,配置文件关注哪些地方需要拦截。而在ROSE中,则是在需要拦截的地方关注我要被谁拦截。

以上纯属个人观点,欢迎交流!


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值