JSPServlet5(三)

编程入门 行业动态 更新时间:2024-10-26 04:30:05

JSPServlet5(三)

JSPServlet5(三)

过滤器是什么?

抽象点来说, 就是介于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;@Overridepublic void init(FilterConfig config) throws ServletException{this.config = config;}@Override
throws 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的日志里.@Overridepublic 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实体字符&lt这样.

现在的问题是, 我们用来取得用户留言的getParameter()函数中并没有过滤HTML字符这样的设置, 我们也无法直接重定义HttpServletRequest接口的这些方法. 于是, Servlet给出了一个类: HttpServletRequestWrapper.

HttpServletRequestWrapper类实现了HttpServletRequest接口, 只要继承了HttpServletRequestWrapper类, 就可以重定义HttpServletRequest接口里面的方法, 当然也包括getParameter().

如下代码通过继承HttpServletRequestWrapper类实现了一个替换字符的请求封装器:

public class EscapeWrapper extends HttpServletRequestWrapper{
//EscapeWrapper类继承了HttpServletRequestWrapperpubic EscapeWrapper(HttpServletRequest request){super(request); /*必须调用父类的构造器, 确保请求传入的是此构造器*///定义了一个接收请求的构造器,并用super()调用父类HttpServletRequestWrapper接收请求的构造器, //这也说明真正的请求, 将不再通过HttpServletRequestWrapper的构造器传入, //而是通过EscapeWrapper类的构造器(即此构造器)传入}@Overridepublic 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对象的方法进行重定义扩充并封装.

关于响应封装器的例子(比如对响应内容的压缩处理)在这里就不再给出, 处理方法与请求封装器相似, 也是封装器搭配过滤器使用.

更多推荐

JSPServlet5(三)

本文发布于:2024-02-12 19:07:30,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1689018.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!