过滤器&监听器
1 过滤器
过滤器介绍
过滤器可以过滤访问web资源的所有请求和响应.
作用类似网站的门卫.
02-过滤器的工作原理
过滤器的工作原理图
文字总结(过滤器工作原理)
1.浏览器访问web资源时,tomcat创建的请求和响应对象会首先进入过滤器,过滤器(开发人员)可以根据请求信息来决定是否放行.
2.如果过滤器(开发人员)不放行(默认),过滤器(开发人员)可以直接给浏览器响应信息.
3.如果过滤器(开发人员)放行,请求和响应对象才能到达web资源,web资源就可以处理请求响应信息.
4.过滤器放行就意味着web资源处理了请求响应,在web资源设置响应信息之后,在响应信息到达浏览器之前,过滤器(开发人员)还可以改变响应信息.
03-过滤器入门案例
需求
演示过滤器的工作原理
模拟登陆用户放行,未登录用户拦截.用有没有传user参数表示是否登录.
步骤分析
1.编写一个web资源 resource.jsp
2.编写一个过滤器HelloFilter,
模拟登陆用户放行,未登录用户拦截.用有没有传user参数表示是否登录.
3.启动测试
没有滤器时直接访问到资源 resource.jsp
没有user参数的请求被拦截了,过滤器直接响应了一个字符P
有user参数的请求被放行了,访问到了resource.jsp
有user参数的请求被放行了(过滤器还可以改变响应信息,把响应的resource.jsp资源重定向到京东首页)
具体实现
1.编写一个web资源 resource.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
http://localhost:8080/xxx/jsp/resource.jsp
<br/>
我是web资源/xxx/jsp/resource.jsp
<%
System.out.println("我是web资源/xxx/jsp/resource.jsp");
%>
</body>
</html>
2.编写一个过滤器HelloFilter,
模拟登陆用户放行,未登录用户拦截.用有没有传user参数表示是否登录.
HelloFilter.java
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 演示 过滤器基本原理
*/
public class HelloFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
* 过滤方法
* @param servletRequest 请求对象
* @param servletResponse 响应对象
* @param chain 过滤器链条,决定是否放行
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
// 1.浏览器访问web资源时,tomcat创建的请求和响应对象会首先进入过滤器,过滤器(开发人员)可以根据请求信息来决定是否放行.
HttpServletRequest request = (HttpServletRequest) servletRequest;//强转成为http协议的
HttpServletResponse response = (HttpServletResponse) servletResponse;//强转成为http协议的
String url = request.getRequestURL().toString();//获取请求URL
System.out.println("HelloFilter.doFilter 执行过滤 url="+url);
String user = request.getParameter("user");//获取请求参数user的值
if(user == null){//表示未登录 2.如果过滤器(开发人员)不放行(默认),过滤器(开发人员)可以直接给浏览器响应信息.
System.out.println("HelloFilter.doFilter 不放行 url="+url);
response.getWriter().write("P");//过滤器(开发人员)可以直接给浏览器响应信息
}else{//表示登录 3.如果过滤器(开发人员)放行,请求和响应对象才能到达web资源,web资源就可以处理请求响应信息.
chain.doFilter(request, response);//过滤器放行request,response到达web资源,放行就意味着web资源处理了请求响应
System.out.println("HelloFilter.doFilter 放行之后 url="+url);
//4.过滤器放行就意味着web资源处理了请求响应,在web资源设置响应信息之后,在响应信息到达浏览器之前,过滤器(开发人员)还可以改变响应信息.
// response.sendRedirect("https://www.jd.com");//在web资源设置响应信息之后,在响应信息到达浏览器之前,过滤器(开发人员)还可以改变响应信息.
}
}
@Override
public void destroy() {
}
}
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- 配置一个过滤器实例 filter-class过滤器类全类名 filter-name过滤器别名(随便写)-->
<filter>
<filter-name>helloFilter</filter-name>
<filter-class>com.xxx.filter.HelloFilter</filter-class>
</filter>
<!-- 配置一个过滤器的映射地址(对什么样的路径进行过滤) filter-name给哪个过滤器配置映射 url-pattern对什么样的路径进行过滤-->
<filter-mapping>
<filter-name>helloFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
注解配置(作用等效上面的xml配置)
/**
* 演示 过滤器基本原理
*/
@WebFilter("/*")
public class HelloFilter implements Filter {
3.启动测试
没有滤器时直接访问到资源 resource.jsp
没有user参数的请求被拦截了,过滤器直接响应了一个字符P
有user参数的请求被放行了,访问到了resource.jsp
有user参数的请求被放行了(过滤器还可以改变响应信息,把响应的resource.jsp资源重定向到京东首页)
04-过滤器链
问题?
如果访问一个web资源经过多个过滤器,那么多个过滤器如何工作
过滤器链工作原理
知识点
//多个过滤器的执行顺序怎么判断
1.如果是xml,按照过滤器配置的上下顺序,越靠上的越优先执行.
2.如果是注解配置,按照类名的字典顺序执行.
3.如果是xml和注解混合,一般xml优先
如果确实要控制过滤器执行顺序,推荐使用xml配置来精确控制.
需求
演示过滤器链工作原理
步骤分析
1.编写过滤器AAFilter,过滤所有请求
2.编写过滤器BBFilter,过滤所有请求
3.启动测试
具体实现
1.编写过滤器AAFilter,过滤所有请求
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 演示 过滤器链
*/
@WebFilter("/*")
public class AAFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
/**
* 过滤方法
*
* @param servletRequest
* @param servletResponse
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;//请求对象
HttpServletResponse response = (HttpServletResponse) servletResponse;//响应对象
String url = request.getRequestURL().toString();//过滤器过滤的web资源
System.out.println("AAFilter.doFilter 执行过滤 url="+url);
chain.doFilter(request, response);//过滤器放行,web资源处理请求和响应
System.out.println("AAFilter.doFilter 放行之后 url="+url);
}
public void destroy() {
}
}
2.编写过滤器BBFilter,过滤所有请求
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 演示 过滤器链
*/
@WebFilter("/*")
public class BBFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
/**
* 过滤方法
*
* @param servletRequest
* @param servletResponse
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;//请求对象
HttpServletResponse response = (HttpServletResponse) servletResponse;//响应对象
String url = request.getRequestURL().toString();//过滤器过滤的web资源
System.out.println("BBFilter.doFilter 执行过滤 url="+url);
chain.doFilter(request, response);//过滤器放行,web资源处理请求和响应
System.out.println("BBFilter.doFilter 放行之后 url="+url);
}
public void destroy() {
}
}
3.启动测试
05-过滤器生命周期
问题?
过滤器对象什么时候创建,什么时候执行过滤,什么时候销毁
知识点
1.过滤器在项目启动时创建初始化一次.
2.每次访问web资源都会执行过滤方法
3.项目停止运行时销毁一次
扩展(面试题)
web服务器中的监听器Listener,过滤器Filter,Servlet在项目启动时就创建的先后顺序是
Listener > Filter > Servlet
需求
演示过滤器Filter的生命周期
具体代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 演示 过滤器基本原理
*/
@WebFilter("/*") //对什么样的路径进行过滤
public class HelloFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("HelloFilter.init 创建初始化");
}
/**
* 过滤方法
* @param servletRequest 请求对象
* @param servletResponse 响应对象
* @param chain 过滤器链条,决定是否放行
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
// 1.浏览器访问web资源时,tomcat创建的请求和响应对象会首先进入过滤器,过滤器(开发人员)可以根据请求信息来决定是否放行.
HttpServletRequest request = (HttpServletRequest) servletRequest;//强转成为http协议的
HttpServletResponse response = (HttpServletResponse) servletResponse;//强转成为http协议的
String url = request.getRequestURL().toString();//获取请求URL
System.out.println("HelloFilter.doFilter 执行过滤 url="+url);
String user = request.getParameter("user");//获取请求参数user的值
if(user == null){//表示未登录 2.如果过滤器(开发人员)不放行(默认),过滤器(开发人员)可以直接给浏览器响应信息.
System.out.println("HelloFilter.doFilter 不放行 url="+url);
response.getWriter().write("P");//过滤器(开发人员)可以直接给浏览器响应信息
}else{//表示登录 3.如果过滤器(开发人员)放行,请求和响应对象才能到达web资源,web资源就可以处理请求响应信息.
chain.doFilter(request, response);//过滤器放行request,response到达web资源,放行就意味着web资源处理了请求响应
System.out.println("HelloFilter.doFilter 放行之后 url="+url);
//4.过滤器放行就意味着web资源处理了请求响应,在web资源设置响应信息之后,在响应信息到达浏览器之前,过滤器(开发人员)还可以改变响应信息.
// response.sendRedirect("https://www.jd.com");//在web资源设置响应信息之后,在响应信息到达浏览器之前,过滤器(开发人员)还可以改变响应信息.
}
}
@Override
public void destroy() {
System.out.println("HelloFilter.destroy 销毁了");
}
}
运行效果
06-过滤器的映射模式
问题?
过滤器的url映射模式除了/*是否可以有其它写法
知识点
过滤器的url-pattern(对什么样的路径进行过滤) 取值可以是
1.精确匹配(了解) 例如 /aa 表示 匹配/aa资源请求
2.目录匹配 例如 /bb/* 表示 匹配/bb 路径下的资源请求
3.后缀匹配 例如 *.do 表示 匹配以.do后缀的资源的请求
4.全局匹配 例如 /* 表示网站匹配网站中的所有资源请求
需求
编写过滤器,只过滤网站中的所有servlet,其它资源都不过滤
步骤分析
1.编写PatternServlet 配置映射地址.do结尾(代表网站中所有的servlet资源)
2.编写过滤器期ServletFilter 配置映射模式为 *.do
3.启动测试
访问所有以.do结尾的servlet时,都被过滤器过滤
访问非servlet资源时,都不经过过滤器
具体实现
1.编写PatternServlet 配置映射地址.do结尾(代表网站中所有的servlet资源)
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 演示 过滤器的url-pattern映射模式
* http://localhost:8080/xxx/PatternServlet.do
*/
@WebServlet("/PatternServlet.do") //所有servlet都以.do结果
public class PatternServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8"); //接收post请求乱码问题
response.setContentType("text/html;charset=UTF-8"); //处理响应乱码问题
PrintWriter writer = response.getWriter();//响应字符流
System.out.println("PatternServlet.doPost 我是Servlet资源");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response); // 如果是get请求,调用doPost方法执行
}
}
2.编写过滤器期ServletFilter 配置映射模式为 *.do(只过滤所有servlet资源)
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 演示 过滤所有servlet资源
*/
@WebFilter("*.do") //匹配所有以.do结尾(所有servlet)的资源请求
public class ServletFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
/**
* 过滤方法
*
* @param servletRequest
* @param servletResponse
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;//请求对象
HttpServletResponse response = (HttpServletResponse) servletResponse;//响应对象
String url = request.getRequestURL().toString();//过滤器过滤的web资源
System.out.println("ServletFilter.doFilter 执行过滤 url="+url);
chain.doFilter(request, response);//过滤器放行,web资源处理请求和响应
System.out.println("ServletFilter.doFilter 放行之后 url="+url);
}
public void destroy() {
}
}
3.启动测试
访问所有以.do结尾的servlet时,都被过滤器过滤
访问非servlet资源时,都不经过过滤器
07-过滤器拦截方式
问题?
如果一个servlet请求转发到jsp
或者一个servlet响应重定向到jsp
那么,当servlet被过滤时,这个jsp过滤器是否过滤
知识点
1.过滤器默认情况下只拦截新的请求对象
请求转发中jsp中的请求还是原来第一个servlet中的请求,所以请求转发的jsp不会被拦截
响应重定向中jsp中的请求是一个新的请求对象,所以拦截还会拦截响应重定向中的jsp.
2.我们可以设置过滤器的拦截方式为forward,来拦截请求转发的jsp
public enum DispatcherType {
FORWARD,(拦截请求转发)
REQUEST,(默认值,只拦截新的请求对象)
步骤分析
1.编写一个ForwardServlet,把请求转发给forward.jsp
2.编写forward.jsp
3.编写一个过滤器ForwardFilter ,过滤所有资源请求
4.启动测试
过滤器默认情况下只拦截新的请求对象,请求转发的jsp不会被拦截
给过滤器配置过滤类型,过滤新的请求,也过滤请求转发,请求转发的jsp也被拦截
具体实现
1.编写一个ForwardServlet,把请求转发给forward.jsp
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 演示 过滤器拦截方式
* http://localhost:8080/xxx/ForwardServlet
*/
@WebServlet("/ForwardServlet")
public class ForwardServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ForwardServlet.doPost 我是请求转发的Servlet资源");
//请求转发
request.getRequestDispatcher("/jsp/forward.jsp").forward(request, response);//请求转发到/jsp/forward.jsp
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response); // 如果是get请求,调用doPost方法执行
}
}
2.编写forward.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
http://localhost:8080/xxx/jsp/forward.jsp
<br/>
我是请求转发的JSP资源/xxx/jsp/forward.jsp
<%
System.out.println("我是请求转发的JSP资源/xxx/jsp/forward.jsp");
%>
</body>
</html>
3.编写一个过滤器ForwardFilter ,过滤所有资源请求
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 演示
*/
//@WebFilter("/*")//默认拦截新的请求
@WebFilter(value="/*",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})//拦截新的请求,拦截请求转发
public class ForwardFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
/**
* 过滤方法
*
* @param servletRequest
* @param servletResponse
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;//请求对象
HttpServletResponse response = (HttpServletResponse) servletResponse;//响应对象
String url = request.getRequestURL().toString();//过滤器过滤的web资源
System.out.println("ForwardFilter.doFilter 执行过滤 url="+url);
chain.doFilter(request, response);//过滤器放行,web资源处理请求和响应
System.out.println("ForwardFilter.doFilter 放行之后 url="+url);
}
public void destroy() {
}
}
4.启动测试
过滤器默认情况下只拦截新的请求对象,请求转发的jsp不会被拦截
给过滤器配置过滤类型,过滤新的请求,也过滤请求转发,请求转发的jsp也被拦截
08- 案例-过滤器解决全局乱码
问题?
我们所有的servlet在接收post方式提交的表单时,有中文就会乱码
我们所有的servlet在响应html内容时,都需要设置响应体的内容类型及字符集
每个servlet中都要写一样的代码,有没有什么办法简化?
解决
使用过滤器统一处理请求和响应乱码问题
逻辑分析图
步骤分析
1.编写encoding.html页面,使用post方式提交中文
2.编写EncodingServlet,接收表单提交的数据,并且给浏览器响应中文信息
3.编写一个EncodingFilter,在放行之前设置请求体字符集,设置响应体内容类型及字符集,来解决网站全局乱码问题
4.启动测试
没有编码过滤器时,接收表单参数是乱码,响应中文信息时乱码
有了编码过滤器之后,接收表单参数不乱码了,响应中文信息也不乱码
具体实现
1.编写encoding.html页面,使用post方式提交中文
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
http://localhost:8080/xxx/static/encoding.html
<br/>
<form method="post" action="/xxx/EncodingServlet">
信息<input type="text" name="msg"/><br/>
<button>提交</button>
</form>
</body>
</html>
2.编写EncodingServlet,接收表单提交的数据,并且给浏览器响应中文信息
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 演示 编码过滤器,解决网站全局乱码问题
* http://localhost:8080/xxx/EncodingServlet
*/
@WebServlet("/EncodingServlet")
public class EncodingServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//接收请求信息
String msg = request.getParameter("msg");//接收post提交的中文信息
System.out.println("msg = " + msg);
//设置响应信息
String str = "我是中文信息666";//要响应给浏览器的字符串
PrintWriter writer = response.getWriter();//通向浏览器的响应字符流
writer.write(str);//响应给浏览器
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response); // 如果是get请求,调用doPost方法执行
}
}
3.编写一个EncodingFilter,在放行之前设置请求体字符集,设置响应体内容类型及字符集,来解决网站全局乱码问题
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 演示 编码过滤器,解决网站全局乱码问题
*/
@WebFilter("/*")
public class EncodingFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
/**
* 过滤方法
*
* @param servletRequest
* @param servletResponse
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;//请求对象
HttpServletResponse response = (HttpServletResponse) servletResponse;//响应对象
//使用过滤器统一处理请求和响应乱码问题
request.setCharacterEncoding("UTF-8"); //接收post请求乱码问题
response.setContentType("text/html;charset=UTF-8"); //处理响应乱码问题
chain.doFilter(request, response);//过滤器放行,web资源处理请求和响应
}
public void destroy() {
}
}
4.启动测试
没有编码过滤器时,接收表单参数是乱码,响应中文信息时乱码
有了编码过滤器之后,接收表单参数不乱码了,响应中文信息也不乱码
09-案例-敏感词过滤器
问题1?
网站中有很多Servlet要接收各种参数,有的servlet需要对敏感词进行处理,
例如(你大爷,ZZ,TMD)都会替换成 *星星
解决1
使用过滤器统一替换脏字成星
问题2?
我们在过滤器中完成了脏字替换以后,发现request没有setParameter设置参数的方法.(严重问题)
解决2
使用面向对象技术的继承HttpServletRequest,重写它的getParameter方法,
改变getParameter的默认行为:接收字符参数,增强为接收字符串参数且做脏字过滤
问题3?
我们在写HttpServletRequest子类时发现HttpServletRequest不是一个简单的类,它是一个接口,有非常多的抽象方法.
我们如果重写它的getParameter方法,我们还必须实现它其它的所有抽象方法,这个工作量非常繁重!!!
解决3
tomcat已经帮我解决了问题3.
被包装类 HttpServletRequest
包装类 HttpServletRequestWrapper
知识点
装饰着设计模式的设计要点
1.包装类要持有被包装类的引用
2.重写需要增强的方法(开发人员编写)
3.不需要关注的方法直接调用被包装类原来的方法
被包装类 HttpServletRequest
包装类 HttpServletRequestWrapper
增强的方法 getParameter
重写类 DirtyRequest
逻辑分析图
步骤分析(在08案例基础上,把EncodingFilter替换为DirtyFilter过滤器)
1.编写重写类DirtyRequest继承包装类HttpServletRequestWrapper,重写增强的方法 getParameter
接收参数,脏字过滤
2.编写DirtyFilter过滤器,在放行之前把request偷梁换柱为DirtyRequest
3.启动测试
具体实现
1.编写重写类DirtyRequest继承包装类HttpServletRequestWrapper,重写增强的方法 getParameter
接收参数,脏字过滤
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.Arrays;
import java.util.List;
/**
* 改变getParameter的默认行为:接收字符参数,增强为接收字符串参数且做脏字过滤
*/
public class DirtyRequest extends HttpServletRequestWrapper {
//1.包装类要持有被包装类的引用
public DirtyRequest(HttpServletRequest request) {
super(request);
}
/**
* 2.重写需要增强的方法(开发人员编写)
* 需要增强的方法
* 改变getParameter的默认行为:接收字符参数,
* 增强为接收字符串参数且做脏字过滤
* @param name
* @return
*/
@Override
public String getParameter(String name) {
String msg = super.getRequest().getParameter(name);//有脏字的参数
List<String> dirtys = Arrays.asList("你大爷","ZZ","TMD");//准备脏字集合
for (String dirty : dirtys) {//迭代脏字
if (msg.contains(dirty)) {//判断请求信息msg是否包含dirty脏字
StringBuffer sb = new StringBuffer();//创建一个带缓冲的字符串对象
for(int i=0;i<dirty.length();i++){
sb.append("*");//dirty字符有几个就拼接几个*
}
msg = msg.replace(dirty, sb.toString());//把msg中的脏字dirty替换为*
}
}
return msg;
}
}
2.编写DirtyFilter过滤器,在放行之前把request偷梁换柱为DirtyRequest
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;//请求对象
HttpServletResponse response = (HttpServletResponse) servletResponse;//响应对象
//使用过滤器统一处理请求和响应乱码问题
request.setCharacterEncoding("UTF-8"); //接收post请求乱码问题
response.setContentType("text/html;charset=UTF-8"); //处理响应乱码问题
//在放行之前把request偷梁换柱为DirtyRequest
DirtyRequest dirtyRequest = new DirtyRequest(request);
chain.doFilter(dirtyRequest, response);//过滤器放行,web资源处理请求和响应
}
3.启动测试
2 监听器
10-监听器入门简介
监听器介绍
在web服务器中,监听器可以监听服务器中对象的事件动作.
例如
ServletContextListener 可以监听当前项目对象ServletContext(application)的创建和销毁(项目启动和停止)
HttpSessionListener 可以监听当前项目中会话对象session的创建和销毁(一次会话的开始和结束)
需求
编写监听器,监听当前项目的启动和停止
具体代码
MyApp.java
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* 监听项目的启动和停止
*/
public class MyApp implements ServletContextListener {
/**
* 当项目启动时触发执行
* @param sce
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("当前项目启动运行了");
}
/**
* 当项目停止运行时触发执行
*/
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("当前项目停止运行了");
}
}
myApp的web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- 配置一个监听器实例-->
<listener>
<listener-class>com.xxx.listener.MyApp</listener-class>
</listener>
运行效果
需求
监听当前项目中会话对象session的创建和销毁
步骤分析
1.编写MyHttpSession监听器,监听当前项目中会话对象session的创建和销毁
2.编写JSP页面,提供安全退出的功能
3.启动测试
访问jsp时,因为jsp翻译的.java中有request.getSesion这个方法,所以会创建当前会话session对象
访问安全退出功能时,当前会话对象session销毁
具体实现
1.编写MyHttpSession监听器,监听当前项目中会话对象session的创建和销毁
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
*监听当前项目中会话对象session的创建和销毁
*/
@WebListener
public class MyHttpSession implements HttpSessionListener {
/**
* session创建时
* @param se
*/
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("MyHttpSession.sessionCreated 有session创建了 sessionId="+se.getSession().getId());//打印session的唯一标志
}
/**
* session销毁时
* @param se
*/
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("MyHttpSession.sessionDestroyed 有session销毁了 sessionId="+se.getSession().getId());//打印session的唯一标志
}
}
2.编写JSP页面,提供安全退出的功能
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>安全退出</title>
</head>
<body>
http://localhost:8080/xxx/jsp/loginout.jsp
<br/>
<%
session.invalidate();//安全退出
%>
安全退出成功!!!
</body>
</html>
3.启动测试
访问jsp时,因为jsp翻译的.java中有request.getSesion这个方法,所以会创建当前会话session对象
访问安全退出功能时,当前会话对象session销毁
附录
修改Filter模板
模板内容
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
/**
* 演示
*/
@javax.servlet.annotation.WebFilter("/*")
public class ${Class_Name} implements javax.servlet.Filter {
public void init(javax.servlet.FilterConfig config) throws javax.servlet.ServletException {
}
/**
* 过滤方法
* @param servletRequest
* @param servletResponse
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse, javax.servlet.FilterChain chain) throws java.io.IOException, ServletException {
javax.servlet.http.HttpServletRequest request = (javax.servlet.http.HttpServletRequest) servletRequest;//请求对象
javax.servlet.http.HttpServletResponse response = (javax.servlet.http.HttpServletResponse) servletResponse;//响应对象
String url = request.getRequestURL().toString();//过滤器过滤的web资源
chain.doFilter(request, response);//过滤器放行,web资源处理请求和响应
}
public void destroy() {
}
}
扩展
web服务器中的监听器Listener,过滤器Filter,Servlet在项目启动时就创建的先后顺序是
Listener > Filter > Servlet
;#end
#parse(“File Header.java”)
/**
-
演示
/
@javax.servlet.annotation.WebFilter("/")
public class ${Class_Name} implements javax.servlet.Filter {public void init(javax.servlet.FilterConfig config) throws javax.servlet.ServletException {
}
/**-
过滤方法
-
@param servletRequest
-
@param servletResponse
-
@param chain
-
@throws IOException
-
@throws ServletException
*/
@Override
public void doFilter(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse, javax.servlet.FilterChain chain) throws java.io.IOException, ServletException {javax.servlet.http.HttpServletRequest request = (javax.servlet.http.HttpServletRequest) servletRequest;//请求对象
javax.servlet.http.HttpServletResponse response = (javax.servlet.http.HttpServletResponse) servletResponse;//响应对象
String url = request.getRequestURL().toString();//过滤器过滤的web资源
chain.doFilter(request, response);//过滤器放行,web资源处理请求和响应
}
public void destroy() {
}
-
}
```tex
扩展
web服务器中的监听器Listener,过滤器Filter,Servlet在项目启动时就创建的先后顺序是
Listener > Filter > Servlet