javaWEB之过滤器

javaWEB三大组件,Servlet、Listener、Filter,在上一篇博客中javaWEB监听器介绍了监听器,这篇博客记录一下过滤器 FIlter

1、什么是过滤器

  • 过滤器是JavaWeb三大组件之一,它与Servlet很相似!但是过滤器是用来拦截请求的,而不是处理请求的。
  • 当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,那么会继承执行用户请求的Servlet;如果Filter不“放行”,那么就不会执行用户请求的Servlet。
    其实可以这样理解,当用户请求某个Servlet时,Tomcat会去执行注册在这个请求上的Filter,然后是否“放行”由Filter来决定。可以理解为,Filter来决定是否调用Servlet!当执行完成Servlet的代码后,还会执行Filter后面的代码。
    在这里插入图片描述

2、实现一个简单的Filter

1、编写一个类继承Filter接口

public class MyFilter 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(" 被拦截了");
    }

    @Override
    public void destroy() {
		// 过滤器注销时调用,一般是服务器关机或者重启。
    }
}

2、在web.xml中注册这个Filter,注册的方式和Servlet类似

		<filter>
            <filter-name>UserFilter</filter-name>
            <filter-class>TestFilter.BFilter</filter-class> // 过滤器的全类名
        </filter>
        
    <filter-mapping>
        <filter-name>UserFilter</filter-name>
        <url-pattern>/index.jsp</url-pattern> // 要拦截的url
    </filter-mapping>

3、配置完上面两步一个简单的过滤器就搞定了,可以去访问index.jsp试试,会发现MyFilter类执行了doFilter,但是没有执行 index.jsp,这是因为没有放行。如果想执行index.jsp,需要下边的代码

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		System.out.println("filter start...");
		chain.doFilter(request, response);
		System.out.println("filter end...");
	}

3、过滤器详解

  • 1、生命周期
    init(FilterConfig):在服务器启动时会创建Filter实例,并且每个类型的Filter只创建一个实例,从此不再创建!在创建完Filter实例后,会马上调用init()方法完成初始化工作,这个方法只会被执行一次;
    doFilter(ServletRequest req,ServletResponse res,FilterChain chain):这个方法会在用户每次访问“目标资源(pattern>index.jsp)”时执行,如果需要“放行”,那么需要调用FilterChain的doFilter(ServletRequest,ServletResponse)方法,如果不调用FilterChain的doFilter()方法,那么目标资源将无法执行;
    destroy():服务器会在创建Filter对象之后,把Filter放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁Filter对象,在销毁Filter对象之前,服务器会调用Filter对象的destory()方法。

  • 2、FilterConfig
    你已经看到了吧,Filter接口中的init()方法的参数类型为FilterConfig类型。它的功能与ServletConfig相似,与web.xml文件中的配置信息对应。下面是FilterConfig的功能介绍:
    ServletContext getServletContext():获取ServletContext的方法;
    String getFilterName():获取Filter的配置名称;与元素对应;
    String getInitParameter(String name):获取Filter的初始化配置,与元素对应;
    Enumeration getInitParameterNames():获取所有初始化参数的名称。

