JSP&Servlet5(三) --- 过滤器 封装器
来源:互联网 发布:淘宝微信转换工具 编辑:程序博客网 时间:2024/06/18 16:58
过滤器是什么?
抽象点来说, 就是介于Servlet之间的独立的元件, 可以随时加入到应用程序之中, 也可以随时移除.
具体点来说, 比如针对某些特定的页面, 只有特定的用户才能浏览, 这个时候我们就希望能把所有登录的用户进行过滤, 只给一些用户访问的权限, 这就可以在Servlet之前实现一个用户验证的过滤器.
过滤器通常搭配封装器来使用. 关于封装器可分为请求封装器和响应封装器, 具体概念及用法将在下面介绍.
1. 实现与设置过滤器
在Servlet中要实现过滤器, 必须要实现Filter接口, 并使用@WebFilter标注或在web.xml中定义过滤器, 让容器知道应该加载哪些过滤器类.
Filter接口有三个需要实现的方法:init(), doFilter(), destroy(), Filter接口的代码如下:
public interface Filter{ public void init(FilterConfig filterConfig) throws ServletException; //FilterConfig类似与Servlet接口init方法参数上的ServletConfig(针对每个Servlet,容器都会为其生成一个ServletConfig对象), //FilterConfig是实现Filter接口的类上使用标注或web.xml中过滤器设置信息的代表对象. //如果在定义过滤器时设置了初始参数, 则可以通过FilterConfig的getInitparameter()方法来取得初始参数. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; public void destroy();}
重点来看一下doFilter()方法:
doFilter()方法类似与Servlet接口的service()方法. 当请求来到容器时, 容器发现在Servlet的service()方法之前可以应用过滤器时, 就会调用过滤器的doFilter()方法. 可以在doFilter()方法中进行service()的前置处理, 而后决定是否要调第三个参数chain的doFilter()方法, 即决定是否要运行下一个过滤器.
如果调用了chain的doFilter()方法, 就会运行下一个过滤器, 如果没有过滤器了, 就会运行Servlet的service()方法. 陆续调用完过滤器的Filter()至service()后, 流程会以堆栈顺序返回.
所以在FilterChain的doFilter()运行完毕后, 就可以针对service()做后续处理, 如下:
//service()前置处理chain.doFilter();//service()后置处理
实现一个过滤器
例: 以下实现一个简单评测性能的过滤器, 用于记录请求到响应之间的时间差, 了解Servlet处理请求到响应所需花费的事件.
实现Filter接口代码如下:
@WebFilter(fileName = "performance", urlPatterns = {"/*"})public class PerformanceFilter implements Filter{ private FilterConfig config; @Override public void init(FilterConfig config) throws ServletException{ this.config = config; } @Overridethrows IOException, ServletException{ long begain = System.currentTimeMillis(); chain.doFilter(request, response); config.getServletContext().log("Request process in " + (System.currentTimeMillis() - begain) + " milliseconds"); } //ServletContext.log("xxxx"): 将xxxx写进tomcat的日志里. @Override public void destroy(){}}
还可以在@WebFilter()标注中设置dispatcherType来设置触发过滤器的时机, 代码如下:
@WebFilter( filterName = "some", urlPatterns = {"/some"}, dispatcherType = { DispatcherType.REQUEST, /*不设置任何dispatcherType, 默认是REQUEST*/ DispatcherType.FORWORD, /*通过RequestDispatcher的forword()而来的请求可以套用过滤器*/ DispatcherType.INCLUDE, /*通过RequestDispatcher的include()而来的请求可以套用过滤器*/ DispatcherType.ERROR, /*由容器处理例外而转发过来的请求可以触发过滤器*/ DispatcherType.ASYNC, /*异步处理的请求可以触发过滤器*/ })
如果有某个url或者Servlet会应用多个过滤器, 则根据在web.xml中出现的先后顺序来决定过滤器的运行顺序.
2. 请求封装器
请求封装器是什么? 就是对request的已有方法进行扩充并封装.
实现一个封装器
例: 实现字符替换过滤器: 假设有一个留言板程序, 有些用户会在留言中输入一些HTML标签, 基于安全性考虑, 我们不希望用户输入的标签被浏览器当作网页的一部分, 所以要使用过滤器将<这样的符号替换为HTML实体字符<这样.
现在的问题是, 我们用来取得用户留言的getParameter()函数中并没有过滤HTML字符这样的设置, 我们也无法直接重定义HttpServletRequest接口的这些方法. 于是, Servlet给出了一个类: HttpServletRequestWrapper.
HttpServletRequestWrapper类实现了HttpServletRequest接口, 只要继承了HttpServletRequestWrapper类, 就可以重定义HttpServletRequest接口里面的方法, 当然也包括getParameter().
如下代码通过继承HttpServletRequestWrapper类实现了一个替换字符的请求封装器:
public class EscapeWrapper extends HttpServletRequestWrapper{//EscapeWrapper类继承了HttpServletRequestWrapper pubic EscapeWrapper(HttpServletRequest request){ super(request); /*必须调用父类的构造器, 确保请求传入的是此构造器*/ //定义了一个接收请求的构造器,并用super()调用父类HttpServletRequestWrapper接收请求的构造器, //这也说明真正的请求, 将不再通过HttpServletRequestWrapper的构造器传入, //而是通过EscapeWrapper类的构造器(即此构造器)传入 } @Override public String getParameter(String name){ //重定义getParameter()方法 String value = getRequest().getParameter(name); return StringEscapeUtils.escapeHtml(value); //将取得的请求参数值进行字符替换 //StringEscapeUtils是Apache Commons Lang程序库中的一个字符串操作类 }}
使用上面的封装器搭配下面的过滤器来进行字符过滤的功能, 过滤器的代码如下:
@WebFilter("/*")public class EscapeFilter implements Filter{ public void init(FilterConfig fconfig) throws ServletException{} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{ HttpServletRequest requestWrapper = new EscapeWrapper((HttpServletRequest) request); //将原请求对象包裹至前面写好的封装器中 chain.doFilter(requestWrapper, response); //将封装器中的request传入doFilter()中, 执行下一个过滤器或Servlet的service()方法 }}
3. 响应封装器
前面说完了请求封装器, 现在来说说响应封装器. 类似于请求封装器, 响应封装器就是对response的已有方法进行扩充并封装.
与HttpServletRequest对象相似, 封装器通过继承HttpServletResponseWrapper类(父类:ServletResponseWrapper类)来对HttpServletResponse对象的方法进行重定义扩充并封装.
关于响应封装器的例子(比如对响应内容的压缩处理)在这里就不再给出, 处理方法与请求封装器相似, 也是封装器搭配过滤器使用.
- JSP&Servlet5(三) --- 过滤器 封装器
- servlet5-过滤器
- servlet5
- servlet5
- JSP&Servlet5(一) --- Servlet进阶API
- JSP&Servlet5(二) --- 应用程序事件 监听器
- Servlet过滤器与封装器
- JSP过滤器
- jsp过滤器
- JSP过滤器
- JSP过滤器
- jsp---->过滤器
- jsp过滤器
- jsp 过滤器
- jsp过滤器
- JSP 过滤器
- JSP过滤器
- jsp过滤器
- BZOJ 2140 稳定婚姻 (Tarjan)
- POJ3694(tarjan缩点+并查集+LCA)
- HDU 3974 Assign the task(dfs序 + 线段树区间赋值,单点查询)
- so file红色 No such file or directory
- Java基础应用之循环控制(使用while与自增运算符循环遍历数组)
- JSP&Servlet5(三) --- 过滤器 封装器
- 快速排序 && 归并排序
- 安卓常用控件3之图片框(ImageView)
- 红黑树的简析
- The Luckiest number POJ
- Linux进程间通信——使用匿名管道
- Creating test database for alias 'postgres'... Got an error creating the test database: permission
- read/write/open
- Java基础应用之循环控制(使用for循环输出杨辉三角)