目录
web的三大组件
servlet(控制器)
filter(过滤器)
listener(监听器)
当用户访问服务器资源时,过滤器将请求拦截下来,完成一些通用的操作。
应用场景:登录验证、统一编码处理、敏感字符过滤。
作用:过滤掉请求的路径。

定义一个类来实现Filter接口,并重写init、doFilter、destroy三个方法。
- public class MyFilter implements Filter {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- System.out.println("init");
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- System.out.println("doFilter");
- }
-
- @Override
- public void destroy() {
- System.out.println("destroy");
- }
- }
在web.xml配置文件中配置
- "1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
-
- <filter>
- <filter-name>MyFilterfilter-name>
-
- <filter-class>cn.itssl.filter.MyFilterfilter-class>
- filter>
-
- <filter-mapping>
- <filter-name>MyFilterfilter-name>
-
- <url-pattern>/hello.htmlurl-pattern>
- filter-mapping>
- web-app>
init方法
服务器启动项目加载,创建filter对象,执行init方法(只执行一次)
doFilter方法
用户访问被拦截目标资源时,执行doFilter方法,执行多次
destroy方法
在服务器关闭前,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源。
注意:过滤器一定是优先于Servlet创建的。
Filter生命周期和Servlet生命周期对比:
Filter生命周期:
1、当服务器启动时就初始化
2、每次请求都会走doFilter方法,
3、服务器正常关闭,Filter销毁
Servlet生命周期:
1、用户第一次访问时servlet初始化,并且只初始化一次
2、每次请求都会走service方法,
3、服务器正常关闭,Servlet销毁
在开发时,我们可以指定过滤器的拦截路径来定义拦截目标资源的范围
精准匹配
用户访问指定目标资源(/show.jsp)时,过滤器进行拦截
目录匹配
用户访问指定目录下(/user/*)所有资源时,过滤器进行拦截
后缀匹配
用户访问指定后缀名(*.html)的资源时,过滤器进行拦截
匹配所有
用户访问该网站所有资源(/*)时,过滤器进行拦截
- <filter>
- <filter-name>MyFilterfilter-name>
- <filter-class>cn.itssl.web.MyFilterfilter-class>
- filter>
- <filter-mapping>
- <filter-name>MyFilterfilter-name>
-
-
- <url-pattern>/hello.htmlurl-pattern>
- <url-pattern>/UserServleturl-pattern>
- <url-pattern>/show.jspurl-pattern>
-
-
- <url-pattern>*.htmlurl-pattern>
-
-
-
-
- filter-mapping>
chain.doFilter(request,response) 放行、执行后续组件。
- package cn.itssl.web;
-
- import javax.servlet.*;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- /**
- * @Auther: itssl
- * @Date: 12:07
- * @Desc
- */
- public class MyFilter implements Filter {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- System.out.println("--init--");
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- System.out.println("--doFilter--");
- //默认不放行
- //我不仅要拦截还要放行
- HttpServletRequest request = (HttpServletRequest) servletRequest;
- HttpServletResponse response = (HttpServletResponse) servletResponse;
- //获取资源的请求路径
- String path = request.getRequestURI().substring(request.getContextPath().length());
-
- //判断请求路径是否满足
- if("/hello.html".equals(path) || "/userServlet".equals(path)){
- //放行实现
- filterChain.doFilter(request,response);
- }
-
- }
-
- @Override
- public void destroy() {
- System.out.println("--destroy--");
- }
- }
使用注解形式,可以省去配置web.xml的过程,直接在类上面写@WebFilter注解,里面书写拦截的路径。
- @WebFilter(urlPatterns = "/*")
- 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 {
-
- }
-
- @Override
- public void destroy() {
-
- }
- }
在我们的java程序中,有时也需要监视某些事情,一旦被监视的对象发生相应的变化,我们应该采取相应的操作。
使用场景:
历史访问次数、统计在线人数、系统启动时初始化配置信息。
1、监听作用域对象的创建和销毁。
* ServletRequestListener:监听请求对象的创建和销毁 。
* HttpSessionListener:监听会话对象(session)的创建和销毁 。
* ServletContextListener:监听应用的创建和销毁。
2、监听作用域对象的属性的添加、删除、替换。
第一类:监听三个数据范围对象(request、session、ServletContext)的创建和销毁监听器
ServletContextListener 监听ServletContext 对象的创建和销毁
HttpSessionListener 监听session 创建和销毁
ServletRequestListener 监听request 对象创建和销毁
第二类:监听三个数据范围对象中属性变更(增加、替换、删除)的监听器setAttribute() removeAttribute()
ServletContextAttributeListener, 监听ServletContext 对象属性的变更
HttpSessionAttributeListener 监听session 对象属性变更
ServletRequestAttributeListener 监听request对象的属性变更
首先需要定义一个类来实现ServletContextListener监听器
- public class MyServletContextListener implements ServletContextListener{
-
- // Public constructor is required by servlet spec
- public MyServletContextListener() {
- }
-
- public void contextInitialized(ServletContextEvent sce) {
-
- System.out.println("ServletContextListener创建了...........");
- }
-
- public void contextDestroyed(ServletContextEvent sce) {
- System.out.println("ServletContextListener销毁了...........");
-
- }
- }
配置web.xml文件
- "1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
- version="3.1">
-
- <listener>
- <listener-class>com.itssl.listener.MyServletContextListenerlistener-class>
- listener>
- web-app>
有用户使用网站,在线人数就+1;用户退出网站,在线人数就-1
定义一个类用来监听整个项目,也是整个域,实现ServletContextListener接口
- @WebListener
- public class InitNumberListener implements ServletContextListener {
-
- public InitNumberListener() {
- }
-
- public void contextInitialized(ServletContextEvent sce) {
-
- ServletContext servletContext = sce.getServletContext();
- servletContext.setAttribute("number", 0);
- }
-
- public void contextDestroyed(ServletContextEvent sce) {
-
- }
- }
定义一个类实现HttpSeesionListener接口,用来监听session域的创建和销毁
- @WebListener
- public class NumberChangeListener implements HttpSessionListener {
- @Override
- public void sessionCreated(HttpSessionEvent httpSessionEvent) {
-
- ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
- int number = (int) servletContext.getAttribute("number");
-
- servletContext.setAttribute("number",number+1);
-
- }
-
- @Override
- public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
- ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
- int number = (int) servletContext.getAttribute("number");
-
- servletContext.setAttribute("number",number-1);
- }
- }
定义一个类,用来销毁session域,退出网页功能,让人数-1
-
- @WebServlet("/logoutServlet")
- public class LogoutServlet extends HttpServlet {
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // 处理post请求乱码问题
- request.setCharacterEncoding("utf-8");
- // 设置响应数据的编码
- response.setContentType("text/html;charset=utf-8");
- // 销毁
- request.getSession().invalidate();
-
- }
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- this.doPost(request, response);
- }
- }
index.jsp
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>$Title$title>
- head>
- <body>
- 在线人数: ${number}
- <br>
- <a href="/logoutServlet">退出系统a>>
- body>
- html>