一、Servlet过滤器:
Servlet过滤器拦截请求和响应,以便查看、提取或操作客户机和服务器之间交换的数据。
Servlet过滤器介于与之相关的Servlet或JSP页面与客户端之间,
工作原理:当某个资源与Servlet过滤器关联后,对该资源的所有请求都会经过Servlet过滤器,Servlet过滤器在Servlet被调用之前会检查请求对象(Request对象),并决定是将请求转发给过滤器链中的下一个资源还是中止该请求并响应用户。
特点:
Servlet过滤器可以检查和修改ServletRequest和ServletResponse对象。
Servlet过滤器可以被指定和特定的URL关联,只有当客户请求访问该URL时,才会触发过滤器。
Servlet过滤器可以被串联在一起,形成管道效应,协同修改请求和响应对象。
Servlet过滤器是Servlet的一种特殊用法,主要用来完成一些通用的操作。比如编码的过滤,判断用户的登陆状态等等。
Servlet过滤器的适用场合:
1、用户认证与授权管理
2、统计Web应用的访问量,和访问的命中率,形成访问报告
3、实现Web应用的日志处理功能
4、实现数据压缩功能
5、对传输的数据进行加密
6、实现XML文件的XSLT转换
创建过滤器须实现javax.servlet.Filter接口,该接口内定义了3个方法:
1、init(FilterConfig config):
用于初始化过滤器,并获取web.xml文件中配置的过滤器初始化参数。
2、doFilter(ServletRequest reg, ServletResponse res,FilterChain chain):
用于进行过滤操作,该方法的第一个参数为ServletRequest对象, 此对象给过滤器提供了对进入的信息(包括表单数据、Cookie和HTTP请求头)的完全访问;第二个参数为ServletResponse,用于 响应使用ServletRequest对象访问的信息,通常在简单的过滤器中忽略此参数;最后一个参数为 FilterChain,该参数用来调用过滤 器链中的下一个资源。FilterChain参数用于访问后续过滤器。
3、destroy():
Servlet容器在销毁过滤器实例前调用该方法,这个方法中可以释放Servlet过滤器占用的资源。性质等同与servlet的destory()方法。
这三个方法并不是我们手动进行调用的,只要我们实现了javax.servlet.Filter接口,服务器就会在需要调用某一个方法的时候调用该方法。
Servlet过滤器的创建步骤:
A.实现javax.servlet.Filter接口的servlet类
B.实现init方法,读取过滤器的初始化参数
C.实现doFilter方法,完成对请求或响应的过滤
D.调用FilterChain接口对象的doFilter方法,向后续的过滤器传递请求或响应
F.在web.xml中配置Filter
在web.xml中配置Servlet过滤器包括下面两个步骤:
(1)命名Servlet过滤器和指定Servlet 过滤器相应的实现类,并且可选择指定传递至Servlet过滤器的初始化参数。初始化参数可以配置一个,也可以配置多个,还可以没有初始化参数。
(2)将Servlet 过滤器映射至 URL 或 Servlet,这是通过<filter-mapping>元素来实现的。
将Servlet 过滤器映射至 URL的配置代码如下:
<filter-mapping> <filter-name>FilterName</filter-name> <url-pattern>/path</url-pattern> </filter-mapping>
<filter-name>元素和<filter>元素的子元素<filter-name>一致。<url-pattern>元素指定了过滤器的映射路径。
Servlet过滤器还可映射至Servlet :
<filter-mapping> <filter-name>FilterName</filter-name> <servlet-name>ServletName</servlet-name> </filter-mapping>
<servlet-name>元素指定过滤器映射的Servlet的名称
案例:过滤器处理中文乱码:
以登录为例,新建一个项目,然后建立一个登录页面:
1、login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2><font color="red">${sessionScope.info } </font></h2>
<form action="LoginServlet" method="post">
用户名:<input type="text" name="username" value="${user.username }"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
2、User.java:
package com.yun.entity;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3、LoginServlet.java:
package com.yun.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.yun.entity.User;
/**
* Servlet implementation class LoginServlet
*/
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public LoginServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username=request.getParameter("username");
String password=request.getParameter("password");
User user=new User();
user.setUsername(username);
user.setPassword(password);
HttpSession session=request.getSession();
session.setAttribute("user", user);
RequestDispatcher dis=null;
if ("admin".equals(username)&&"admin".equals(password)) {
session.setAttribute("info", "Success");
dis=request.getRequestDispatcher("success.jsp");
}else {
session.setAttribute("info", "Error");
dis=request.getRequestDispatcher("login.jsp");
}
dis.forward(request, response);
}
}
4、success.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
${sessionScope.info } <br>
用户名:${user.username } <br>
密码:${user.password }
</body>
</html>
5、web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>testFilter002</display-name> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> <servlet> <description></description> <display-name>LoginServlet</display-name> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.yun.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/LoginServlet</url-pattern> </servlet-mapping> </web-app>
这样,这个登录的功能就完成了,此时我们进行登录,然后发现页面中的中文都是乱码,此时我们就可以使用过滤器filter来进行编码的过滤:
我们新建,直接选择Filter(也可以建立class,然后自己实现javax.servlet.Filter接口),然后工具就会让我们选择是否添加初始化参数,设置这个Filter的mapping等,并且直接为我们实现了javax.servlet.Filter接口。我们自己手动配置也是可以的,使用工具会方便一点。
我们设置请求的url是所有的请求,即/*
此时我们看到工具为我们生成的代码:
1、web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>testFilter002</display-name> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> <servlet> <description></description> <display-name>LoginServlet</display-name> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.yun.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/LoginServlet</url-pattern> </servlet-mapping> <filter> <display-name>EncodFilter</display-name> <filter-name>EncodFilter</filter-name> <filter-class>com.yun.filter.EncodFilter</filter-class> <init-param> <param-name>myFilter</param-name> <param-value>encode</param-value> </init-param> </filter> <filter-mapping> <filter-name>EncodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
2、EncodFilter.java:
package com.yun.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* Servlet Filter implementation class EncodFilter
*/
public class EncodFilter implements Filter {
/**
* Default constructor.
*/
public EncodFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
// place your code here
// pass the request along the filter chain
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
此时,我们就可以在filter中进行代码编写,获得初始化参数,进行编码处理等:
1、EncodFilter.java:
package com.yun.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class EncodFilter implements Filter {
private String myFilter;
public EncodFilter() {
// TODO Auto-generated constructor stub
}
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("init param: "+myFilter);
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
myFilter=fConfig.getInitParameter("myFilter");
}
}
此时,我们看到这个初始化参数以及打印出来了,而且页面的中文都可以正常显示出来了。
在编程的过程中,尽可能的要避免进行硬编码,要把经常改动的配置不要写在源代码中,应该写在配置文件 中。
我们可以把这个过滤编码的过滤器再改动一下,就是把我们要设置的编码设置为这个过滤器的初始化参数,这样我们再改这个编码的时候就不需要进行更改代码,直接改配置文件web.xml即可了:
1、web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>testFilter002</display-name> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> <servlet> <description></description> <display-name>LoginServlet</display-name> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.yun.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/LoginServlet</url-pattern> </servlet-mapping> <filter> <display-name>EncodFilter</display-name> <filter-name>EncodFilter</filter-name> <filter-class>com.yun.filter.EncodFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>EncodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
2、EncodFilter.java:
package com.yun.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class EncodFilter implements Filter {
private String myEncoding="ISO-8859-1";
private FilterConfig config;
public EncodFilter() {
// TODO Auto-generated constructor stub
}
public void destroy() {
this.config=null;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding(myEncoding);
response.setCharacterEncoding(myEncoding);
chain.doFilter(request, response);
}
public void init(FilterConfig fConfig) throws ServletException {
this.config=fConfig;
String encoding=config.getInitParameter("encoding");
if(encoding !=null){
myEncoding=encoding;
}
}
}
这样,这个编码过滤的例子就完成了。
参考代码,自己写的代码 testFilter002
参考视频:中软岗前培训 servlet过滤器监听器视频
参考文档:中软培训ppt
案例:
过滤器还可以进行认证用户,就是我们可以指定哪个ip可以访问应用,哪个ip不可以访问应用。
1、login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="LoginServlet" method="post">
用户名:<input type="text" name="username" value="${user.username }"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
2、LoginServlet.java:
package com.yun.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username=request.getParameter("username");
String password=request.getParameter("password");
if("admin".equals(username)&&"admin".equals(password)){
request.getRequestDispatcher("success.jsp").forward(request, response);
}else {
request.getRequestDispatcher("login.jsp").forward(request, response);
}
}
}
3、IpFilter.java:
package com.yun.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class IpFilter implements Filter {
private FilterConfig config;
private String filterIP;
@Override
public void destroy() {
this.config=null;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println(request.getLocalAddr()+" "+request.getLocalName()+" "+request.getLocalPort());
System.out.println(request.getRemoteAddr()+" "+request.getRemoteHost()+" "+request.getRemotePort());
String remoteIP=request.getRemoteAddr();
if(remoteIP.equals(filterIP)){
request.getRequestDispatcher("error.jsp").forward(request, response);
}else {
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig fconfig) throws ServletException {
this.config=fconfig;
filterIP=config.getInitParameter("filterIP");
if(filterIP==null){
filterIP="";
}
}
}
4、web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>testFilter003</display-name> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> <servlet> <description></description> <display-name>LoginServlet</display-name> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.yun.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/LoginServlet</url-pattern> </servlet-mapping> <filter> <filter-name>ipFilter</filter-name> <filter-class>com.yun.filter.IpFilter</filter-class> <init-param> <param-name>filterIP</param-name> <param-value>127.0.0.1</param-value> </init-param> </filter> <filter-mapping> <filter-name>ipFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
5、success.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
登录成功!!!
</body>
</html>
6、error.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
该IP地址不允许登录该系统
</body>
</html>
这样,当我们使用127.0.0.1这个ip进行登录系统的时候,就会被IpFilter这个过滤器拦截下来,跳转到error.jsp中。否则,就可以正常请求到LoginServlet这个servlet中进行逻辑操作。
二、Servlet监听器:
Servlet监听器工作原理:
Servlet监听器是Web应用程序事件模型的一部分,当Web应用中的某些状态发生改变时,Servlet容器就会产生相应的事件,比如创建ServletContext对象时触发ServletContextEvent事件,创建HttpSession对象时触发HttpSessionEvent事件,Servlet监听器可接收这些事件,并可以在事件发生前、发生后可以做一些必要的处理。
根据监听对象的不同,Servlet2.4规范将Servlet监听器划分为以下3种:
ServletContext事件监听器:用于监听应用程序环境对象。
HttpSession事件监听器:用于监听用户会话对象。
ServletRequest事件监听器:用于监听请求消息对象。
1.ServletContext事件监听器:
对ServletContext对象进行监听的接口有ServletContextAttributeListener和ServletContextListener,其中ServletContextAttributeListener用于监听ServletContext对象中属性的改变,包括增加属性、删除属性和修改属性。ServletContextListener用于监听ServletContext对象本身的改变,例如ServletContext对象的创建和销毁。
ServletContext事件监听器中的接口和方法如表所示:
ServletContextAttributeListener:
attributeAdded(ServletContextAttributeEvent scae) 增加属性时激发此方法
attributeRemoved(ServletContextAttributeEvent scae) 删除属性时候激发此方法
attributeReplaced(ServletContextAttributeEvent scae) 修改属性时激发此方法
ServletContextListener:
contextDestroyed(ServletContextEvent sce) 销毁ServletContext时激发此方法
contextInitialized(ServletContextEvent sce) 创建ServletContext时激发此方法
ServletContextListener调用机制:
当在Web应用中部署了实现该接口的实现类后,在Web容器加载Web应用时(例如:启动服务器)就会自动调用contextInitialized()方法,而当Web容器销毁Web应用时(例如:关闭服务器),会自动调用contextDestroyed()方法。
ServletContextAttributeListener:
addributeAdded():触发该事件的代码:context.setAttribute("counter",new Integer(0));
attributeReplaced():触发该事件的代码:context.setAttribute("counter",new Integer(100));
attributeRemoved():触发该事件的代码:contextremoveAttribute("counter");
2.HttpSession事件监听器:
对会话对象进行监听的接口有HttpSessionAttributeListener、HttpSessionListener、HttpSessionActivationListener和HttpSessionBindingListener。其中HttpSessionAttributeListener用于监听HttpSession对象中属性的改变,例如属性的增加、删除和修改。HttpSessionListener用于监听HttpSession对象的改变,例如HttpSession对象的创建与销毁,HttpSessionActivationListener用于监听HttpSession对象的状态,例如HttpSession对象是被激活还是被钝化。HttpSessionBindingListener用于监听HttpSession对象的绑定状态,例如添加对象和移除对象。
HttpSession事件监听器中的接口和方法如表所示:
HttpSessionAttributeListener:
attributeAdded(HttpSessionBindingEvent hsbe) 增加属性时激发此方法
attributeRemoved(HttpSessionBindingEvent hsbe) 删除属性时候激发此方法
attributeReplaced(HttpSessionBindingEvent hsbe) 修改属性时激发此方法
HttpSessionListener:
sessionCreated(HttpSessionEvent hse) 创建HttpSession时激发此方法
sessionDestroyed(HttpSessionEvent hse) 销毁HttpSession时激发此方法
HttpSessionActivationListener:
sessionDidActivate(HttpSessionEvent se) 激活HttpSession时激发此方法
sessionWillPassivate(HttpSessionEvent se) 钝化HttpSession时激发此方法
HttpSessionBindingListener:
valueBound(HttpSessionBindingEvent hsbe) 调用setAttribute()方法时激发此方法
valueUnbound(HttpSessionBindingEvent hsbe) 调用removeAttribute ()方法时激发此方法
HttpSessionListener也有初始化和销毁的方法:
sessionCreated()
sessionDestroyed()
web.xml的配置:
<listener>
<listener-class>com.TestListener</listener-class>
</listener>
HttpSessionAttributeListener:
attributeAdded():产生事件的代码:session.setAttribute("username","Sun");
attributeReplaced():产生事件的代码:session.setAttribute("username","zhang");
attributeRemoved():产生事件的代码:session.removeAttribute("username");
HttpSessionBindingListener:
valueBound()
valueUnbound()
调用机制:如果一个类实现了HttpSessionBindingListener接口,则当这个类的对象通过session.setAttribute()被绑定到Session对象中时,则该对象的valueBound()方法被自动调用,当这个对象从Session中删除时(调用session.invalidate()和session.removeAttribute()方法,或者Session对象过期) valueUnbound()方法将被自动调用。
HttpSessionActivationListener:
sessionDidActivate()
sessionWillPassivate()
调用机制:
活化(Activate)与钝化(POassivate)是Web容器为了更好的利用系统资源或者进行服务器负载平衡等原因而对特定对象采取的措施。
会话对象的钝化指的是暂时将会话对象通过对象序列化的方式储存到硬盘上,而会话对象活化与钝化相反,Web容器把硬盘上的储存的会话对象文件重新加载到Web容器中。
sessionDidActivate()与sessionWillPassivate()方法分别于会话对象活化后和会话对象钝化前由容器进行自动调用。
3.ServletRequest事件监听器
对请求消息对象进行监听的接口有ServletRequestListener和ServletRequestAttributeListener,其中ServletRequestListener用于监听ServletRequest对象的变化,例如ServletRequest对象的创建和销毁。ServletRequestAttributeListener用于监听ServletRequest对象中属性的变化,例如属性的增加、删除和修改。ServletRequest事件监听器的接口和方法如表所示:
ServletRequestAttributeListener:
attributeAdded(ServletRequestAttributeEvent srae) 增加属性时激发此方法
attributeRemoved(ServletRequestAttributeEvent srae) 删除属性时候激发此方法
attributeReplaced(ServletRequestAttributeEvent srae) 修改属性时激发此方法
ServletRequestListener:
requestDestroyed(ServletRequestEvent sre) 销毁ServletRequest时激发此方法
requestInitialized(ServletRequestEvent sre) 创建ServletRequest时激发此方法
ServletRequestListener:
requestInitialized()
requestDestroyed()
调用机制:
与ServletContextListener接口类似,在Web应用中部署实现该接口的实现类后,在HttpServletRequest对象(JSP中request对象)建立或者被销毁时,由Web容器自动调用requestInitialized()或者requestDestroyed()方法。
ServletRequestAttributeListener:
attributeAdded() :触发事件的代码:request.setAttribute("username","sun");
attributeReplaced() :触发事件的代码:request.setAttribute("username","zhang");
attributeRemoved() :触发事件的代码:request.removeAttribute("username");
Servlet监听器典型应用:
统计在线人数:
当一个用户是在线的,也就是登陆在系统中的时候,当用户进入到系统之后,服务器就会为这个用户创建一个session对象,而当用户离开系统之后,这个session对象就会被销毁掉,所以我们可以根据session的创建和销毁的监听事件来完成在线人数的统计:
首先,新建一个项目,然后我们创建一个普通的类,让这个类实现javax.servlet.http.HttpSessionListener这个接口,这个这个类就是一个Session的监听器了。
这样这个类就默认实现了父类的两个监听方法:
public class AccountListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent sessionEvent) {
}
@Override
public void sessionDestroyed(HttpSessionEvent sessionEvent) {
// TODO Auto-generated method stub
}
}
sessionCreated()是当创建session的时候执行的监听方法,sessionDestroyed()方法是当销毁session时执行的方法。
我们在session被创建的时候把在线人数加1,在session被销毁的时候把在线人数减1即可。并且把这个在线人数的变量放在全局变量servletContext上下文中,就是application中。
1、AccountListener.java:
package com.yun.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class AccountListener implements HttpSessionListener {
private int countNumber;//在线人数
@Override
public void sessionCreated(HttpSessionEvent sessionEvent) {
//用户登录系统后,服务器为为其会创建session,激发该方法
countNumber++;
//把在线人数加1,放在上下文中
sessionEvent.getSession().getServletContext().setAttribute("count", countNumber);
}
@Override
public void sessionDestroyed(HttpSessionEvent sessionEvent) {
//用户退出系统后,会销毁session,激发该方法
countNumber--;
//把在线人数减1,放在上下文中
sessionEvent.getSession().getServletContext().setAttribute("count", countNumber);
}
}
然后我们把这个监听器配置在web.xml中,
2、web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>testListener004</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <listener> <listener-class>com.yun.AccountListener</listener-class> </listener> </web-app>
然后我们在写一个访问页面,用于用户访问,并在页面显示在线人数:
3、index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>统计在线人数</title>
</head>
<body>
当前在线人数:
<h3> ${count }</h3>
</body>
</html>
这样,我们在访问系统的index.jsp这个页面的时候,就会显示当前在线人数,为了创建多个session,我们可以使用多个浏览器进行访问,或者对一个浏览器反复的进行清除cookie进行访问,或者使用其他机器对这个项目进行访问,就会发现在线人数开始进行增长了。
这样这个在线人数统计的监听器例子就完成了。