过滤器filter&监听器listener

过滤器&监听器

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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值