- Spring
Boot中有两种拦截网页方式,可以对未登录的请求进行拦截,防止用户跳过登录,直接进入界面
- Filter 过滤器
- HandlerInterceptor 拦截器
- Filter和HandlerInterceptor的区别:
- Filter是Servlet容器规定的,只能使用在servlet容器中,而拦截器则是独立存在的,可以在任何情况下使用
- 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
- Filter在servlet前后起作用。而拦截器执行在方法前后,异常抛出前后,因此拦截器具有更大的弹性
Filter->
Interceptor.preHandle->
Handler->
Interceptor.postHandle->
Interceptor.afterCompletion->
Filter->
因此所有在spring框架中应该优先使用拦截器。
- 拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
- 拦截器的执行过程是在过滤器的doFilter中执行的,可以多次调用,过滤器的初始化会在项目启动时执行,只能初始化一次
Filter 过滤器
- Filter是Servlet容器规定的,只能使用在servlet容器中使用
- 拦截器是属于spring的一个组件,因此可以使用spring的所有资源,对象,如service对象,数据源,事务控制等
注解方式
- @WebFilter这个注解是Servlet3.0的规范,且并没有指定执行的顺序,其执行顺序依赖于Filter的名称,是根据Filter类名(注意不是配置的filter的名字)的字母顺序倒序排列
- @WebFilter指定的过滤器优先级都高于FilterRegistrationBean配置的过滤器
属性名 |
描述 |
filterName |
指定过滤器的 name 属性,等价于 <filter-name> |
value |
该属性等价于 urlPatterns 属性。但是两者不应该同时使用。 |
urlPatterns |
指定一组过滤器的 URL 匹配模式。等价于 <url-pattern> 标签。 |
servletNames |
指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 <servlet-name> 的取值。 |
dispatcherTypes |
指定过滤器的转发模式。具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。 |
initParams |
指定一组过滤器初始化参数,等价于 <init-param> 标签。 |
asyncSupported |
声明过滤器是否支持异步操作模式,等价于 <async-supported> 标签。 |
description |
该过滤器的描述信息,等价于 <description> 标签。 |
displayName |
该过滤器的显示名,通常配合工具使用,等价于 <display-name> 标签。 |
- 创建一个Filter,并使用WebFilter注解进行修饰命名,表示该类是一个Filter,以便于启动类进行扫描的时候确认
示例
@WebFilter(urlPatterns = "/*",filterName = "filter2") public class FilterAnnotationTest implements Filter {
@Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("过滤器2开始初始化"); }
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("过滤器2开始工作"); filterChain.doFilter(servletRequest,servletResponse); }
@Override public void destroy() { System.out.println("过滤器2销毁"); } } |
代码方式
直接重写实现Filter接口,在添加 @Configuration 注解的配置类中使用 FilterRegistrationBean 注册
示例
public class FilterDemo implements Filter {
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; System.out.println("过滤器开始工作。。"+httpServletRequest.getRequestURL()); filterChain.doFilter(servletRequest,servletResponse); }
@Override public void destroy() { System.out.println("过滤器开始销毁"); } } |
然后利用filterRegistrationBean来进行注册
示例
@Configuration public class FilterDemo { @Bean @Order(2) //spring boot会按照order值的大小,从小到大的顺序来依次过滤 public FilterRegistrationBean configFilter(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new FilterDemo()); filterRegistrationBean.addUrlPatterns("/*"); filterRegistrationBean.setName("sessionFilter"); //filterRegistrationBean.setOrder(2); return filterRegistrationBean; } } |
HandlerInterceptor 拦截器
- 实现HandlerInterceptor拦截器,可以实现对请求进行预处理,后处理
- 编写拦截器实现类AdminInterceptor,实现接口HandlerInterceptor
示例
public class AdminInterceptor implements HandlerInterceptor {
// 在请求处理之前进行调用(Controller方法调用之前) @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // System.out.println("执行了TestInterceptor的preHandle方法"); try { //统一拦截(查询当前session是否存在user)(这里user会在每次登陆成功后,写入session) User user=(User)request.getSession().getAttribute("USER"); if(user!=null){ return true; //向后执行 } response.sendRedirect(request.getContextPath()+"你的登陆页地址"); } catch (IOException e) { e.printStackTrace(); } return false;//停止执行 }
// 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后) @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { // System.out.println("执行了TestInterceptor的postHandle方法"); }
// 在整个请求结束之后被调用,主要是用于进行资源清理工作 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // System.out.println("执行了TestInterceptor的afterCompletion方法"); }
} |
- 注册拦截器,通过编写拦截器配置文件类并继承 WebMvcConfigurer类,并重写其中的方法 addInterceptors并且在主类上加上注解 @Configuration,将拦截器添加到自定义的配置类中
示例
@Configuration public class LoginConfig implements WebMvcConfigurer {
@Override public void addInterceptors(InterceptorRegistry registry) { //注册TestInterceptor拦截器 InterceptorRegistration registration = registry.addInterceptor(new AdminInterceptor());
registration.addPathPatterns("/**"); //拦截所有路径
registration.excludePathPatterns( //添加不拦截的静态资源 "/login", //登录界面路径 "/**/*.html", //html静态资源 "/**/*.js", //js静态资源,"/js/**" "/**/*.css", //css静态资源,"/css/**" "/**/*.img", "/**/*.woff", "/**/*.ttf" ); } } |