SpringMVC的AOP拦截controller

用途

一般实现日志管理(自定义注解的方式)。

首先我们为什么需要做日志管理,在现实的上线中我们经常会遇到系统出现异常或者问题。这个时候就马上打开CRT或者SSH连上服务器拿日子来分析。受网络的各种限制。于是我们就想为什么不能直接在管理后台查看报错的信息呢。于是日志管理就出现了。

其次个人觉得做日志管理最好的是Aop,有的人也喜欢用拦截器。都可以,在此我重点介绍我的实现方式。

Aop有的人说拦截不到Controller。有的人说想拦AnnotationMethodHandlerAdapter截到Controller必须得拦截org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter。

首先Aop可以拦截到Controller的,这个是毋容置疑的其次须拦截AnnotationMethodHandlerAdapter也不是必须的。最起码我没有验证成功过这个。我的spring版本是4.0.3。

Aop之所以有的人说拦截不到Controller是因为Controller被jdk代理了。我们只要把它交给cglib代理就可以了。

第一步 定义两个注解:

package com.yj.aop;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**  
 *自定义注解 拦截Controller  
 */ 
@Target({ElementType.PARAMETER, ElementType.METHOD})//只能方法使用
@Retention(RetentionPolicy.RUNTIME)//表明注解可以变jvm编译
@Documented
public @interface SystemControllerLog {

    String description() default "";

}



package com.yj.aop;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**  
 *自定义注解 拦截service  
 */   
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemServiceLog {

    String description() default "";
}

第二步 创建一个切点类

package com.yj.aop;

import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 切点类
 * @author jing
 *
 */
@Aspect
@Component
public class SystemLogAspect {

    //controller层切点
    @Pointcut("@annotation(com.yj.aop.SystemControllerLog)")
    public void controllerAspect(){};
    //service层切点
    @Pointcut("@annotation(com.yj.aop.SystemServiceLog)")
    public void serviceAspect(){};

    @Before("controllerAspect()")
    public void deBefore(JoinPoint joinPoint){

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();    
 //       HttpSession session = request.getSession();        
        //请求的IP    
        String ip = request.getRemoteAddr();    
         try {    
            //*========控制台输出=========*//    
            System.out.println("=====前置通知开始=====");    
            System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
            System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));    
            System.out.println("请求人:" + "1111");    
            System.out.println("请求IP:" + ip);       
            System.out.println("=====前置通知结束=====");    
        }  catch (Exception e) {    
            e.printStackTrace();    
        }    
    }

    /**  
     * 异常通知 用于拦截service层记录异常日志  
     *  
     * @param joinPoint  
     * @param e  
     */    
    @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")    
     public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {    
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();    
        //获取请求ip    
        String ip = request.getRemoteAddr();    
         try {    
              /*========控制台输出=========*/    
            System.out.println("=====异常通知开始=====");    
            System.out.println("异常代码:" + e.getClass().getName());    
            System.out.println("异常信息:" + e.getMessage());    
            System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
            System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));    
            System.out.println("请求人:" + "请求人");    
            System.out.println("请求IP:" + ip);    
            System.out.println("请求参数:" + "请求参数");    
            System.out.println("=====异常通知结束=====");    
        }  catch (Exception ex) {    
             e.printStackTrace();
        }    

    }    

    /**  
     * 获取注解中对方法的描述信息 用于Controller层注解  
     *  
     * @param joinPoint 切点  
     * @return 方法描述  
     * @throws Exception  
     */    
     public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {    
        String targetName = joinPoint.getTarget().getClass().getName();    
        String methodName = joinPoint.getSignature().getName();    
        Object[] arguments = joinPoint.getArgs();    
        Class targetClass = Class.forName(targetName);    
        Method[] methods = targetClass.getMethods();    
        String description = "";    
         for (Method method : methods) {    
             if (method.getName().equals(methodName)) {    
                Class[] clazzs = method.getParameterTypes();    
                 if (clazzs.length == arguments.length) {    
                    description = method.getAnnotation(SystemControllerLog. class).description();    
                     break;    
                }    
            }    
        }    
         return description;    
    }    

     /**  
      * 获取注解中对方法的描述信息 用于service层注解  
      *  
      * @param joinPoint 切点  
      * @return 方法描述  
      * @throws Exception  
      */    
      public  static String getServiceMthodDescription(JoinPoint joinPoint)    
              throws Exception {    
         String targetName = joinPoint.getTarget().getClass().getName();    
         String methodName = joinPoint.getSignature().getName();    
         Object[] arguments = joinPoint.getArgs();    
         Class targetClass = Class.forName(targetName);    
         Method[] methods = targetClass.getMethods();    
         String description = "";    
          for (Method method : methods) {    
              if (method.getName().equals(methodName)) {    
                 Class[] clazzs = method.getParameterTypes();    
                  if (clazzs.length == arguments.length) {    
                     description = method.getAnnotation(SystemServiceLog. class).description();    
                      break;    
                 }    
             }    
         }    
          return description;    
     }    
}    

第三步 写配置文件,把Controller的代理权交给cglib

1、要明确,我们是在SpringMVC上aop监测,那么所有的报扫描注入都在SpringMVC的配置文件中完成,不要再spring的配置文件中完成,不然在开启代理后,发现还是没有起到任何作用。

2、扫描controller

<!-- 扫描controller(controller层注入) -->
    <context:component-scan base-package="com.yj.controller"/>

3、当然你此AOP切点用到了servrice层的话 要加

<!-- 扫描service(service层注入) -->
    <context:component-scan base-package="com.yj.service"/>

4、切点类扫描。(此扫描加不加都可以实现,具体区别你们可以百度)

<!--切点类路径-->
<context:component-scan base-package="com.ht.annotation" annotation-config="true"/>

5、在SpringMVC的配置文件中开启他的代理模式

<!--通知spring使用cglib而不是jdk的来生成代理方法 AOP可以拦截到Controller-->
    <aop:aspectj-autoproxy proxy-target-class="true" />

第四步 使用

controller的使用

package com.yj.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.yj.aop.SystemControllerLog;

@Controller()
public class TextController {

    @RequestMapping("text")
    @SystemControllerLog(description="aop测试")
    public void text(){
        System.out.println("text    运行");
    }
}

service的使用

    //此处为AOP拦截Service记录异常信息。方法不需要加try-catch 
    @SystemServiceLog(description="aop测试")
    public void text(){
        System.out.println("text    运行");
    }

第五步 用的到jar (这里我就写maven)

            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.8.0</version>
            </dependency>

参考:http://blog.csdn.net/czmchen/article/details/42392985
参考:http://blog.csdn.net/tianjun2012/article/details/47809739

猜你喜欢

转载自blog.csdn.net/jingyang07/article/details/74352522