Filter过滤器

来源:互联网 发布:云计算判断题 编辑:程序博客网 时间:2024/06/04 22:53

Filter的基本功能是对servlet容器调用servlet的过程进行拦截,从而在servlet进行响应处理的前后实现一些特殊的功能。

在servletAPI中定义了三个接口类来供开发人员编写filter程序:Filter,FilterChain,FilterConfig。

Filter程序是一个实现了Filter接口的JAVA类,与servlet程序相似,它由servlet容器进行调用和执行。

Filter程序需要在web.xml文件中进行注册和设置它所能拦截的资源:Filter程序可以拦截Jsp,Servlet,静态图片文件和静态HTML文件。

Filter的基本工作原理

当在web.xml注册了一个Filter来对某个servlet程序进行拦截处理时,这个Filter就成了servlet容器与该servlet程序的通信线路上的一道关卡,该Filter可以对servlet容器发送给servlet程序的请求和servlet程序回送给servlet容器的相应内容进行拦截,可以决定是否将请求继续传递给servlet程序,以及对请求和相应信息是否进行修改。

在一个web应用程序中可以注册多个filter程序,每个filter程序都可以对一个或一组servlet程序进行拦截。

若有多个Filter程序对某个servlet程序的访问过程进行拦截,当针对该servlet的访问请求到达时,web容器将把这多个Filter程序组合成Filter链(过滤器链)。Filter链中各个Filter的拦截顺序与它们在应用程序 web.xml中映射的顺序一致。

简单Filter实例

新建两个页面,实现跳转:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>Title</title></head><body>  <a href="two.jsp">to two.jsp</a></body></html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>Title</title></head><body>    <h2>TWO</h2></body></html>
实现filter接口:

package com.sa.filter;import javax.servlet.*;import java.io.IOException;public class HelloFilter implements Filter{    @Override    public void init(FilterConfig filterConfig) throws ServletException {        System.out.println("init");    }    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        System.out.println("doFilter");    }    @Override    public void destroy() {        System.out.println("destroy");    }}
在web.xml中配置filter:

    <filter>        <filter-name>helloFilter</filter-name>        <filter-class>com.sa.filter.HelloFilter</filter-class>    </filter>    <filter-mapping>        <filter-name>helloFilter</filter-name>        <url-pattern>/pages/filter/two.jsp</url-pattern>    </filter-mapping>

测试:




Filter相关API:

Filter接口:

public void init(FilterConfig filterConfig) throws ServletException :类似于servlet的init方法,在创建filter对象后,立即执行,且只执行一次。filter对象在servlet容器加载当前web应用时被创建。该方法用于对当前的filter进行初始化操作,Filter实例是单例的。FilterConfig类似于ServletConfig,可以在web.xml文件中,配置当前filter的初始化参数。

    <filter>        <filter-name>helloFilter</filter-name>        <filter-class>com.sa.filter.HelloFilter</filter-class>        <init-param>            <param-name>name</param-name>            <param-value>sasa</param-value>        </init-param>    </filter>    <filter-mapping>        <filter-name>helloFilter</filter-name>        <url-pattern>/pages/filter/two.jsp</url-pattern>    </filter-mapping>


public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException :真正的filter逻辑代码需要编写在该方法中。每次拦截都会调用该方法。

    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        System.out.println("doFilter");        //放行        filterChain.doFilter(servletRequest,servletResponse);    }
FilterChain:Filter链,多个Filter构成一个Filter链。把请求传给Filter链中的下一个Filter,若当前Filter是Filter链的最后一个,将把请求给到目标Servlet或JSP。多个filter拦截的顺序和<filter-mapping> 配置的顺序有关,靠前的先被调用。

public void destroy():销毁释放当前filter所占用的资源,在filter销毁之前被调用,且只被调用一次。

实现登录拦截:

login.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>登录</title></head><body><h2>${msg}</h2>    <form action="<%=request.getContextPath()%>/pages/filter/hello.jsp" method="post">        name:<input type="text" name="name">        pwd:<input type="text" name="pwd">        <input type="submit" value="提交">    </form></body></html>
hello.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>Title</title></head><body>   <h1>hello:{param.name}></h1></body></html>
NameFilter:

package com.sa.filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class NameFilter implements Filter{    private FilterConfig filterConfig;    @Override    public void init(FilterConfig filterConfig) throws ServletException {         this.filterConfig=filterConfig;    }    @Override    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {        String name=request.getParameter("name");        String name1=filterConfig.getInitParameter("name");            if (!name.equals(name1)) {                request.setAttribute("msg", "名字错辣");                request.getRequestDispatcher("/pages/filter/login.jsp").forward(request,response);                return;            } else {                filterChain.doFilter(request, response);            }    }    @Override    public void destroy() {    }}

