Servlet 过滤器和监听器

时间:2023-02-13 10:48:32

恰同学少年,风华正茂;书生意气,挥斥方遒。—《沁园春·长沙》


1 过滤器的定义

过滤器是一个服务器端的组件,它主要用于客户端(浏览器)的请求进行过滤处理,再将过滤后的请求转发到下一资源,他在 JSP网站开发中具有非常重要的作用。

过滤器实质就是在 Web 应用服务器上的一个 Web 应用组件,用于拦截客户端(浏览器)对目标资源的请求,并对这些请求进行处理再发给目标资源。

过滤器拦截请求,不是禁止访问,相应处理后,还会转到目标地址
所拦截的请求路径可以是 servlet 或者是某个页面路径 /index.jsp等
过滤器拦截servlet或者jsp页面内容,比如内容替换,再向用户展现修改后的页面

过滤源—>过滤规则—->过滤结果

观看一个视频网站时,对于同一个网页地址,登录过的用户,直接能观看,未登录的用户,则跳转到登录界面

访问一个页面时,该页面无法加载或不存在,可以过滤请求,返回一个错误页

2 过滤器的工作原理

没有过滤器,用户直接访问资源。

Servlet 过滤器和监听器

Servlet 过滤器和监听器

Servlet 过滤器和监听器

Servlet 过滤器和监听器

3 过滤器两种配置方法

过滤器和Servlet 十分类似,都需要进行配置,在 Servlet3.0 中,提供了采用注解的方式配置过滤器,如:

@WebFilter(filterName="FirstFilter",
urlPatterns="/*",
initParams={
@WebInitParam(name="mood",value="awake")})

urlPatterns 属性:用于指定那些 URL 应用该过滤器。如果指定所有页面均应用该过滤器可以设置为“/*”。
initParams 属性 用于指定初始化参数

在web.xml 文件中配置

 <filter>
<filter-name>FirstFilter</filter-name>
<filter-class>filter.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>指定一个过滤器。
<filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。
<filter-class>元素用于指定过滤器的完整的限定类名。
<init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。
在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。

<filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
<filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字
<url-pattern>设置 filter 所拦截的请求路径(过滤器关联的URL样式)


FirstFilter.java

//package filetr;

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.annotation.WebFilter;

/**
* Servlet Filter implementation class FirstFilter
*/

@WebFilter("/*")// 采用注解的方式
public class FirstFilter implements Filter {

/**
* Default constructor.
*/

public FirstFilter() {
// 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
}
}

init() 过滤器的初始化方法,Web容器创建过滤器实例后将调用这个方法,这个方法可以获取web.xml文件中的过滤器参数。

doFilter() 完成实际的过滤操作。过滤器的核心方法,当用户请求访问与过滤器关联的URL时,Web容器将先调用过滤器的doFilter方法。 FilterChain参数可以调用chain.doFilter方法,将请求传给下一个过滤器(或目标资源),或利用转发、重定向将请求转发到其他资源。

destroy() Web容器在销毁过滤器实例前调用该方法,可以释放过滤器占用的资源。(大多数情况下用不到)

4 过滤器示例

FilterConfig 使用

Filter 的 init 方法中提供了一个 FilterConfig 对象。

如 web.xml 文件配置如下:

<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.runoob.test.LogFilter</filter-class>
<init-param>
<param-name>Site</param-name>
<param-value>菜鸟教程</param-value>
</init-param>
</filter>

在 init 方法使用 FilterConfig 对象获取参数:

public void  init(FilterConfig config) throws ServletException {
// 获取初始化参数
String site = config.getInitParameter("Site");
// 输出初始化参数
System.out.println("网站名称: " + site);
}

示例

利用过滤器,实现网站访问计数器的功能,并在配置过滤器时,将网站访问的初始值设置为 1000.

每一次访问页面,都会通过过滤器,过滤器里使count 值每次 加一,达到计数器的效果。

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>主界面</title>
</head>
<body>
<h2>
欢迎光临,<br>
您是本站的第【
<%=application.getAttribute("count") %>
】位访客!
</h2>
</body>
</html>

CountFilter.java

//package com.mingrisoft;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;

/**
* Servlet过滤器实现类CountFilter
*/

@WebFilter(urlPatterns = { "/index.jsp" }, initParams = { @WebInitParam(name = "count", value = "1000") })
public class CountFilter implements Filter {
private int count; // 来访数量

/**
* 默认构造方法
*/

public CountFilter() {
System.out.println("CountFilter的构造方法 ....");
}

/**
* 销毁方法
*/

public void destroy() {
System.out.println("CountFilter的destroy ....");
}

/**
* 过滤处理方法
*/

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
count++; // 访问数量自增
// 将ServletRequest转换成HttpServletRequest
HttpServletRequest req = (HttpServletRequest) request;
// 获取ServletContext
ServletContext context = req.getServletContext();
context.setAttribute("count", count); // 将来访数量值放入到ServletContext中
System.out.println("CountFilter的start ....");
chain.doFilter(request, response); // 向下传递过滤器
System.out.println("CountFilter的end ....");
}

