Web 项目 tiger 之13 注册 Servlet 三大组件之 Filter

本文导读

  • 本文承接《  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(过滤器) 简述

  1. Filter(过滤器) 是 Servlet 技术中最实用的技术之一
  2. Web开发人员通过 Filter 技术,对 web 服务器管理的所有 web 资源(如动态的 Jsp、 Servlet,以及静态的 image、 html、CSS、JS 文件等) 进行过滤拦截,从而实现一些特殊的功能(如实现 URL 级别的权限访问控制、过滤敏感词汇、压缩响应信息等) 
  3. Filter 主要用于对用户请求进行预处理,也可以对 HttpServletResponse 进行后期处理(如编码设置,返回时禁用浏览器缓存等)
  4. Filter 使用完整流程:Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后Filter再对服务器响应进行后处理

过滤器 VS 拦截器

  • Servlet 的 Filter 经常会拿来与 Spring MVC 的 Interceptor 做对比
  1. 拦截器是基于 Java 的反射机制的,而过滤器是基于函数回调
  2. 拦截器不依赖与 servle t容器,过滤器依赖与 servlet 容器
  3. 拦截器只能对 action 请求起作用,而过滤器则可以对几乎所有的请求起作用
  4. 拦截器可以访问 action 上下文、值栈里的对象,而过滤器不能访问
  5. 在 action 的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
  6. 拦截器可以获取 IOC 容器中的各个 bean,而过滤器就不行,这点很重要,在拦截器里注入一个 service,可以调用业务逻辑
  7. 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

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/81584608