PwdFilter:

package com.sa.filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class PwdFilter implements Filter{    private FilterConfig filterConfig;    @Override    public void init(FilterConfig filterConfig) throws ServletException {        this.filterConfig=filterConfig;    }    @Override    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {        String pwd=request.getParameter("pwd");        String pwd1=filterConfig.getServletContext().getInitParameter("pwd");            if (!pwd.equals(pwd1)) {                request.setAttribute("msg", "密码错辣");                request.getRequestDispatcher("/pages/filter/login.jsp").forward(request,response);                return;            } else {                filterChain.doFilter(request, response);            }    }    @Override    public void destroy() {    }}

配置web.xml:

    <filter>        <filter-name>nameFilter</filter-name>        <filter-class>com.sa.filter.NameFilter</filter-class>        <init-param>            <param-name>name</param-name>            <param-value>sasa</param-value>        </init-param>    </filter>    <filter-mapping>        <filter-name>nameFilter</filter-name>        <url-pattern>/pages/filter/hello.jsp</url-pattern>    </filter-mapping>    <filter>        <filter-name>pwdFilter</filter-name>        <filter-class>com.sa.filter.PwdFilter</filter-class>    </filter>    <filter-mapping>        <filter-name>pwdFilter</filter-name>        <url-pattern>/pages/filter/hello.jsp</url-pattern>    </filter-mapping>    <context-param>        <param-name>pwd</param-name>        <param-value>123</param-value>    </context-param>

测试:



Dispatcher元素:指定过滤器所拦截的资源被servlet容器调用的方式,可以是request,include,forword,error之一,默认为request,可以设置多个<dispatcher>子元素来指定filter对资源的多种调用方式进行拦截。

①:request:当用户直接访问页面时,web容器将会调用过滤器,如果目标资源是通过requestDispatcher的include()或forWord()方法访问则不会触发过滤器。

通过get或post请求直接访问。

②:forword:如果目标资源是通过requestDispatcher的forword()方法访问时,那么该过滤器将会被调用,除此之外,该过滤器不会被调用。

或<jsp:forword page=""/> 或通过page指令的errorPage转发页面,<%@page errorPage="error.jsp"%>

③:include:如果目标资源是通过requestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。

或<jsp:include file="/..." />

④:error:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

在web.xml文件中通过error-page节点声明

测试:

现在想通过两种方式访问two.jsp:一种是通过request请求,一种是通过forword请求。

one.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><script>    function a() {        window.location.href="<%=request.getContextPath()%>/pages/1011/two.jsp";    }</script><head>    <title>one</title>    <button onclick="a();" >request</button></head><body></body></html>
two.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>two</title></head><body>  <h1>this is two</h1></body></html>
three.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>three</title></head><body>    <a href="four.jsp">forword</a></body></html>
four.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>four</title></head><body>  <jsp:forward page="two.jsp"></jsp:forward></body></html>

filter1:

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {        System.out.println("Filter1");        chain.doFilter(req, resp);    }

filter2:

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {        System.out.println("Filter2");        chain.doFilter(req, resp);    }

配置xml:

    <filter>        <filter-name>Filter1</filter-name>        <filter-class>com.sa.filter.Filter1</filter-class>    </filter>    <filter-mapping>        <filter-name>Filter1</filter-name>        <url-pattern>/pages/1011/two.jsp</url-pattern>    </filter-mapping>    <filter>        <filter-name>Filter2</filter-name>        <filter-class>com.sa.filter.Filter2</filter-class>    </filter>    <filter-mapping>        <filter-name>Filter2</filter-name>        <url-pattern>/pages/1011/two.jsp</url-pattern>    </filter-mapping>

通过request访问two.jsp:


通过forword访问two.jsp:


可以得知filter的默认监视请求方式是request。

修改xml文件:

    <filter>        <filter-name>Filter1</filter-name>        <filter-class>com.sa.filter.Filter1</filter-class>    </filter>    <filter-mapping>        <filter-name>Filter1</filter-name>        <url-pattern>/pages/1011/two.jsp</url-pattern>    </filter-mapping>    <filter>        <filter-name>Filter2</filter-name>        <filter-class>com.sa.filter.Filter2</filter-class>    </filter>    <filter-mapping>        <filter-name>Filter2</filter-name>        <url-pattern>/pages/1011/two.jsp</url-pattern>        <dispatcher>FORWARD</dispatcher>    </filter-mapping>
通过request访问two.jsp:

通过forword访问two.jsp:



原创粉丝点击