Filter过滤器注意事项

Filter

Filter简单介绍

web 服务器的三大组件 Servlet Filter Listener
Filter是用来执行过滤任务的一个对象,他的作用范围:

  1. 请求一个资源(动态资源Servlet,JSP,静态资源)
  2. 来自一个资源的响应
  3. 以上两个都可以

filter过滤请求和响应

  1. filter可以拦截请求,可以修改请求头,请求内容
  2. filter可以拦截来自服务端的响应。(response),可以修改响应头和响应内容。
  3. 放行请求

在这里插入图片描述

Filter的实现

  1. Filter是一个接口,所以需要实现这个接口
public HelloFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException{}
    //执行过滤方法
    @Override
    public void doFilter(ServletRequest request,ServletResponse response,
    FilterChain chain) throws IOException, ServletException{
        String money = request.getParameter("money");
        if(money != null){
            //带钱了
            chain.doFilter(request,response);//放行
            //在chain.doFilter(request,response);之前拦截request,在chain.doFilter之后拦截response。
        }else{
            //没带钱
            response.getWriter.write("no money,no way");
        }
    }
    @Override
    public void destroy(){}
}
  1. 在实现了Filter接口之后,我们需要对Filter进行初始化和配置,所以需要在web.xml中配置

<!--配置filter的映射信息-->
<filter>
    <!-- filter 起的别名-->
    <filter-name>HelloFilter</filter-name>
    <!-- filter 起的全类名-->
    <filter-name>com.atguigu.filter.HelloFilter</filter-name>
</filter>

<filter-mapping>
    <!--filter的别名-->
    <filter-name>HelloFilter</filter-name>
    <!-- 要过滤哪些地址的请求,b下面表示访问hello.jsp的请求-->
    <url-pattern>/hello.jsp</url-pattern>
</filter-mapping>
  1. 配置完成之后就可以使用Filter了

Filter的生命周期

我们在实现接口的时候发现Filter有init方法和destroy方法

服务器管理的Filter也有生命周期(从创建到销毁的过程)

  1. 创建-初始化。项目加载进服务器,创建Filter对象,并执行Filter对象的构造器方法和init方法。单例多线程。(这一步与Servlet不一样)
  2. 每次拦截执行doFilter方法。服务器启动的时候需要初始化Filter。
  3. 销毁,当项目从服务器中卸载时Filter销毁
@Override
public void init(FilterConfig filterConfig) throws ServletException{
}
@Override
public void destroy()

url-parttern 匹配规则

  1. 精确匹配 (写要拦截的资源的详细路径() /hello.jsp /page/a.jsp)
  2. 路径匹配:/路径名/* 该目录下的所有资源。
    拦截所有访问路径名下的匹配。
  3. 后缀匹配:*.后缀名,(模糊匹配)
    所有以给定的后缀结尾的都拦截。
  4. 如果以上三种都不能满足要求,则以在filter中动态配置
@Override
public void dpFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException,ServletException{
    HttpServletRequest req = (HttpServletRequest) request;
    String uri = req.getRequestURI();
    //这样就获得的请求地址,可以通过对该地址进行判断,从而执行是否过滤。
}

Filter乱码问题(web请求和响应过程的原理)

如果在chain.doFilter(request,response);之前使用response返回,会发生乱码问题,为什么?
现象:

  1. 在放行之前response写中文,中文在客户端显示乱码。
  2. 在放行之后写中文,中文在客户端正常显示。
  3. 若不放行,依然显示乱码

根本原因:都是在放行之前操作,或者直接操作(没放行直接响应)。
因为我们知道响应乱码的解决一定要在response写东西之前设置。jsp页面一执行就设置编码。放行请求就是等jsp写完页面之后的response,这个response已经设置后编码了。但是如果在请求之前给response写东西,那么就是在设置编码格式之前东西,这就会使response编码格式混乱,以至于出现乱码问题。
在整个客户端与服务器的交互过程中,一个请求对应一个响应,只要请求来了,立马先造一个响应对象。以后处理整个请求,都用的是这个request和这个response
jsp就是一个servlet,给接收到的response添加响应内容。

chain只有一个功能就是放行请求,只要不显式调用,请求不放行。

在这里插入图片描述

init方法中的filterConfig

init方法中的filterConfig参数可以获得一些Filter的初始化信息,并且可以获得该项目的ServletContext。

@Override
public void init(FilterConfig filterConfig) throws ServletException{
    String filterName = filterConfig.getFilterName;//filter别名
    //filter初始化参数
    String filterinitParameter = filterConfig.getInitParameter("keyvalue");
    //ServletContext-->对应web应用
    ServletContext servletContext = filterConfig.getServletContext();
    //获取web初始化参数
    String initParmeter = servletContext.getInitParameter("key");
    //在web.xml中配置,context-param中可以获得。
}

Filter链 多个filter拦截同一个资源

如果有多个Filter拦截同一个页面,那么多个Filter会按照在web.xml中的顺序执行拦截的顺序。具体过程如下图所示

在这里插入图片描述

Filter中 dispatcher的配置

dispatcher共有以下四种配置,告诉服务器拦截哪些资源。

  • FORWARD 拦截转发过来的
  • INCLUDE 拦截包含的
  • REQUEST 直接请求的
  • ERROR 发生错误的,去全局配置的一个错误页面就会被拦截,不是指页面上的errpage,因为errpage是请求转发的。

默认设置为REQUEST,直接请求会拦截

<filter-mapping>
    <!--filter的别名-->
    <filter-name>HelloFilter</filter-name>
    <!-- 要过滤哪些地址的请求,b下面表示访问hello.jsp的请求-->
    <url-pattern>/hello.jsp</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

使用Filter实现事务控制

思想:请求过来处理一些工作(包含一系列工作)–>响应结束。整个过程都是一个线程只要监控这一个线程即可,线程执行期间发生异常,回滚。
通过Filter来监控线程
请求->第一次被Filter拦截->执行其他->回到Filter被拦截->响应完成,都是一个线程在执行。在执行其他工作中有很多步骤,比如修改图书,保存订单,保存订单项。只要执行这些操作作用同一个连接而且这个连接需要手动关闭。
我们在第一次被Filter拦截的时候将每个线程对应的连接保存到map中,并将该链接的自动commit关闭。调用chain.doFilter(request,response);方法。
因为所有的Servlet的方法的执行都是被chain.doFilter(request,response);该方法调用,所以在整个过程发生异常的时候,我们让异常都throws到该方法,该方法就可以捕获异常,一旦捕获到异常,回滚事务,没有捕获到异常,提交事务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值