SpringBoot中对于拦截器的使用与应用场景解析

应用场景

  • 权限检查:检查是否有访问某接口的权限;
  • 日志记录:记录请求信息的日志,便于进行信息监控与统计;
  • 性能检测:慢日志等记录时间的场景;

如何实现拦截器

拦截器接口

public interface HandlerInterceptor {
	/**
	 * 预处理回调方法,预处理
	 * @param request	请求
	 * @param response	响应
	 * @param handler	响应的处理器,自定义Controller
	 * @return	返回true则流程继续,返回false则流程中断,此时需要通过response参数产生响应
	 * @throws Exception
	 */
	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return true;
	}

	/**
	 * 后处理回调方法,前后端不分离环境下可以通过modelAndView对模型数据进行处理
	 * @param request	请求
	 * @param response	响应
	 * @param handler	自定义处理器
	 * @param modelAndView	视图
	 * @throws Exception
	 */
	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
	}

	/**
	 * 整个接口的处理完毕回调函数,该函数内部可以进行处理链中资源的回收,或者记录
	 * 该接口所耗费的时间,进行性能检测
	 * @param request
	 * @param response
	 * @param handler
	 * @param ex
	 * @throws Exception
	 */
	default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable Exception ex) throws Exception {
	}

}

这三个方法在MVC结构中可以简单理解为:

  • Controller前(preHandle)
  • Controller后(postHandle)
  • 接口完全处理完毕(afterCompletion)

拦截器接口实现实例

实现一个拦截器的主要步骤有三步:

  1. 编写类实现HandlerInterceptor接口
  2. 编写配置类实现WebMvcConfigurer接口注册拦截器
  3. 指定需要拦截的路径与放行的路径

一、实现HandlerInterceptor接口

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @ClassName InterceptorDemo
 * @Description 实现HandlerInterceptor接口
 * @Author 黄乙轩
 * @Date 2021/6/20 10:31
 * @Version 1.0
 **/

public class InterceptorDemo implements HandlerInterceptor{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        System.out.println(handler);
        String id = request.getParameter("id");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }
}

二、编写配置类

/**
 * @ClassName InterceptorConfig
 * @Description 编写配置类注册拦截器
 * @Author 黄乙轩
 * @Date 2021/6/20 10:36
 * @Version 1.0
 **/

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration registration = registry.addInterceptor(new InterceptorDemo());
    }
}

这里需要注意一点,就是拦截器的运行顺序是按照注册的顺序执行的。

三、指定拦截路径与放行路径
这里我们假设我们需要拦截所有的请求,除了login请求不进行拦截。

/**
 * @ClassName InterceptorConfig
 * @Description 编写配置类注册拦截器
 * @Author 黄乙轩
 * @Date 2021/6/20 10:36
 * @Version 1.0
 **/

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration registration = registry.addInterceptor(new InterceptorDemo());
        registration
                .addPathPatterns("/**")
                .excludePathPatterns("/login");
    }
}

这样一个简单的拦截器就完成了。

我们来开启服务来进行一下简单的测试。

Demo展示

/**
 * @ClassName Controller
 * @Description Controller类
 * @Author 黄乙轩
 * @Date 2021/6/20 10:38
 * @Version 1.0
 **/

@CrossOrigin
@RestController
public class Controller {
    @RequestMapping("/demo")
    public void demo(@RequestParam("id")String id){
        System.out.println("id:"+id);
        System.out.println("demo");
    }

    @RequestMapping("/login")
    public void login(){
        System.out.println("login");
    }
}

利用Postman进行测试;
先来进行demo接口的测试:
在这里插入图片描述
在这里插入图片描述

在进行 login 接口的测试:
在这里插入图片描述
在这里插入图片描述
可以看到并没有进行拦截;

可以观测到后端的响应顺序是:
preHandler => controller => postHandle => afterCompletion

如此一个简单的拦截器就完成了;

一些SpringBoot中使用拦截器的坑点

拦截器中无法自动注入

场景:在一次写项目的过程中,使用到了拦截器以及单点登录;我想现在后端拦截器中进行权限查询,但是我发现他不能进行自动注入,@Autowired 之后对象为空。

原因:我们可以看到这个地方:在这里插入图片描述
我们是通过new来创建的对象,而在SpringBoot中并不会把new创建的对象当做bean进行管理。

解决方法:通过构造注入与@Bean注解进行管理,同时记得给拦截器加上@Component注解

例:

	@Bean
    public InterceptorDemo getInterceptorDemo(){
        return new InterceptorDemo();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration registration = registry.addInterceptor(getInterceptorDemo());
        registration
                .addPathPatterns("/**")
                .excludePathPatterns("/login");
    }

总结

拦截器的应用场景很多,而且在SpringBoot中十分重要,其操作其实十分简单,主要是实现 HandlerInterceptor 接口以及编写配置类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值