一. Filter介绍

Filter可以认为是Servlet的一种加强版,它主要用于对用户请求进行预处理,也可以对HTTPServletResponse进行后处理,是个典型的处理链。它的完整处理流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

Filter有如下几个用处:

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

Filter有如下种类

  • 用户授权的Filter:filter负责检查用户请求,根据请求过滤用户非法请求
  • 日志Filter:详细记录某些特殊的用户请求
  • 负责解码的Filter:包括对非标准编码的请求编码。
  • 能改变XML内容的XSLT Filter等
  • Filter可拦截多个请求或响应;一个请求或响应也可被多个Filter拦截

创建Filter的两个步骤

  • 创建Filter处理类
  • web.xml文件中配置Filter

二. 创建Filter

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

  • void init():用于Filter的初始化
  • void destroy():用于Filter销毁前,完成某些资源的回收
  • void doFilter():实现过滤功能
@WebFilter(filterName = "Filter")
public class Filter implements javax.servlet.Filter {
private FilterConfig config;
public void destroy() {
} public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
ServletContext context = this.config.getServletContext();
long before = System.currentTimeMillis();
System.out.println("开始过滤...");
HttpServletRequest request = (HttpServletRequest)req;
System.out.println("已经截获到用户的请求地址"+request.getServletPath());
chain.doFilter(req,resp);
long after = System.currentTimeMillis();
System.out.println("过滤结束");
System.out.println("请求被定位到"+request.getServletPath()+",所花的时间为"+(after-before)); } public void init(FilterConfig config) throws ServletException {
this.config = config;
} }

如果时检查权限的filter,则根据用户请求的HttpSession,判断用户权限是否足够。如果权限不够,直接调用重定向即可,无需调用chain.doFilter()方法

三. 配置Filter

配置Filter和配置Servlet非常相似,需要配置如下两个部分

  • 配置Filter名
  • 配置FIlter拦截URL模式

配置Filter同样有两种方式

  • 在Filter类中通过注解进行配置
  • 在web.xml中通过配置文件进行配置

@webFilter修饰一个Filter类,用于对Filter进行配置,它支持下表的常用属性

@webFilter支持的常用属性
属性 是否必须 说明
asyncSupported 指定Filter是否支持异步操作模式
dispatcherTypes 指定该Filter对哪种dispatcher模式的请求进行过滤,该属性支持ASYNC,FORWARD,INCLUDE,REQUEST这5个值的任意组合
displayName 指定Filter的显示名
filterName 指定该Filter的名称
initParams 用于该FIlter配置参数
servletNames 该属性可指定多个Servlet的名称,用于指定该Filter仅对这几个Servlet执行过滤
urlPatterns/value 指定该Filter拦截的URL

在web.xml中也可以配置Filter,与配置Servlet类似,如下是为上面程序配置的

<!--定义Filter-->
<filter>
<filter-name>log</filter-name>
<filter-class>java.gdut.filter.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>log</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

实际上Filter和Servlet十分相似,区别只是Filter的doFilter()方法里多了一个FilterChain的参数,通过该参数可以控制是否放行用户请求。在实际项目中,Filter的doFilter() 方法里的代码就是从多Servlet的Service()方法里抽取的通用代码,通过使用Filter可以实现更好的代码复用。例如权限控制,日志记录等。

由于Filter与Servlet非常相似,所以它们的生命周期配置初始化参数非常相似。可以参考Servlet 一章(http://www.cnblogs.com/yumiaoxia/p/9032758.html)

下面将定义一个较为实用的Filter,该Filter对用户请求进行过滤,该Filter通过doFilter()方法来设置request编码的字符集,从而避免每个JSP,servlet                           都需要设置;还会验证用户是否登录,如果没有登录,系统直接跳转到登录页面

@WebFilter(filterName = "AuthorityFilter",urlPatterns = {"/*"},
initParams = {@WebInitParam(name="encoding",value = "GBK")
@WebInitParam(name="loginPage",value = "/login.jsp")
@WebInitParam(name="prologin",value = "/progin.jsp")})
public class AuthorityFilter implements Filter {
private FilterConfig config;
public void destroy() {
this.config = null;
} public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
String encoding = config.getInitParameter("encoding");
String loginPage = config.getInitParameter("loginPage");
String proLogin = config.getInitParameter("prologin");
req.setCharacterEncoding(encoding);
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession(true);
String requestPath = request.getServletPath(); if(session.getAttribute("user") == null
&& !requestPath.endsWith(loginPage)
&& !requestPath.endsWith(proLogin)){
request.setAttribute("tip","您还没登录");
request.getRequestDispatcher("/loginPage").forward(req,resp);
}else{
//放行
chain.doFilter(req,resp);
} chain.doFilter(req, resp);
} public void init(FilterConfig config) throws ServletException {
this.config = config; } }

三. 使用URL Rewririte实现网页的伪静态

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

xxx.jsp?param=value...

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

对于Java Web应用说,要实现伪静态非常简单:可以通过Filter拦截所有发向*.html请求,然后按某种规则将请求forward到实际的*.jsp页面即可。现有的URL Rewrite开源项目为这种思路提供了实现。使用URLRewrite实现网站的伪静态也非常简单。

  1. 登录http://tuckey.org/urlrewrite/站点下载Url Rewrite的最新版本。
  2. 下载URL Rewrite。直接下载它的urlrewritefilter-4.0.3.jar即可,并将该jar包复制到web应用的WEB-INF/lib路径下
  3. 在web.xml文件中配置启用URL Rewrite Filter,在web.xml文件添加如下片段
    <!--配置URL Rewrite的Filter拦截所有的请求-->
    <filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
  4. 在应用的WEB-INF路径下增加urlrewrite.xml文件,该文件定义了伪静态映射规则,这份规则是基于正则表达式的。

