javaweb过滤器与监听器
一、过滤器程序的基本结构、web.xml文件的配置过程和过滤器的执行过程
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0"><filter><filter-name>FirstFilter</filter-name><filter-class>filter.FirstFilter</filter-class><init-param><param-name>course</param-name><param-value>Java EE</param-value></init-param></filter><!-- 配置FirstFilter只拦截test.html --><filter-mapping><filter-name>FirstFilter</filter-name><url-pattern>/test.html</url-pattern></filter-mapping></web-app>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>Title</title>
</head>
<body>这是一个测试过滤器
</body>
</html>
package filter;import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;public class FirstFilter implements Filter { //实现Filter接口FilterConfig config = null;//定义一个FilterConfig对象为类的实例变量public void init(FilterConfig filterConfig) throws ServletException {config = filterConfig;//获取FilterConfig对象引用}public void destroy() {config = null;}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {String str = config.getInitParameter("course");//获取过滤器初始参数response.setContentType("text/html;charset=utf-8");PrintWriter out = response.getWriter();out.println("<font color=blue>前置程序块<br>");out.println("过滤器初始参数:course=" + str + "</font><br><br>");chain.doFilter(request, response);//调用"过滤器链"方法out.println("<br><font color=blue>后置程序块</font><br>");}
}
过滤器需要实现Filter接口,并重写Filter的三个方法:init()、destory()、doFilter()
过滤器的执行顺序:多个过滤器的拦截路径相同时,首先按照<filter-mapping>标记在web.xml中出现的先后顺序执行过滤器,然后按照过滤器类名的字典顺序执行注解的过滤器。
二、注解配置过滤器:字符编码过滤器及权限验证过滤器的实现
package filter;import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.annotation.WebServlet;import java.io.IOException;@WebFilter(filterName = "EncodingFilter", urlPatterns = "/*",initParams = {@WebInitParam(name = "encode", value = "UTF-8")})
public class EncodingFilter implements Filter {private String encode = null;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {encode = filterConfig.getInitParameter("encode");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {servletRequest.setCharacterEncoding(encode);servletResponse.setContentType("text/html;charset="+encode);filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {Filter.super.destroy();}
}
package filter;import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;import java.io.IOException;@WebFilter(filterName = "ValidationFilter", value = "/admin/*")
public class ValidationFilter implements Filter {@Overridepublic void init(FilterConfig Config) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpSession session = ((HttpServletRequest) request).getSession();if(session.getAttribute("user") == null){((HttpServletResponse) response).sendRedirect("login.jsp");}chain.doFilter(request, response);}@Overridepublic void destroy() {Filter.super.destroy();}
}
<form action="loginServlet"><div id="table_div"><table align="center"><tr><td colspan="2"><h2>学生信息管理系统</h2></td></tr><tr><td>账号:</td><td><input class="inputinfo" type="text" name="account" placeholder="账号" /></td></tr><tr ><td>密码:</td><td><input class="inputinfo" type="password" name="password" placeholder="密码" /></td></tr><tr><td colspan="2"><input id="btn_submit" type="submit" value="登录" /></td></tr></table></div></form>
package servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;/* Servlet implementation class LoginServlet*/
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {private static final long serialVersionUID = 1L;protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String account = request.getParameter("account");String password = request.getParameter("password");if (account.equals("Sarah") && password.equals("123456")) {request.getSession().setAttribute("user", account);response.sendRedirect("admin/showAllBooks");} else {response.sendRedirect("login.jsp");}}protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// TODO Auto-generated method stubdoGet(request, response);}}
三、application、session两类对象的创建与销毁时间监听
package listener;import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.ServletRequestEvent;
import jakarta.servlet.ServletRequestListener;
import jakarta.servlet.annotation.WebListener;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;
//添加监听器注解
@WebListener
//由MyListener类实现ServletContext、HttpSession、ServletRequest三类对象创建、销毁事件的监听
public class MyListener implements ServletContextListener, HttpSessionListener, ServletRequestListener {public void contextInitialized(ServletContextEvent sce) {System.out.println("\\n ServletContext对象被创建了");}public void contextDestroyed(ServletContextEvent sce) {System.out.println("\\n ServletContext对象被销毁了");}public void sessionCreated(HttpSessionEvent se) {System.out.println("\\n HttpSession对象被创建了");}public void sessionDestroyed(HttpSessionEvent se) {System.out.println("\\n HttpSession对象被销毁了");}public void requestDestroyed(ServletRequestEvent sre) {System.out.println("\\n servletRequest对象被销毁了");}public void requestInitialized(ServletRequestEvent sre) {System.out.println("\\n servletRequest对象被创建了");}}
package servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;import java.io.IOException;
import java.io.PrintWriter;@WebServlet(value="/test")
public class TestServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=utf-8");HttpSession session = request.getSession();//得到会话:如果没有会话,就创建一个PrintWriter out = response.getWriter();out.println("<html>");out.println("<head>");out.println("<title>Servlet事件监听</title>");out.println("</head>");out.println("<body>");out.println("<h2>创建了一个会话!</h2>");out.println("</body>");out.println("</html>");}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}
}
<html><head><title>servlet事件监听器</title></head><body><h2>用html文档测试servlet事件监听器</h2></body>
</html>
(1)启动Tomcat服务器(如果Tomcat已启动,请先关闭),观察控制台输出的信息。这说明了什么?
答:服务器启动时执行contextInitialized(ServletContextEvent sce)方法。首先servletContext全局对象被创建
(2)打开浏览器,输入http://127.0.0.1:8080/lab6_3/index.html网址,观察控制台输出的信息。这又说明了什么?
答:执行requestInitialized(ServletRequestEvent sre)方法,servletRequest对象被创建,随后自动执行requestDestory(ServletRequestEvent sre)方法,servletRequest对象被销毁了
(3)打开浏览器,输入http://127.0.0.1:8080/lab6_3/test网址,观察控制台输出的信息。这又说明了什么?
答:执行requestInitialized(ServletRequestEvent sre)方法,servletRequest对象被创建,紧接着执行了sessionCreated(HttpSessionEvent se)方法,HttpSession对象被创建,最后自动执行requestDestroyed(ServletRequestEvent sre)方法,servletRequest对象被销毁
问题:web.xml中的如下标记实现什么功能?
<session-config>
<session-timeout>1</session-timeout>
</session-config>
(4)过1分钟之后,再次观察控制台输出的信息。这又说明了什么?
答:实现了1分钟后执行sessionDestoryed(HttpSessionEvent se)方法
请总结application、session两类对象创建、销毁事件监听的方法与步骤。注意:不同监听接口、事件、方法的差异。
答:首先要实现ServletContextListener、HttpSessionListener、ServletRequestListener。重写三类对象创建和销毁的事件以便监听。当触发相应的Servlet对象就可以实现相应的监听。
- ServletContextListener:监听application的产生与销毁
- HttpSessionListener:监听session的产生与销毁
- ServletRequestListener:监听request的产生与销毁
四、application、session两类对象属性变化事件监听
package listener;
import jakarta.servlet.*;
import jakarta.servlet.http.*;//由MySttributeListener类实现application、session两类对象属性变化事件的监听
public class MyAttributeListener implements ServletContextAttributeListener, HttpSessionAttributeListener {public void attributeAdded(ServletContextAttributeEvent scae) {System.out.println("\\n application对象中增加了一个名为" + scae.getName()+ "的属性,该属性值为" + scae.getValue());}public void attributeRemoved(ServletContextAttributeEvent scae) {System.out.println("\\n application对象中的" + scae.getName() + "属性被删除了\\n");}public void attributeReplaced(ServletContextAttributeEvent scae) {System.out.println("\\n application对象中" + scae.getName() + "的属性值被替换成了"+ scae.getServletContext().getAttribute(scae.getName()));}public void attributeAdded(HttpSessionBindingEvent hbe) {System.out.println("\\n session对象中增加了一个名为" + hbe.getName()+ "的属性,该属性值为" + hbe.getValue());}public void attributeRemoved(HttpSessionBindingEvent hbe) {System.out.println("\\n session对象中的" + hbe.getName() + "属性被删除了\\n");}public void attributeReplaced(HttpSessionBindingEvent hbe) {System.out.println("\\n session对象中" + hbe.getName() + "的属性值被替换成了"+ hbe.getSession().getAttribute(hbe.getName()));}}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0"><!-- <session-config>-->
<!-- <session-timeout>1</session-timeout>-->
<!-- </session-config>--><!-- 把MyAttributeListener类设置事件为监听器 --><listener><listener-class>listener.MyAttributeListener</listener-class></listener><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list></web-app>
<html><head><title>测试session对象属性变化</title></head><body><%@ page contentType="text/html;charset=gb2312"%><H4>这是一个测试session对象属性变化的页面</H4><%session.setAttribute("width", "98.7654");session.setAttribute("width", "9876.54");session.removeAttribute("width");%></body>
</html>
<html><head><title>测试application对象属性变化</title></head><body><%@ page contentType="text/html;charset=gb2312"%><H4>这是一个测试application对象属性变化的页面</H4><%application.setAttribute("length", "123.45");application.setAttribute("length", "1234.5");application.removeAttribute("length");%></body>
</html>
application、session两种事件对象的getName()、getValue()的功能是什么?如何获得变化过的属性值?
答:getName()获取application或session的属性名;getValue()获取application或session的属性值。
application对象获得变化过的属性值:getServletContext().getAttribute(getName())
session对象获得变化过的属性值:getSession().getAttribute(getName());
(1)打开浏览器,输入http://127.0.0.1:8080/lab6_4/ServletContextAttributeTest.jsp网址,观察控制台输出的信息。这说明了什么?
答:application对象设置属性时调用attributeAdded(ServletContextAttributeEvent scae)方法,重新更改属性时调用attributeReplaced(ServletContextAttributeEvent scae)方法,删除属性时调用attributeRemoved(ServletContextAttributeEvent scae)方法
(2)在浏览器输入http://127.0.0.1:8080/lab6_4/HttpSessionAttributeTest.jsp网址,观察控制台输出的信息。这又说明了什么?
答:session对象设置属性时调用attributeAdded(HttpSessionBindingEvent hbe)方法,重新更改属性时调用attributeReplaced(HttpSessionBindingEvent hbe)方法,删除属性时调用attributeRemoved(HttpSessionBindingEvent hbe)方法
请总结application、session两类对象属性变化事件监听的方法与步骤。注意:不同监听接口、事件差异,在方法名上有什么相似之处?
答:session对象和application对象都是设置属性时调用attributeAdded()方法,重新更改属性时调用attributeReplaced()方法,删除属性时调用attributeRemoved()方法。
ServletContextAttributeListener和HttpSessionAttributeListener包含的方法名称相同,只是参数不同。