Filter
1.1 Filter概述
Filter 表示过滤器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。Servlet 我们之前都已经学习过了,Filter和Listener 我们今天都会进行学习。
过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。
如下图所示,浏览器可以访问服务器上的所有的资源(servlet、jsp、html等)
而在访问到这些资源之前可以使过滤器拦截来下,也就是说在访问资源之前会先经过 Filter,如下图
1.2Filter快速入门
拦截器拦截到后可以做什么功能呢?
过滤器一般完成一些通用的操作
比如每个资源都要写一些代码完成某个功能,我们总不能在每个资源中写这样的代码吧,而此时我们可以将这些代码写在过滤器中,因为请求每一个资源都要经过过滤器。
我们之前做的品牌数据管理的案例中就已经做了登陆的功能,而如果我们不登录能不能访问到数据呢?我们可以在浏览器直接访问首页 ,可以看到 查询所有
的超链接
1.init和destroy是生命周期有关的方法 doFilter是过滤器的核心方法将来每次访问过滤器都会访问这个方法
2.其中Filter的路径不是资源的访问路径而是要拦截资源的路径
过滤器是拦截对资源访问的请求的
3.dofilter中做了一些操作然后放走人家 然后让他继续访问后续资源 chain.doFilter(request,response)
快速入门webFilter里面写的是拦截路径
@WebFilter("/*")
public class FilterDemo implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo...");
//放行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
在doFilter方法中输出一句话,并放行
上述代码中的
chain.doFilter(request,response);
就是放行,也就是让其访问本该访问的资源。
1.3 Filter执行流程
如上图是使用过滤器的流程,我们通过以下问题来研究过滤器的执行流程:
-
放行后访问对应资源,资源访问完成后,还会回到Filter中吗?
从上图就可以看出肯定 会 回到Filter中
-
如果回到Filter中,是重头执行还是执行放行后的逻辑呢?
如果是重头执行的话,就意味着
放行前逻辑
会被执行两次,肯定不会这样设计了;所以访问完资源后,会回到放行后逻辑
,执行该部分代码。
执行逻辑为:
首先执行Filter中放行前的逻辑 放行 访问web资源 响应回来执行放行后逻辑
1.4 Filter拦截路径配置
拦截路径表示 Filter 会对请求的哪些资源进行拦截,使用 @WebFilter
注解进行配置。如:@WebFilter("拦截路径")
拦截路径有如下四种配置方式:
- 拦截具体的资源:/index.jsp:只有访问index.jsp时才会被拦截
- 目录拦截:/user/*:访问/user下的所有资源,都会被拦截
- 后缀名拦截:*.jsp:访问后缀名为jsp的资源,都会被拦截
- 拦截所有:/*:访问所有资源,都会被拦截
hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>hello JSP~</h1>
<%
System.out.println("2.hello jsp");
%>
</body>
</html>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>index JSP~</h1>
<%
System.out.println("index jsp");
%>
</body>
</html>
1.5 过滤器链
1.5.1 概述
过滤器链是指在一个Web应用,可以配置多个过滤器,这多个过滤器称为过滤器链。
如下图就是一个过滤器链,我们学习过滤器链主要是学习过滤器链执行的流程
上图中的过滤器链执行是按照以下流程执行:
- 执行
Filter1
的放行前逻辑代码 - 执行
Filter1
的放行代码 - 执行
Filter2
的放行前逻辑代码 - 执行
Filter2
的放行代码 - 访问到资源
- 执行
Filter2
的放行后逻辑代码 - 执行
Filter1
的放行后逻辑代码
以上流程串起来就像一条链子,故称之为过滤器链。
FilterDemo.java
@WebFilter("/*")
public class FilterDemo implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//1.放行前 对request数据进行处理 同时response是没有数据的
System.out.println("1.FilterDemo...");
//放行 的时候就用方形前处理完成request数据
filterChain.doFilter(servletRequest, servletResponse);
//3.放行后 等资源访问完成 response对象内部才有数据 所以放行后才对资源进行处理
System.out.println("5.FilterDemo");
}
@Override
public void destroy() {
}
}
FilterDemo2.java
@WebFilter("/*")
public class FilterDemo2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//1.放行前 对request数据进行处理 同时response是没有数据的
System.out.println("2.FilterDemo...");
//放行 的时候就用方形前处理完成request数据
filterChain.doFilter(servletRequest, servletResponse);
//3.放行后 等资源访问完成 response对象内部才有数据 所以放行后才对资源进行处理
System.out.println("4.FilterDemo");
}
@Override
public void destroy() {
}
}
hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>hello JSP~</h1>
<%
System.out.println("3.hello jsp");
%>
</body>
</html>
这两个过滤器看似没有任何关系 到底如何执行先后
这里先执行Filter1的代码 再执行Filter2的代码 注解配置的Filter,优先级按照过滤器类名的自然排序
也就是FilterDemo和FilterDemo2的类名一个个字符进行比较 注解配置的Filter,优先级按照过滤器类名(字符串)的自然排序
2.Listener
2.1 概述
-
Listener 表示监听器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。
-
监听器可以监听就是在
application
,session
,request
三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。request 和 session 我们学习过。而
application
是ServletContext
类型的对象。ServletContext
代表整个web应用,在服务器启动的时候,tomcat会自动创建该对象。在服务器关闭时会自动销毁该对象。
2.2 分类
JavaWeb 提供了8个监听器:
这里面只有 ServletContextListener
这个监听器后期我们会接触到,ServletContextListener
是用来监听 ServletContext
对象的创建和销毁。
ServletContextListener
接口中有以下两个方法
void contextInitialized(ServletContextEvent sce)
:ServletContext
对象被创建了会自动执行的方法void contextDestroyed(ServletContextEvent sce)
:ServletContext
对象被销毁时会自动执行的方法
2.3 代码演示
sevletContext对象代表web应用程序创建 对象就被创建了说明web应用加载成功
我们只演示一下 ServletContextListener
监听器
- 1.定义一个类,实现
ServletContextListener
接口 - 2.重写所有的抽象方法
- 3.使用
@WebListener
进行配置
代码如下:
@WebListener
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//加载资源
System.out.println("ContextLoaderListener");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
//释放资源
}
}
Connected to server
[2023-03-11 11:05:16,322] Artifact brand-demo:war exploded: Artifact is being deployed, please wait…
11-Mar-2023 23:05:17.070 信息 [RMI TCP Connection(2)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。
ContextLoaderListener