关于JavaWeb中的过滤器详解

在这里插入图片描述

Filter

Filter是Servlet技术中最实用的技术,通过Filter过滤技术,对web服务器上所有的web资源进行管理:例如Jsp,
Servlet, 静态图片文件或静态 html 文件等进行拦截/放行,从而能够实现一些特殊的功能。

实现功能

比如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能 处理编码。

它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理

如何使用过滤器

使用Filter的完整流程:

  1. Filter对用户请求进行预处理;
  2. 将请求交给Servlet进行处理并生成响应;
  3. 最后Filter再对服务器响应进行后处理。

具体描述----->>>>

1,在HttpServletRequest到达 Servlet 之前,拦截客户的HttpServletRequest。根据需要检查HttpServletRequest,也可以修改HttpServletRequest 头和数据。

2,在HttpServletResponse到达客户端之前,拦截HttpServletResponse根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

3Filter接口中有一个doFilter方法,当开发人员编写好Filter,并配置对哪个web资源进行拦截后,Web服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法**,doFilter方法中有一个filterChain对象,用于继续传递给下一个filter,**在传递之前我们可以定义过滤请求的功能,在传递之后,我们可以定义过滤响应的功能

简单的框架实现---->>>
首先定义一个servlet

public class MyServlet1 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().println("MyServlet1--invoke");
    }
}

然后定义一个过滤器----->>>

自定义过滤器要实现servlet包下的Filter接口,接口中有有三个方法-----

初始化方法----init(FilterConfig filterConfig)

过滤方法---- doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)

销毁过滤器方法----destroy()

其中和新方法是 doFilter方法来对请求和访问进行过滤和处理的;

import javax.servlet.*;
import java.io.IOException;

public class MyFilter implements Filter {
//初始化方法
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化完成");
    }
//过滤方法
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("请求已过滤");
    }
//销毁方法
    @Override
    public void destroy() {

    }
}

准备好这些后,还要指定过滤器访问哪个servlet时使用该过滤器;

配置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_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>MyServlet1</servlet-name>
        <servlet-class>com.gavin.myfiflter.MyServlet1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet1</servlet-name>
        <url-pattern>/MyServlet1.do</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>MyFilter</filter-name>
        <filter-class>com.gavin.fiflter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyFilter</filter-name>
        <!--对哪个资源请求和响应进行过滤-->
        <url-pattern>/MyServlet1.do</url-pattern>

    </filter-mapping>
</web-app>

框架搭建完毕后,运行
在这里插入图片描述但是浏览器中闭关没有输出任何信息,是因为我们只是定义了过滤,对过滤之后没有进行任何处理,所以相当于给全部过滤掉了,那这个时候需要添加一些代码对请求/响应进行过滤处理,这时候服务器才能对请求做出真正的响应;
在这里插入图片描述

完善过滤器代码

import javax.servlet.*;
import java.io.IOException;

public class MyFilter implements Filter {
//初始化方法
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化完成");
    }
//过滤方法
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("请求已过滤");
        //放行请求,继续让过滤链中的其他过滤器过滤
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("对响应进行过滤");
        servletResponse.getWriter().print("过滤之后添加的响应内容");

    }
//销毁方法
    @Override
    public void destroy() {
        System.out.println("已销毁");
    }
}

再次访问之后-----
在这里插入图片描述
同时一个而过滤器可以过滤多个servlet对象

在这里插入图片描述

同servlet对象一样,Filter对象的创建也是交给web服务器完成的,在web服务器创建和使用及最后销毁filter时,会调用filter对应的方法

构造方法:

实例化一个Filter对象的方法

初始化方法:

public void init(FilterConfig filterConfig);

和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。

拦截请求方法

public void doFilter

这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。

销毁方法:

public void destroy();

Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。

简要描述:
1 WEB 容器启动时,会对Filter进行构造并初始化 一次
2 每次请求目标资源时,都会执行doFilter的方法
3 WEB容器关闭是,会销毁Filter对象

过滤器链的使用

搭建架构-----
准备两个过滤器,一个servlet
在这里插入图片描述
过滤器链原理分析---->>>
在这里插入图片描述
web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

使用过滤器链的好处是我们可以将不同的过滤功能分散到多个过滤器中,分工明确,避免一个过滤器做太多的业务处理,降低了代码的耦合度,这体现了单一职责的设计原则,应用了责任链的代码设计模式.

决定过滤器的执行顺序是由filter-mapping标签决定

过滤器参数初始化

过滤器的配置跟servlet类似,可以在web.xml中配置一些初始化参数
在这里插入图片描述那这些参数该如何取出来呢?
我们回到Filter的生命周期–
初始化的时候我们可以覆写一下 init()方法
public void init(FilterConfig filterConfig) throws ServletException

在这个方法中有一个参数FilterConfig filterConfig),通过这个参数来取出数据!
在这里插入图片描述在这里插入图片描述通过配置文件比较麻烦的话,我们还可以通过注解模式来开发过滤器

注解模式开发过滤器

/*@WebServlet(name= "MyServlet3")*/
@WebFilter(urlPatterns = "/MyServlet3.do" ,initParams ={@WebInitParam(name="UserInfo",value = "张三"),@WebInitParam(name="Charset",value = "UTF-8") })
public class NewFilterDemo implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println(filterConfig.getFilterName());
        System.out.println(filterConfig.getInitParameter("Charset"));
        System.out.println(filterConfig.getInitParameter("UserInfo"));

        filterConfig.getServletContext().setAttribute("userN","Gavin");
    }

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

    }

    @Override
    public void destroy() {

    }
}

注解两种方式---->>>
在这里插入图片描述
注解方式下过滤器的执行顺序------
在配置文件模式下配置的过滤器执行顺序跟过滤器的放置顺序有关系,那么在注解模式下,过滤器的执行顺序是怎样的呢?

做一个测试----->>>>
准备两个过滤器-----

Filter0_Demo
和Filter1_Demo,都对MyServlet3.do进行过滤-----结果
在这里插入图片描述下面修改一下Filter0_Demo为Filter8_Demo
在这里插入图片描述
再次添加一个过滤器----Filter6_Demo
在这里插入图片描述可以看到确实是按照名字进行排序的,所以在命名过滤器时要注意名字的命名规范,一般原则是Filter数字_过滤器描述

过滤器处理post乱码

先看一下 form表单 通过get的方式请求,服务器获得的数据

<%--
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <form action="PostDemo.do" method="get">
    用户名:<input type="text" name="user" placeholder="请输入用户名">&emsp;码:<input type="password" name="pwd" placeholder="请输入密码">
    <input type="submit" value="提交">
  </form>
  </body>
</html>

在这里插入图片描述后台得到的数据
在这里插入图片描述换成post方式得到的数据---->>>
在这里插入图片描述怎么办?在servlet中设置解码方式----

在这里插入图片描述但是如果servlet很多的话挨个写?..
这时候过滤器就可以起作用了>
可以使得买次请求时都通过过滤器设置编码格式为UTF-8

在这里插入图片描述最后实现的结果跟在每个Servlet种单独设置是一样的----->>

在这里插入图片描述
还有一个间接的方式----在定义过滤器时可以将charset 放到 初始化时的参数中,通过读取参数来完成charset的设置;

具体操作如下:
在这里插入图片描述
在这里插入图片描述
方式二是通过注解的方式完成----->

在这里插入图片描述
Cannot invoke “String.toLowerCase(java.util.Locale)” because “enc” is null 该如何解决?

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeMartain

祝:生活蒸蒸日上!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值