吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2200|回复: 7
上一主题 下一主题
收起左侧

[Java 转载] springboot之aop切面获取请求中的信息

[复制链接]
跳转到指定楼层
楼主
逸帅 发表于 2021-2-4 18:02 回帖奖励
本帖最后由 逸帅 于 2021-2-4 18:10 编辑

springboot之aop切面获取请求
项目场景:

在学习springboot的博客开发中,通过aop切面,对博客中的操作进行记录




问题描述:
问题:
在切面方法中,无法获取请求的参数和类名,方法,ip等



解决方法:

[Java] 纯文本查看 复制代码
@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);
    }







过程:

RequestContextHolder是一个包含了request请求的容器,所以要获取请求中的信息,自然要从容器中获取。
然而RequestContextHolder只能获取RequestAttributes对象,要取得request,必须从ServletRequestAttributes获取
通过查看底层的源码,可以发现ServletRequestAttributes是继承了AbstractRequestAttributes,然后AbstractRequestAttributes继承了RequestAttributes
也就是说ServletRequestAttributesRequestAttributes的子类,所以直接强转就可以了
通过强转后的ServletRequestAttributes直接getRequest,即可得到request对象

使用了内部类封装所需要打印的值

[Java] 纯文本查看 复制代码
//    内部类,封装需要得到的值
    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) +
                '}';
    }

  

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
hualonghongyan 发表于 2021-2-4 18:20
// 获取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);
3#
hualonghongyan 发表于 2021-2-4 18:21
4#
 楼主| 逸帅 发表于 2021-2-4 18:37 |楼主
hualonghongyan 发表于 2021-2-4 18:21
看我上面的demo,你的那个 貌似不行

你这个demo应该是按照百度前面几篇文章得到的吧,我这个也能获取到值的,其实也差不多的,都是要得到ServletRequestAttributes对象,然后获得HttpServletRequest,requestAttributes可以直接调用getRequest方法哦,你可以试试,感觉比你那种简单一点点
5#
Tisrop 发表于 2021-2-4 22:20
这种一般都是通过实现RequestBodyAdvice
[Java] 纯文本查看 复制代码
@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;
    }
}
6#
 楼主| 逸帅 发表于 2021-2-5 09:10 |楼主
Tisrop 发表于 2021-2-4 22:20
这种一般都是通过实现RequestBodyAdvice
[mw_shl_code=java,true]@ControllerAdvice(assignableTypes={Ana ...

应该是有多种方法,但是感觉RequestContextHolder好像看起来简单一点点
7#
hualonghongyan 发表于 2021-2-5 09:38
逸帅 发表于 2021-2-4 18:37
你这个demo应该是按照百度前面几篇文章得到的吧,我这个也能获取到值的,其实也差不多的,都是要得到Serv ...

好吧,我看差啦,我以为你贴的代码是获取不到的哈哈哈,原来是解决方案
8#
 楼主| 逸帅 发表于 2021-2-5 11:53 |楼主
hualonghongyan 发表于 2021-2-5 09:38
好吧,我看差啦,我以为你贴的代码是获取不到的哈哈哈,原来是解决方案

嘻嘻,没事啦,我们一起进步
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 18:05

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表