JavaWeb学习笔记(二)(过滤器Filter与监听器Listener)

概述

JavaEE阶段有三个大组件:Jsp/Servlet、Filter、Listener

一个普通的Java类继承了实现Servlet接口的实现类(HttpServlet),称为Servlet,JSP就是Servlet

一、过滤器(Filter)

1.1 过滤器图解

一个普通的Java类实现了一个Servlet API提供的Filter接口的实现类,称为Filter。过滤器是比较核心的技术,它可以对WEB服务器中所有的WEB资源(动态、静态)进行管理,例如:JSP/Servlet、静态资源(HTML/JS/CSS/图片)、文件(上传的文件)资源
可以对请求和响应的资源进行“拦截”(需要自己设置拦截的规则),拦截之后我可以实现一些特殊的功能。

在这里插入图片描述

1.2过滤器配置

过滤器的配置过程,跟Servlet的配置过程是类似,也有两种版本:web.xml中<filter>注册和@WebFilter注册,可以定义拦截规则。

(1)新建一个普通的Java类,实现Filter接口,必须要实现doFilter方法,其他方法为接口默认方法

过滤器使用 FilterChain 调用链中的下一个过滤器,如果调用的过滤器是链中的最后一个过滤器,则调用链末尾的资源。

package com.yu.filter;

import javax.servlet.*;
import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 鱼
 * @Date: 2021/07/05/7:16
 * @Description:
 */
public class Demo01Filter implements Filter {
    public Demo01Filter(){
        System.out.println(Demo01Filter.class+"构造方法..创建对象...什么时候实例化");
    }
    /*doFilter方法必须要实现*/
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println(Demo01Filter.class+"...执行特殊功能的代码..."+Math.random());
        System.out.println("<---"+Demo01Filter.class+"前");
        /*设置放行*/
        filterChain.doFilter(servletRequest,servletResponse);//访问下一个过滤器或资源
        System.out.println("--->"+Demo01Filter.class+"后");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println(Demo01Filter.class+"对成员变量进行初始化操作...赋值");
        /*取xml中配置的初始值*/
        System.out.println(filterConfig.getInitParameter("name"));//初语
        System.out.println(filterConfig.getInitParameter("age"));//18
        System.out.println(filterConfig.getInitParameter("world"));//没有配置:null
    }

    @Override
    public void destroy() {
        System.out.println(Demo01Filter.class+"...关闭服务器进行销毁");
    }
}

(2)在web.xml中进行配置,过滤器的注册配置拦截的规则

<?xml version="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>
        <filter-name>Demo01Filter</filter-name>
        <filter-class>com.yu.filter.Demo01Filter</filter-class>
        <!--在xml文件中进行初始化赋值-->
        <init-param>
            <param-name>name</param-name>
            <param-value>初语</param-value>
        </init-param>
        <init-param>
            <param-name>age</param-name>
            <param-value>18</param-value>
        </init-param>
    </filter>
    <!--设置拦截规则-->
    <filter-mapping>
        <filter-name>Demo01Filter</filter-name>
        <!--
        可使用通配符:
        /*:所有的请求都会被该过滤器进行处理
        /sys/*:所有以sys开头的请求都会被该过滤器处理
        *.jsp  *.html  *.xxx:特殊(不是"/"开头),所有以后缀名jsp,html等等(自己设置)结尾的请求都会被该过滤器处理
        /1.jpg:只有当访问的是具体的1.jpg的时候会被该过滤器处理
        -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
过滤规则:
  • /*:所有的请求都会被该过滤器进行处理
  • /sys/*:所有以sys开头的请求都会被该过滤器处理
  • *.jsp *.html *.xxx:特殊(不是"/"开头),所有以后缀名jsp,html等等(自己设置)结尾的请求都会被该过滤器处理
  • /1.jpg:只有当访问的是具体的1.jpg的时候会被该过滤器处理

注意:

过滤器在服务器启动的时候,进行实例化和初识化数据操作,所以,过滤器错误,服务器无法使用

测试index.jsp文件:

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/7/5
  Time: 7:09
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <base href="${pageContext.request.contextPath}/">
    <meta charset="UTF-8">
    <title>$Title$</title>
  </head>
  <body>
  <%
    System.out.println("index.jsp页面");
  %>
    <h3 style="color: cyan">晓看天色暮看云</h3>
    <h3 style="color: pink">行也思君</h3>
    <h3 style="color: pink">坐也思君</h3>
  </body>
</html>

未放行前:(访问服务器空白,不显示index内容)在这里插入图片描述
设置放行后:
在这里插入图片描述
在这里插入图片描述

1.3 拦截规则

(1)设置多个拦截规则

package com.yu.filter;

import javax.servlet.*;
import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 鱼
 * @Date: 2021/07/05/7:16
 * @Description:
 */
