使用过滤器改进应用程序

一、过滤器的目的

过滤器是可以拦截访问资源的请求、资源的响应或者同时拦截两者的应用组件。过滤器可以检测和修改请求和响应,同时也可以拒绝、重定向或转发请求。javax.servlet.Filter接口实现了过滤器技术,使用HttpServletRequest和HttpServletResponse。过滤器可以在部署描述符中以以编程的方式声明,它们可以有初始化参数并且可以访问ServletContext。

日志过滤器

在应用程序开发中,需要记录所有应用程序的请求和每个请求的结果(状态码,长度等其它信息)。通常Web容器提供了请求日志的机制,但如果需要在请求日志中显示出一些特有的信息,可以使用过滤记录请求。

验证过滤器

如果需要确保只有授权用户才可以访问应用程序,通常可以检查每个请求的信息,保证用户已登录,过滤器可以通过将验证和授权操作集中到一个位置的方式使工作变得简单。

压缩和加密过滤器

存在着网络带宽有限而CPU资源充足的情况,通常在数据传输之前对数据进行压缩。过滤器可以在收到请求时,请求保持不变,但在响应返回给用户时,使用过滤器可以压缩相应对象。

错误处理过滤器

对于Web用用程序而言,出现错误,是一个HTTP响应代码500,一般还会伴随着一个普通的HTML页面,写着“Internal Server Error”以及一些诊断信息。对于在本地运行的应用程序对开发者是有用的,但是对于远程的应用程序来说是不必要的。需要通过过滤器给用户显示出更加友好的和通用的错误处理页面,并记录必要的错误信息。

二、创建、声明和映射过滤器

创建过滤器就是实现Filter接口一样,过滤器在初始化的时候将调用init方法,他可以访问过滤器的配置初始化参数和ServletContext。当请求进入到过滤器中,doFilter方法将会被调用,它提供了对ServletRequest、ServletResponse和FilterChain对象的访问。在doFilter中,可以拒绝请求或者调用FilterChain对象的doFilter方法,可以封装请求和响应对象。

过滤器链

尽管只有一个Servlet可以处理请求,但是可以使用许多的过滤拦截请求。在过滤器链中每一个过滤器接受进入的请求并将它传递到下一个过滤链中,直到所有匹配的过滤器都处理完成,最终再将它传入Servlet中。调用FilterChain.doFilter()将触发过滤器链的持续执行。如果当前的过滤器没有调用FilterChain.doFilter(),将把控制权返回值Servlet容器中。

映射到URL模式和Servlet名称

同Servlet一样,过滤器可以被映射到URL模式,这会决定哪个或哪些过滤器将拦截某个请求。任何匹配某个过滤器的URL模式的请求在被匹配的Servlet处理之前将首先进入该过滤器,通过使用URL模式,不仅可以拦截Servlet请求,还可以拦截其它资源。

但是当现在已经有多个URL已经映射到Servlet上,并且希望某些过滤器映射到这些URL上。与映射到URL上相反,可以将这些过滤器映射到一个或多个Servlet名称上。

1.在部署描述符中使用<filter>和<filter-mapping>元素:

    <filter>
<filter-name>filterA</filter-name>
<filter-class>com.wrox.AnyRequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>filterA</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

在声明了过滤器之后,可以将它映射到任意数目的URL或Servlet名称。当然过滤器URL映射还可以包含通配符。

2.使用注解声明和映射过滤器

@WebFilter{
filterName = "myFilter",
urlPatterns = {"/foo","/bar/*"},
serVletNames = {"myServlet"},
dispatcherTypes = {DispatcherType.REQUEST,
DispatcherType.ASYNC}
}

但是不可以对对过滤器链上的过滤器进行排序

三、过滤器排序

过滤器的顺序决定了过滤器在过滤器链中出现的位置,这里将会使用部署描述符来进行配置,因为注解无法进行排序配置。

URL模式映射和Servlet名称映射,匹配请求的过滤器将按照它们出现在部署描述符或者编程式配置中的顺序添加到过滤器链中,但是需要注意URL映射的过滤器优先级比Servlet名称映射到的过滤器高,由URL模式匹配的过滤器总是出现在有Servlet名称匹配的过滤器之前。

    <filter>
<filter-name>filterA</filter-name>
<filter-class>com.wrox.FilterA</filter-class>
</filter> <filter-mapping>
<filter-name>filterA</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <filter>
<filter-name>filterB</filter-name>
<filter-class>com.wrox.FilterB</filter-class>
</filter> <filter-mapping>
<filter-name>filterB</filter-name>
<url-pattern>/servletTwo</url-pattern>
<url-pattern>/servletThree</url-pattern>
</filter-mapping> <filter>
<filter-name>filterC</filter-name>
<filter-class>com.wrox.FilterC</filter-class>
</filter> <filter-mapping>
<filter-name>filterC</filter-name>
<url-pattern>/servletTwo</url-pattern>
</filter-mapping>

这是一个filter的实例:

这是处理中的第一个过滤器,它将记录处理请求的时间,并记录所有访问应用程序的请求信息——IP地址、时间戳、请求方法等信息,finally块中是日志的操作。