下面是本应用所使用的urlrewrite.xml伪静态规则文件。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN">
<!-- Configuration file for UrlRewriteFilter http://www.tuckey.org/urlrewrite/ -->
<urlrewrite>
<rule>
<!--所有配置如下正则表达式的请求-->
<from>/userinf-(/w*).html</from>
<to type="forward">/userinf.jsp?username=$1</to>
</rule>
</urlrewrite>

初学filter的更多相关文章

  1. django 操作数据库--orm(object relation mapping)---models

    思想 django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM). PHP:activerecord Java:Hibernate C#:Ent ...

  2. 初学 Java Web 开发,请远离各种框架,从 Servlet 开发

    Web框架是开发者在使用某种语言编写Web应用服务端时关于架构的最佳实践.很多Web框架是从实际的Web项目抽取出来的,仅和Web的请求和响应处 理有关,形成一个基础,在开发别的应用项目的时候则可以从 ...

  3. 初学javaweb,远离各自框架

    OSCHINA 软件库有一个分类--Web框架,该分类中包含多种编程语言的将近500个项目. Web框架是开发者在使用某种语言编写Web应用服务端时关于架构的最佳实践.很多Web框架是从实际的Web项 ...

  4. JS初学之-选项卡(图片切换类)

    初学选项卡,主要问题卡在了索引值上面,花了较长的时间学习. 索引值其实很好理解,就是为每一个元素用JS的方法添加一个属性,即自定义属性. 在for循环里的函数里用i,会直接弹出这个数组的length, ...

  5. JS初学之-if else图片顺序及循环切换

    初学JS,代码还需多多改进,自学中... <!doctype html><html><head><meta charset="utf-8" ...

  6. ELK初学搭建(elasticsearch)

    ELK初学搭建(elasticsearch) elasticsearch logstash kibana ELK初学搭建 elasticsearch 1.环境准备 centos6.8_64 mini ...

  7. 初学VUE2.0

    初学VUE2.0 (个人笔记,写完后发现好乱....下期使用markdown书写.) 概述 webstorm添加对VUE的支持 http://www.jianshu.com/p/142dae4f8b5 ...

  8. 那些年我们没能bypass的xss filter[from wooyun]

    原文链接:http://zone.wooyun.org/content/6899 小弟初学xss才10天.不过个人很喜欢收集xss payload.在这里把自己平时挖xss时会用到的payloads列 ...

  9. 初学Direct X(5)

    初学Direct X(5) 前面学习了使用表面绘制屏幕,但这种方法与另一种比较起来,有着绘图速度颇慢以及缺乏对任何透明类型的支持,这就是前面的篮框以及炸弹会有黑色背景的原因,这种方法就是纹理.他可以绘 ...

随机推荐

  1. Python对象(下)

    前面一篇文章介绍了一些Python对象的基本概念,这篇接着来看看Python对象相关的一些内容. Python对象的比较 Python对象有三个要素:身份,类型和值,所以我们就分别从这三个角度出发看看 ...

  2. 【Ubuntu】Windows 远程桌面连接ubuntu及xrdp的一些小问题(远程桌面闪退、连接失败、tab补全功能,无菜单栏,error - problem connecting )【转】

    转:https://blog.csdn.net/u014447845/article/details/80291678 1.远程桌面闪退,shell可以用的问题:(1)需要在该用户目录创建一个.xse ...

  3. MySQL实现树状所有子节点查询的方法

    本文实例讲述了MySQL实现树状所有子节点查询的方法.分享给大家供大家参考,具体如下: 在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方 ...

  4. 雷达波Shader

    OSG版本: vert #version varying out vec3 v; void main() { gl_FrontColor = gl_Color; gl_Position = ftran ...

  5. 最简单的GLSL,Shader

    Vertex Shader void main() { gl_FrontColor = gl_Color; gl_Position = ftransform(); } Fragment Shader ...

  6. 第五篇:Hadoop流

    前言 Hadoop流提供了一个API,允许用户使用任何脚本语言编写Map函数或Reduce函数. 本文对此知识点进行介绍. Hadoop流的工作原理 在以前的例子中,Map和Reduce工作都是由类来 ...

  7. 编写java的时候出现“编码GBK的不可映射字符”

    今天在编写文件的时候,使用 javac ***.java 但是java文件里面会出现一些中文的信息,So:会报错 方法: 加参数-encoding UTF-8 例如:javac -encodig UT ...

  8. Charles抓包(iOS的http/https请求)

    Charles抓包(iOS的http/https请求) Charles安装 HTTP抓包 HTTPS抓包 1. Charles安装 官网下载安装Charles:https://www.charlesp ...

  9. PHP behavior 机制简单实现

    <?php class Base{ private $_m = array(); public function attachBehavior($behaviorObj){ $behaviorO ...

  10. ( ( (int(*)(uint, ushort, uint *, uint, int)) (*((uint *)(TCM_BASE + 0x8))) ) (a,b,c,d,e) )

    (  (  (int(*)(uint, ushort, uint *, uint, int))  (*((uint *)(TCM_BASE + 0x8)))  ) (a,b,c,d,e)  ) 首先红 ...