spring boot AOP和spring boot統一異常處理
阿新 • • 發佈:2019-02-20
一,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實現記錄一些請求日誌,統一異常處理,使介面統一返回格式的結果給呼叫方,使介面更加的友好,複雜的應用,可以自己在研究。