2019独角兽企业重金招聘Python工程师标准>>>
SpringCloud后端要对前端请求进行拦截,也就是日志记录,使用SpringAOP方式即面向切面方式进行拦截。
首先,拦截请求地址(ip),使用HandlerInterceptorAdapter,它拦截的是请求地址,所以针对请求地址做一些验证、预处理操作比较合适,比如下面,我用它来统计请求访问这个地址的响应时间。
RequestLog
import org.;
import org.;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/*
HandlerInterceptoer拦截的是请求地址,所以针对请求地址做一些验证、预处理等操作比较合适,
比如需要统计请求这个地址的响应时间
*/
/* Filter是Servlet规范规定的,不属于spring框架,也是用于请求的拦截。
但是它适合更粗粒度的拦截,在请求前后做一些编解码处理、日志记录等。
*/
public class RequestLog extends HandlerInterceptorAdapter {
private static final Logger LOGGER = ();
/**
* 前置检查,方法执行前
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String ip = ();
Instant startTime = ();
("logrequestStartTime", startTime);
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取用户token
Method method = ();
("用户:"+ip+",访问目标:"+().getName() + "." + ());
return true;
}
/**
* 方法执行中
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
// controller处理完成
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = ();
Instant startTime = (Instant) ("logrequestStartTime");
Instant endTime = ();
long executeTime = ()- ();
// log it
if (executeTime > 1000) {
("[" + ().getName() + "." + () + "] 执行耗时 : "
+ executeTime + "ms");
} else {
("[" + ().getSimpleName() + "." + () + "] 执行耗时 : "
+ executeTime + "ms");
}
}
}
然后,进行面向切面拦截,将请求日志记录下来
import ;
import ;
import ;
import ;
import org.;
import org.;
import ;
import ;
import ;
import ;
import ;
/**
* Created by pd on 17/12/07.
*/
//描述切面类
@Aspect //@Aspect注解就是告诉spring 这是一个aop类,AOP切面
@Configuration //可理解为用spring的时候xml里面的<beans>标签,类中 @Bean可以理解为用Spring的时候xml里面的<bean>标签
public class LogRecordAspect {
private static final Logger logger = ();
// 用@Pointcut来注解一个切入方法
//@Pointcut注解 声明这是一个需要拦截的切面,也就是说,当调用任何一个controller方法的时候,都会激活这个aop
@Pointcut("execution(* .*Controller.*(..))") //两个..代表所有子目录,最后括号里的两个..代表所有参数
public void excudeService() {
}
//@Around注解 环绕执行,就是在调用之前和调用之后,都会执行一定的逻辑
@Around("excudeService()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
RequestAttributes ra = ();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletRequest request = ((ServletRequestAttributes) ()).getRequest();
String url = ().toString();
String method = ();
String uri = ();
String queryString = ();
try{
Object[] args =();
for(int i=0;i<;i++){
if(args[i] instanceof RequestInfo<?>){
RequestInfo<?> r= (RequestInfo<?>) args[i];
("请求开始, 各个参数, url: {}, method: {}, uri: {}, params: {}", url, method, uri, ());
}else{
("请求开始, 各个参数, url: {}, method: {}, uri: {}, params: {}", url, method, uri,args[i]);
}
}
}catch (Exception e){
("请求开始, 各个参数, url: {}, method: {}, uri: {}, params: {}", url, method, uri,queryString);
}
// result的值就是被拦截方法的返回值
Object result = ();
//("请求结束,controller的返回值是 " + ());
//("请求结束,controller的返回值是 " + result);
return result;
}
}