一,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)