Filter 介绍

Filter 可认为是 Servlet 的一种加强版,它主要用于对用户请求进行预处理,也可以对 HttpServletResponse 进行后处理,是个典型的处理链。

Filter 也可对用户请求生成响应,这一点与 Servlet 相同,但实际上很少会使用 Filter 向用户请求生成响应。使用 Filter 完整的流程是:Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后 Filter 再对服务器响应进行后处理。

Filter 有如下几个用处:

1、在 HttpServletRequest 到达 Servlet 之前,拦截用户的 HttpServletRequest

2、根据需要检查 HttpServletRequest,也可以修改 HttpServletRequest 头和数据

3、在 HttpServletResponse 到达客户端之前,拦截 HttpServletResponse

4、根据需要检查 HttpServletResponse,也可以修改 HttpServletResponse 头和数据

Filter 主要有如下几个种类:

1、用户授权的 Filter:Filter 负责检查用户请求,根据请求过滤用户非法请求。

2、日志 Filter:详细记录某些特殊的用户请求。

3、负责解码的 Filter:包括对非标准编码的请求解码。

4、能改变 XML 内容的 XSLT Filter 等。

5、Filter 可负责拦截多个请求或响应:一个请求或响应也可被多个 Filter 拦截。

创建一个 Filter 只需两个步骤:

1、创建 Filter 处理类

2、web.xml 中配置 Filter

创建 Filter 类

创建 Filter 必须实现 javax.servlet.Filter 接口,在该接口中定义了如下三个方法:

1、void init(FilterConfig config):用于完成 Filter 的初始化

2、void destroy():用于 Filter 销毁前,完成某些资源的回收

3、void doFilter(ServletRequest request, ServletResponse response, FilterChain chain):实现过滤功能,该方法就是对每个请求及响应增加的额外处理。

LogFilter.java

package com.baiguiren;

import java.io.IOException;

import javax.servlet.*;

@WebFilter(filterName="log", urlPatterns={"/*"})
public class LogFilter implements Filter
{
    // FilterConfig 可用于访问 Filter 的配置信息
    private FilterConfig config;

    // 实现初始化方法
    public void init(FilterConfig config)
    {
        this.config = config;
    }

    // 实现销毁方法
    public void destroy()
    {
        this.config = null;
    }

    // 执行过滤的核心方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException
    {
        // 下面代码用于对用户请求进行预处理
        // 获取 ServletContext 对象,用于记录日志
        ServletContext context = this.config.getServletContext();
        long before = System.currentTimeMillis();
        System.out.println("开始过滤...");
        // 将请求转换成 HttpServletRequest 请求
        HttpServletRequest hRequest = (HttpServletRequest)request;
        // 输出提示信息
        System.out.println("Filter 已经拦截到用户请求的地址: " + hRequest.getServletPath());

        // Filter 只是链式处理,请求依然放行到目的地址
        chain.doFilter(request, response);

        // 下面代码用于对服务器响应执行后处理
        long after = System.currentTimeMillis();
        // 输出提示信息
        System.out.println("过滤结束");
        System.out.println("请求被定位到" + hRequest.gerRequestURI() + " 所花的时间为:" + (after - before));
    }
}

  

配置 Filter

配置 FIlter 与配置 Servlet 非常相似,都需要配置如下两个部分。

1、配置 Filter 名

2、配置 Filter 拦截 URL 模式

区别在于:Servlet 通常只配置一个 URL,而 Filter 可以同时拦截多个请求的 URL。因此,在配置 Filter 的 URL 模式时通常会使用模式字符串,使得 Filter 可以拦截多个请求。与配置 Servlet 相似的是,配置 Filter 同样有两种方式。

1、在 Filter 中通过注解进行配置

2、在 web.xml 文件中通过配置文件进行配置。