public class Text02Filter implements Filter {
    public Text02Filter(){
        System.out.println(Text02Filter.class+"构造方法..创建对象...什么时候实例化");
    }
    /*doFilter方法必须要实现*/
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println(Text02Filter.class+"...执行特殊功能的代码..."+Math.random());
        System.out.println("<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>"+ Text02Filter.class+"前");
        /*设置放行*/
        filterChain.doFilter(servletRequest,servletResponse);//访问下一个过滤器或资源
        System.out.println("<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>"+ Text02Filter.class+"后");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println(Text02Filter.class+"对成员变量进行初始化操作...赋值");
    }

    @Override
    public void destroy() {
        System.out.println(Text02Filter.class+"...关闭服务器进行销毁");
    }
}

配置文件:

  <filter>
        <filter-name>Text02Filter</filter-name>
        <filter-class>com.yu.filter.Text02Filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Text02Filter</filter-name>
        <!--只要访问Example01Servlet就会被过滤器处理-->
        <servlet-name>Example01Servlet</servlet-name>
        <!--<url-pattern>/sys/*</url-pattern>
        <url-pattern>*.php</url-pattern>-->
    </filter-mapping>

servlet代码:

package com.yu.servlet; /**
 * Created with IntelliJ IDEA.
 *
 * @Author: 鱼
 * @Date: 2021/07/05/8:13
 * @Description:
 */

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "Example01Servlet",
        value = {"/sys/example01",
                "/view/example01",
                "/example01.html",
                "/sys/example.php",
                "/example.asp"
})
public class Example01Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(request.getRequestURI());
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.write("<h3>访问路径:"+request.getRequestURI()+"</h3>");
        out.close();
    }

}

1.3.1关于跳转方式启动过滤器
package com.yu.filter;

import javax.servlet.*;
import java.io.IOException;

public class Test03Filter implements Filter {
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		System.out.println(Test03Filter.class+"*************************************"+Math.random());
		filterChain.doFilter(servletRequest,servletResponse);/*访问下一个过滤器或者资源*/
	}
}

xml:

<filter>
    <filter-name>Test03Filter</filter-name>
    <filter-class>com.yu.filter.Test03Filter</filter-class>
</filter>
<!-- 设置多个拦截规则 -->
<filter-mapping>
    <filter-name>Test03Filter</filter-name>
    <url-pattern>/user/*</url-pattern>
</filter-mapping>

结果:先执行过滤器,后访问资源
在这里插入图片描述

1.3.2改造过滤器的配置:只有请求转发的跳转才能触发过滤器
    <filter>
        <filter-name>Test03Filter</filter-name>
        <filter-class>com.yu.filter.Test03Filter</filter-class>
    </filter>
    <!-- 设置多个拦截规则 -->
    <filter-mapping>
        <filter-name>Test03Filter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

结果:请求转发的跳转才触发过滤器
在这里插入图片描述

1.4 常用的过滤器

  • 解决POST请求中文的编码过滤器
  • 登录过滤器(Session过滤器)
  • 日志过滤器等等

(1)约定不允许直接访问JSP页面,解决方法:WEB-INF文件夹下就可以

package com.yu.filter; /**
 * Created with IntelliJ IDEA.
 *
 * @Author: 鱼
 * @Date: 2021/07/05/9:52
 * @Description:
 */

import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebFilter(filterName = "JSPFilter",urlPatterns = "/*")
public class JSPFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
        //对象下转型
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        //获取请求的路径
        String path = request.getRequestURI();
        if (path.endsWith(".jsp")){//字符串匹配:.jsp结尾
            response.setContentType("text/html;charset=UTF-8");
            PrintWriter out = response.getWriter();
            out.write("<h3>不知道写什么,不允许直接访问jsp页面</h3>");
            out.close();

        }else{

            chain.doFilter(request, response);
        }


    }
}

(2)编码过滤器,针对于POST请求,都需设置request.setCharacterEncoding("UTF-8");

package com.yu.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter(filterName = "EncodingFilter",value = "/*")
public class EncodingFilter implements Filter {
	private static final String METHOD = "POST";
	private static final String ENCODING = "UTF-8";
	private static final String CONTENT_TYPE_ENCODING = "text/html;charset=UTF-8";

	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
		//对象下转型,使用子类中新增的方法
		HttpServletRequest request = (HttpServletRequest)req;
		HttpServletResponse response = (HttpServletResponse)resp;
		//获取请求的方式
		String method = request.getMethod();
		if(METHOD.equalsIgnoreCase(method)){//是否为post请求
			request.setCharacterEncoding(ENCODING);//解决POST请求中文乱码问题
		}
		response.setContentType(CONTENT_TYPE_ENCODING);
		chain.doFilter(req, resp);
	}
}

(3)登录过滤器,有一些WEB资源只有用户登录之后才能访问

  • lastIndexOf方法:如果要检索的字符串值没有出现,则该方法返回 -1。
