上面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请求进行拦截
public interface HandlerInterceptor {
/**前置处理:在业务处理器处理请求之前被调用*/
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception;
/**中置处理:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView ,现在这个很少使用了*/
void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception;
/**后置处理:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等*/
void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception;
使用示例(HandlerInterceptorAdapter
实现了HandlerInterceptor
接口)
public class TestFilter extends HandlerInterceptorAdapter {
private final Logger logger = LoggerFactory.getLogger(TestFilter.class);
@Override
public boolean preHandle(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())){
return true;
}
//这里的异常是我自定义的异常,系统抛出异常后框架捕获异常然后转为统一的格式返回给前端, 其实这里也可以返回false
throw new FastRuntimeException(20001,"No access");
}
private Long getUserId(String userToken){
Long userId = null;
return userId;
}
private boolean checkAuth(Long userId,String requestURI){
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 {}
}
public interface ClientHttpRequestInterceptor {
/**只有这一个方法,在项目中直接使用 restTemplate.getForObject 的时候,会对这种请求进行拦截*/
ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException;
使用示例(SESSIONID
可以从RequestContextHolder
中拿到)
public class RestClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(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);
}
}
public interface RequestInterceptor {
/**在项目中使用Feign调用的时候,可以使用此拦截器*/
void apply(RequestTemplate template);
}
使用示例
public class FeignInterceptor implements RequestInterceptor {
private static final String SESSIONID = "SESSIONID";
private static final String SESSIONID_PREFIX = "SESSIONID=";
private static final String COOKIE = "Cookie";
@Override
public void apply(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;
}
}
}
}