web.xml配置

 <filter>
        <filter-name>MyFilter</filter-name>
        <filter-class>TestFilter.MyFilter</filter-class>
        <init-param>
            <param-name>name1</param-name>
            <param-value>这是初始值一</param-value>
        </init-param>
        <init-param>
            <param-name>name2</param-name>
            <param-value>这是初始值二</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>MyFilter</filter-name>
        <url-pattern>/index.jsp</url-pattern>
    </filter-mapping>
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String filterName = filterConfig.getFilterName(); // 获取过滤器的名字,这里是MyFilter
        String initParameter = filterConfig.getInitParameter("name1"); //获取对应的初始化的值,这里是这是初始值一
        String initParameter1 = filterConfig.getInitParameter("name2"); //获取对应的初始化的值,这里是这是初始值二
        Enumeration<String> initParameterNames = filterConfig.getInitParameterNames(); // 获取的是初始化参数的名的一个Enumeration
        
    }
  • 3、FilterChain
    doFilter()方法的参数中有一个类型为FilterChain的参数,它只有一个方法:doFilter(ServletRequest,ServletResponse)。
    前面我们说doFilter()方法的放行,让请求流访问目标资源!但这么说不严密,其实调用该方法的意思是,当前过滤器放行了,但不代表其他过滤器也放行。
    也就是说,一个目标资源上,可能部署了多个过滤器,就好比在你去北京的路上有多个打劫的匪人(过滤器),而其中第一伙匪人放行了,但不代表第二伙匪人也放行了,所以调用FilterChain类的doFilter()方法表示的是执行下一个过滤器的doFilter()方法,或者是执行目标资源!
    如果当前过滤器是最后一个过滤器,那么调用chain.doFilter()方法表示执行目标资源,而不是最后一个过滤器,那么chain.doFilter()表示执行下一个过滤器的doFilter()方法。

  • 4、过个filter拦截同一个url,执行filter的顺序根据在 web.xml中的配置的前后顺序决定的,在前边的会先执行,在后边的会后执行

  • 5、四种拦截方式
    现在创建两个jsp,一个a.jsp,一个b.jsp,在web.xml配置过滤器拦截 对于 b.jsp的请求,在a.jsp 中 写:request.getRequestDispathcer(“/b.jsp”).forward(request,response),当访问a.jsp是会发现直接请求到了b.jsp,过滤器没有起到作用,也就是说,默认情况下,只能直接访问目标资源才会执行过滤器,而forward执行目标资源,不会执行过滤器!

    其实过滤器有四种拦截方式!分别是:REQUEST、FORWARD、INCLUDE、ERROR。最为常用的就是REQUEST和FORWARD两种拦截方式
    REQUEST:直接访问目标资源时执行过滤器。包括:在地址栏中直接访问、表单提交、超链接、重定向,只要在地址栏中可以看到目标资源的路径,就是REQUEST;
    FORWARD:转发访问执行过滤器。包括RequestDispatcher#forward()方法、<jsp:forward>标签都是转发访问;
    INCLUDE:包含访问执行过滤器。包括RequestDispatcher#include()方法、<jsp:include>标签都是包含访问;
    ERROR:当目标资源在web.xml中配置为<error-page>中时,并且真的出现了异常,转发到目标资源时,会执行过滤器。

 <filter-mapping>
        <filter-name>MyFilter</filter-name>
        <url-pattern>/index.jsp</url-pattern>
        <dispatcher>REQUEST</dispatcher>  // 设置拦截方式
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>

接下啦演示出错的时候

	<filter-mapping>
		<filter-name>myfilter</filter-name>
		<url-pattern>/b.jsp</url-pattern>
		<dispatcher>ERROR</dispatcher>
	</filter-mapping>
	<error-page>
		<error-code>500</error-code>
		<location>/b.jsp</location>
	</error-page>
  <body>
  <h1>a.jsp</h1>
   <%
   if(true)
   	throw new RuntimeException("");
   %>
  </body>

4、过滤器的应用场景

执行目标资源之前做预处理工作,例如设置编码,这种试通常都会放行,只是在目标资源执行之前做一些准备工作;
通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户IP是否已经被禁用;
在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理

5、Filter小结

Filter的三个方法:
void init(FilterConfig):在Tomcat启动时被调用;
void destroy():在Tomcat关闭时被调用;
void doFilter(ServletRequest,ServletResponse,FilterChain):每次有请求时都调用该方法;

FilterConfig类:与ServletConfig相似,用来获取Filter的初始化参数
ServletContext getServletContext():获取ServletContext的方法;
String getFilterName():获取Filter的配置名称;
String getInitParameter(String name):获取Filter的初始化配置,与元素对应;
Enumeration getInitParameterNames():获取所有初始化参数的名称。

FilterChain类:
void doFilter(ServletRequest,ServletResponse):放行!表示执行下一个过滤器,或者执行目标资源。可以在调用FilterChain的doFilter()方法的前后添加语句,在FilterChain的doFilter()方法之前的语句会在目标资源执行之前执行,在FilterChain的doFilter()方法之后的语句会在目标资源执行之后执行。

四各拦截方式:REQUEST、FORWARD、INCLUDE、ERROR,默认是REQUEST方式。
REQUEST:拦截直接请求方式;
FORWARD:拦截请求转发方式;
INCLUDE:拦截请求包含方式;
ERROR:拦截错误转发方式。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值