本文导读
- 本文承接《 Web 项目 tiger 之12 注册 Servlet 三大组件之 Servlet》
- Spring Boot 由于默认以 Jar 包方式启动嵌入式的 Servlet 容器来启动 Spring Boot 的 web 应用,没有 web.xml 文件,所以无法再像以前一样通过在 web.xml 配置来使用 Filter ,所以 Spring Boot 提供了其它的方式。
- 本文前半部分都是关于 Servlet 的 Filter 的回顾与铺垫,本文核心的东西在 "Spring Boot 注册 Filter" 部分
Filter(过滤器) 简述
- Filter(过滤器) 是 Servlet 技术中最实用的技术之一
- Web开发人员通过 Filter 技术,对 web 服务器管理的所有 web 资源(如动态的 Jsp、 Servlet,以及静态的 image、 html、CSS、JS 文件等) 进行过滤拦截,从而实现一些特殊的功能(如实现 URL 级别的权限访问控制、过滤敏感词汇、压缩响应信息等)
- Filter 主要用于对用户请求进行预处理,也可以对 HttpServletResponse 进行后期处理(如编码设置,返回时禁用浏览器缓存等)
- Filter 使用完整流程:Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后Filter再对服务器响应进行后处理
过滤器 VS 拦截器
- Servlet 的 Filter 经常会拿来与 Spring MVC 的 Interceptor 做对比
- 拦截器是基于 Java 的反射机制的,而过滤器是基于函数回调
- 拦截器不依赖与 servle t容器,过滤器依赖与 servlet 容器
- 拦截器只能对 action 请求起作用,而过滤器则可以对几乎所有的请求起作用
- 拦截器可以访问 action 上下文、值栈里的对象,而过滤器不能访问
- 在 action 的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
- 拦截器可以获取 IOC 容器中的各个 bean,而过滤器就不行,这点很重要,在拦截器里注入一个 service,可以调用业务逻辑
- SpringMVC 有自己的拦截器
web. xml 方式的 Filter
- 这一部分主要用于简单的回忆 Servlet 的 FIlter 的知识点,好用于与之后的 Spring Boot 方式进行对比
自定义 FIlter
web. xml 配置
运行测试
Spring Boot 注册 Filter
- 这里才是本文的重点,上面纯粹是回顾和铺垫
- 关于 Servler 的 Filter 的实际应用这里不做累述,无论是“设置应用的统一编码”、“请求\响应乱码过滤器”、“动态资源禁止缓存过滤器’、“自动登录过滤器” 等等,都不做深入讲解,这里只说如何使用 Spring Boot 来注册 Servlet 的 Filter 组件
自定义 Filter
package com.lct.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* Created by Administrator on 2018/8/11 0011.
* 标准 Servlet 过滤器,实现 javax.servlet.Filter 接口
* 并重写它的 三个方法
*/
public class SystemFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("javax.servlet.Filter::服务器启动....");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
/**
* 转为 HttpServletRequest 输出请求路径 容易查看 请求地址
*/
HttpServletRequest request = (HttpServletRequest) servletRequest;
System.out.println("javax.servlet.Filter::过滤器放行前...." + request.getRequestURL());
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("javax.servlet.Filter::过滤器返回后...." + request.getRequestURL());
}
@Override
public void destroy() {
System.out.println("javax.servlet.Filter::服务器关闭....");
}
}
注册 FilterRegistrationBean
- 如同 Servlet 组件需要将 ServletRegistrationBean 也添加到 Spring 容器中一样,FIlter 同样需要添加 FilterRegistrationBean
package com.lct.config;
import com.lct.component.MyLocaleResolve;
import com.lct.filter.SystemFilter;
import com.lct.servlet.BookServlet;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.DispatcherType;
import java.util.Arrays;
/**
* Created by Administrator on 2018/7/28 0028.
* 自定义配置类
*/
@Configuration
public class MyMvcConfig {
/**
* 将我们自己的 LocaleResolver 组件交于 Spring 容器管理
* 从而覆盖 Spring Boot默认的区域信息解析器
*
* @return
*/
@Bean
public LocaleResolver localeResolver() {
return new MyLocaleResolve();
}
/**
* 自定义嵌入式Servlet容器定制器组件
* 然后修改应用上下文路径以及 Tomcat 端口
*
* @return
*/
@Bean
public WebServerFactoryCustomizer webServerFactoryCustomizer() {
/**
* 使用 ConfigurableServletWebServerFactory
*/
return new WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>() {
@Override
public void customize(ConfigurableServletWebServerFactory configurableServletWebServerFactory) {
/**
* 修改应用上下文路径以及 Tomcat 端口
*/
configurableServletWebServerFactory.setContextPath("/cat");
configurableServletWebServerFactory.setPort(8084);
}
};
}
/**
* 注册 Servlet 三大组件 之 Servlet
* 添加 ServletRegistrationBean ,就相当于以前在 web.xml 中配置的 <servlet></servlet>标签
*/
@Bean
public ServletRegistrationBean myServlet() {
/**第二个参数是个不定参数组,可以配置映射多个请求
* 相当于以前在 web.xml中配置的 <servlet-mapptin></servlet-mapptin>*/
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new
BookServlet(), "/bookServlet");
return registrationBean;
}
/**
* 注册 Servlet 三大组件 之 Filter (过滤器)
* 添加 FilterRegistrationBean ,就相当于以前在 web.xml 中配置的 <filter></filter> 标签
*/
@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
/**同样添加自定义的 Filter*/
registrationBean.setFilter(new SystemFilter());
/**然后设置过滤的路径,参数是个集合 ,相当于 web.xml中配置的 <filter-mapptin></filter-mapptin>
* "/*": 表示过滤所有 get 与 post 请求*/
registrationBean.setUrlPatterns(Arrays.asList("/*"));
/**
* setDispatcherTypes 相当于 web.xml 配置中 <filter-mapptin> 下的 <dispatcher> 标签
* 用于过滤非常规的 get 、post 请求
* REQUEST:默认方式,写了之后会过滤所有静态资源的请求
* FORWARD:过滤所有的转发请求,无论是 jsp 中的 <jsp:forward</>、<%@ page errorPage= %>、还是后台的转发
* INCLUDE:过滤 jsp 中的动态包含<jsp:include 请求
* ERROR:过滤在 web.xml 配置的全局错误页面
* 了解即可,实际中也很少这么做
*/
registrationBean.setDispatcherTypes(DispatcherType.REQUEST);
return registrationBean;
}
}
运行测试
- 因为页面上的所有静态的资源的请求都属于 Request 范畴,所以都被过滤了,实际中通常不这么做的
com.lct.component.LoginHandlerInterceptor ::: http://localhost:8084/cat/user/users
javax.servlet.Filter::过滤器返回后....http://localhost:8084/cat/user/users
javax.servlet.Filter::过滤器放行前....http://localhost:8084/cat/user/users
com.lct.component.LoginHandlerInterceptor ::: http://localhost:8084/cat/user/users
javax.servlet.Filter::过滤器返回后....http://localhost:8084/cat/user/users
javax.servlet.Filter::过滤器放行前....http://localhost:8084/cat/asserts/css/bootstrap.min.css
javax.servlet.Filter::过滤器放行前....http://localhost:8084/cat/asserts/css/dashboard.css
javax.servlet.Filter::过滤器放行前....http://localhost:8084/cat/asserts/js/jquery-3.2.1.slim.min.js
javax.servlet.Filter::过滤器返回后....http://localhost:8084/cat/asserts/css/dashboard.css
javax.servlet.Filter::过滤器返回后....http://localhost:8084/cat/asserts/js/jquery-3.2.1.slim.min.js
javax.servlet.Filter::过滤器返回后....http://localhost:8084/cat/asserts/css/bootstrap.min.css
javax.servlet.Filter::过滤器放行前....http://localhost:8084/cat/asserts/js/popper.min.js
javax.servlet.Filter::过滤器返回后....http://localhost:8084/cat/asserts/js/popper.min.js
javax.servlet.Filter::过滤器放行前....http://localhost:8084/cat/asserts/js/bootstrap.min.js
javax.servlet.Filter::过滤器放行前....http://localhost:8084/cat/asserts/js/feather.min.js
javax.servlet.Filter::过滤器返回后....http://localhost:8084/cat/asserts/js/bootstrap.min.js
javax.servlet.Filter::过滤器返回后....http://localhost:8084/cat/asserts/js/feather.min.js
javax.servlet.Filter::过滤器放行前....http://localhost:8084/cat/userList.js
javax.servlet.Filter::过滤器放行前....http://localhost:8084/cat/asserts/js/Chart.min.js
com.lct.component.LoginHandlerInterceptor ::: http://localhost:8084/cat/userList.js
javax.servlet.Filter::过滤器返回后....http://localhost:8084/cat/userList.js
javax.servlet.Filter::过滤器返回后....http://localhost:8084/cat/asserts/js/Chart.min.js