JavaWeb12-三大组件之过滤器-Filter

news2024/11/28 0:59:04

1. 官方文档

文档:java_ee_api_中英文对照版.chm

2. Filter 过滤器说明

2.1 为啥要过滤器-需求示意图

● 一图胜千言
在这里插入图片描述

2.2 过滤器介绍

  1. Filter 过滤器它是 JavaWeb 的三大组件之一(Servlet 程序、Listener 监听器、Filter 过滤器)
  2. Filter 过滤器是 JavaEE 的规范,是接口
    在这里插入图片描述
  3. Filter 过滤器它的作用是:拦截请求,过滤响应。
  4. 应用场景
    ● 权限检查
    ● 日记操作
    ● 事务管理

3. Filter 过滤器基本原理

● 一图胜千言
在这里插入图片描述

4. Filter 过滤器快速入门

● 需求:
在 web 工程下,有后台管理目录 manage,要求该目录下所有资源(html、图片、jsp 、Servlet 等)用户登录后才能访问。

在这里插入图片描述
在这里插入图片描述
● 思路分析-程序框架图(帮助理解, 编程小技巧, 作用:清晰思路.=> 慢慢通过这样方式来锻炼自己的编程思维!!

  1. 一会自己先画图,(思路) ->看到老师是怎么思考,并完成 -> 2. 走代码[听得进去.]
    在这里插入图片描述

听老师说明, 完成模块的套路/流程[多年的体会]
2. 先完成一个正确的流程-看到一个效果-> 写后面代码就可以验证. 2. 加入其它的功能[1. 加入 session,验证合法性]
3. 完善功能

  • 代码实现

1.创建login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>管理后台登录</title>
</head>
<body>
<h1>管理后台登录</h1>
<%
    System.out.println("request=" + request);
%>
<form action="<%=request.getContextPath() %>/loginCheckServlet" method="post">
    u:<input type="text" name="username"/> <br/><br/>
    p:<input type="password" name="password"/> <br/><br/>
    <input type="submit" value="用户登录"/></form>
</body>
</html>

2.创建 LoginCheckServlet.java

public class LoginCheckServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取到用户名和密码->DB
        //假设密码是123456, 就可以通过
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("request=" + request);
        if("123456".equals(password)) {

            //合法, 讲用户名,加入session
            request.getSession().setAttribute("username", username);
            //请求转发到admin.jsp
            request.getRequestDispatcher("/manage/admin.jsp")
                    .forward(request,response);
        } else {
            //不合法, 返回登录页面
            request.getRequestDispatcher("/login.jsp")
                    .forward(request,response);

        }
    }

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

3.创建…\manage\admin.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>后台管理</title>
    <base href="<%=request.getContextPath() %>/manage/"/>
</head>
<body>
<h1>后台管理</h1>
<%
    //验证request对象是和前面的filter是一个对象
    System.out.println("request=" + request);
%>
<a href="#">用户列表</a>||<a href="#">添加用户</a>||<a href="#">删除用户</a>
<hr/>
<img src="shunping.jpg" height="300"/>
</body>
</html>

4.图片自行准备,放到manage包下即可

5.创建 ManageFilter.java

