03 过滤器和监听器

一、过滤器

过滤器就是在原数据和目标数据之间起过来作用的中间组件。
JSPWeb应用程序中,过滤器是一种在服务端运行的Web组件程序,它可以截取客户端给服务端发的请求,也可以截取服务器给客户端的响应。
在这里插入图片描述

1,1、过滤器使用的3个场景

  1. 不文明的词汇被*所代替;
    (当用户提交评论时,评论内容先经过过滤器,过滤器将不文明的词汇替换成*,过来后的评论内容传递到目标文件。)
  2. 表单提交的中文需要进行请求编码设置,可以通过过滤器统一进行请求编码设置。
  3. 通过过滤器为上传的图片统一添加水印。

1.2、过滤器的简单工作过程

Web容器获得一个对资源的请求时,Web容器判断是否存在过滤器和这个资源关联。如果存在关联就把请求交给过滤器去处理,在过滤器中可以对请求的内容做出改变,然后再将请求转交给被请求的资源。
当请求的资源做出响应时,web容器同样会将响应先转发给过滤器,在过滤器中可以对响应做出处理,然后再将响应发送给客户端。
在这整个过程中客户端和目标资源是不知道过滤器存在。

1.3、过滤器链

在一个web应用程序中可以配置多个过滤器,从而形成过滤器链。在请求资源时,过滤器链中的过滤器依次对请求作出处理。在接受到响应时再按照相反的顺序对响应作出处理。
在这里插入图片描述
注意:
在过滤器中不一定必须将请求发送给被请求资源,也可以直接给客户端做出响应。

1.4、开发过滤器的步骤

  1. 定义过滤器类,实现java.servlet.Filter接口;
  2. 重写init()方法、doFilter()方法和destory()方法;
  3. 配置过滤器。

实例1:开发过滤器

项目的信息

Dynamic Web Project项目
testFiltercom.bennett.filterFirstFilter
第一步:创建过滤器类
package com.bennett.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 FirstFilter implements Filter  {	
	public void init(FilterConfig config) {	
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("过滤器1请求");
		chain.doFilter(request, response);
		System.out.println("过滤器1响应");
	}
	
	public void destroy() {	
	}
}
第二步:配置过滤器

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
  <display-name>testFilter</display-name>
  
  <filter>
  	<filter-name>firstFilter</filter-name>
  	<filter-class>com.bennett.filter.FirstFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>firstFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
 
</web-app>

解释:
1、 <filter>节点描述该Filter对应的类;

2、 <filter-mapping>中的<filter-name>必须和<filter>节点中的值相同;

3、<filter-class>配置过滤器类的存储路径;

