ssm springaop 自定义注解加日志数据到数据库

弄得过程中出现过好多问题。(报错时候切入方法不正常执行,)

1、需要导的包:slf4j-log4j12-1.6.2.jar  slf4j-api-1.6.2.jar  (这两个jar包版本最好保持一致,之前我使用不同版本报错)

aspectjweaver-1.6.8_2.jar    log4j-1.2.15.jar  aopalliance-1.0.jar

2、新建一个log.java  自定义注解类

  package com.user.sessionFilter;
 import java.lang.annotation.*;
 //https://blog.csdn.net/erlian1992/article/details/53402519   
 //自定义注解  相关知识参考上面链接
 @Target({ElementType.PARAMETER, ElementType.METHOD})  
 @Retention(RetentionPolicy.RUNTIME)  
 @Documented  
 public @interface Log {
   //自定义注解
     /** 要执行的操作类型比如:add操作 **/  
     public String operationType() default "";  
      
     /** 要执行的具体操作比如:添加用户 **/  
     public String operationName() default "";

 }

3、新建一个SystemLogAspect .java  

执行顺序如下: 

//正常 device : -->around-->before-->method-->after-->afterReturn

  //报错 device : -->around-->before-->method-->after-->afterthrowing

package com.user.sessionFilter;
import java.lang.reflect.Method;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.user.entity.SystemLog;
import com.user.entity.User;
import com.user.service.SystemLogService;
@Aspect
@Component
public class SystemLogAspect {
  //正常 device : -->around-->before-->method-->after-->afterReturn
  //报错 device : -->around-->before-->method-->after-->afterthrowing
    //注入Service用于把日志保存数据库  
    @Autowired  //这里我用resource注解,一般用的是@Autowired,他们的区别如有时间我会在后面的博客中来写
    private SystemLogService systemLogService;  
    @Autowired
    WebContextHolder  webContextHolder ;
    private  static  final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);  
    
    //Controller层切点  
    @Pointcut("execution(* com.user.service.AopService.*(..))") 
      //@Pointcut("execution(* com.user.action.AopController.*(..))")
    public  void controllerAspect() {  
    }  
     /* joinPoint.getArgs();//輸入的參數列表  
      joinPoint.getTarget().getClass().getName();//類全路徑  
      joinPoint.getSignature().getDeclaringTypeName();//接口全路徑  
      joinPoint.getSignature().getName();//調用的方法  
*/    /** 
     * 前置通知 用于拦截Controller层记录用户的操作 
     * 
     * @param joinPoint 切点 
     */ 
    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) {
        System.out.println("==========执行controller前置通知===============");
        if(logger.isInfoEnabled()){
            logger.info("before " + joinPoint);
            logger.info("before start");
            joinPoint.getArgs();//輸入的參數列表  
            joinPoint.getTarget().getClass().getName();//類全路徑  
            joinPoint.getSignature().getDeclaringTypeName();//接口全路徑  
            joinPoint.getSignature().getName();//調用的方法  
            logger.info("before end");
        }
    }    
    
    //配置controller环绕通知,使用在方法aspect()上注册的切入点
      @Around("controllerAspect()")
      public void around(ProceedingJoinPoint pjp ){
          System.out.println("==========开始执行controller环绕通知===============");
          long start = System.currentTimeMillis();
          try {
          pjp.proceed();
             // ((ProceedingJoinPoint) joinPoint).proceed();
              long end = System.currentTimeMillis();
              if(logger.isInfoEnabled()){
                  logger.info("around " + pjp + "\tUse time : " + (end - start) + " ms!");
              }
             
              System.out.println("==========结束执行controller环绕通知===============");
           } catch (Throwable e) {
               long end = System.currentTimeMillis();
               if(logger.isInfoEnabled()){
                   logger.info("around " + pjp + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
               }
           }
       }
     
    /**
     * 
     *Project:my
     *Description: 
     *@author Krystal
     * 2018年5月13日上午2:43:47
     * @param joinPoint
     */
      @After("controllerAspect()")  
    public  void after(JoinPoint joinPoint) {  
      System.out.println("=====after=====");  
     } 
     
     //配置后置返回通知,使用在方法aspect()上注册的切入点
       @AfterReturning("controllerAspect()")
       public void afterReturn(JoinPoint joinPoint){
       HttpServletRequest request = webContextHolder.getRequest();      
           //读取session中的用户  
           HttpSession session = request.getSession();  
           User user = (User) session.getAttribute("user");  
         //请求的IP  
          String ip = request.getRemoteAddr();
         // User user =new User();        
         // user.setId(1);
         // user.setName("张三");
         // String ip = "127.0.0.1";
           try {  
              
              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 operationType = "";
              String operationName = "";
               for (Method method : methods) {  
                   if (method.getName().equals(methodName)) {  
                      Class[] clazzs = method.getParameterTypes();  
                       if (clazzs.length == arguments.length) {  
                          operationType = method.getAnnotation(Log.class).operationType();
                           operationName = method.getAnnotation(Log.class).operationName();
                           break;  
                      }  
                  }  
              }
              //*========控制台输出=========*//  
              System.out.println("=====controller后置通知开始=====");  
              System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);  
              System.out.println("方法描述:" + operationName);  
              System.out.println("请求人:" + user.getName());  
              System.out.println("请求IP:" + ip);  
              //*========数据库日志=========*//  
              SystemLog log = new SystemLog();  
              log.setDescription(operationName);  
              
              log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);  
              log.setRequestIp(ip);  
              log.setExceptioncode( "Exceptioncode");  
              log.setExceptionDetail( "ExceptionDetail");  
              log.setParams( "setParams");  
              log.setCreateBy(user.getName());  
              log.setCreateDate(new Date());  
              //保存数据库  
              systemLogService.insertSystemLog(log);  
              System.out.println("=====controller后置通知结束=====");  
          }  catch (Exception e) {  
              //记录本地异常日志  
              logger.error("==后置通知异常==");  
              logger.error("异常信息:{}", e.getMessage());  
          }  
       }
     
     /** 
      * 异常通知 用于拦截记录异常日志 
      * 
      * @param joinPoint 
      * @param e 
      */  
      @AfterThrowing(pointcut = "controllerAspect()", throwing="e")  
      public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {  
    // HttpSession session = request.getSession();  
          //读取session中的用户  
         // User user = (User) session.getAttribute("user");  
         // User user = (User) request.getSession().getAttribute("user");
         //获取请求ip  
         
         //获取用户请求方法的参数并序列化为JSON格式字符串  
    //  HttpServletRequest request = webContextHolder.getRequest();      
      ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();  
          HttpServletRequest request =attributes.getRequest();  
      //读取session中的用户  
          HttpSession session = request.getSession();  
          User user = (User) session.getAttribute("user"); 
          String ip = request.getRemoteAddr();
        
         //User user = new User();
        // user.setId(1);
        // user.setName("张三");
        // String  ip = "127.0.0.1";
         
         String params = "";  
          if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {  
              for ( int i = 0; i < joinPoint.getArgs().length; i++) {  
                 //params += JsonUtil.getJsonStr(joinPoint.getArgs()[i]) + ";";  
             }  
         }  
          try {  
              
              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 operationType = "";
              String operationName = "";
               for (Method method : methods) {  
                   if (method.getName().equals(methodName)) {  
                      Class[] clazzs = method.getParameterTypes();  
                       if (clazzs.length == arguments.length) {  
                           operationType = method.getAnnotation(Log.class).operationType();
                           operationName = method.getAnnotation(Log.class).operationName();
                           break;  
                      }  
                  }  
              }
              /*========控制台输出=========*/  
             System.out.println("=====异常通知开始=====");  
             System.out.println("异常代码:" + e.getClass().getName());  
             System.out.println("异常信息:" + e.getMessage());  
             System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType);  
             System.out.println("方法描述:" + operationName);  
             System.out.println("请求人:" + user.getName());  
             System.out.println("请求IP:" + ip);  
             System.out.println("请求参数:" + params);  
                /*==========数据库日志=========*/  
             SystemLog log = new SystemLog();
             log.setDescription(operationName);  
             log.setExceptioncode(e.getClass().getName());  
             log.setExceptionDetail(e.getMessage());  
             log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
             log.setParams(params);  
             log.setCreateBy(user.getName());  
             log.setCreateDate(new Date());  
             log.setRequestIp(ip);  
             //保存数据库  
             systemLogService.insertSystemLog(log);  
             System.out.println("=====异常通知结束=====");  
         }  catch (Exception ex) {  
             //记录本地异常日志  
            logger.error("==异常通知异常==");  
             logger.error("异常信息:{}", ex.getMessage());  
         }  
          /*==========记录本地异常日志==========*/  
         logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName());  
   
     }  
     

 }

