一,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实现记录一些请求日志,统一异常处理,使接口统一返回格式的结果给调用方,使接口更加的友好,复杂的应用,可以自己在研究。