JavaWeb之Filter和Listener技术

Posted 生命是有光的

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaWeb之Filter和Listener技术相关的知识,希望对你有一定的参考价值。

✍目录总览

✍ javaEE进阶之旅

🔥javaEE进阶之旅地址
🔥JavaWeb之HTTP协议(一)https://blog.csdn.net/Augenstern_QXL/article/details/119580669
🔥JavaWeb之Servlet技术(二)https://blog.csdn.net/Augenstern_QXL/article/details/119581366
🔥JavaWeb之JSP技术(三)https://blog.csdn.net/Augenstern_QXL/article/details/119581658
🔥JavaWeb之Cookie和Session技术(四)https://blog.csdn.net/Augenstern_QXL/article/details/119713398
🔥JavaWeb之Filter和Listener技术(五)https://blog.csdn.net/Augenstern_QXL/article/details/119725322

1、过滤器Filter

1.1、过滤器概念及作用

  • 过滤器——Filter,它是JavaWeb三大组件之一。另外两个是Servlet和Listener。

  • 它是在2000年发布的Servlet2.3规范中加入的一个接口。是Servlet规范中非常实用的技术。

  • 它可以对web应用中的所有资源进行拦截,并且在拦截之后进行一些特殊的操作。

  • 常见应用场景:登录验证;过滤敏感词汇;中文乱码问题等等。

1.2、步骤

  1. 导包
    • javax.servlet.jsp-api
    • servlet-api
    • jstl-api
    • standard
  <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
  1. 定义一个类,实现接口Filter

  2. 复写方法

  3. 在web.xml中配置拦截路径

1.3、字符编码过滤器

编写一个字符编码过滤器,我们想要通过过滤器来解决中文乱码问题

先编写一个没有配置编码的 Servlet

ShowServlet.java

public class ShowServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 这里没有配置编码,打印在网站上会乱码
        resp.getWriter().write("你好,世界!");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  • 在web.xml中注册servlet映射
    • 一个Servlet可以指定多个映射路径
<servlet>
    <servlet-name>ShowServlet</servlet-name>
    <servlet-class>com.kuang.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ShowServlet</servlet-name>
    <url-pattern>/servlet/show</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>ShowServlet</servlet-name>
    <url-pattern>/show</url-pattern>
</servlet-mapping>

好了,Demo写好之后我们就可以编写字符编码过滤器了

  1. 定义一个类,实现接口Filter,复写方法

CharacterEncodingFilter.java

// 字符编码过滤器
public class CharacterEncodingFilter implements Filter {
    // 初始:web服务器启动,就已经初始化了,随时等待过滤对象出现!
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化!");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // Chain:链
        // 1.过滤器中的所有代码,在过滤特定请求的时候都会执行
        // 2.必须要让所有过滤器继续同行 filterChain.doFilter(servletRequest,servletResponse)

        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=UTF-8");
        
