filter&listener
今日内容:
Filter(过滤器) [今天]
Listener(监听器) [明天]
Web阶段的三大组件:
Servlet[最最最重要的]
Filter<偶尔可能用到的>
Listener(基本很少用到的)
第1章 过滤器简介
1.1 为什么要使用过滤器
当用户想要访问某些资源时,我们需要他/她/它满足一定的条件,此时我们就可以给这些资源创建一个过滤器,
满足条件的用户可以访问,反之不能访问
1.2 什么是过滤器
在Java只要实现Filter接口的类,我们就称为过滤器
第2章 过滤器的应用场景
2.1 过滤论坛中用户发表内容中的非法字符
2.2 登录权限检查
第3章 过滤器开发步骤
3.1 Filter的API介绍
a.定义一个实现类,实现Filter接口
b.重写doFilter方法,该方法就表示执行过滤的方法
c.如果请求满足要求,那么放行(访问目标资源)!!
如果请求不满足要求,那么拦截
3.2 使用步骤
1. 编写一个Servlet,路径为/test,并在web.xml配置或者注解配置
2. 给目标资源添加一个过滤器
a.定义一个实现类,实现Filter接口
b.重写doFilter方法,该方法就表示执行过滤的方法
c.如果请求满足要求,那么放行(访问目标资源)!!
如果请求不满足要求,那么拦截
3.配置过滤器
web.xml配置:
<!--配置Filter-->
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>com.itheima.web.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/test</url-pattern>
</filter-mapping>
注解配置:
@WebFilter(filterName = "TestFilter",urlPatterns = "/目标资源的路径")
4.过滤器拦截到目标资源之后执行doFilter方法,默认不放行!!
如果需要放行,那么调用:
filterChain.doFilter(servletRequest,servletResponse);
3.3 注意事项
过滤器的doFilter默认拦截(不放行),想要放行,调用filterChain.doFilter(servletRequest,servletResponse)
3.4 XML方式代码演示
<!--配置Servlet-->
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.itheima.web.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
<!--配置Filter-->
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>com.itheima.web.filter.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/test</url-pattern>
</filter-mapping>
3.5 注解方式代码演示
/**
* 目标资源
*/
@WebServlet(name = "MyServlet",urlPatterns = "/my")
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//0.设置响应体和请求体的编码
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//1.输出
System.out.println("目标资源到达了...");
}
}
/**
* 目标资源过滤器
*/
@WebFilter(filterName = "MyFilter",urlPatterns = "/my")
public class MyFilter implements Filter {
//过滤方法
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器执行了...");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
}
第4章 过滤器的执行流程
4.1 生活案例类比过滤器流程
比如:坐飞机/火车的安全检查
4.2 图解过滤器的执行流程(图)
注意: 当过滤器放行后,执行目标资源,当前目标资源执行后,
又会回到过滤器接着执行过滤器的以后的内容,最后才响应给浏览器
第5章 过滤器的生命周期
5.1 init方法
init方法称为初始化方法,当过滤器创建后调用(服务器启动时创建)
5.2 doFilter方法
doFilter方法称为过滤方法,当访问目标资源时调用(访问一次,调用一次)
5.3 destory方法
destory方法称为销毁方法,当过滤器被销毁时调用(正常关闭服务器或者从服务器中卸载该项目)
5.4 过滤器生命周期总结(了解)
当项目随着服务器启动后,调用过滤器的init
当用户访问的路径是过滤器过滤的路径时,调用过滤器的doFilter
当正常关闭服务器或者从服务器中卸载该项目时,调用过滤器的destory
第6章 过滤器映射路径
6.1 精确匹配模式
urlPatterns = "/具体的资源路径"
6.2 模糊匹配模式
-
整个应用的配置(全站过滤)
urlPatterns = "/*" 无论访问当前项目下何种资源,该过滤器都可以拦截
-
指定目录下的路径配置
urlPatterns = "/aa/*" 只要访问当前项目下"/aa/"下的任何资源,该过滤器都可以拦截
-
指定后缀名的路径配置
urlPatterns = "*.jsp" 只要访问当前项目下任何以jsp结尾的资源,该过滤器都可以拦截
第7章 拦截方式
我们可以规定,过滤器拦截目标资源的拦截方式是request或者是forward
7.1 request
拦截方式request,表示直接从浏览器访问的请求(包括重定向),这是默认的拦截方式!!
7.2 forward
拦截方式forward,表示从其他Servlet转发过来的请求
注意:
如果想规定请求的方式是POST还是GET,我们后期可以借助SpringMVC框架来处理
/**
* 目标资源
*/
@WebServlet(name = "TestServlet",urlPatterns = "/test")
public class TestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//0.设置响应体和请求体的编码
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//1.输出
System.out.println("目标资源执行了...");
}
}
//@WebFilter(filterName = "TestFilter",urlPatterns = "/test") 默认拦截类型是request,浏览器直接访问
@WebFilter(filterName = "TestFilter",urlPatterns = "/test",dispatcherTypes = DispatcherType.FORWARD) //拦截类型是forward,浏览器转发访问
public class TestFilter 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("过滤器执行了...");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
/**
* 转发到test的servlet
*/
@WebServlet(name = "ForwardToTestServlet",urlPatterns = "/to")
public class ForwardToTestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//0.设置响应体和请求体的编码
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//1.把请求转发到test
request.getRequestDispatcher("/test").forward(request, response);
}
}
7.3 两种拦截方式能否共存
可以,在配置或注解时,写上两种拦截方式即可
XML:
<filter>
<filter-name>MethodFilter</filter-name>
<filter-class>com.itheima.myfilter.MethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MethodFilter</filter-name>
<url-pattern>/index.jsp</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
注解:
@WebFilter(dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST})
总结
1. 能够说出过滤器的作用
过滤器是对目标资源访问的请求进行拦截的,如何条件放行,返回不放行
========================
a.创建目标资源(servlet,html,jsp,图片,txt)
b.创建Filter的实现类,重写doFilter方法
默认是不放行
如果需要放行:调用filterChain的dofilter(request,response)
c.配置Filter实现类的拦截路径
xml配置:
<filter>
<filter-mappging>
注解配置:
@WebFilter(filterName="..",urlPatterns="/拦截资源的路径")
=========================
2. 能够说出过滤器生命周期相关方法
init 服务器启动执行
doFilter 每次访问目标资源执行
destory 正常关闭服务器或者卸载项目执行
3.过滤器的路径匹配写法
a.精确匹配 /test
b.目录匹配 /目录名/*
c.扩展名匹配 *.jsp *.html
d.全站匹配 /* (Servlet也有缺省匹配,"/")
4.拦截方式
dispatcherType.request(默认的): 只拦截浏览器直接请求(重定向)
dispatcherType.forward(可配置): 只拦截其他资源转发过来的请求(请求转发)
第8章 过滤器链
8.1 什么是过滤器链
访问目标资源时,需要经过多个过滤器,只有这些过滤器都放行了,请求才能到达目标资源
这里的多个过滤器,我们称为过滤器链
比如: 做飞机去北京(身份证,登机牌,体温,体温,到达你北京的"家")
8.2 过滤器链中多个过滤器的执行顺序
8.3 XML配置代码演示
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!--Servlet类-->
<servlet>
<servlet-name>ObjectServlet</servlet-name>
<servlet-class>com.itheima.web.servlet.ObjectServlet</servlet-class>
</servlet>
<!--Servlet路径-->
<servlet-mapping>
<servlet-name>ObjectServlet</servlet-name>
<url-pattern>/obj</url-pattern>
</servlet-mapping>
<!--配置BFilter-->
<filter>
<filter-name>BFilter</filter-name>
<filter-class>com.itheima.web.filter.BFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BFilter</filter-name>
<url-pattern>/obj</url-pattern>
</filter-mapping>
<!--配置AFilter-->
<filter>
<filter-name>AFilter</filter-name>
<filter-class>com.itheima.web.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/obj</url-pattern>
</filter-mapping>
</web-app>
如果是XML配置的过滤器,那么在前的过滤器先执行,在后的过滤器后执行
只有当前所有的过滤器链都放行的情况下请求才能达到目标资源
如果有一个过滤器不放行,那么请求到此就结束了
8.4 注解配置代码演示
/**
* 目标Servlet
*/
@WebServlet(name = "ObjectServlet",urlPatterns = "/obj")
public class ObjectServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//0.设置响应体和请求体的编码
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//1.输出
System.out.println("请求达到目标资源...");
}
}
@WebFilter(filterName = "AFilter",urlPatterns = "/obj")
public class AFilter 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("A过滤器执行了..");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
@WebFilter(filterName = "BFilter",urlPatterns = "/obj")
public class BFilter 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("B过滤器执行了..");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
如果是注解配置的过滤器,那么过滤器执行的先后顺序和配置的过滤器名有关(ASCII码值小的过滤器先执行..)
只有当前所有的过滤器链都放行的情况下请求才能达到目标资源
如果有一个过滤器不放行,那么请求到此就结束了
所以在后期开发中,我们建议使用xml配置过滤器,xml便于控制过滤器链的执行顺序!!!
8.5 过滤器链的执行流程(图)
第9章 案例:非法字符
9.1 案例需求
创建一个发表言论的表单页面,点击发表时,通过过滤器检查是否有非法字符串,如果有不让发表,如果没有正常发表言论
9.2 案例分析
我们发表言论之前需要经过一个过滤器
a.如果有非法词语 那么不放行
b.如果没有非法词语 那么放行
9.3 实现步骤
a.创建BBS.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>BBS论坛</title></head>
<body>
<form method="post" action="${pageContext.request.contextPath}/bbs">
请发表你的言论:
<input type="text" name="message">
<input type="submit" value="提交">
</form>
</body>
</html>
注意:我们使用${pageContext.request.contextPath},获取项目的根路径 "/项目名" 更加灵活
b.发表言论Servlet
/**
* 发表言论的Servlet
*/
@WebServlet(name = "BBSServlet",urlPatterns = "/bbs")
public class BBSServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//0.设置响应体和请求体的编码
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//1.获取请求中发表的言论数据
String message = request.getParameter("message");
//2.输出到页面
response.getWriter().println("您的言论:"+message+",发表成功");
}
}
c.发表言论的非法词语过滤器
/**
* BBS论坛发表言论的过滤器
*/
@WebFilter(filterName = "BBSFilter",urlPatterns = "/bbs")
public class BBSFilter implements Filter{
public ArrayList<String> words = new ArrayList<String>();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
try {
//3.读取words.txt中敏感词
String realPath = filterConfig.getServletContext().getRealPath("/words.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(realPath), "UTF-8"));
//标准循环
String line = "";
while ((line = br.readLine()) != null) {
words.add(line);
}
br.close();
System.out.println(words);
} catch (IOException ie) {
ie.printStackTrace();
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//要对用户发表的言论进行过滤
//0.将父类ServletRequest,ServletResponse转成子类HttpServletRequest和HttpServletResponse
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
//1.设置响应体和请求体的编码
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//2.通过request获取数据
String message = request.getParameter("message");
System.out.println(message);
//4.判断message中是否含有非法言论
for (String word : words) {
//判断message中是否含有非法言论
if (message.contains(word)) {
//言论不合法
response.getWriter().println("您的言论不合法!");
return;
}
}
//5.放行
filterChain.doFilter(request, response);
}
}
注意: 我们过滤器每访问一次就会执行一次doFilter方法,所以我们把读取words.txt的代码放到init方法中
这样就不会每次都去重写读取,而是在过滤器创建的时候读取一次就够了,提高代码的性能!!
9.4 案例加强—使用装饰者模式完成非法字符过滤(了解)
装饰设计模式: 也叫包装设计模式
可以在不改变原有类的基础上,对类的某个方法进行增加
装饰设计模式一般的步骤:
a.继承原有类
b.构造方法时,传入原有类的引用
c.需要增强的方法我们进行重写,不需要增强的方法不需要重写(使用原来的方法即可)
案例1:
比如:对BufferedReader进行增强,读取一行时,不仅仅可以读取内容,还要加上行号
//包装BufferedReader的readline方法,能输出行号
public class LineNumberBufferedReader extends BufferedReader {
//子类可以继承父类的方法
private int num = 1;
public LineNumberBufferedReader(Reader reader) {
super(reader);
}
//要增强谁,覆盖谁
public String readLine() throws IOException {
String data = super.readLine();
if (data == null) return null;
return (num++) + ":" + data;
}
public static void main(String[] args) {
//读LineNumberReader源码
try {
InputStream in = new FileInputStream("E:\\heima126\\day26_IlleageWords\\web\\words.txt");
Reader reader = new InputStreamReader(in, "UTF-8");//字符流
BufferedReader bufferedReader = new BufferedReader(reader);
//读一行
LineNumberBufferedReader lineNumberReader = new LineNumberBufferedReader(bufferedReader);
//带行号
String data = null;
while ((data = lineNumberReader.readLine()) != null) {
System.out.println(data);
}
lineNumberReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
案例2:对HttpServletRequest的getParameter方法进行增强,通过getParameter获取数据时,如果数据中
有敏感词,把对应的敏感词变为**号
//对普通的HttpServletRequest类的装饰类
public class DirtyWordsHttpServletRequest extends HttpServletRequestWrapper {
private List<String> dicts;
public DirtyWordsHttpServletRequest(HttpServletRequest request, List<String> dicts) {
super(request);
this.dicts = dicts;
}
//重点:重写getParameter方法,获取数据时,如果有敏感词在方法中替换成*号
public String getParameter(String name) {
String param = super.getParameter(name);
if (param == null)
return null; //有值:替换脏词
if (dicts != null && dicts.size() > 0) {
for (String word : dicts) {
if (param.contains(word)) {
StringBuffer sb = new StringBuffer();//StringBuilder
for (int i = 0; i < word.length(); i++) {
//word有几个字符,就搞几个*
sb.append("*");
}
param = param.replace(word, sb.toString());
}
}
}
//最后返回的内容,所有的敏感词都已经替换成*号了
return param;
}
}
/**
* BBS论坛发表言论的过滤器
*/
@WebFilter(filterName = "BBSFilter",urlPatterns = "/bbs")
public class BBSFilter implements Filter{
public ArrayList<String> words = new ArrayList<String>();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
try {
//3.读取words.txt中敏感词
String realPath = filterConfig.getServletContext().getRealPath("/words.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(realPath), "UTF-8"));
//标准循环
String line = "";
while ((line = br.readLine()) != null) {
words.add(line);
}
br.close();
System.out.println(words);
} catch (IOException ie) {
ie.printStackTrace();
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//要对用户发表的言论进行过滤
//0.将父类ServletRequest,ServletResponse转成子类HttpServletRequest和HttpServletResponse
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
//1.设置响应体和请求体的编码
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//2.通过request获取数据
String message = request.getParameter("message");
System.out.println(message);
//4.由于我们已经对HttpServletRequest进行了增强
DirtyWordsHttpServletRequest newRequest = new DirtyWordsHttpServletRequest(request,words);
//5.放行,使用newRequest代替原来的request,那么目标资源拿到的就是newRequest
filterChain.doFilter(newRequest, response);
}
@Override
public void destroy() {
}
}
/**
* 发表言论的Servlet
*/
@WebServlet(name = "BBSServlet",urlPatterns = "/bbs")
public class BBSServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//0.设置响应体和请求体的编码
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//1.获取请求中发表的言论数据
String message = request.getParameter("message");
//2.输出到页面
response.getWriter().println("您的言论:"+message+",发表成功");
}
}
第10章 综合案例:解决全站乱码
10.1 案例需求
使用一个全站过滤器,统一处理请求体和响应体中的中文乱码
以后我们写的所有Servlet都不需要关系中文乱码了!!!
10.2 实现步骤
a.创建一个过滤器
b.配置过滤器的拦截路径("/*")
c.在过滤器的doFilter方法中,处理请求体和响应体的乱码!
d.放行到目标资源
10.3 代码实现
/**
* 全站中文乱码的过滤器
*/
@WebFilter(filterName = "EncodingFilter", urlPatterns = "/*")
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
//过滤的方法
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//1.将servletRequest和servletResponse转回HttpServletRequest和HttpServletResponse
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//要求请求体和响应体的中文乱码进行处理
//a.响应体我们所有都需要处理中文乱码
response.setContentType("text/html;charset=UTF-8");
//b.如果是post请求,设置请求体的中文乱码
if (request.getMethod().equalsIgnoreCase("POST")) {
request.setCharacterEncoding("UTF-8");
}
//放行
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
注意: 该乱码过滤器,我们可以保存下来,以后直接拿过来使用,但是我们建议改成web.xml配置
并且把该过滤器配置到所有过滤器的前面,保证先执行该过滤器,解决中文乱码!!!
第11章 监听器入门(了解)
11.1 什么是监听器
在Java中监听器主要监听某些事件
a.各种域对象的创建和销毁事件(ServletContext,HttpSession,HttpServletRequest)
b.各种域对象的属性增加和减少事件(ServletContext,HttpSession,HttpServletRequest)
11.2 监听器的使用场景
a.获取项目启动之后的初始化信息(Spring框架会使用)
b.统计在线人数(监听HttpSession对象的创建和销毁)
11.3 开发一个监听器(以ServletContextListenner为例)
-
API介绍
ServletContextListenner是一个接口,其中有两个方法 void contextDestroyed(ServletContextEvent sce); 监听ServletContext销毁事件 void contextInitialized(ServletContextEvent sce); 监听ServletContext创建事件
-
使用步骤
1.创建一个类实现ServletContextListenner接口 2.实现类重写接口中两个方法contextDestroyed和contextInitialized /** * ServletContext的监听器 */ public class MyServletContextListener implements ServletContextListener{ @Override public void contextInitialized(ServletContextEvent servletContextEvent) { System.out.println("ServletContext创建了"); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println("ServletContext销毁了"); } } 3.使用web.xml配置 或者 注解配置
-
XML方式演示
<!--配置监听器--> <listener> <listener-class>com.itheima.web.listener.MyServletContextListener</listener-class> </listener>
-
注解方式演示
/** * ServletContext的监听器 */ @WebListener //监听器的注解,只需要一个@WebListener,不需要任何的属性 public class MyServletContextListener implements ServletContextListener{ @Override public void contextInitialized(ServletContextEvent servletContextEvent) { System.out.println("ServletContext创建了"); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println("ServletContext销毁了"); } }
其他域对象也有类似的监听器
HttpSessionListener 监听Httpsession域的创建于销毁的监听器 ServletRequestListener 监听ServletRequest域的创建于销毁的监听器
11.4 域对象的生命周期回顾
ServletContext域对象
创建: 项目启动时创建
销毁: 项目卸载时或者服务器正常关闭时
HttpSession域对象
创建: 在本次会话中第一次调用getSession方法时,第一次访问该jsp页面时创建
销毁: 关闭浏览器默认30分钟后销毁
HttpServletRequest域对象
创建: 每次请求都会创建
销毁: 成功响应浏览器了,就销毁
11.5 ServletContextAttributeListener监听器使用
-
ServletContextAttributeListener的作用
监听ServletContext域对象中属性的变化(新增,删除,修改)
-
ServletContextAttributeListener的API
ServletContextAttributeListener是一个接口,其中有三个方法: void attributeAdded(ServletContextAttributeEvent scab); 监听属性添加到servletcontext中 void attributeRemoved(ServletContextAttributeEvent scab); 监听属性从servletcontext中移除 void attributeReplaced(ServletContextAttributeEvent scab); 监听属性从 servletcontext中被替换
-
ServletContextAttributeListener的使用步骤
a.创建ServletContextAttributeListener接口的实现类 b.重写接口中三个监听方法 c.在web.xml中配置或者注解配置
-
ServletContextAttributeListener的代码实现
/** * ServletContext属性监听器 */ public class MyServletContextAttributeListener implements ServletContextAttributeListener { @Override public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) { String name = servletContextAttributeEvent.getName(); Object value = servletContextAttributeEvent.getValue(); System.out.println("向ServletContext域对象中添加数据了..." + name + "..." + value); } @Override public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) { String name = servletContextAttributeEvent.getName(); Object value = servletContextAttributeEvent.getValue(); System.out.println("从ServletContext域对象中删除数据了..." + name + "..." + value); } @Override public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) { String name = servletContextAttributeEvent.getName(); Object value = servletContextAttributeEvent.getValue(); System.out.println("对ServletContext域对象中数据进行修改了..." + name + "..." + value); } } 配置: <listener> <listener-class> com.itheima.web.listener.MyServletContextAttributeListener </listener-class> </listener>
-
其他监听器有兴趣可以自行研究
HttpSessionAttributeListener 监听HttpSession中属性的增删改事件 ServletRequestAttributeListener 监听Request中属性的增删改事件