4、controller ---》service

    @Controller
 @RequestMapping("SystemLog")
 public class AopController {
 
     @Autowired
     private AopService userService;
     
     @RequestMapping("testAOP")
    // @Log(operationType="addOperation:",operationName="添加用户")  
     public ModelAndView testAOP( HttpServletRequest request, HttpServletResponse response,Model model){  
    String success ="0";
    try {
        User user =new User();
        user.setName("sy");
        user.setPsd("22");
              success= userService.insertUser(user);
              System.out.println("dsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsdsd");
} catch (Exception e) {
success="0";
}
    if("0".equals(success)){
    return new  ModelAndView("user/aopFail");
    }
         return new  ModelAndView("user/aopSuccess");

     }

service:(具体切入方法在此)

operationType与operationName和log.java中定义的一致  

@Log(operationType="addOperation:",operationName="添加用户正常")  

public String insertUser(User user){
iUserMapper.insertUser(user);
return "1";
}

 5、springMvc.xml配置  红色为配置

 <context:component-scan base-package="com.user" >
<!--<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> -->
</context:component-scan>
<aop:aspectj-autoproxy  />  

<!-- <aop:aspectj-autoproxy proxy-target-class="true" />  --> 
   <!--  </aop:aspectj-autoproxy>   -->
<!--开启aopproxy-target-class="true"默认是false,更改为true时使用的是cglib动态代理,这样只能实现对Controller层的日志记录
   proxy-target-class等于true是强制使用cglib代理,proxy-target-class默认是false,如果你的类实现了接口 就走JDK代理,如果没有,走cglib代理  
      注:对于单利模式建议使用cglib代理,虽然JDK动态代理比cglib代理速度快,但性能不如cglib 

       https://blog.csdn.net/bobozai86/article/details/79229455 -->  

6、最后附上表

CREATE TABLE `systemlog` (
  `id` int(20) NOT NULL auto_increment,
  `description` varchar(100) default NULL,
  `method` varchar(100) default NULL,
  `requestIp` varchar(100) default NULL,
  `exceptioncode` varchar(100) default NULL,
  `exceptionDetail` varchar(100) default NULL,
  `params` varchar(100) default NULL,
  `createBy` varchar(100) default NULL,
  `createDate` timestamp NULL default NULL COMMENT '系统日志',
  PRIMARY KEY  (`id`),
  KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

猜你喜欢

转载自blog.csdn.net/sinat_34338162/article/details/80420559