1. 程式人生 > >spring boot AOP和spring boot統一異常處理

spring boot AOP和spring boot統一異常處理

一,spring AOP

spring boot使用AOP,程式碼如下,程式碼比較簡單就不細說了,直接上程式碼,可以使用AOP做日誌處理

package com.qwrt.fire.sensor.aop;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by jack on 2017/7/10.
 * 記錄呼叫Controller的日誌
 */
@Aspect
@Component
public class LogAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
    private static final ThreadLocal<Long> timeTreadLocal = new ThreadLocal<>();

    @Pointcut("execution(* com.qwrt.fire.sensor.rest..*.*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
    //@Pointcut("execution(* com.qwrt.fire.user.rest..*(..))")
    public void log() {
    }

    @Before("log()")
    public void before(JoinPoint joinPoint) {
        timeTreadLocal.set(System.currentTimeMillis());
        // 接收到請求,記錄請求內容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //獲取請求的request
        HttpServletRequest request = attributes.getRequest();
        //獲取所有請求的引數,封裝為map物件
        // Map<String,Object> parameterMap = getParameterMap(request);
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //獲取被攔截的方法
        Method method = methodSignature.getMethod();
        //獲取被攔截的方法名
        String methodName = method.getName();
        logger.info("AOP begin ,請求開始方法  :{}", method.getDeclaringClass() + "." + methodName + "()");
        //獲取所有請求引數key和value
        String keyValue = getReqParameter(request);
        logger.info("請求url = {}", request.getRequestURL().toString());
        logger.info("請求方法requestMethod = {}", request.getMethod());
        logger.info("請求資源uri = {}", request.getRequestURI());
        logger.info("所有的請求引數 key:value = {}", keyValue);
    }


    @After("log()")
    public void after() {
        logger.info("aop的after()方法");
    }

    //controller請求結束返回時呼叫
    @AfterReturning(returning = "result", pointcut = "log()")
    public Object afterReturn(Object result) {
        logger.info("AOP afterReturn,返回值result = {}", result.toString());
        // System.out.println("返回值="+result.toString());
        long startTime = timeTreadLocal.get();
        double callTime = (System.currentTimeMillis() - startTime) / 1000.0;
        logger.info("呼叫controller花費時間time = {}s", callTime);
        return result;
    }

    /**
     * 獲取所有請求引數,封裝為map物件
     *
     * @return
     */
    public Map<String, Object> getParameterMap(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        Enumeration<String> enumeration = request.getParameterNames();
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        StringBuilder stringBuilder = new StringBuilder();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getParameter(key);
            String keyValue = key + " : " + value + " ; ";
            stringBuilder.append(keyValue);
            parameterMap.put(key, value);
        }
        return parameterMap;
    }

    public String getReqParameter(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        Enumeration<String> enumeration = request.getParameterNames();
        //StringBuilder stringBuilder = new StringBuilder();
        JSONArray jsonArray = new JSONArray();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getParameter(key);
            JSONObject json = new JSONObject();
            //String keyValue = key+" : " +value+" ; ";
            json.put(key, value);
            //stringBuilder.append(keyValue);
            jsonArray.add(json);
        }
        //JSONObject jsonObject = new JSONObject();
        //jsonObject.put("請求引數為:",jsonArray.toString());
        return jsonArray.toString();
    }


}


上面的程式碼是對指定包下面的所有controller進行請求前後的攔截,列印日誌。利用了aop的切面,切點知識。

二,統一異常處理

      spring boot的統一異常處理,利用統一異常處理,可以對請求的結果統一格式,不把一些錯誤資訊返回給呼叫端,返回結果更加友好,程式碼如下:

package com.qwrt.fire.sensor.aop;

import com.alibaba.fastjson.JSONObject;
import com.qwrt.fire.common.util.JsonUtil;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * Created by jack on 2017/8/24.
 * 統一異常處理
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    public JSONObject defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        JSONObject jsonObject = JsonUtil.getFailJsonObject(e.getMessage());
        return jsonObject;
    }


}

   使用RestControllerAdvice註解,這個註解可以對所有controller的異常進行統一的處理。

  @ExceptionHandler註解,表示要處理的異常有哪些,可以處理多種型別的異常,賦值給value就行了。

   總結:上面就是spring boot的aop和統一異常簡單實現,可以利用他們做一些相關的事情,比如aop實現記錄一些請求日誌,統一異常處理,使介面統一返回格式的結果給呼叫方,使介面更加的友好,複雜的應用,可以自己在研究。