4、<url-pattern>指定该过滤器关联的URL,比如/*指的是对所有资源都过滤。/admin/*指的是对admin目录下的所有资源文件进行过滤

第三步:测试过滤器

在这里插入图片描述

实例2:开发过滤器链

项目的信息

Dynamic Web Project项目
testFiltercom.bennett.filterSecondFilter
第一步:创建过滤器类
package com.bennett.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 SecondFilter implements Filter  {
	
	public void init(FilterConfig config) {		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("过滤器2请求");
		chain.doFilter(request, response);
		System.out.println("过滤器2响应");
	}
	
	public void destroy() {
		
	}
}
第三步:配置过滤器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
  <display-name>testFilter</display-name>
  <!-- 第一个过滤器的配置 -->
   <filter>
  	<filter-name>firstFilter</filter-name>
  	<filter-class>com.bennett.filter.FirstFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>firstFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
  
   <!-- 第二个过滤器的配置 -->
   <filter>
  	<filter-name>secondFilter</filter-name>
  	<filter-class>com.bennett.filter.SecondFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>secondFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
第三步:测试过滤器

在这里插入图片描述
过滤器链工作流程
在这里插入图片描述

实例3:使用过滤器实现汉字编码过滤器

项目的信息

Dynamic Web Project项目
testFiltercom.bennett.filterCharacterFilter
第一步:定义过滤器类
package com.bennett.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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CharacterFilter implements Filter  {
	private String encode = "utf-8";
	
	@Override
//	从web.xml配置文件中读取默认编码,如果没有配置编码,默认使用utf-8
	public void init(FilterConfig filterConfig) {
//		FilterConfig用于从web.xml中配置读取默认编码
		encode = filterConfig.getInitParameter("encode");
		if(encode == null) {
			encode = "UTF-8";
		}else {
			encode = encode.toUpperCase();
		}
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		if("POST".equalsIgnoreCase(request.getMethod())) {
//			request.setCharacterEncoding(encode);
			request.setCharacterEncoding(encode);
			response.setContentType("text/html;charset="+encode);
			chain.doFilter(request, response);
			return;
		}
		chain.doFilter(request, response);
		
	}
	@Override
	public void destroy() {
		
	}

}
第二步:配置过滤器
<!-- 第三个过滤器的配置 --> 
   <filter>
  	<filter-name>characterFilter</filter-name>
  	<filter-class>com.bennett.filter.CharacterFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>characterFilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>
第三步:测试过滤器

创建一个jsp文件:add.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试编码过滤器</title>
</head>
<body>
	<form action="MyServlet" method="post">
		请输入汉字:<input type="text" name="key" value="我是汉字">
		<input type="submit" value="发送">
	</form>
</body>
</html>

创建Servlet文件:MyServlet.java

package com.bennett.filter;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
   
    public MyServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request,response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String key = request.getParameter("key");
		System.out.println("key = "+ key);
	}

}

效果图展示
在这里插入图片描述
在这里插入图片描述
项目目录结构:
在这里插入图片描述

二、监听器

监听器的作用是监听Web应用程序中某一个对象,并根据应用程序的需求做出相应的处理,JavaWeb应用程序中,Servlet容器提供了多种监听器。

监听器描述
ServletRequestListener监听request对象的 创建和销毁
ServletRequestAttributeListener监听向request作用域赋值和取值
HttpSessionListener监听session对象的创建和销毁
HttpSessionAttributeListener监听向session作用域赋值和取值
ServletContextListener监听application对象的 创建和销毁
ServletContextAttributeListener监听向application作用域赋值和取值

开发过滤器的步骤:

  1. 定义监听器类,实现监听器接口;
  2. 重写相应的方法;
  3. 配置监听器

实例4:统计在线人数

思路如下:
当有用户访问时,web容器会创建会话,当有用户退出时,web容器会销毁会话。HttpSessionListener监听器能够监听会话的创建和销毁,在会话创建时,在线人数加1,在会话销毁时,在线人数减1。在线人数需要存储在变量中,这个变量的值需要能够在每一位访问者的页面上显示,因此该变量存储在application作用域中。

项目的信息

Dynamic Web Project项目
onlinecom.bennett.listenerServletContextListenerImpl
HttpSessionListenerImpl
第一步:创建application对象监听器

com.bennett.listener包中创建类ServletContextListenerImpl,实现java.servlet。ServletContextListener接口,用于监听application对象的创建和销毁。当application创建时(web容器启动时),设置在线人数为0,当application对象销毁时(web容器关闭),清空在线人数。

ServletContextListenerImpl.java

package com.bennett.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ServletContextListenerImpl implements ServletContextListener{
	
	public void contextInitialized(ServletContextEvent event) {
		int num = 0;
		ServletContext application = event.getServletContext();
		application.setAttribute("onLineNum", num);
	}
	
	public void contextDestroyed(ServletContextEvent event) {
		ServletContext application = event.getServletContext();
		application.removeAttribute("onLineNum");
	}
}

解释:
1、ServletContextListener监听器用于监听application对象创建和销毁;

2、当application创建时,监听器自动调用contextInitialized()方法;

3、当application对象销毁时,监听器自动调用contextDestory()方法;

4、contextInitialized()方法中的参数ServletContextEventgetServletContext()方法用于获取创建的application对象,并将在线人数0保存到键为onLineNumapplication作用域中。

5、当application对象销毁时,在contextDestory()方法中将为onLineNum的对象从application作用域中移除。

第二步:配置application监听器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
  <display-name>online</display-name>
  <!-- 配置application监听器  -->
  <listener>
  	<listener-class>com.bennett.listener.ServletContextListenerImpl</listener-class>
  </listener>
</web-app>

解释:
1、 <listener>节点配置监听器;
2、<listener-class>指明监听器类的路径。

第三步:创建session监听器

HttpSessionListenerImpl.java

package com.bennett.listener;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class HttpSessionListenerImpl implements HttpSessionListener{
	public void sessionCreated(HttpSessionEvent event) {
		ServletContext application = event.getSession().getServletContext();
		Integer num = (Integer) application.getAttribute("onLineNum");
		if(num != null) {
			int count = num;
			count = count + 1;
			application.setAttribute("onLineNum", count);
		}else {
			application.setAttribute("onLineNum", 1);
		}
	}
	
	public void sessionDestoryed(HttpSessionEvent event) {
		ServletContext application = event.getSession().getServletContext();
		Integer num = (Integer) application.getAttribute("onLineNum");
		int count = num;
		count = count + 1;
		application.setAttribute("onLineNum", count);
	}
}

解释:

1、当session被创建时,会调用监听器的sessionCreated()方法;

2、当session被注销时,会调用监听器的sessionDestoryed()方法;

3、在sessionCreated()方法中实现在线人数加1的功能;

4、在sessionDestoryed()方法中实现在线人数减1的功能。

第四步:配置session监听器
<!-- 配置session监听器  -->
  <listener>
  	<listener-class>com.bennett.listener.HttpSessionListenerImpl</listener-class>
  </listener>
第五步:在界面上显示在线人数

WebContent目录下创建online.jsp文件,用于显示在线人数。

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
	当前在线人数: ${onLineNum}
</body>
</html>
第六步:测试在线人数

将项目部署到tomcat容器,启动tomcat容器,在浏览器中访问该项目的online.jsp文件,查看在线人数。

结果展示
在这里插入图片描述
不同的浏览器会产生不同的session对象,刷新之后就会显示最大数。
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值