Spring MVC經過AOP切面編程 來攔截controller 實現日誌的寫入

首選須要參考的是:【參考】http://www.cnblogs.com/guokai870510826/p/5977948.htmlhtml

               http://www.cnblogs.com/guokai870510826/p/5981015.htmljava

1:首先定義mavenweb

 

  <!--配置aop切面編程須要引入的包-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>4.1.7.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.5.3</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.4</version>
    </dependency>
    <dependency>
      <groupId>aopalliance</groupId>
      <artifactId>aopalliance</artifactId>
      <version>1.0</version>
    </dependency>
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.2.4</version>
    </dependency>

 

2:在攔截controller以前 須要自定義一個註解spring

package com.cdms.aop;

import java.lang.annotation.*;

/**
 * Created by 草帽boy on 2017/2/21.
 */

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemLog {
    String module()  default "";
    String methods()  default "";
}

其目的是 如圖:數據庫

三:配置spring-web.xml 編程

 

  <!--Aop切面編程的配置-->
    <aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
    <bean id="logAopAction" class="com.cdms.aop.LogAopAction"></bean>

四:aop的實現類中處理記錄日誌的邏輯json

package com.cdms.aop;

import com.cdms.dto.User;
import com.cdms.entity.Log;
import com.cdms.util.SessionUtil;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * Created by 草帽boy on 2017/2/21.
 */
@Aspect
public class LogAopAction {
    //獲取開始時間
    private long BEGIN_TIME ;

    //獲取結束時間
    private long END_TIME;

    //定義本次log實體
    private Log log = new Log();

    @Pointcut("execution(* com.cdms.controller..*.*(..))")
    private void controllerAspect(){}

    /**
     * 方法開始執行
     */
    @Before("controllerAspect()")
    public void doBefore(){
        BEGIN_TIME = new Date().getTime();
        System.out.println("開始");
    }

    /**
     * 方法結束執行
     */
    @After("controllerAspect()")
    public void after(){
        END_TIME = new Date().getTime();
        System.out.println("結束");
    }

    /**
     * 方法結束執行後的操做
     */
    @AfterReturning("controllerAspect()")
    public void doAfter(){

        if(log.getState()==1||log.getState()==-1){
            log.setActionTime(END_TIME-BEGIN_TIME);
            log.setGmtCreate(new Date(BEGIN_TIME));
            System.out.println(log);
            System.out.println(">>>>>>>>>>存入到數據庫");
        }else {
            System.out.println(log);
            System.out.println(">>>>>>>>不存入到數據庫");
        }
    }

    /**
     * 方法有異常時的操做
     */
    @AfterThrowing("controllerAspect()")
    public void doAfterThrow(){
        System.out.println("例外通知-----------------------------------");
    }


    /**
     * 方法執行
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("controllerAspect()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        //日誌實體對象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //獲取當前登錄用戶信息
        User loginUser = SessionUtil.getLoginSession(request);
        if(loginUser==null){
            log.setLoginAccount("—— ——");
        }else{
            log.setLoginAccount(loginUser.getUserAuth().getIdentity());
        }

        // 攔截的實體類,就是當前正在執行的controller
        Object target = pjp.getTarget();
        // 攔截的方法名稱。當前正在執行的方法
        String methodName = pjp.getSignature().getName();
        // 攔截的方法參數
        Object[] args = pjp.getArgs();
        // 攔截的放參數類型
        Signature sig = pjp.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("該註解只能用於方法");
        }
        msig = (MethodSignature) sig;
        Class[] parameterTypes = msig.getMethod().getParameterTypes();

        Object object = null;

        Method method = null;
        try {
            method = target.getClass().getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (SecurityException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        if (null != method) {
            // 判斷是否包含自定義的註解,說明一下這裏的SystemLog就是我本身自定義的註解
            if (method.isAnnotationPresent(SystemLog.class)) {
                SystemLog systemlog = method.getAnnotation(SystemLog.class);
                log.setModule(systemlog.module());
                log.setMethod(systemlog.methods());
                log.setLoginIp(getIp(request));
                log.setActionUrl(request.getRequestURI());

                try {
                    object = pjp.proceed();
                    log.setDescription("執行成功");
                    log.setState((short) 1);
                } catch (Throwable e) {
                    // TODO Auto-generated catch block
                    log.setDescription("執行失敗");
                    log.setState((short)-1);
                }
            } else {//沒有包含註解
                object = pjp.proceed();
                log.setDescription("此操做不包含註解");
                log.setState((short)0);
            }
        } else { //不須要攔截直接執行
            object = pjp.proceed();
            log.setDescription("不須要攔截直接執行");
            log.setState((short)0);
        }
        return object;
    }

    /**
     * 獲取ip地址
     * @param request
     * @return
     */
    private String getIp(HttpServletRequest request){
        if (request.getHeader("x-forwarded-for") == null) {
            return request.getRemoteAddr();
        }
        return request.getHeader("x-forwarded-for");
    }
}

 其中個人Log實體類以下圖所示session

/**
     * 日誌id
     */
    private Integer id;

    /**
     * 當前操做人id
     */
    private String loginAccount;

    /**
     * 當前操做人ip
     */
    private String loginIp;

    /**
     * 操做請求的連接
     */
    private String actionUrl;

    /**
     * 執行的模塊
     */
    private String module;

    /**
     * 執行的方法
     */
    private String method;

    /**
     * 執行操做時間
     */
    private Long actionTime;

    /**
     * 描述
     */
    private String description;

    /**
     * 執行的時間
     */
    private Date gmtCreate;

    /**
     * 該操做狀態,1表示成功,-1表示失敗!
     */
    private Short state;

 

四:咱們在看一下 controller中的註解怎麼寫app

    /**
     * 登錄消息驗證
     * @param userAuth 用戶登錄信息
     * @param request http協議請求
     * @return 一個帶參數的json數據
     */
    @RequestMapping(value = "/toLogin",method = RequestMethod.POST,
            produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    @SystemLog(methods = "用戶管理",module = "用戶登錄")
    public JSONObject toLogin(UserAuth userAuth, HttpServletRequest request){
        JSONObject loginJson = userService.userLogin(userAuth);
        //表示登錄成功
        if(loginJson.get("key").equals("success")){
            //放入到session中
            SessionUtil.setLoginSession(request,loginJson.get("data"));
            return JSONOperation.successMessage("登錄成功!");
        }
        return loginJson;
    }

在控制檯的打印結果是:maven

開始
結束
Log{id=null, loginAccount='919132691@qq.com', loginIp='127.0.0.1', actionUrl='/user/toLogin', module='用戶登錄', method='用戶管理', actionTime=0, description='執行成功', gmtCreate=Tue Feb 21 18:56:15 CST 2017, state=1}
>>>>>>>>>>存入到數據庫
相關文章
相關標籤/搜索