        System.out.println("CharacterEncodingFilter执行前");
        filterChain.doFilter(servletRequest,servletResponse); // 让我们的请求继续走,如果不写,程序到这里就被拦截了
        System.out.println("CharacterEncodingFilter执行后");

    }

    // 销毁
    @Override
    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }
}
  1. 在web.xml中配置拦截路径
    • 只要是/servlet下面的任何请求,都会经过这个过滤器
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
<!--        只要是/servlet下面的任何请求,都会经过这个过滤器    -->
    <url-pattern>/servlet/*</url-pattern>

</filter-mapping>

1.4、过滤器生命周期方法

  • init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
  • doFilter:每一次请求被拦截资源时,会执行。执行多次
  • destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源

1.5、过滤器配置详解

拦截路径配置

  • 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
  • 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
  • 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
  • 拦截所有资源:/* 访问所有资源时,过滤器都会被执行

1.6、多个过滤器的执行顺序

在过滤器的配置中,有过滤器的声明和过滤器的映射两部分,到底是声明决定顺序,还是映射决定顺序呢?

  • <filter-mapping>的配置前后顺序决定过滤器的调用顺序,也就是由映射配置顺序决定。

1.7、过滤器的五种拦截行为

我们的过滤器目前拦截的是请求,但是在实际开发中,我们还有请求转发和请求包含,以及由服务器触发调用的全局错误页面。默认情况下过滤器是不参与过滤的,要想使用,需要我们配置。配置的方式如下:

<!--配置过滤器-->
<filter>
    <filter-name>FilterDemo1</filter-name>
    <filter-class>com.itheima.web.filter.FilterDemo1</filter-class>
    <!--配置开启异步支持,当dispatcher配置ASYNC时,需要配置此行-->
    <async-supported>true</async-supported>
</filter>
<filter-mapping>
    <filter-name>FilterDemo1</filter-name>
    <url-pattern>/ServletDemo1</url-pattern>
    <!--过滤请求:默认值。-->
    <dispatcher>REQUEST</dispatcher>
    <!--过滤全局错误页面:当由服务器调用全局错误页面时,过滤器工作-->
    <dispatcher>ERROR</dispatcher>
    <!--过滤请求转发:当请求转发时,过滤器工作。-->
    <dispatcher>FORWARD</dispatcher>
    <!--过滤请求包含:当请求包含时,过滤器工作。它只能过滤动态包含,jsp的include指令是静态包含-->
    <dispatcher>INCLUDE</dispatcher>
    <!--过滤异步类型,它要求我们在filter标签中配置开启异步支持-->
    <dispatcher>ASYNC</dispatcher>
</filter-mapping>

1.8、过滤器与Servlet的区别

方法/类型ServletFilter备注
初始化 方法void init(ServletConfig);void init(FilterConfig);几乎一样,都是在web.xml中配置参数,用该对象的方法可以获取到。
提供服务方法void service(request,response);void dofilter(request,response,FilterChain);Filter比Servlet多了一个FilterChain,它不仅能完成Servlet的功能,而且还可以决定程序是否能继续执行。所以过滤器比Servlet更为强大。 在Struts2中,核心控制器就是一个过滤器。
销毁方法void destroy();void destroy();

2、监听器Listener

2.1、ServletContextListener

ServletContextListener:监听 ServletContext 对象的创建和销毁

2.2、步骤

  1. 定义一个类,实现 ServletContextListener 接口,复写方法
public class ContextLoaderListener implements ServletContextListener {
    /**
     * 监听 ServletContext 对象创建。ServletContext 对象服务器启动后自动创建
     * 在服务器启动后自动调用
     * @param servletContextEvent
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext 对象被创建了...");
    }

    /**
     * 服务器关闭后,ServletContext 对象被销毁。当服务器正常关闭后该方法被调用
     * @param servletContextEvent
     */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext 对象被销毁了...");
    }
}

  1. 在 web.xml 中配置
<!--    配置监听器  -->
<listener>
    <listener-class>com.kuang.listener2.ContextLoaderListener</listener-class>
</listener>

2.3、加载资源文件

我们一般很少用 监听器,一般在监听器中加载资源文件

public class ContextLoaderListener implements ServletContextListener {
    /**
     * 监听 ServletContext 对象创建。ServletContext 对象服务器启动后自动创建
     * 在服务器启动后自动调用
     * @param servletContextEvent
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        // 加载资源文件
        // 1.获取ServletContext对象
        ServletContext servletContext = servletContextEvent.getServletContext();
        // 2.加载资源文件
        String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
        // 3.获取真实路径
        String realPath = servletContext.getRealPath(contextConfigLocation);

        // 4.加载进内存
        try {
            FileInputStream is = new FileInputStream(realPath);
            System.out.println(is);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("ServletContext 对象被创建了...");
    }

    /**
     * 服务器关闭后,ServletContext 对象被销毁。当服务器正常关闭后该方法被调用
     * @param servletContextEvent
     */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext 对象被销毁了...");
    }
}

在 web.xml 中配置初始化参数

<!--    指定初始化参数  -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>

以上是关于JavaWeb之Filter和Listener技术的主要内容,如果未能解决你的问题,请参考以下文章

JavaWeb开发之Listener&Filter

JavaWeb详解(第三篇)之Servlet基础简介-过滤器Filter&Listener监听器

JavaWeb之Filter&Listener

JavaWeb之Listener&Filter

024期JavaWeb面试题:Filter和Listener

JavaWeb核心之Servlet