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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM