动力节点JavaWeb视频
从底层源码开始讲起, 讲解的非常详细,对比过尚硅谷的视频,推荐动力节点。
视频是直播的录像,有些时候比较啰嗦,尤其到EL表达式之后,1小时的内容能讲3小时。
系列文章目录
- 第一章 配置环境、配置IDEA
- 第二章 GenericServlet源码解析 特别重要
- 第三章 HttpServlet
- 第四章 HttpServletRequest
- 第五章 重定向 使用注解简化配置文件
- 第六章 JSP (上)
- 第七章 JSP (下)EL表达式 JTSL标签库
- 第八章 Session、Cookie
- 第九章 Filter过滤器、Listner 监听器
第九章 Filter过滤器、Listner 监听器
Filter过滤器
作用: 在执行Servlet之前和之后执行一段代码。
特点: 大量重复的代码得以优化;使用责任链设计模式,每个过滤器都是独立的,对于整个工作链来说,无论是要插入新的过滤器、删除过滤器、改变过滤器的执行顺序,只要修改web.xml中过滤器的前后顺序就可以,不用修改代码。符合对内关闭,对外开放的原则。
Filter执行流程
示例:给AServlet 设置过滤器 AFilter
执行过程:
- web.xml配置过滤器
- 服务器启动时会创建Filter的对象,并执行Filter中的
init()
方法。 - 浏览器输入Servlet的地址后
- 执行Filter的
doFilter()
方法中的代码 - 在执行到doFilter方法的
chain.doFilter(request,response);
时,会执行链条上的其他过滤器,如果没有其他过滤器,则会执行Servlet对象的相关方法。 - AServlet相关的方法执行完毕后,会返回来继续执行
doFilter()
方法中chain.doFilter()
后面的代码。 - 当关闭服务器时,执行Filter的
destroy()
- 为什么过滤器会在指定的Servlet之前执行呢?
配置文件中<url-pattern>
的值:/servlet/*
,表示在路径开始为/servlet
的所有Servlet添加此过滤器
<-- web.xml 配置文件 -->
<filter>
<filter-name>afilter</filter-name>
<filter-class>com.tomcat.javaweb.test.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>afilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
public class AFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("服务器开启自动创建AFilter类对象,并执行init方法");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("AFilter的doFilter在chain之前执行的代码");
chain.doFilter(request,response);
System.out.println("AFilter的doFilter在chain之后执行的代码");
}
@Override
public void destroy() {
System.out.println("AFilter被销毁");
}
}
@WebServlet("/servlet/aservlet")
public class AServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("执行了AServlet");
}
}
- 结果:
// 开启服务器
服务器开启自动创建AFilter类对象,并执行init方法
//用户发送Sevlet的请求
AFilter的doFilter在chain之前执行的代码
执行了AServlet
AFilter的doFilter在chain之后执行的代码
//关闭服务器时
AFilter被销毁
Filter的路径设置
- 匹配所有路径:
/*
- 精确匹配:
"/servlet/aservlet/"
,与Servlet的路径完全一致 - 后缀匹配:Servlet的路径:
/a.do
;Filter的匹配路径:*.do
。注意:后缀匹配时路径最前面不能有/
- 前缀匹配:
/sevlet/*
;匹配所有/sevlet
开始的路径
Filter的执行顺序
- 在web.xml中配置Filter(建议使用)
当有多个Filter时,执行顺序是按照web.xml配置文件中,Filter的<filter-mapping>
标签的前后顺序依次执行。 - 使用@WebFilter注解
有多个Filter时,按照Filter类名的字典顺序依次执行。
Listner 监听器
服务器对请求域、会话域、应用域的创建和销毁的监听
- 注解:@WebListener
ServletContextListener
ServletRequestListener
HttpSessionListener
- 应用域的监听的实现
@WebListener
public class ContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("服务器开始时ServletContextListener执行");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("服务器关闭时ServletContextListener执行");
}
}
服务器对请求域、会话域、应用域的内通过Attribute增加、删除、修改数据的监听
- 注解:@WebListener
ServletContextAttributeListener
ServletRequestAttributeListener
HttpSessionAttributeListener
- 应用域数据监听的实现
@WebListener
public class ContextAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent scae) {
System.out.println("application应用域 添加 数据时触发");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent scae) {
System.out.println("application应用域 删除 数据时触发");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent scae) {
System.out.println("application应用域 属性值被更改 时触发");
}
}
Session中的其他监听器
HttpSessionBindingListener
HttpSessionIdListener
HttpSessionActivationListener
- HttpSessionBindingListener示例,统计网站登录的人数:
- 数据类实现监听器的两个方法。
- 当数据类对象被Session绑定时执行
valueBound(HttpSessionBindingEvent event)
- 当Session被销毁是,数据同时销毁,触发此监听器,执行
valueUnbound(HttpSessionBindingEvent event)
方法。
// 用户的数据类,用户登录后,类对象会设置到Session中。用户退出或者会话超时后session会被删除,数据也会被移除
public class User implements HttpSessionBindingListener {
@Override
public void valueBound(HttpSessionBindingEvent event) {
ServletContext servletContext = event.getSession().getServletContext();
Object count = servletContext.getAttribute("count");
Integer count1 = (Integer) count;
count1++;
servletContext.setAttribute("count", count1);
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
ServletContext servletContext = event.getSession().getServletContext();
Object count = servletContext.getAttribute("count");
Integer count1 = (Integer) count;
count1--;
servletContext.setAttribute("count", count1);
}
private String username;
private String password;
.
.
}