public class RequestLogFilter implements Filter
{
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
Instant time = Instant.now();
StopWatch timer = new StopWatch();
try
{
timer.start();
chain.doFilter(request, response);
}
finally
{
timer.stop();
HttpServletRequest in = (HttpServletRequest)request;
HttpServletResponse out = (HttpServletResponse)response;
String length = out.getHeader("Content-Length");
if(length == null || length.length() == 0)
length = "-";
System.out.println(in.getRemoteAddr() + " - - [" + time + "]" +
" \"" + in.getMethod() + " " + in.getRequestURI() + " " +
in.getProtocol() + "\" " + out.getStatus() + " " + length +
" " + timer);
}
} @Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void destroy() { }
}

Java Web高级编程(三)的更多相关文章

  1. Java Web高级编程(二)

    使用会话维持状态 一.会话 为了实现关联同一个用户端的多个请求和这些请求之间数据的共享,需要用到会话,会话用于维持请求和请求之间的状态.从服务器的角度,当用户的Web浏览器打开第一个链接到服务器的套接 ...

  2. Java Web高级编程(一)

    Servlet 一.创建Servlet类 在Java EE中,Servlet用来接收和响应终端用户的请求.Servlet是所有Web应用程序的核心类,是唯一既可以直接处理和响应用户请求,也可以将处理工 ...

  3. Java Web高级编程(四)

    WebSocket 一.WebSocket的产生 用户希望Web页面可以进行交互,用于解决这个问题的技术是JavaScript,现在Web上有许多的可用的JavaScript框架,在使用极少的Java ...

  4. java web高级编程 笔记1

    chapter1:了解web应用程序 web应用程序主要组件: Servlet 过滤器 监听器 JSP chapter2:各类web容器介绍 略 chapter3:Servlet介绍 Servlet是 ...

  5. Java Web高性能开发(三)

    今日要闻: Clarifai:可识别视频中物体 最近几年,得益于深度学习技术的发展,谷歌和Facebook等企业的研究人员在图形识别软件领域取得了重大突破.现在,一家名为Clarifai的创业公司则提 ...

  6. C++面向对象高级编程(三)基础篇

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 概要 一.拷贝构造 二.拷贝赋值 三.重写操作符 四.生命周期 本节主要介绍 Big Three 即析构函数,拷贝构造函数,赋值拷贝函数,前面主 ...

  7. JavaEE-实验三 Java数据库高级编程

    该博客仅专为我的小伙伴提供参考而附加,没空加上代码具体解析,望各位谅解 1.在MySQL中运行以下脚本 CREATE DATABASE mydatabase; USE mydatabase; CREA ...

  8. java web学习总结(三十一) -------------------EL表达式

    一.EL表达式简介 EL 全名为Expression Language.EL主要作用: 1.获取数据 EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象.获取数 ...

  9. java web学习总结(三十) -------------------JSTL表达式

    一.JSTL标签库介绍 JSTL标签库的使用是为弥补html标签的不足,规范自定义标签的使用而诞生的.使用JSLT标签的目的就是不希望在jsp页面中出现java逻辑代码 二.JSTL标签库的分类 核心 ...

随机推荐

  1. python 小白(无编程基础,无计算机基础)的开发之路,辅助知识6 python字符串/元组/列表/字典互转

    神奇的相互转换,小白同学可以看看,很有帮助 #1.字典dict = {'name': 'Zara', 'age': 7, 'class': 'First'} #字典转为字符串,返回:<type ...

  2. iOS 视频直播弹幕的实现

    弹幕,并不是一个多么复杂的功能. 1.弹幕的实现性分析 首先,从视觉上明确当前弹幕所具有的功能 从屏幕右侧滑入左侧,直至完全消失 不管是长的弹幕,还是短的弹幕,速度一致(可能有的需求是依据弹幕长度,调 ...

  3. Web 动画帧率(FPS)计算

    我们知道,动画其实是由一帧一帧的图像构成的.有 Web 动画那么就会存在该动画在播放运行时的帧率.而帧率在不同设备不同情况下又是不一样的. 有的时候,一些复杂或者重要动画,我们需要实时监控它们的帧率, ...

  4. HTTP/2之服务器推送(Server Push)最佳实践

    商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处.   WeTest 导读 HTTP/1.X出色地满足互联网的普遍访问需求,但随着互联网的不断发展,其性能越来越成为瓶颈.IETF在2015 ...

  5. Scala入门系列(十):函数式编程之集合操作

    1. Scala的集合体系结构 Scala中的集合体系主要包括(结构跟Java相似): Iterable(所有集合trait的根trait) Seq(Range.ArrayBuffer.List等) ...

  6. google开源服务器apprtc的搭建

    本文参考网帖: http://www.jianshu.com/p/c55ecf5a3fcf http://io.diveinedu.com/2015/02/05/%E7%AC%AC%E5%85%AD% ...

  7. idea快速搭建springboot项目

    Spring Boot是由Pivotal团队提供的全新框架,设计目的是用来简化新Spring应用的初始搭建以及开发过程.它主要推崇的是'消灭配置',实现零配置. 那么,如何在idea中创建一个spri ...

  8. attr设置checked,disabled等属性失效的问题,jquery的attr和prop的区别

    最近做项目遇到一个问题,radio设置了默认checked值,attr("checked",true)切换checked值失效 最后发现是jquery1.6版本之后,attr和pr ...

  9. java 集合学习笔记

    1.Collection(单列结合) List(有序,数据可重复) ArrayList:底层数据结构是数组,查询快,增删慢,线程不安全,效率高. Vector:底层数据结构是数组,查询快,增删慢,线程 ...

  10. linhaifeng

    http://www.cnblogs.com/linhaifeng/p/7278389.html http://blog.51cto.com/egon09