public class ManageFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //当Tomcat 创建 Filter创建,就会调用该方法,进行初始化
        //老韩提醒:回忆我们自己实现tomcat底层机制+servlet程序, 就会了然
        //
        System.out.println("ManageFilter init被调用...");
    }

    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {

        //到每次调用该filter时,doFilter就会被调用

        //如果这里,没有调用继续请求的方法,则就停止
        //如果继续访问目标资源-> 等价于放行

        //老师说明:在调用过滤器前,servletRequest对象=request已经被创建并封装
        //所以:我们这里就可以通过servletRequest获取很多信息, 比如访问url , session
        //比如访问的参数 ... 就可以做事务管理,数据获取,日志管理等
        //获取到session
        //可以继续使用 httpServletRequest 方法.
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        System.out.println("输入密码=" + httpServletRequest.getParameter("password"));
        HttpSession session = httpServletRequest.getSession();
        //获取username session对象, 还可以继续使用
        Object username = session.getAttribute("username");
        if (username != null) {
            //解读filterChain.doFilter(servletRequest, servletResponse)
            //1. 继续访问目标资源url
            //2. servletRequest 和 servletResponse 对象会传递给目标资源/文件
            //3. 一定要理解filter传递的两个对象,再后面的servlet/jsp 是同一个对象(指的是在一次http请求)
            System.out.println("servletRequest=" + servletRequest);
            System.out.println("日志信息==");
            System.out.println("访问的用户名=" + username.toString());
            System.out.println("访问的url=" + httpServletRequest.getRequestURL());
            System.out.println("访问的IP=" + httpServletRequest.getRemoteAddr());
            filterChain.doFilter(servletRequest, servletResponse);
        } else {//说明没有登录过..回到登录页面
            servletRequest.getRequestDispatcher("/login.jsp").
                    forward(servletRequest, servletResponse);
        }
    }

    @Override
    public void destroy() {
        //当filter被销毁时,会调用该方法
        System.out.println("ManageFilter destroy()被调用..");
    }
}

6.在 web.xml 配置过滤器

<!--老师解读:filter一般写在其它servlet的前面
        1. 观察我们发现filter 配置和 servlet 非常相似. filter也是被tomcat管理和维护
        2. url-pattern 就是当请求的url 和 匹配的时候,就会调用该filter
        3. /manage/* 第一个 / 解析成 http://ip:port/工程路径
        4. 完整的路径就是 http://ip:port/工程路径/manage/* 当请求的资源url满足该条件时
        都会调用filter , /manage/admin.jsp
    -->
    <filter>
        <filter-name>ManageFilter</filter-name>
        <filter-class>com.hspedu.filter.ManageFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ManageFilter</filter-name>
        <url-pattern>/manage/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>LoginCheckServlet</servlet-name>
        <servlet-class>com.hspedu.servlet.LoginCheckServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginCheckServlet</servlet-name>
        <url-pattern>/loginCheckServlet</url-pattern>
    </servlet-mapping>

7.完成测试, 看看过滤器是否生效

拓展:

回顾手写Tomcat,完善并加深对过滤器的理解
MyTomcatV3.java

/**
 * 第3版的Tomcat, 实现通过xml+反射来初始化容器
 */
public class HspTomcatV3 {

    //1. 存放容器 servletMapping
    // -ConcurrentHashMap
    // -HashMap
    // key            - value
    // ServletName    对应的实例

    public static final ConcurrentHashMap<String, HspHttpServlet>
            servletMapping = new ConcurrentHashMap<>();


    //2容器 servletUrlMapping
    // -ConcurrentHashMap
    // -HashMap
    // key                    - value
    // url-pattern       ServletName

    public static final ConcurrentHashMap<String, String>
            servletUrlMapping = new ConcurrentHashMap<>();


    //你可以这里理解session, tomcat还维护一个容器
    public static final ConcurrentHashMap<String, HttpSession>
            sessionMapping = new ConcurrentHashMap<>();
    

    //你可以这里理解filter, tomcat还维护了filter的容器
    public static final ConcurrentHashMap<String, String>
            filterUrlMapping = new ConcurrentHashMap<>();

    public static final ConcurrentHashMap<String, Filter>
            filterMapping = new ConcurrentHashMap<>();
    //变强..
    public static void main(String[] args) {
        HspTomcatV3 hspTomcatV3 = new HspTomcatV3();
        hspTomcatV3.init();
        //启动hsptomcat容器
        hspTomcatV3.run();
    }


