几种常见的拦截器使用

在日常开发中,我们常用拦截器如HandlerInterceptor,ClientHttpRequestInterceptor,RequestInterceptor,AsyncClientHttpRequestInterceptor等,

这几种拦截器都是HTTP拦截器,在处理业务逻辑之前对http请求信息进行处理,比如获取请求头,请求参数,设置请求头,请求参数等;

HandlerInterceptor拦截器

HandlerInterceptor是SpringMVC中的拦截器,它拦截的目标是请求的地址,比MethodInterceptor先执行。

实现一个HandlerInterceptor拦截器可以实现HandlerInterceptor接口,也可以继承HandlerInterceptorAdapter类。

java 复制代码
public interface HandlerInterceptor {

    /**前置处理:在业务处理器处理请求之前被调用*/
	boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception;

	/**中置处理:在业务处理器处理请求执行完成后,生成视图之前执行。*/
	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接口):

java 复制代码
public class CustomInterceptor implements HandlerInterceptor {  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        System.out.println("在Controller方法调用之前执行:" + request.getRequestURI());  
        //只有返回true才会继续向下执行,返回false取消当前请求  
        return true;  
    }  
  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)  
            throws Exception {  
        System.out.println("在Controller方法调用之后,视图被渲染之前执行:" + request.getRequestURI());  
    }  
      
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)  
            throws Exception {  
        System.out.println("在视图被渲染之后执行:" + request.getRequestURI());  
    }  
}  

MethodInterceptor拦截器

MethodInterceptor是AOP项目中的拦截器,它拦截的目标是方法,即使不是Controller中的方法。

实现MethodInterceptor拦截器大致分为两种,一种是实现MethodInterceptor接口,另一种利用AspectJ的注解或配置。

使用示例(实现MethodInterceptor接口):

java 复制代码
//自定义注解类  
@Documented  
@Retention(RetentionPolicy.RUNTIME)  
@Target({ElementType.METHOD})  
public @interface Log {  
     
}

//方法拦截器  
public class CustomMethodInterceptor implements MethodInterceptor{  
    @Override  
    public Object invoke(MethodInvocation invocation) throws Throwable {  
        System.out.println("before...");  
        Object object = invocation.proceed();  
        System.out.println("after...");  
        return object;  
    }  
}

@Configuration  
public class AspectjAutoConfig {  
    @Bean  
    public DefaultPointcutAdvisor getDefaultPointcutAdvisor() {  
        DefaultPointcutAdvisor pointcutAdvisor = new DefaultPointcutAdvisor();  
        pointcutAdvisor.setOrder(Ordered.HIGHEST_PRECEDENCE + 500);  
        //基于方法注解进行拦截  
        AnnotationMatchingPointcut pointcut = new AnnotationMatchingPointcut(null, Log.class);  
        CustomMethodInterceptor advice = new CustomMethodInterceptor();  
        pointcutAdvisor.setPointcut(pointcut);  
        pointcutAdvisor.setAdvice(advice);  
        return pointcutAdvisor;  
    }  
}  

public interface CountryMapper {  
    void show();  
}  
  
  
@Component  
public class CountryMapperImpl implements CountryMapper {  
    //用自定义注解类标注方法,该方法会被自定义方法拦截器进行拦截处理  
    @Log  
    @Override  
    public void show(){  
        System.out.println("invoke show...");  
    }  
}  
    
@RestController
@SpringBootApplication
public class Main{  
    @Autowired  
    private CountryMapper countryMapper;  
      
    public static void main(String[] args){  
        SpringApplication.run(Main.class, args);  
    }  
      
    @GetMapping("/index")  
    public String index(){  
        countryMapper.show();  
        return LocalDateTime.now().toString();  
    }  
}

ClientHttpRequestInterceptor拦截器

ClientHttpRequestInterceptor是对RestTemplate的请求进行拦截的,在项目中直接使用restTemplate.getForObject的时候,会对这种请求进行拦截,经常被称为:RestTemplate拦截器或者Ribbon拦截器。

java 复制代码
public interface ClientHttpRequestInterceptor {

	/**只有这一个方法,在项目中直接使用 restTemplate.getForObject 的时候,会对这种请求进行拦截*/
   ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
         throws IOException;
}

使用示例(实现ClientHttpRequestInterceptor 接口):

java 复制代码
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拦截器

RequestInterceptor常被称为是Feign拦截器,由于Feign调用底层实际上还是http调用,因此也是一个http拦截器。

在项目中使用Feign调用的时候,可以使用此拦截器。

java 复制代码
public interface RequestInterceptor {

  /**在项目中使用Feign调用的时候,可以使用此拦截器*/
  void apply(RequestTemplate template);
}

使用示例(实现RequestInterceptor接口):

java 复制代码
public class FeignRequestInterceptor implements RequestInterceptor, Ordered {
	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;
                }
            }
    }
}

AsyncClientHttpRequestInterceptor拦截器

AsyncClientHttpRequestInterceptor从Spring 5.0开始,同样是处理http请求,主要是针对 AsyncRestTemplate的请求进行拦截,但目前标记为不推荐使用;

使用示例(实现AsyncClientHttpRequestInterceptor接口):

java 复制代码
public class TestAsyncRestTemplateInterceptor implements AsyncClientHttpRequestInterceptor, Ordered {
    public TestAsyncRestTemplateInterceptor() {
    }

    public int getOrder() {
        return 10;
    }

    public ListenableFuture<ClientHttpResponse> intercept(HttpRequest request, byte[] body, AsyncClientHttpRequestExecution execution) throws IOException {
           URI uri = request.getURI();
           String serviceName = uri.getHost();
           map.put("spring-application-name", serviceName);
           String reqAttr = URLEncoder.encode(JacksonSerializer.serializer.serialize(map), StandardCharsets.UTF_8.name());
           request.getHeaders().add("reqAttr", reqAttr);
           return execution.executeAsync(request,body);
    }
}
相关推荐
搬码后生仔1 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net
凡人的AI工具箱1 小时前
每天40分玩转Django:Django国际化
数据库·人工智能·后端·python·django·sqlite
Lx3522 小时前
Pandas数据重命名:列名与索引为标题
后端·python·pandas
小池先生2 小时前
springboot启动不了 因一个spring-boot-starter-web底下的tomcat-embed-core依赖丢失
java·spring boot·后端
小蜗牛慢慢爬行3 小时前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
wm10434 小时前
java web springboot
java·spring boot·后端
龙少95435 小时前
【深入理解@EnableCaching】
java·后端·spring
溟洵7 小时前
Linux下学【MySQL】表中插入和查询的进阶操作(配实操图和SQL语句通俗易懂)
linux·运维·数据库·后端·sql·mysql
SomeB1oody10 小时前
【Rust自学】6.1. 定义枚举
开发语言·后端·rust
SomeB1oody10 小时前
【Rust自学】5.3. struct的方法(Method)
开发语言·后端·rust