springboot之aop切面获取请求中的信息
本帖最后由 逸帅 于 2021-2-4 18:10 编辑springboot之aop切面获取请求
项目场景:
在学习springboot的博客开发中,通过aop切面,对博客中的操作进行记录
https://static.52pojie.cn/static/image/hrline/line7.pnghttps://static.52pojie.cn/static/image/hrline/line7.pnghttps://static.52pojie.cn/static/image/hrline/line7.pnghttps://static.52pojie.cn/static/image/hrline/line7.png
问题描述:
问题:
在切面方法中,无法获取请求的参数和类名,方法,ip等
https://static.52pojie.cn/static/image/hrline/line7.pnghttps://static.52pojie.cn/static/image/hrline/line7.pnghttps://static.52pojie.cn/static/image/hrline/line7.pnghttps://static.52pojie.cn/static/image/hrline/line7.png
解决方法:
@Before("log()")//调用log方法
public void doBefore(JoinPoint joinPoint){
System.out.println("------程序执行之前-----------");
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
String url = request.getRequestURL().toString();
String ip= request.getRemoteAddr();
Object[] args = joinPoint.getArgs();
// 类名-->方法名
String methodName = joinPoint.getSignature().getDeclaringTypeName()+"-->"
+joinPoint.getSignature().getName();
getRequestLog getRequestLog = new getRequestLog(url,ip,methodName,args);
System.out.println(getRequestLog);
}
https://static.52pojie.cn/static/image/hrline/line7.pnghttps://static.52pojie.cn/static/image/hrline/line7.pnghttps://static.52pojie.cn/static/image/hrline/line7.pnghttps://static.52pojie.cn/static/image/hrline/line7.png
过程:
RequestContextHolder是一个包含了request请求的容器,所以要获取请求中的信息,自然要从容器中获取。
然而RequestContextHolder只能获取RequestAttributes对象,要取得request,必须从ServletRequestAttributes获取
通过查看底层的源码,可以发现ServletRequestAttributes是继承了AbstractRequestAttributes,然后AbstractRequestAttributes继承了RequestAttributes
也就是说ServletRequestAttributes是RequestAttributes的子类,所以直接强转就可以了
通过强转后的ServletRequestAttributes直接getRequest,即可得到request对象
使用了内部类封装所需要打印的值
// 内部类,封装需要得到的值
private class getRequestLog{
private String url;
private String ip;
private String methodName;
private Object[] requestParms;
public getRequestLog() {
}
public getRequestLog(String url, String ip, String methodName, Object[] requestParms) {
this.url = url;
this.ip = ip;
this.methodName = methodName;
this.requestParms = requestParms;
}
@Override
public String toString() {
return "getRequestLog{" +
"url='" + url + '\'' +
", ip='" + ip + '\'' +
", methodName='" + methodName + '\'' +
", requestParms=" + Arrays.toString(requestParms) +
'}';
}
// 获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes
.resolveReference(RequestAttributes.REFERENCE_REQUEST);
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
Method method = signature.getMethod();
// 获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
// 获取请求的方法名
String methodName = method.getName();
methodName = className + "." + methodName;
// 请求的参数
Map<String, String> rtnMap = converMap(request.getParameterMap());
// 将参数所在的数组转换成json
String params = JSONUtil.toJsonStr(rtnMap); 看我上面的demo,你的那个 貌似不行 hualonghongyan 发表于 2021-2-4 18:21
看我上面的demo,你的那个 貌似不行
你这个demo应该是按照百度前面几篇文章得到的吧,我这个也能获取到值的,其实也差不多的,都是要得到ServletRequestAttributes对象,然后获得HttpServletRequest,requestAttributes可以直接调用getRequest方法哦,你可以试试,感觉比你那种简单一点点 这种一般都是通过实现RequestBodyAdvice
@ControllerAdvice(assignableTypes={AnalyzeController.class})
public class RequestLogger implements RequestBodyAdvice, ResponseBodyAdvice<MyRequest> {
@Override
public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
return httpInputMessage;
}
@Override
public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParzameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
MDC.put("key1","value1");
MDC.put("key2","value2");
MyRequestContextHolder.setContext(new MyRequest());
RequestContextHolder.getRequestAttributes().setAttribute("",body, RequestAttributes.SCOPE_REQUEST);
return body;
}
@Override
public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return o;
}
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public MyRequest beforeBodyWrite(MyRequest o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
MDC.clear();
MyRequestContextHolder.remove();
return o;
}
} Tisrop 发表于 2021-2-4 22:20
这种一般都是通过实现RequestBodyAdvice
@ControllerAdvice(assignableTypes={Ana ...
应该是有多种方法,但是感觉RequestContextHolder好像看起来简单一点点{:301_978:} 逸帅 发表于 2021-2-4 18:37
你这个demo应该是按照百度前面几篇文章得到的吧,我这个也能获取到值的,其实也差不多的,都是要得到Serv ...
好吧,我看差啦,我以为你贴的代码是获取不到的哈哈哈,原来是解决方案 hualonghongyan 发表于 2021-2-5 09:38
好吧,我看差啦,我以为你贴的代码是获取不到的哈哈哈,原来是解决方案
嘻嘻,没事啦,我们一起进步{:301_987:}
页:
[1]