    //启动HspTomcatV3容器
    public void run() {

        try {
            ServerSocket serverSocket = new ServerSocket(8080);
            System.out.println("=====hsptomcatv3在8080监听======");
            while (!serverSocket.isClosed()) {
                Socket socket = serverSocket.accept();
                HspRequestHandler hspRequestHandler =
                        new HspRequestHandler(socket);
                new Thread(hspRequestHandler).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //直接对两个容器进行初始化
    public void init() {
        //读取web.xml => dom4j =>
        //得到web.xml文件的路径 => 拷贝一份.
        String path = HspTomcatV3.class.getResource("/").getPath();
        //System.out.println("path= " + path);
        //使用dom4j技术完成读取
        SAXReader saxReader = new SAXReader();
        //困难->真的掌握
        try {
            Document document = saxReader.read(new File(path + "web.xml"));
            System.out.println("document= " + document);
            //得到根元素
            Element rootElement = document.getRootElement();
            //得到根元素下面的所有元素
            List<Element> elements = rootElement.elements();
            //遍历并过滤到 servlet servlet-mapping
            for (Element element : elements) {
                if ("servlet".equalsIgnoreCase(element.getName())) {
                    //这是一个servlet配置
                    //System.out.println("发现 servlet");
                    //使用反射将该servlet实例放入到servletMapping
                    Element servletName = element.element("servlet-name");
                    Element servletClass = element.element("servlet-class");
                    servletMapping.put(servletName.getText(),
                            (HspHttpServlet) Class.forName(servletClass.getText().trim()).newInstance());
                } else if ("servlet-mapping".equalsIgnoreCase(element.getName())) {
                    //这是一个servlet-mapping
                    //System.out.println("发现 servlet-mapping");

                    Element servletName = element.element("servlet-name");
                    Element urlPatter = element.element("url-pattern");
                    servletUrlMapping.put(urlPatter.getText(), servletName.getText());

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //验证,这两个容器是否初始化成功
        System.out.println("servletMapping= " + servletMapping);
        System.out.println("servletUrlMapping= " + servletUrlMapping);
    }
}

MyRequestHandler.java

//有了filter机制,可以理解再调用servlet之前,先匹配filter
//1. 根据request对象封装的uri
//2. 到 filterUrlMapping 去匹配
//3. 如果匹配上就调用 filterMapping 对应的filer对象doFilter()
//4. 如果没有匹配上,就直接走我们后的servlet/jsp/html.

String servletName = HspTomcatV3.servletUrlMapping.get(uri);
if (servletName == null) {
    servletName = "";
}

5. Filter 过滤器 url-pattern

1、url-pattern : Filter 的拦截路径, 即浏览器在请求什么位置的资源时,过滤器会进行拦截过滤
2.、精确匹配 <url-pattern>/a.jsp</url-pattern> 对应的 请求地址 http://ip[域名]:port/工程路径/a.jsp 会拦截
3、目录匹配 <url-pattern>/manage/*</url-pattern>对应的 请求地址 http://ip[域名]:port/工程路径/manage/xx , 即 web 工程 manage 目录下所有资源 会拦截
4、后缀名匹配 <url-pattern>*.jsp</url-pattern> 后缀名可变,比如 *.action *.do 等等对应的 请求地址 http://ip[域名]:port/工程路径/xx.jsp , 后缀名为 .jsp 请求会拦截
5、Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在

6. Filter 过滤器生命周期

● Filter 生命周期图解
在这里插入图片描述
● 验证一把

/**
 * 解读
 * 1. filter在web项目启动时, 由tomcat 来创建filter实例, 只会创建一个
 * 2. 会调用filter默认的无参构造器, 同时会调用 init方法, 只会调用一次
 * 3. 在创建filter实例时,同时会创建一个FilterConfig对象,并通过init方法传入
 * 4. 通过FilterConfig对象,程序员可以获取该filter的相关配置信息
 * 5. 当一个http请求和该filter的的url-patter匹配时,就会调用doFilter方法
 * 6. 在调用doFilter方法时,tomcat会同时创建ServletRequest 和 ServletResponse 和 FilterChain对象
 * , 并通过doFilter传入.
 * 7. 如果后面的请求目标资源(jsp,servlet..) 会使用到request,和 response,那么会继续传递
 * 8. 老师的提醒:到javaweb - ssm - springboot , 有 浏览器和 web服务器(tomcat)参与, 而这两个部分不是我们
 *    程序员自己写,所以理解起来比 java se要困难!!!
 */
public class ManageFilter implements Filter {

    private int count = 0;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //当Tomcat 创建 Filter创建,就会调用该方法,进行初始化
        //提醒:回忆我们自己实现tomcat底层机制+servlet程序, 就会了然
        //
        System.out.println("ManageFilter init被调用...");
    }

    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {

        System.out.println("ManageFilter doFilter() 被调用=" + (++count));

        //到每次调用该filter时,doFilter就会被调用

        //如果这里,没有调用继续请求的方法,则就停止
        //如果继续访问目标资源-> 等价于放行

        //老师说明:在调用过滤器前,servletRequest对象=request已经被创建并封装
        //所以:我们这里就可以通过servletRequest获取很多信息, 比如访问url , session
        //比如访问的参数 ... 就可以做事务管理,数据获取,日志管理等
        //获取到session
        //可以继续使用 httpServletRequest 方法.
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        System.out.println("输入密码=" + httpServletRequest.getParameter("password"));
        HttpSession session = httpServletRequest.getSession();
        //获取username session对象, 还可以继续使用
        Object username = session.getAttribute("username");
        if (username != null) {
            //解读filterChain.doFilter(servletRequest, servletResponse)
            //1. 继续访问目标资源url
            //2. servletRequest 和 servletResponse 对象会传递给目标资源/文件
            //3. 一定要理解filter传递的两个对象,再后面的servlet/jsp 是同一个对象(指的是在一次http请求)
            System.out.println("servletRequest=" + servletRequest);
            System.out.println("日志信息==");
            System.out.println("访问的用户名=" + username.toString());
            System.out.println("访问的url=" + httpServletRequest.getRequestURL());
            System.out.println("访问的IP=" + httpServletRequest.getRemoteAddr());
            filterChain.doFilter(servletRequest, servletResponse);
        } else {//说明没有登录过..回到登录页面
            servletRequest.getRequestDispatcher("/login.jsp").
                    forward(servletRequest, servletResponse);
        }
    }

    @Override
    public void destroy() {
        //当filter被销毁时,会调用该方法
        System.out.println("ManageFilter destroy()被调用..");
    }
}

7. FilterConfig

● FilterConfig 接口图
在这里插入图片描述
● FilterConfig 说明

  1. FilterConfig 是 Filter 过滤器的配置类
  2. Tomcat 每次创建 Filter 的时候,也会创建一个 FilterConfig 对象,这里包含了 Filter 配置文件的配置信息。
  3. FilterConfig 对象作用是获取 filter 过滤器的配置内容

● 应用实例
web.xml

<filter>
    <filter-name>HspFilterConfig</filter-name>
    <filter-class>com.hspedu.filter.HspFilterConfig</filter-class>
    <!--这里就是给该filter配置的参数-有程序员根据业务逻辑来设置-->
    <init-param>
        <param-name>ip</param-name>
        <param-value>127.0</param-value>
    </init-param>
    <init-param>
        <param-name>port</param-name>
        <param-value>8888</param-value>
    </init-param>
    <init-param>
        <param-name>email</param-name>
        <param-value>hsp@sohu.com</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>HspFilterConfig</filter-name>
    <url-pattern>/abc/*</url-pattern>
</filter-mapping>
/**
 * 老师解读: 演示FilterConfig使用
 */
public class HspFilterConfig implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("HspFilterConfig init() 被调用..");
        //通过filterConfig 获取相关的参数
        String filterName = filterConfig.getFilterName();
        ip = filterConfig.getInitParameter("ip");
        ServletContext servletContext = filterConfig.getServletContext();
        //可以获取到该filter所有的配置参数名
        Enumeration<String> initParameterNames =
                filterConfig.getInitParameterNames();

        //遍历枚举
        while (initParameterNames.hasMoreElements()) {
            System.out.println("名字=" + initParameterNames.nextElement());
        }

        System.out.println("filterName= " + filterName);
        System.out.println("ip= " + ip);
        System.out.println("servletContext= " + servletContext);


    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    }

    @Override
    public void destroy() {

    }
}

● 完成测试, 直接启动就看到相应的输出信息

● 简单应用, 如果访问 ip 是 128.12 网段,就返回登录页面
先思考一把…
代码:
web.xml

<filter>
    <filter-name>HspFilterConfig</filter-name>
    <filter-class>com.hspedu.filter.HspFilterConfig</filter-class>
    <!--这里就是给该filter配置的参数-有程序员根据业务逻辑来设置-->
    <init-param>
        <param-name>ip</param-name>
        <param-value>127.0</param-value>
    </init-param>
    <init-param>
        <param-name>port</param-name>
        <param-value>8888</param-value>
    </init-param>
    <init-param>
        <param-name>email</param-name>
        <param-value>hsp@sohu.com</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>HspFilterConfig</filter-name>
    <url-pattern>/abc/*</url-pattern>
</filter-mapping>
/**
 * 老师解读: 演示FilterConfig使用
 *
 */
public class HspFilterConfig implements Filter {

    private String ip; //从配置获取的ip

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("HspFilterConfig init() 被调用..");
        //通过filterConfig 获取相关的参数
        String filterName = filterConfig.getFilterName();
        ip = filterConfig.getInitParameter("ip");


    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //通过forbidden ip 来进行控制
        //先获取到访问ip
        String remoteAddr = servletRequest.getRemoteAddr();
        if(remoteAddr.contains(ip)) {
            System.out.println("封杀该网段..");
            servletRequest.getRequestDispatcher("/login.jsp").
                    forward(servletRequest,servletResponse);
            return; //直接返回
        }

        //继续访问目标资源
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

8. FilterChain 过滤器链

8.1 说明

一句话: FilterChain: 在处理某些复杂业务时,一个过滤器不够,可以设计多个过滤器共同完成过滤任务,形成过滤器链。

8.2 基本原理示意图

● 一图胜千言
在这里插入图片描述
在这里插入图片描述

8.3 应用实例

  1. 需求: 演示过滤器链的使用
    在这里插入图片描述
  2. 创建 AFilter.java
public class AFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        System.out.println("AFilter---> 线程id=" +
                Thread.currentThread().getId());

        System.out.println("AFilter doFilter 的前置代码...");
        System.out.println("执行 AFilter doFilter()");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("AFilter doFilter 的后置代码...");
    }

    @Override
    public void destroy() {

    }
}
  1. 创建 BFilter.java
public class BFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        System.out.println("BFilter---> 线程id=" +
                Thread.currentThread().getId());

        System.out.println("BFilter doFilter 的前置代码...");

        System.out.println("执行 BFilter doFilter()");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("BFilter doFilter 的后置代码...");
    }

