Filter和Listener

一、Filter过滤器

1 概念

可以实现拦截功能,对于指定资源的限定进行拦截,替换,同时还可以提高程序的性能。在Web开发时,不同的Web资源中的过滤操作可以放在同一个Filter中完成,这样可以不用多次编写重复代码,从而提高了程序的性能。

Filter有三个接口,Filter接口、FilterConfig接口和FilterChain接口,都位于javax.servlet中。

FilterChain接口的doFilter()方法用于调用过滤器链中的下一个过滤器,如果这个过滤器是链上的最后一个过滤器,则将请求提交给处理程序或将响应发给客户端。

2 Filter生命周期

Filter的生命周期可分为创建、执行、销毁三个阶段。

  • Web服务器启动的时候会创建Filter实例对象,并调用init()方法,完成对象初始化。Filter对象只会创建一次,init()方法也只执行一次。
  • 客户端发送请求资源,如有有符合条件的Filter映射路径,就会按照类名顺序执行doFilter()方法,doFilter()可以执行多次。
  • 服务器关闭,Web服务器调用destroy()方法摧毁Filter对象。

3 Filter的实现

@WebFilter注解

@WebFilter注解的属性filterName用于设置Filter的名称,urlPattern属性用于匹配用户请求的URL,例如"/MyServlet",表示过滤器MyFilter会拦截发送到/MyServlet资源的请求。这个URL还可以使用通配符"*"表示,例如,"*.do"匹配所有以".do"结尾的Servlet路径。

创建Servlet类

java 复制代码
@WebServlet(name = "MyServlet",urlPatterns = "/MyServlet")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       resp.getWriter().write("Hello Servlet");
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

创建Filter类

java 复制代码
@WebFilter(filterName = "MyFilter",urlPatterns = "/MyServlet")
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        PrintWriter writer = servletResponse.getWriter();
        writer.write("Hello Filter");
    }

    @Override
    public void destroy() {

    }
}

没有拦截器运行结果

使用Filter运行结果

4 Filter映射和过滤器链的使用

4.1Filter映射

拦截不同访问方式的请求

注解中的dispatcherTypes属性可以指定过滤器的转发模式,dispatcherTypes属性有4个常用值:Request,INCLUDE、FORWARD、ERROR。

  • REUQUEST :当对include()和forwa()方法进行访问目标资源时,过滤器不会被调用,除外过滤器都会被调用。
  • INCLUDE:当对include()方法进行访问目标资源时,过滤器会被调用,除外过滤器不会被调用。
  • FORWARD:除了forward()外,过滤器不会被调用。
  • ERROR:除异常处理机制调用目标外,过滤器不被调用。

创建Forward类

java 复制代码
@WebServlet(name = "forwardServlet",urlPatterns = "/Forward")
public class Forward extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getRequestDispatcher("/helloworld.jsp").forward(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

创建跳转界面,在web目录下创建

html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>成功</h1>
<%int a = 2;%>
<%=a%>
<%! public int print(){
    int a = 1;
    int b = 2;
    return a+b;
}%>
<%= print() %>
</body>
</html>

创建Filter类

java 复制代码
@WebFilter(filterName = "ForwardFilter",urlPatterns = "/helloworld.jsp",dispatcherTypes = DispatcherType.FORWARD)
public class forwardFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        PrintWriter writer = servletResponse.getWriter();
        writer.write("Hello ForwardFilter");
    }

    @Override
    public void destroy() {
    }
}

启动服务器,访问/forwar页面时,会请求转发到helloworld.jsp页面,但我们启用了过滤器,因此helloworld.jsp页面被拦截,输出doFilter()中的内容。我们在Filter类中的注解设置了dispatcherTypes = DispatcherType.FORWARD,因此在请求转发的时候会被拦截。

4.2 Filter链

Fliter链是指可以对同一个范文目标设置多个过滤器Filter,那么这些过滤器就形成了一个过滤链。

Filter链使用FilterChain对象,FilterChain对象提供了一个doFilter()方法,该方法的作用是让Filter链上的当前过滤器放行,使请求进入下一个Filter。

