SpringBoot常用拦截器(HandlerInterceptor,ClientHttpRequestInterceptor,RequestInterceptor)

SpringBoot常用拦截器(HandlerInterceptor,ClientHttpRequestInterceptor,RequestInterceptor)

上面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调用的时候,可以使用此拦截器;

谈谈HandlerInterceptor

从包路径可以看出,这个是处理客户端http servlet请求的,此项目spring-webmvcspring-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 {}

}

谈谈ClientHttpRequestInterceptor
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);
    }
}

谈谈RequestInterceptor
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;
                }
            }
    }

}

你可能感兴趣的:(java,SpringBoot,spring,boot,java,spring)