/**
* @see Filter#init(FilterConfig)
*/

public void init(FilterConfig fConfig) throws ServletException {
System.out.println("CountFilter的init ....");
String param = fConfig.getInitParameter("count"); // 获取初始化参数
count = Integer.valueOf(param); // 将字符串转换为int
}

}
第一次启动index.jsp
CountFilter的构造方法 ....
CountFilter的init ....
CountFilter的start ....
CountFilter的end ....

刷新一次index.jsp页面,执行一次doFilter()
CountFilter的start ....
CountFilter的end ....

5 Servlet 监听器

Servlet 监听器可以监听到 在特定事件发生的事件,并根据其做出相应的反应。

监听器的作用是监听 Web 容器的有效期事件,因此它是由容器管理的。利用 Listener 接口监听在容器中的某个执行程序,并且根据应用程序的需求做出适当的响应。

下表列出了 Servlet 和 JSP中的 8 个Listener 和 6 个Event 类。

Listener接口 Event类
ServletContextListener ServletContextEvent
ServletContextAttributeListener ServletContextAttribute
HttpSessionListener / HttpSessionActivationListener HttpSessionEvent
HttpSessionAttributeListener / HttpSessionBindingListener HttpSessionBindingEvent
ServletRequestListener ServletRequestEvent
ServletRequestAttributeListener ServletRequestAttributeEvent

Servlet 上下文监听

Servlet 上下文监听可以监听 ServletContext 对象的创建、删除、属性的添加、删除和修改操作,该监听器需要用到一下两个接口。
1.ServletContextListener 接口

它主要实现监听 ServletContext 的创建和删除。

2.ServletAttributeListener 接口

它主要实现监听 ServletContext 属性的增加、删除、修改操作。

示例

创建并配置上下文监听器,实现当项目发布时,在控制台输出提示信息“初始化”;当项目被移去时,在控制台输出文字“销毁”。
FirstListener.java

//package com.mingrisoft;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;


@WebListener //配置监听器
public class FirstListener implements ServletContextListener {

/**
* 默认构造方法
*/

public FirstListener() {
}

/**
* Servlet上下文初始化成功时触发的方法
*/

public void contextInitialized(ServletContextEvent arg0) {
System.out.println("初始化");
}

/**
* Servlet上下文被销毁时触发的方法
*/

public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("销毁");
}
}

6 综合实例-编写一个字符编码过滤器

其实就是把这两句封装在过滤器中,让它可以重用。

request.setCharacterEncoding("UTF-8"); // 设置request的编码格式                        response.setContentType("text/html; charset=UTF-8");// 设置response字符编码

CharactorFilter.java

//package com.mingrisoft;

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.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;

/**
* Servlet过滤器实现类CharactorFilter
*/

@WebFilter(urlPatterns = { "/*" }, initParams = { @WebInitParam(name = "encoding", value = "UTF-8") }) // 配置过滤器
public class CharactorFilter implements Filter {
String encoding = null; // 字符编码

public CharactorFilter() {
}

/**
* 销毁方法
*/

public void destroy() {
encoding = null;
}

/**
* 过滤处理方法
*/

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (encoding != null) { // 判断字符编码是否为空
request.setCharacterEncoding(encoding); // 设置request的编码格式 //
response.setContentType("text/html; charset=" + encoding);// 设置response字符编码
}
chain.doFilter(request, response); // 传递给下一过滤器
}

/**
* 初始化方法
*/

public void init(FilterConfig fConfig) throws ServletException {
encoding = fConfig.getInitParameter("encoding"); // 获取初始化参数
}

}

AddServlet .java

//package com.mingrisoft;

import java.io.IOException;
import java.io.PrintWriter;

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

/**
* Servlet implementation class AddServlet
*/

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

/**
* 处理GET请求的方法
*/

protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);// 处理GET请求
}

/**
* 处理POST请求的方法
*/

protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 处理POST请求
PrintWriter out = response.getWriter(); // 获取 PrintWriter
String id = request.getParameter("id"); // 获取图书编号
String name = request.getParameter("name"); // 获取名称
String author = request.getParameter("author"); // 获取作者
String price = request.getParameter("price"); // 获取价格
out.print("<h2>图书信息添加成功</h2><hr>"); // 输出图书信息
out.print("图书编号:" + id + "<br>");
out.print("图书名称:" + name + "<br>");
out.print("作者:" + author + "<br>");
out.print("价格:" + price + "<br>");
out.flush(); // 刷新流
out.close(); // 关闭流
}
}

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>添加图书信息</title>
<style type="text/css">
ul {
list-style: none;
}

li{padding:5px;}

</style>
</head>
<body>
<section>
<h2>   添加图书信息</h2>
<form action="AddServlet" method="post">
<ul>
<li>图书编号:<input type="text" name="id"></li>
<li>图书名称:<input type="text" name="name"></li>
<li>作  者:<input type="text" name="author"></li>
<li>价  格:<input type="text" name="price"></li>
<li>     <input type="submit" value="添 加"></li>
</ul>
</form>
</section>
</body>
</html>

Servlet 过滤器和监听器