在整个链的过程中,如果有两个过滤器,Filter1和Filter2,首先对Filter1进行处理,然后执行doFilter()将方法交给Filter2,Filter2处理完执行doFilter()方法,发送最后的请求,浏览器接收后做出响应,同样也会被拦截器所拦截,但拦截的顺序与前面相反。

创建Filter1

java 复制代码
@WebFilter(filterName = "MyFilter01",urlPatterns = "/MyServlet")
public class MyFilter01 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        PrintWriter writer = servletResponse.getWriter();
        writer.write("Hello 01 ");
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

创建Filter2

java 复制代码
@WebFilter(filterName = "MyFilter02",urlPatterns = "/MyServlet")
public class MyFilter02 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        PrintWriter writer = servletResponse.getWriter();
        writer.write("Hello 02  ");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

拦截目标资源

java 复制代码
@WebServlet(name = "MyServlet",urlPatterns = "/MyServlet")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       resp.getWriter().write("Hello Servlet");
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

拦截器的执行顺序是通过命名来执行的。

二、Listener监听器

2.1 概念

Servlet提供了监听器(Listener),专门用于监听Servlet事件。比如监听鼠标单击事件、监听键盘按下事件等。

Listener在监听过程中会涉及几个重要组成部分。

  • (1)事件:用户的一个操作,如单击一个按钮、调用一个方法、创建一个对象等。
  • (2)事件源:产生事件的对象。比如按钮
  • (3)事件监听器:负责监听发生在事件源上的事件。
  • (4)事件处理器:监听器的成员方法,当事件发生的时候会触发对应的处理器(成员方法)。

注意:当用户执行一个操作触发事件源上的事件时,该事件会被事件监听器监听到,当监听器监听到事件发生时,相应的事件处理器就会对发生的事件进行处理。

2.2 监听接口

创建ServletContextlistener监听

java 复制代码
@WebListener
public class MyListener implements ServletContextListener{
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("对象被创建");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("对象被摧毁");
    }
}

重启服务器并关闭,控制台打印信息。

三、Servlet 3.0新特性

常见注解:

  • @WebServlet :修饰Servlet类,用于部署Servlet类。
  • @WebFilter:修饰Filter类,用于部署Filter类
  • @WebListener:修饰Listener类,用于部署Listener类。
  • @WebInitParam:与@WebServlet或@WebFilter注解连用,为@WebServlet或@WebFilter注解配置参数。
  • @MultipartConfig:修饰Servlet类,指定Servlet类负责处理multipart/form-data类型的请求(主要用于处理上传文件)
  • @ServletSecurity:修饰Servlet类,与JAAS(Java验证和授权API)有关的注解。
相关推荐
chaser&upper35 分钟前
Spring 服务调用接口时,提示You should be redirected automatically to target URL:
java
一切皆有迹可循3 小时前
IntelliJ IDEA中Spring Boot项目整合MyBatis:从零实现高效数据持久化
java·spring boot·intellij-idea·mybatis
雾月554 小时前
LeetCode 941 有效的山脉数组
java·开发语言·数据结构·算法·leetcode·职场和发展
小诸葛的博客6 小时前
Apache BookKeeper Ledger 的底层存储机制解析
java
半旧5186 小时前
重构谷粒商城11:node快速入门
java·前端·重构
嘤国大力士7 小时前
C++11&QT复习 (十六)
java·开发语言·c++
菜鸟起航ing7 小时前
【Java面试系列】Spring Boot中自动配置原理与自定义Starter开发实践详解 - 3-5年Java开发必备知识
java·spring boot·面试·自动配置·自定义starter
李白的粉7 小时前
基于springboot+vue的课程管理系统
java·毕业设计·课程设计·源代码·课程管理系统
DDDiccc7 小时前
SpringCloud微服务(一)Eureka+Nacos
java·spring cloud·微服务
橘猫云计算机设计7 小时前
ASP.NET图书馆借阅系统(源码+lw+部署文档+讲解),源码可白嫖!
java·数据库·后端·爬虫·小程序·毕业设计·asp.net