目录
2.3.1 实现javax.servlet.Filter接口
一、了解过滤器和监听器
过滤器和监听器
普通程序员与高级程序员工作区别
【普通程序员】:业务实现。——增删改查
【高级程序员】:不负责业务实现细节——业务整理、程序调优。
二、Filter过滤器
2.1 过滤器概念
过滤器:就是在源数据和目的数据之间起过滤作用的组件
HTML
过滤器是JavaWeb三大组件之一(servlet、Listener、Filter),它与Servlet很相似,但是过滤器是用来拦截请求的,而不是处理请求的。
具体概述:
在Web应用中,过滤器是驻留在服务器端的web组件,可以截取客户端和资源之间的请求与响应信息,且对这些信息进行过滤。WEB开发人员通过Filter技术,对web服务器管理的所有web资源(JSP,Servlet,静态图片文件或静态html文件等)进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制。过滤敏感词汇、压缩响应信息等一些高级功能。
当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter"放行",那么会继承执行用户请求的Servlet;如果Filter不"放行",那么久不会执行用户请求的Servlet。可以理解为,Filter来决定是否调用Servlet。当执行完成Servlet的代码后,还会执行Filter后面的代码。
2.2 过滤器的作用
统一编码,统一用户认证,屏蔽非法文字,进行响应数据压缩
应用场景:HTML
1.对用户进行统一认证,对用户的请求进行记录和审核
用户认证就是判断一个用户是否为合法用户的过程。
目前用户认证大都是基于Cookie、Session实现的。注册、登录几乎是所有web站点都具备的两个功能。以商城系统为例,用户输入登录名、密码进行注册、登录,这样系统内就可以为用户保存如:购物车、订单、商品喜好等个性化信息。用户认证使用户授权的基础。以商城系统为例,商家需要先进行用户认证,系统才能判断它是否有某个店铺的管理权。API调用和网页浏览一样,也需要用户认证。
2.对用户传输的数据过滤和替换,转换图像格式,对响应内容进行压缩,减少网络传输。
每个请求和响应对象都需要设置字符编码,可以通过过滤器来对所有请求和响应对象进行过滤,进行字符集设置。
3.对请求和响应进行加密和解密
2.3过滤器的实现步骤
声明过滤器类并让其实现Filter接口;重写指定方法
在web.xml配置过滤器
Servlet API提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则吧这个Java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。
Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,web服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
(1)调用目标资源之前,让一段代码执行。
(2)是否调用目标资源(即是否让用户访问web资源)
(3)调用目标资源之后,让一段代码执行。
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChiain对象是filter接口中最重要的一个对象,它也提供了doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。
过滤器实现:
2.3.1 实现javax.servlet.Filter接口
java:
public class FilterDemo1 implements Filter{}
2.3.2 实现接口中的抽象方法
java:
/
* 过滤器对象被销毁之前执行的方法
* 服务器关闭或重载时,过滤器对象销毁
*/
public void destroy() {
System.out.println("过滤器被销毁");
}
/
* 对请求进行过滤的方法
* ServletRequest 请求对象
* ServletResponse 响应对象
* FilterChain 过滤链对象
* 作用:将通过此过滤器的请求,传递给下一个过滤器或目标Servlet
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("过滤器执行过滤方法");
System.out.println("DemoFilterdoFilter执行之前");
对请求放行的方法
chain.doFilter(request, response);
System.out.println("DemoFilterdoFilter执行之后");
}
/
* 过滤器对象创建之后执行的方法,对过滤器进行初始化
* 其中FilterConfig参数为当前过滤器的配置,获取过滤器的初始化参数
* 当服务器启动时,过滤器对象被创建
*/
public void init(FilterConfig fConfig) throws ServletException {
System.out.println("过滤器初始化");
}
2.3.3 在web.xml配置过滤器
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_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>Web_03</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- 以上为web.xml的固定格式 -->
<!-- 过滤器 -->
<!-- 实例化 -->
<filter>
<!-- filter文件的名字 -->
<filter-name>loginFilter</filter-name>
<!-- filter的路径 -->
<filter-class>com.java.web.filter.loginFilter</filter-class>
</filter>
<!-- 配置 -->
<filter-mapping>
<!-- filter名字 -->
<filter-name>loginFilter</filter-name>
<!-- 自定义路径实现名 -->
<url-pattern>/loginFilter.do</url-pattern>
</filter-mapping>
</web-app>
过滤路径:
1.具体路径:某个Servlet的路径
例如:/hello
2.路径后缀统配:*.后缀名
例如: *.do *.html *.action
3.全路径统配: /*
过滤所有的请求,包括请求Servlet,jsp,以及请求静态资源
<urlpattern/*</urlpattern</filtermapping
2.3.4 Filter生命周期
过滤器的声明周期:实例化过滤器——初始化——过滤——销毁
Filter实例化:web应用程序启动时,web服务器将创建Filter的实例对象,filter对象只会创建一次
初始化:当Filter对象实例化之后,就会调用init方法,完成对象的初始化功能,init方法也只会执行一次
过滤:Filter会对配置了过滤器的资源的请求和响应进行过滤,而且是每次请求和响应都会进行过滤
销毁:当应用服务器重启或停止,都会执行destroy方法销毁Filter,destroy方法在Filter的生命周期中仅执行一次。
Filter的创建:
Filter的创建和销毁由WEB服务器负责。web应用程序启动时,web服务器将创建Filter的实例对象,并调用其init方法,完成对象的初始化功能,从而为后续的用户请求做好拦截的准备工作,filter对象指挥创建一次,init方法也只会执行一次。通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
Filter的销毁:
web容器调用destdestroyory方法销毁Filter。destroy方法在Filter的生命周期中仅执行一次。在destroy方法中,可以释放过滤器使用的资源。
2.3.5 FilterConfig配置对象
用户在配置filter时,可以使用为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。
因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得:
java:
得到filter的名称:
String getFilterName()
返回在部署描述中执行名称的初始化参数的值。如果不存在返回null:
String getInitParameter(String name)
返回过滤器的所有初始化参数的名字的枚举集合:
Enumeration getInitParameterNames()
返回Servlet上下文对象的引用:
public ServletContext getServletContext()
2.4 过滤器在WEB应用中实例
2.4.1 字符编码过滤器
在学习中,我们需要在每个Servlet里面对请求和响应对象设置字符集,name代码重用性低,不利于维护,而且还存在硬编码的问题;name我们可以把对请求和响应设置字符集的代码放在过滤器里面,提高代码重用性;把字符集相关的配置放在过滤器的初始化参数,解决硬编码问题。
java:
package com.zking.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;
/
* 字符编码过滤器
* 对所有的请求和响应对象设置字符集
* 用来提高代码复用性和解决硬编码问题。
*
* @author zkingzz
*
*/
public class EncodingFilter implements Filter {
private String encoding;
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
System.out.println("字符集过滤器开始过滤");
// 对请求对象设置字符集
servletRequest.setCharacterEncoding(encoding);
//对相应对象设置字符集
servletResponse.setCharacterEncoding(encoding);
servletResponse.setContentType("text/html;charset=" + encoding);
// 放行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String encoding = filterConfig.getInitParameter("encoding");
this.encoding = encoding;
}
}
xml:
<!-- 过滤器 -->
<!-- 实例化 -->
<filter>
<!-- filter文件的名字 -->
<filter-name>loginFilter</filter-name>
<!-- filter的路径 -->
<filter-class>com.java.web.filter.loginFilter</filter-class>
</filter>
<!-- 配置 -->
<filter-mapping>
<!-- filter名字 -->
<filter-name>loginFilter</filter-name>
<!-- 自定义路径实现名 -->
<url-pattern>/loginFilter.do</url-pattern>
</filter-mapping>
三、Listener监听器
概述:
先理解什么是监听器,可能某些初学者 听到监听器这个词汇会感到有些不明觉厉,实际上监听器这种东西没各位想象的那么复杂;
监听器就是一个专门用于:对其它对象产生的特定事件,或状态改变后进行监听和相应处理的对象
监听器其实就是一个实现特定接口的普通 Java程序,这个程序专门用于监听另一个 Java对象的方法调用或属性改变。
当被监听对象发生上述事件后,监听器某个方法立即被执行。
使用场景:
(1)统计在线人数和在线用户
(2)系统启动时加载初始化信息
(3)统计网站访问量
(4)跟Spring结合,做相关操作
3.1 介绍:
来自于servlet规范中【一组接口,8个】
专门用于监听【域对象生命周期变化】以及【域对象共享数据变化情况】
监听器接口实现类,只能由开发人员负责实现
JavaWeb中的监听器是 Servlet规范中定义的一种特殊类,它用于监听 Web应用程序中的 ServletContext、 HttpSession和 ServletRequest等域对象的创建与销毁事件,以及监听这些域对象中的属性发生修改的事件。
域对象:
在某一个范围之内,可以为servlet之间提供共享数据的对象。
分类:
ServletContext application 全局作用域对象
在tomcat运行期间,可以为当前工程中所有的Servlet提供共享数据。
HttpSession session 会话作用域对象
在一次会话过程中,为参与本次会话的Servlet提供共享数据
HttpServletRequest request 请求作用域对象
在一次请求过程中,比如【请求转发】,为参与本次请求的所有Servlet提供共享数据
3.2 案例:统计在线人数Demo
java:
实现一个用于监听当前 Web服务中 Session数量的监听器;可以简单的理解为统计在线人数
首先我们需要实现 Servlet规定的监听器接口
public class OnlineCountListener implements HttpSessionListener {
//实现该接口后会必须重写下面这两个方法
@Override
public void sessionCreated(HttpSessionEvent se) {
//该方法是会在 Session创建时被调用,也就是 Session创建的监听事件
//拿到上下文对象
ServletContext context = se.getSession().getServletContext();
Integer onlineCount = (Integer) context.getAttribute("onlineCount");
//在触发 Session创建监听事件时,如果 onlineCount变量为 0我们将其设置为 1,表示第一//个用户在线
if (onlineCount==null){
onlineCount = new Integer(1);
//如果不为 0表示之前有用户在线,我们将在线人数 +1
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
//打印输出 方便测试,可以去掉
System.out.println(onlineCount);
//将在线人数的变量赋值添加到上下文对象中,方便前端取值
context.setAttribute("onlineCount",onlineCount);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
//这个方法则相反,会在Session被销毁时调用
//销毁部分则逻辑相反
ServletContext context = se.getSession().getServletContext();
Integer onlineCount = (Integer) context.getAttribute("onlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count1);
}
context.setAttribute("onlineCount",onlineCount);
}
}
注册监听器
监听器写完之后我们需要和过滤器一样,将其注册到 web.xml中才能生效
xml:
<!-- 监听器设置 -->
<listener>
<!-- 监听器文件路径 -->
<listener-class>com.java.web.listener.VisitorListener</listener-class>
</listener>
我们再写一个 jsp,让它能够拿到并展示在线人数
<body>
<div>
<h2>当前网站在线人数为:
<span style="backgroundcolor: aquamarine${applicationScope.get("onlineCount")}>
</span>
</h2>
</div>
</body>
小结:
Filter过滤器它是JavaWeb的三大组件之一。三大组件:servlet程序、Listener监听器、Filter过滤器
Filter过滤器它是JavaEE的规范,也就是接口。
Filter过滤器它的作用:拦截请求,过滤响应。
拦截请求常见的应用场景有:
权限检查、日记操作、事务管理、......