上面3种拦截器,都是http拦截器,在处理业务逻辑之前对http请求信息进行处理,比如获取请求头,请求参数,设置请求头,请求参数等等
思路清晰,先说jar包:
HandlerInterceptor
—>spring-webmvc
项目,org.springframework.web.servlet.HandlerInterceptor
ClientHttpRequestInterceptor
—>spring-web
项目,org.springframework.http.client.ClientHttpRequestInterceptor
RequestInterceptor
—>feign-core
项目,feign.RequestInterceptor
一目了然,从项目名称和包路径可以看出,3个拦截器分别属于3个不同的项目,所以他们之前的作用也有区别,在这里我大概讲一下3个拦截器的基本应用和区别:
3个拦截器的共同点,都是对http请求进行拦截,但是http
请求的来源不同
HandlerInterceptor
是最常规的,其拦截的http
请求是来自于客户端浏览器之类的,是最常见的http
请求拦截器;ClientHttpRequestInterceptor
是对RestTemplate
的请求进行拦截的,在项目中直接使用restTemplate.getForObject
的时候,会对这种请求进行拦截,经常被称为:RestTempalte
拦截器或者Ribbon
拦截器;RequestInterceptor
常被称为是Feign
拦截器,由于Feign
调用底层实际上还是http
调用,因此也是一个http
拦截器,在项目中使用Feign调用的时候,可以使用此拦截器;从包路径可以看出,这个是处理客户端http servlet
请求的,此项目spring-webmvc
与spring-mvc
项目关闭密切,HandlerInterceptor
可以对请求的各个阶段进行拦截,可以说是非常全面了。这个也是常规项目中用的最多的,对http请求进行拦截
publicinterfaceHandlerInterceptor{/**前置处理:在业务处理器处理请求之前被调用*/booleanpreHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;/**中置处理:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView ,现在这个很少使用了*/voidpostHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;/**后置处理:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等*/voidafterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;
使用示例(HandlerInterceptorAdapter
实现了HandlerInterceptor
接口)
publicclassTestFilterextendsHandlerInterceptorAdapter{privatefinal Logger logger= LoggerFactory.getLogger(TestFilter.class);@OverridepublicbooleanpreHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception{ logger.info("request请求地址path[{}] uri[{}]", request.getServletPath(),request.getRequestURI());//request.getHeader(String) 从请求头中获取数据//从请求头中获取用户token(登陆凭证根据业务而定) Long userId=getUserId(request.getHeader("H-User-Token"));if(userId!= null&&checkAuth(userId,request.getRequestURI())){returntrue;}//这里的异常是我自定义的异常,系统抛出异常后框架捕获异常然后转为统一的格式返回给前端, 其实这里也可以返回falsethrownewFastRuntimeException(20001,"No access");}private LonggetUserId(String userToken){ Long userId= null;return userId;}privatebooleancheckAuth(Long userId,String requestURI){returntrue;}@OverridepublicvoidpostHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception{}@OverridepublicvoidafterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception{}
}
publicinterfaceClientHttpRequestInterceptor{/**只有这一个方法,在项目中直接使用 restTemplate.getForObject 的时候,会对这种请求进行拦截*/ ClientHttpResponseintercept(HttpRequest request,byte[] body, ClientHttpRequestExecution execution)throws IOException;
使用示例(SESSIONID
可以从RequestContextHolder
中拿到)
publicclassRestClientHttpRequestInterceptorimplementsClientHttpRequestInterceptor{@Overridepublic ClientHttpResponseintercept(HttpRequest request,byte[] body, ClientHttpRequestExecution execution)throws IOException{ HttpHeaders headers= request.getHeaders(); headers.add("Cookie","SESSIONID=b8dd5bd9-9fb7-48cb-a86b-e079cb554fb8"); log.info("拦截器已添加header");return execution.execute(request,body);}}
publicinterfaceRequestInterceptor{/**在项目中使用Feign调用的时候,可以使用此拦截器*/voidapply(RequestTemplate template);}
使用示例
publicclassFeignInterceptorimplementsRequestInterceptor{privatestaticfinal String SESSIONID="SESSIONID";privatestaticfinal String SESSIONID_PREFIX="SESSIONID=";privatestaticfinal String COOKIE="Cookie";@Overridepublicvoidapply(RequestTemplate requestTemplate){ ServletRequestAttributes servletAttributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest httpServletRequest= servletAttributes.getRequest(); Cookie[] cookies= httpServletRequest.getCookies();for(Cookie cookie: cookies){if(SESSIONID.equals(cookie.getName())){ requestTemplate.header(COOKIE, SESSIONID_PREFIX+cookie.getValue());break;}}}}