上面 Filter 类使用了 @WebFilter 配置该 Filter 的名字为 log,它会拦截向 /* 发送的所有的请求。

@WebFilter 属性:

asyncSupported:指定该 Filter 是否支持异步操作模式。

dispatcherTypes:指定该 Filter 仅对哪种 dispatcher 模式的请求进行过滤。该属性支持 ASYNC、ERROR、FORWARD、INCLUDE、REQUEST 这 5 个值得任意组合。默认为同时过滤 5 种模式的请求。

displayName:指定该 FIlter 的显示名

filterName:指定该 FIlter 的名称

initParams:用于为该 FIlter 配置参数

servletNames:该属性值可指定多个 Servlet 的名称,用于指定该 FIlter 仅对这几个 Servlet 执行过滤

urlPatterns/value:这两个属性的作用完全相同。都指定该 FIlter 所拦截的 URL。

web.xml 配置

<!-- 配置 Filter -->
<filter>
  <!-- Filter 的名字,相当于指定 @WebFilter 的 filterName 属性 -->
  <filter-name>log</filter-name>
  <!-- Filter 的实现类 -->
  <filter-class>com.baiguiren.LogFilter</filter-class>
</filter>
<!-- 定义 Filter 拦截的 URL 地址 -->
<filter-mapping>
  <!-- Filter 的名字 -->
  <filter-name>log</filter-name>
  <!-- Filter 负责拦截的 URL,相当于指定 @WebFilter 的 urlPatterns 属性 -->
  <url-pattern>/*</url-pattern>
</filter-mapping>

  

在实际项目中,Filter 里 doFilter() 方法里的代码就是从多个 Servlet 的 service() 方法里抽取的通用代码,通过使用 Filter 可以实现更好的代码复用。

假设系统包含多个 Servlet,这些 Servlet 都需要进行的一些通用处理:比如权限控制、记录日志等,这将导致在这些 Servlet 的 service 方法中有部分代码是相同的 -- 为了解决这种代码重复的问题,可以考虑把这些通用处理提取到 FIlter 中完成,这样各 Servlet 中剩下的只是特定请求相关的处理代码,而通用处理则交给 FIlter 完成。

Filter 与 Servlet 具有完全相同的生命周期。

下面将定义一个 Filter,该 Filter 对用户请求进行过滤,Filter 将通过 doFilter 方法来设置 request 编码的字符集,从而避免每个 JSP、Servlet 都需要设置;而且还会验证用户是否登录,没有登录则跳转到登录页:

AuthorityFilter.java

package com.baiguiren;

import java.io.IOException;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

import javax.servlet.annotation.*;

@WebFilter(filterName="authority", urlPatterns={"/*"},
    initParams={
        @WebInitParam(name="encoding", value="UTF-8"),
        @WebInitParam(name="loginPage", value="/login.jsp"),
        @WebInitParam(name="proLogin", value="/proLogin.jsp")
    }
)
public class AuthorityFilter implements Filter
{
    // FilterConfig 可用于访问 Filter 的配置信息
    private FilterConfig config;

    // 实现初始化方法
    public void init(FilterConfig config)
    {
        this.config = config;
    }

    // 实现销毁方法
    public void destroy()
    {
        this.config = null;
    }

    // 执行过滤的核心方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException
    {
        // 获取该 Filter 的配置参数
        String encoding = config.getInitParameter("encoding");
        String loginPage = config.getInitParameter("loginPage");
        String proLogin = config.getInitParameter("proLogin");

        // 设置 request 字符集
        request.setCharacterEncoding(encoding);
        HttpServletRequest requ = (HttpServletRequest)request;
        HttpSession session = requ.getSession(true);

        // 获取客户端请求的页面
        String requestPath = requ.getServletPath();
        // 如果 session 范围的 user 为 null,即表明没有登录
        // 且用户的请求既不是登录页面,也不是处理登录的页面
        if (session.getAttribute("user") == null
            && !requestPath.endsWith(loginPage)
            && !requestPath.endsWith(proLogin))
        {
            // forward 到登录页
            request.setAttribute("tip", "你还没有登录!");
            request.getRequestDispatcher(loginPage).forward(request, response);
        } else {
            // 放行请求
            chain.doFilter(request, response);
        }
    }
}

  

上面的代码使用注解配置,也可以在 web.xml 中配置:

<filter>
  <filter-name>authority</filter-name>
  <filter-class>com.baiguiren.Authority</filter-class>
  <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
  <init-param>
    <param-name>loginPage</param-name>
    <param-value>/login.jsp</param-value>
  </init-param>
  <init-param>
    <param-name>proLogin</param-name>
    <param-value>/proLogin.jsp</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>authority</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

  

上面的配置保证了普通用户只能访问 login.jsp 和 proLogin.jsp,其他页面都需要登录之后才能访问。

使用 URL Rewrite 实现网站伪静态

对于以 JSP 为表现层开发的动态网站来说,用户访问的 URL 通常有如下形式:

xxx.jsp?name=value...

大部分搜索引擎都会优先考虑收录静态的 HTML 页面,而不是这种动态的 *.jsp、*.php 页面。但实际上大部分网站都是动态的,不可能全部都是静态的 HTML 页面,因此大部分网站都会考虑使用伪静态 -- 就是将 *.jsp 这种动态 URL 伪装成静态的 HTML 页面。

对于 JavaWeb 应用来说,要实现这种伪静态非常简单:可以通过 Filter 拦截所有发向 *.html 的请求,然后按某种规则将请求 forward 到实际的 *.jsp 页面即可。

实现伪静态步骤:

1、到 http://www.tuckey.org/urlrewrite/ 下载 URL Rewrite 的最新版本

2、把上一步下载的 jar 包放在 WEB-INF/lib 目录下

3、在 web.xml 文件中配置启用 URLRewrite Filter,在 web.xml 中增加如下配置片段

4、在应用的 WEB-INF 路径下增加 urlrewrite.xml 文件,该文件定义了伪静态映射规则,这份伪静态规则是基于正则表达式的

urlwrite.xml

<?xml version="1.0" encoding="UTF-8"?>

<urlrewrite>
    <rule>
        <!-- 所有配置如下正则表达式的请求 -->
        <from>/userinf-(\w*).html</from>
        <!-- 将被 forward 到如下 JSP 页面,其中 $1 代表上面第一个正则表达式所匹配的字符串 -->
        <to type="forward">/userinf.jsp?username=$1</to>
    </rule>
</urlrewrite>

  

上面的规则文件中只定义了一个简单的规则:所有发向 /userinf-(\w*).html 的请求都被 forward 到 userinf.jsp 页面,并将 (\w*) 正则表达式所匹配的内容作为 username 参数值。

<%@ page contentType="text/html; charset=UTF-8" %>

<%
// 获取请求参数
String user = request.getParameter("username");
%>

<html>
    <head>
        <title><%=user%>的个人信息</title>
    </head>
    <body>
        <%
            out.println("现在时间是: " + new java.util.Date() + "<br/>");
            out.println("用户名: " + user);
        %>
    </body>
</html>

  

原文地址:https://www.cnblogs.com/eleven24/p/8647557.html

时间: 2024-07-31 13:45:25

Filter 介绍的相关文章

Filter介绍,运行顺序,实例

Filter介绍 Filter可觉得是Servlet的一种"变种",它主要用于对用户请求进行预处理,也能够对HttpServletResponse进行后处理,是个典型的处理链. 它与Servlet的差别在于:它不能直接向用户生成响应. 完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对server响应进行后处理. Filter有例如以下几个用处. 在HttpServletRequest到达Servlet之前,拦截客户的H

Filter介绍,执行顺序,实例

Filter介绍 Filter可认为是Servlet的一种"变种",它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链.它与Servlet的区别在于:它不能直接向用户生成响应.完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理. Filter有如下几个用处. 在HttpServletRequest到达Servlet之前,拦截客户的HttpServ

JSP笔记——8.Filter介绍

跟它的名字一样,filter能够拦截特定的用户请求或者相应,并对这些东西进行处理.虽然很少用,不过也可以对request进行response.filter可以拦截多个请求相应,一个请求响应也可以被多个filter拦截.使用filter只需要创建filter处理类,然后在xml中配置filter. 创建filter类 必须实现Filter接口,里面要有三个方法:init用于初始化filter:destroy用于销毁filter前完成某些资源的回收:doFilter实现过滤功能.因为filter是处

Apache Shiro学习笔记(六)Servlet3.0 Filter介绍

鲁春利的工作笔记,好记性不如烂笔头 Filter接口 Filter也称之为过滤器,通过Filter对所有web资源(例如Jsp, Servlet, 静态文件等)进行拦截,从而实现一些特殊的功能.例如实现URL级别的权限访问控制.过滤敏感词汇.压缩响应信息等. package javax.servlet; /**  * A filter is an object that performs filtering tasks on either the  * request to a resource

Filter介绍

Filter可人为是Servlet的一种“加强版”,它重要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链.使用Filter的完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter在对服务器响应进行后处理. Filter的用处: 在HttpServletRequest到达Servlet之前,拦截用户的HttpServletRequest. 根据需要检查HttpServletRequest

Kalman Filter、Extended Kalman Filter以及Unscented Kalman Filter介绍

模型定义 如上图所示,卡尔曼滤波(Kalman Filter)的基本模型和隐马尔可夫模型类似,不同的是隐马尔科夫模型考虑离散的状态空间,而卡尔曼滤波的状态空间以及观测空间都是连续的,并且都属于高斯分布,因此卡尔曼滤波又称为linear Gaussian Markov model,它的数学定义如下:$$\underbrace{s_{t}=C s_{t-1}+G h_{t}+\gamma_{t}}_{\text { latent process }}, \quad \underbrace{x_{t}

Apache Shiro学习笔记(六)Shiro Filter介绍

鲁春利的工作笔记,好记性不如烂笔头 ShiroFilter

Filter与Servlet的区别和联系

Filter的执行顺序与实例 Filter介绍 Filter可认为是Servlet的一种“变种”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链.它与Servlet的区别在于:它不能直接向用户生成响应.完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理. Filter有如下几个用处. 在HttpServletRequest到达Servlet之前,拦截客

Web.xml详解(转)(Filter,context,listener)

web.xml 详细解释!!(链接) web.xml加载过程(步骤) 首先简单说一下,web.xml的加载过程. 当我们去启动一个WEB项目时,容器包括(JBoss.Tomcat等)首先会读取项目web.xml配置文件里的配置,当这一步骤没有出错并且完成之后,项目才能正常地被启动起来. 启动web项目时,先读取web.xml中的节点: <listener></listener> 和 <context-param></context-param> 容器创建一个