zoukankan      html  css  js  c++  java
  • spring boot: filter/interceptor/aop在获取request/method参数上的区别(spring boot 2.3.1)

    一,filter/interceptor/aop在获取参数上有什么区别?

    1,filter可以修改HttpServletRequest的参数(doFilter方法的功能),

        interceptor/aop都没有这个功能

        但它不提供到被过滤的方法的访问

        注意区分请求request的方法

    2, interceptor能得到所拦截的方法名和参数名,

       不能得到参数值,

       interceptor的postHandle方法能得到ModelAndView参数,

       用来处理模板的公共参数,把页面的公共内容传递给模板

    3, aspect(Aop)能得到注解所在方法的方法名和参数名、参数值,

        还可以修改方法的参数值

       另外:

       filter/interceptor都是针对请求,

       aop则是针对方法

    看代码,有更直观的感受

    说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

             对应的源码可以访问这里获取: https://github.com/liuhongdi/

    说明:作者:刘宏缔 邮箱: 371125307@qq.com

    二,演示项目的相关信息

    1,项目地址

    https://github.com/liuhongdi/filterinterceptoraop

    2,项目原理:

       我们在controller中的一个方法上,

       添加了filter/interceptor/aspect

       然后比较我们能得到哪些参数,对参数做哪些处理?

    3,项目结构:

    如图:

    三,java代码说明:

    1,ParamFilter.java

    @Component
    public class ParamFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("----------------filter init");
        }
       //过滤功能
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("----------------filter doFilter begin");
            //打印得到的request参数
            Enumeration paramNames = servletRequest.getParameterNames();
            while (paramNames.hasMoreElements()) {
                String paramName = (String) paramNames.nextElement();
                String[] paramValues = servletRequest.getParameterValues(paramName);
                if (paramValues.length == 1) {
                    String paramValue = paramValues[0];
                    if (paramValue.length() != 0) {
                        System.out.println("[filter] request parameter name:"+paramName+";value:"+paramValue);
                    }
                }
            }
            //修改请求参数
            HashMap m = new HashMap(servletRequest.getParameterMap());
            m.put("newp", new String[] { "abcd" });
            m.put("v", new String[] { "filterv" });
            HttpServletRequest req = (HttpServletRequest) servletRequest;
            CustomRequestWrapper wrapRequest = new CustomRequestWrapper(req, m);
            servletRequest = wrapRequest;
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
            System.out.println("----------------filter destroy");
        }
    }

    说明:filter中可以修改request参数,

    但不能对方法进行访问

    2,ValidateorInterceptor.java

    @Component
    public class ValidatorInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("---------------interceptor begin");
    
            //打印request参数
            Enumeration<?> temp = request.getParameterNames();
            if (null != temp) {
                while (temp.hasMoreElements()) {
                    String en = (String) temp.nextElement();
                    String value = request.getParameter(en);
                    System.out.println("[interceptor] request parameters: name:"+en+";value:"+value);
                }
            }
    
            //打印method的相关信息
            if(handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                // 获取处理当前请求的 handler 信息
                System.out.println("[interceptor] method 类名:" + handlerMethod.getBeanType().getName());
                System.out.println("[interceptor] method 方法:" + handlerMethod.getMethod().getName());
    
                MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
                for (MethodParameter methodParameter : methodParameters) {
                    // 只能获取参数的名称,type,index,不能获取到参数的值
                    System.out.println("[interceptor] method parameter Name: " + methodParameter.getParameterName());
                    System.out.println("[interceptor] method parameter Type: " + methodParameter.getParameterType());
                    System.out.println("[interceptor] method parameter Index: " + methodParameter.getParameterIndex());
                }
            }
            //sign校验无问题,放行
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        }
    }

    说明:interceptor中,只能得到方法的参数名,不能得到参数值

    3,RedisRateLimiterAspect.java

    @Component
    @Aspect
    public class RedisRateLimiterAspect {
        @Pointcut("@annotation(com.filterinterceptoraop.demo.annotation.RedisRateLimiter)")
        private void pointcut() {}
    
        /*
        *   around,
        *   if reach limit in time
        *   return error info
        * */
        @Around(value = "pointcut()")
        public Object requestLimit(ProceedingJoinPoint joinPoint) throws Exception {
            System.out.println("---------------aop begin");
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
            //打印request参数
            Enumeration<?> temp = request.getParameterNames();
            if (null != temp) {
                while (temp.hasMoreElements()) {
                    String en = (String) temp.nextElement();
                    String value = request.getParameter(en);
                    System.out.println("[aop] request parameter name:"+en+";value:"+value);
                }
            }
    
            //打印方法的信息
            Object[] args = joinPoint.getArgs();
            try {
                Signature signature = joinPoint.getSignature();
                MethodSignature methodSignature = (MethodSignature)signature;
                //获取目标方法
                Method targetMethod = methodSignature.getMethod();
                String method_name = targetMethod.getName();
                System.out.println("[aop] method name:"+method_name);
                String[] paramNames = methodSignature.getParameterNames();
    
                Map<String, Object> nameAndArgs = new HashMap<String, Object>();
                for (int i = 0; i < paramNames.length; i++) {
                    nameAndArgs.put(paramNames[i], args[i]);// paramNames即参数名
                    if (paramNames[i].equals("version")) {
                        //System.out.println("version value:"+args[i]);
                        args[i] = "aopv";
                    }
                    System.out.println("[aop] method parameter name:"+paramNames[i]+";value:"+args[i]);
                }
    
                if (targetMethod.isAnnotationPresent(RedisRateLimiter.class)) {
                    return joinPoint.proceed(args);
                } else {
                    return joinPoint.proceed();
                }
            } catch (Throwable e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    说明:aop中,可以得到方法的参数名和参数值,而且还可以修改方法的参数值

    四,测试效果

    1,访问url:

    http://127.0.0.1:8080/home/home?v=1

    然后查看控制台的输出

    2,filter的输出

    ----------------filter doFilter begin
    [filter] request parameter name:v;value:1

    filter中我们得到了正确的request参数值

    3,interceptor的输出

    ---------------interceptor begin
    [interceptor] request parameters: name:v;value:filterv
    [interceptor] request parameters: name:newp;value:abcd
    [interceptor] method 类名:com.filterinterceptoraop.demo.controller.HomeController
    [interceptor] method 方法:homeMethod
    [interceptor] method parameter Name: version
    [interceptor] method parameter Type: class java.lang.String
    [interceptor] method parameter Index: 0
    [interceptor] method parameter Name: httpServletRequest
    [interceptor] method parameter Type: interface javax.servlet.http.HttpServletRequest
    [interceptor] method parameter Index: 1
    [interceptor] method parameter Name: httpServletResponse
    [interceptor] method parameter Type: interface javax.servlet.http.HttpServletResponse
    [interceptor] method parameter Index: 2
    [interceptor] method parameter Name: modelMap
    [interceptor] method parameter Type: class org.springframework.ui.ModelMap
    [interceptor] method parameter Index: 3

    请求参数v的值变成了filterv,而且增加了一个请求参数:newp,

    这是filter中代码的作用

    可以看到:interceptor得到了它所拦截请求对应的方法名和参数名,

    但没有方法的参数值,它也不能修改request的参数和方法的参数

    4,aop的输出:

    ---------------aop begin
    [aop] request parameter name:v;value:filterv
    [aop] request parameter name:newp;value:abcd
    [aop] method name:homeMethod
    [aop] method parameter name:version;value:aopv
    [aop] method parameter name:httpServletRequest;value:com.filterinterceptoraop.demo.wrapper.CustomRequestWrapper@1ce466d8
    [aop] method parameter name:httpServletResponse;value:org.apache.catalina.connector.ResponseFacade@45eedc13
    [aop] method parameter name:modelMap;value:{}

    aop中的请求参数没有变,

    它可以得到方法的参数名和参数值,

    在这里我们修改参数version的值为 aopv

    5,controller中的输出:

    ---------------controller begin
    [controller] request parameter name:v;value:filterv
    [controller] request parameter name:newp;value:abcd
    [controller] method parameter version:aopv

    controller中接收到的方法的参数值是我们在aop中修改过的

    五,查看spring boot版本

      .   ____          _            __ _ _
     /\ / ___'_ __ _ _(_)_ __  __ _    
    ( ( )\___ | '_ | '_| | '_ / _` |    
     \/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::        (v2.3.1.RELEASE)
  • 相关阅读:
    一起学编程(2--认识世界)
    在CentOS 6 中安装 Apache,Mysql, PHP
    JavaScript的代码库
    http get请求获取server返回的应答数据
    Effective C++ 45-48
    通过telent、php深入了解http协议
    UVA 10069 Distinct Subsequences(DP)
    Linux局域网搭建
    iTextSharp之pdfRead(两个文件文本内容的比较,指定页数的pdf截取,水印的添加)
    c#操作pdf文件系列之创建文件
  • 原文地址:https://www.cnblogs.com/architectforest/p/13298570.html
Copyright © 2011-2022 走看看