package com.yu.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@WebFilter(filterName = "SessionFilter",value = "/*")
public class SessionFilter implements Filter {
	private static final String LOGIN_URL = "/sys/login";
	private static final String SESSION_KEY = "session_user";
	private static List<String> excludeStaticPathList = new ArrayList<>();

	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
		HttpServletRequest request = (HttpServletRequest)req;
		HttpServletResponse response = (HttpServletResponse)resp;
		//获取HttpSession对象
		HttpSession session = request.getSession();
		//获取请求的路径并且获取有后缀的字符串
		String path = request.getRequestURI();
		String ext = null;
		int index = path.lastIndexOf(".");
		if(index!=-1){
			ext = path.substring(index);//获取的后缀名是从.开始截取
		}

		if(path.endsWith(LOGIN_URL)||excludeStaticPathList.contains(ext)){//设置哪些请求不检查session
			chain.doFilter(req, resp); //允许访问,放行
		}else{
			if(session.getAttribute(SESSION_KEY)==null){//没有登录,回到登录页面,重定向
				response.sendRedirect(request.getContextPath()+LOGIN_URL);
				return;
			}
			chain.doFilter(req, resp); //用户已经登录,可以访问资源
		}
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		excludeStaticPathList.add(".html");
		excludeStaticPathList.add(".js");
		excludeStaticPathList.add(".css");
		excludeStaticPathList.add(".png");
		excludeStaticPathList.add(".jpg");
		excludeStaticPathList.add(".jpeg");
		excludeStaticPathList.add(".gif");
		excludeStaticPathList.add(".dmp");
	}
}

二、监听器(Listener)

监听器使用的设计模式是观察者设计模式(单例设计模式、模版设计模式、代理设计模式),监听器是监听WEB域(HttpServletRequest、HttpSession、ServletContext)创建和销毁,以及属性的操作的行为

package com.yu.listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ApplicationListener implements ServletContextListener, ServletContextAttributeListener {
	@Override
	public void attributeAdded(ServletContextAttributeEvent scae) {
		System.out.println("ServletContext添加属性:"+scae.getServletContext().getAttribute("bookName"));
	}

	@Override
	public void attributeRemoved(ServletContextAttributeEvent scae) {
		System.out.println("ServletContext移除属性:"+scae.getServletContext().getAttribute("bookName"));
	}

	@Override
	public void attributeReplaced(ServletContextAttributeEvent scae) {
		System.out.println("ServletContext修改属性:"+scae.getServletContext().getAttribute("bookName"));
	}

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("创建ServletContext对象:"+sce.getServletContext());
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("服务器关闭,销毁ServletContext对象:"+sce.getServletContext());
	}
}

<listener>
    <listener-class>com.yu.listener.ApplicationListener</listener-class>
</listener>
package com.yu.listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener {
	@Override
	public void attributeAdded(HttpSessionBindingEvent se) {
		System.out.println("HttpSession添加属性:"+se.getSession().getAttribute("bookName"));
	}

	@Override
	public void attributeRemoved(HttpSessionBindingEvent se) {
		System.out.println("HttpSession移除属性:"+se.getSession().getAttribute("bookName"));
	}

	@Override
	public void attributeReplaced(HttpSessionBindingEvent se) {
		System.out.println("HttpSession修改属性:"+se.getSession().getAttribute("bookName"));
	}

	@Override
	public void sessionCreated(HttpSessionEvent se) {
		System.out.println("HttpSession,获取的时候才创建该对象:"+se.getSession().getId());
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		System.out.println("HttpSession,调用销毁方法:"+se.getSession().getId());
	}
}

package com.yu.listener;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class RequestListener implements ServletRequestListener, ServletRequestAttributeListener {
	@Override
	public void attributeAdded(ServletRequestAttributeEvent srae) {
		System.out.println("HttpServletRequest添加属性:"+srae.getServletRequest().getAttribute("bookName"));
	}

	@Override
	public void attributeRemoved(ServletRequestAttributeEvent srae) {
		System.out.println("HttpServletRequest移除属性:"+srae.getServletRequest().getAttribute("bookName"));
	}

	@Override
	public void attributeReplaced(ServletRequestAttributeEvent srae) {
		System.out.println("HttpServletRequest修改属性:"+srae.getServletRequest().getAttribute("bookName"));
	}

	@Override
	public void requestDestroyed(ServletRequestEvent sre) {
		System.out.println("一次请求完成,立即销毁:"+sre.getServletRequest());
	}

	@Override
	public void requestInitialized(ServletRequestEvent sre) {
		System.out.println("一次请求开始,重新创建新的对象:"+sre.getServletRequest());
	}
}

访问多次demo01.jsp查看属性的操作行为

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <%
        request.setAttribute("bookName","request-红楼梦"+Math.random());
        application.setAttribute("bookName","servletcontext-水浒传"+Math.random());
        session.setAttribute("bookName","session-西游记"+Math.random());
    %>
</body>
</html>

session销毁行为

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <%
        session.invalidate();
    %>
</body>
</html>

启动会调用ServletContext的销毁以及测试removeAttribute的方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月色夜雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值