    @Override
    public void destroy() {

    }
}
  1. 创建/使用 …\admin\hi.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hi</title>
</head>
<body>
<h1>admin 目录下的 hi.jsp</h1>
<h1>后台管理</h1>
<a href="#">用户列表</a>||<a href="#">添加用户</a>||<a href="#">删除用户</a>
<hr/>
</body>
</html>
  1. 修改 web.xml, 配置过滤器
<filter>
	<filter-name>AFilter</filter-name>
	<filter-class>com.hspedu.servlet.AFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>AFilter</filter-name>
	<url-pattern>/admin/*</url-pattern>
</filter-mapping>

<filter>
	<filter-name>BFilter</filter-name>
	<filter-class>com.hspedu.servlet.BFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>BFilter</filter-name>
	<url-pattern>/admin/*</url-pattern>
</filter-mapping>
  1. 完成测试
    在这里插入图片描述

8.4 FilterChain 注意事项和细节

  1. 多个 filter 和目标资源在一次 http 请求,在同一个线程中
  2. 当一个请求 url 和 filter 的 url-pattern 匹配时, 才会被执行, 如果有多个匹配上,就会顺序执行,形成一个 filter 调用链(底层可以使用一个数据结构搞定)
  3. 多个 filter 共同执行时,因为是一次 http 请求, 使用同一个 request 对象
  4. 多个 filter 执行顺序,和 web.xml 配置顺序保持一致.
  5. chain.doFilter(req, resp)方法 将执行下一个过滤器的 doFilter 方法, 如果后面没有过滤器,则执行目标资源。
  6. 小结:
    注意执行过滤器链时, 顺序是(用前面的案例分析)

Http请求 -> A 过滤器 dofilter()-> A 过滤器前置代码 -> A 过滤器 chain.doFilter() -> B 过滤器 dofilter() -> B 过滤器前置代码 -> B过滤器 chain.doFilter() -> 目标文件 -> B过滤器后置代码 -> A过滤器后置代码 ->返回给浏览器页面/数据

9. Filter 作业练习

9.1 作业布置

● 需求分析: 使用过滤器, 完成如下要求

  1. 点击发表评论页面 topic.jsp, 可以在 showTopic.jsp 显示评论内容
  2. 如果发表的评论内容,有关键字比如 “苹果” “香蕉”, 就返回 topic.jsp, 并提示有禁用词
  3. 要求发表评论到 showTopic.jsp 时,经过过滤器的处理
  4. 禁用词, 配置在过滤器, 在启动项目时动态的获取, 注意处理中文

在这里插入图片描述
在这里插入图片描述
● 思路分析(程序框架图)
在这里插入图片描述

9.2 作业评讲

1、创建 topic.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>发表对阿凡达电影评论</h1>
过滤词: 苹果, 香蕉 ${errorInfo}
<form method="post" action="<%=request.getContextPath()%>/topic/showTopic.jsp">
    用户: <input type="text" name="username"><br/>
    评论: <textarea rows="10" name="content" cols="20"></textarea><br/>
    <input type="submit" value="发表评论">
</form>
</body>
</html>

2、创建 showTopic.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>你发表的评论是</h1>
评论内容: <%=request.getParameter("content")%>
</body>
</html>

3、创建 TopicServlet.java

public class TopicFilter implements Filter {

    //属性-> 存放禁用词
    private String[] forbiddenWords = null;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //获取禁用词
        String forbiddenword = filterConfig.getInitParameter("forbiddenword");
        forbiddenWords = forbiddenword.split(",");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //解决从topic.jsp 提交的中文乱码问题
        servletRequest.setCharacterEncoding("utf-8");

        //判断评论是不是有禁用词
        String content = servletRequest.getParameter("content");
        //循环遍历一把,看看有没有禁用词
        for (String forbiddenWord : forbiddenWords) {//java基础
            if (content.contains(forbiddenWord)) {
                //返回topic.jsp
                servletRequest.setAttribute("errorInfo", "你输入的有禁用词");
                servletRequest.getRequestDispatcher("/topic.jsp")
                        .forward(servletRequest, servletResponse);
                return;//返回
            }
        }

        //继续到目标
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

4、配置过滤器

<filter>
    <filter-name>TopicFilter</filter-name>
    <filter-class>com.hspedu.filter.TopicFilter</filter-class>
    <!--配置禁用词-->
    <init-param>
        <param-name>forbiddenword</param-name>
        <param-value>苹果,香蕉</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>TopicFilter</filter-name>
    <url-pattern>/topic/*</url-pattern>
</filter-mapping>

5、完成测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/533290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图像处理:手写实现图像增广算法(旋转、亮度调整、裁剪与拼接)

前言 图像增广算法在计算机视觉领域扮演着至关重要的角色。随着深度学习的兴起&#xff0c;大规模数据集的需求变得更加迫切&#xff0c;而图像增广算法可以通过对原始图像进行一系列变换&#xff0c;扩充数据集&#xff0c;从而提升模型的泛化能力和鲁棒性。 本文将着重介绍…

win10系统cpu版本 Tensorflow2.5.0的安装

文章目录 前言电脑重装系统了&#xff0c;顺便简单记录一下我的tensorflow2.5.0 CPU的安装过程 一、创建一个虚拟环境&#xff1f;二、确定 输入 y三、激活你的环境四、安装tensorflow2.5.0五、利用清华镜像源加速一下&#xff0c;不然等到猴年马月&#xff01;六&#xff0c;开…

Shape-E:文字到3D的生成模型试用

文章目录 Shape-E&#xff1a;文字到3D的生成模型试用项目介绍项目地址项目使用试用Text to 3DImage to 3D 总结 Shape-E&#xff1a;文字到3D的生成模型试用 项目介绍 Shape-E是一个生成3D模型的工具&#xff0c;可以通过输入文字或者上传图片生成3D模型。该模型的项目地址是…

穿越火线(CF) AI 自瞄 代码 权重 数据集 亲测可用(结尾有资源)

初衷 本人热衷玩CF&#xff0c;同时为一名程序员&#xff0c;近期听说AI霸占FPS游戏&#xff0c;本着学习的态度&#xff0c;特来测试 不喜欢看过程的小伙伴直接看最下面 模型 采用yolov5模型架构 对过程感兴趣的小伙伴下文自行学习 https://zhuanlan.zhihu.com/p/17212138…

数字孪生技术在矿业领域怎样应用?

随着科技的不断发展&#xff0c;数字孪生技术正逐渐走入矿业领域&#xff0c;为这个传统行业带来了全新的变革和机遇。数字孪生技术以其精准模拟和实时监控的特性&#xff0c;为矿业企业提供了更高效、更安全的运营和管理方式。 在矿业开采过程中&#xff0c;数字孪生技术的应…

代码随想录算法训练营day42 | 01背包问题,你该了解这些!,01背包问题,你该了解这些! 滚动数组 , 416. 分割等和子集

代码随想录算法训练营day42 | 背包理论基础&#xff0c;背包理论基础&#xff08;滚动数组&#xff09;&#xff0c; 416. 分割等和子集 1、01背包理论基础背包问题概述01背包二维dp数组01背包案例 2、01背包理论基础&#xff08;滚动数组&#xff09;3、 416. 分割等和子集解…

Redis持久化-Redis主从-Redis哨兵-Redis分片集群

主要内容 Redis持久化Redis主从Redis哨兵Redis分片集群 Redis持久化 Redis有两种持久化的方案: RDB持久化AOF持久化 1. RDB持久化 RDB全称Redis Database Backup file&#xff08;Redis数据备份文件&#xff09;&#xff0c;也被叫做Redis数据快照。简单来说就是把内存中的所…

数字化时代下,制造业企业应该这样做仓库管理

透过现象看本质&#xff0c;在传统的仓储管理中都存在着以下问题&#xff1a; 1.信息化水平较低&#xff0c;以人工为主&#xff0c;以纸张为主&#xff0c;效率低下&#xff0c;容易出现错误&#xff1b; 2.信息流的不对称性&#xff0c;各个过程之间的联系不紧密&#xff0c;…

【高危】Apache Spark UI shell 命令注入漏洞(POC)

漏洞描述 该漏洞是针对此前CVE-2022-33891漏洞的修订&#xff0c;原有漏洞通告中认为3.1.3版本已修复该漏洞&#xff0c;后发现仍受到影响&#xff0c;3.1.3版本已不再维护&#xff0c;官方建议升级至3.4.0版本。 Apache Spark是美国阿帕奇&#xff08;Apache&#xff09;软件…

在这里总有一款高温介电温谱仪适合您(GWJDN-300/600/1000型多种可选)

GWJDN-300型多用途型高温介电温谱仪 关键词&#xff1a;高温介电&#xff0c;变温&#xff0c;电容&#xff0c;损耗 GWJDN-300高温介电温谱仪是一款专门用于评估电介质材料高温介电机制&#xff08;材料极化、储能、驰豫、相变、微结构变化、分子团重新取向等&#xff09;的…

远程控制电脑怎么弄? 远程控制电脑方法介绍

如何免费远程控制电脑&#xff1f; “你好&#xff0c;你知道任何可靠的免费Windows远程控制软件吗&#xff1f;我需要在工作电脑和家用电脑之间进行远程控制&#xff0c;因为我将出差数周。有什么好用的远程控制电脑方法吗&#xff1f;提前致谢&#xff01;” 电脑之间如何…

ChatGPT学习指南

主旨 大家好&#xff0c;我是五竹。心血来潮整理了这份手册并且将为小白们持续更新和GPT相关的资源和教程&#xff0c;专注于打造一部最好的GPT入门指南。此文档永久免费在线查看&#xff0c;欢迎大家转发、收藏、点赞支持&#xff01;后面会在文档中更新&#xff1a;ChatGPT学…

优秀互联网产品经理必备的10张业务图谱

作为离产品最近的人&#xff0c;产品经理是团队的交通枢纽&#xff0c;链接运营的需求和程序员的开发工作。面对庞杂多面的工作&#xff0c;今天小编和大家聊聊产品经理在工作各环节想要精进专业&#xff0c;都需要具备哪些能力。 01学习篇 持续学习的概念早已被大家接受&#…

海量数据同步到DDM(oracle到mysql)

1、由于oracle的rownum性能&#xff0c;所以通过主键ID实现分页&#xff1b; 2、数据可能存在重复&#xff0c;批量插入mysql使用insert ignore语法&#xff1b; 3、DDM数据库&#xff0c;过千万后并发插入&#xff0c;性能就很差&#xff1a;采用单线程一千条批量插入&#…

MySQL--索引--0427--0507

目录 1. MySQL是如何处理数据的 2. MySQL与磁盘的关系 3. MySQL与磁盘交互的基本单位 4.MySQL和磁盘之间联系的总结 5.索引的理解 5.1 理解单个page 5.2 理解多个page 5.3 为什么采用B树 5.4 聚簇索引 和 非聚簇索引 5.5 聚簇索引 和 非聚簇索引下的普通索引 6.索引操作…

Spring 注解之@RestController与@Controller的区别

目录 1&#xff1a;介绍 2&#xff1a;区别 3&#xff1a;总体来说 4&#xff1a;社区地址 1&#xff1a;介绍 RestController 和 Controller 是 Spring MVC 中常用的两个注解&#xff0c;它们都可以用于定义一个控制器类。 2&#xff1a;区别 返回值类型不同&#xff1a;…

STM32单片机声控语音识别RGB彩灯多种模式亮度可调WS2812彩灯

实践制作DIY- GC0129-语音识别RGB彩灯 一、功能说明&#xff1a; 基于STM32单片机设计-语音识别RGB彩灯 二、功能介绍&#xff1a; STM32F103C系列最小系统板5VUSB电源64个灯珠的WS2812灯板1个开关键&#xff08;3档亮度调节&#xff09;1个模式切换键&#xff08;白灯 红灯…

软件测试4年从外包15K跳槽去字节 38K+12,啃完这份笔记你也可以

转行做软件测试已经是第4个年头&#xff0c;一直是一个不温不火的小职员&#xff0c;本本分分做着自己的事情&#xff0c;觉得自己的工作已经遇到了瓶颈&#xff0c;一个偶然的机会&#xff0c;获得了一份软件测试全栈知识点学习笔记&#xff0c;通过几个月的学习&#xff0c;5…

git提交代码到GitLab步骤及拉取远程分支内容

一、本地建立一个空文件夹 点击鼠标右键点击红色箭头方向 Git Hash Here 二、git init 进行初始化 这个时候文件夹中会出现 .git 文件夹 三、添加远程仓库地址 git remote add origin (address) # 添加远程仓库地址 address是远程仓库代码链接 四、如果有分支把远程分支拉到…

跨设备开发的未来:多端能力服务统一技术

多端能力服务统一&#xff08;Multi-Experience Service Orchestration&#xff0c;MESO&#xff09;是一种技术和服务架构的概念&#xff0c;旨在为多种终端设备提供统一的用户体验和功能。它解决了在不同终端设备上使用不同应用程序和服务时出现的问题&#xff0c;使得用户可…