JSP filter过滤器的功能简要介绍

filter功能:
它使用户可以改变一个 request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开 servlet时处理response.换种说法,filter其实是一个”servlet chaining”(servlet 链).
一个filter 包括:
- 在servlet被调用之前截获;
- 在servlet被调用之前检查servlet request;
- 根据需要修改request头和request数据;
- 根据需要修改response头和response数据;
- 在servlet被调用之后截获.
通俗点说法filter相当于加油站,request是条路,response是条路,目的地是servlet,这个加油站设在什么地方对什么数据操作可以由你来控制。
一些需要过滤器的情况:
(1)认证Filter
(2)日志和审核Filter
(3)图片转换Filter
(4)数据压缩Filter
(5)密码Filter
(6)令牌Filter
(7)触发资源访问事件的Filter
(8)XSLT Filter
(9)媒体类型链Filter
1.批量设置请求编码

为了避免提交数据的中文乱码问题,需要在每次使用请求之前设置request.setCharacterEncoding(“gb2312”)编码格式,麻烦。Filter可以批量拦截修改servlet的请求和响应。

我们编写一个EncodingFilter.Java,来批量设置请求编码。

public class EncodingFilter implements Filter {

    public void init(FilterConfig config) throws ServletException {}

    public void destroy() {}

    public void doFilter(ServletRequest request,
            ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {
        request.setCharacterEncoding("gb2312");
        chain.doFilter(request, response);
    }

}

在此EncodingFilter实现了Filter接口,Filter接口中定义的三个方法都要在EncodingFilter中实现,其中doFilter()的代码实现主要的功能:

  • 为请求设置gb2312编码并执行chain.doFilter()继续下面的操作。
  • 转换成对应HttpServletRequest和HttpServletResponse才能进行下面的session操作和页面重定向。

与servlet相似,为了让filter发挥作用还需要在web.xml进行配置。

<filter>
     <filter-name>EncodingFilter</filter-name>
     <filter-class>sam.EncodingFilter</filter-class>
 </filter>

 <filter-mapping>
     <filter-name>EncodingFilter</filter-name>
     <url-pattern>/*</url-pattern>
 </filter-mapping>

filter标签部分定义使用的过滤器,filter-mapping标签告诉服务器把哪些请求交给过滤器处理。这里的/表示所有请求,/表示根路径,(星号)代表所有请求,加在一起就变成了根路径下的所有请求。

这样,所有的请求都会先被EncodingFilter拦截,并在请求里设置上指定的gb2312编码。
2.用filter控制用户访问权限
出于信息安全和其他一些原因的考虑,项目中的一些页面要求用户满足了一定条件之后才能访问(让用户输入帐号和密码),如果输入的信息正确就在session里做一个成功的标记,这里的成功标志就是session中的username有值;其后在请求保密信息的时候判断session中是否有已经登录成功的标记,存在则可以访问,不存在则禁止访问。

假设我们要保护的页面是admin/index.jsp。编写SecurityFilter.java,控制用户访问权限

public class SecurityFilter implements Filter {
public void doFilter(ServletRequest request,
        ServletResponse response,
        FilterChain chain)
        throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;
    HttpSession session = req.getSession();
    if (session.getAttribute("username") != null) {
        chain.doFilter(request, response);
    } else {
        res.sendRedirect("../failure.jsp");
    }
}

web.xml进行如下配置

<filter>
     <filter-name>SecurityFilter</filter-name>
     <filter-class>sam.SecurityFilter</filter-class>
 </filter>
 <filter-mapping>
     <filter-name>SecurityFilter</filter-name>
     <url-pattern>/admin/*</url-pattern>
 </filter-mapping>

定义SecurityFilter过滤器,让它过滤匹配/admin/*的所有请求,/admin/路径下的所有请求都会接受SecurityFilter的检查
因为Filter本来设计成为多种协议服务,http协议仅仅是其中一种,将ServletRequest和ServletResponse转换成HttpServletRequest和HttpServletResponse才能进行下面的session操作和页面重定向。

得到了http请求之后,可以获得请求对应的session,判断session中的username变量是否为null,如果不为null,说明用户已经登录,就可以调用doFilter继续请求访问的资源。如果为null,说明用户还没有登录,禁止用户访问,并使用页面重定向跳转到failure.jsp页面显示提示信息。

因为/failure.jsp的位置在/admin/目录的上一级,所以加上两个点才能正确跳转到failure.jsp,两个点(..)代表当前路径的上一级路径。

3.日志和审核Filter

public class LoggingFilter implements Filter {
  private FilterConfig filterConfig = null;

  public void init(FilterConfig config) throws ServletException {
   this.filterConfig = config;
 }


 //下面是向服务器控制台输出log,这里做的是演示,更多的是使用log4j
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
   String address = request.getRemoteAddr();
   filterConfig.getServletContext().log("User IP: " + address);
   chain.doFilter(request, response);
 }

 public void destroy() {
 }
}

web.xml配置

 <filter>
   <filter-name>LoggingFilter</filter-name>
   <filter-class>samjava.filter.LoggingFilter</filter-class>
  </filter>
  <filter-mapping>
   <filter-name>LoggingFilter</filter-name>
   <url-pattern>/*</url-pattern>
  </filter-mapping>

4.filter所谓的特性
请求映射filter-mapping和servlet-mapping都是将对应的filter或servlet映射到某个url-pattern上,当客户发起某一请求时,服务器先将此请求与web.xml中定义的所有url-pattern进行匹配,然后执行匹配通过的filter和servlet。
可以使用三种方式定义url-pattern。

直接映射一个请求。

<servlet-mapping>
    <servlet-name>TestServlet</servlet-name>
    <url-pattern>/TestServlet</url-pattern>
</servlet-mapping>

映射一个路径下的所有请求。

<servlet-mapping>
    <servlet-name>EncodingFilter</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

需要注意的是,这种写法必须以/开头,写成与绝对路径的形式,即便是映射所有请求也要写成/,不能简化成
映射结尾相同的一类请求。

<servlet-mapping>
    <servlet-name>ControllerServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

需要注意的是,这种请求映射就不能指定某一路径了,它必须是以星号()开始字母结尾,不能写成/.do的形式。

5.过滤链
我们使用了两个过滤器,EncodingFilter负责设置编码,SecurityFilter负责控制权限,那这两个过滤器是怎么起作用的呢?

所有的奥秘就在Filter中的FilterChain中。服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的doFilter()方法。执行的顺序,执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的chain.doFilter()之后的代码,最后返回响应。

代码执行顺序是:

(1)执行EncodingFilter.doFilter()中chain.doFilter()之前的部分:request.setCharacterEncoding(“gb2312”);

(2)执行SecurityFilter.doFilter()中chain.doFilter()之前的部分:判断用户是否已登录

(3)如果用户已登录,则访问请求的资源:/admin/index.jsp

(4)如果用户未登录,则页面重定向到:/failure.jsp

(5)执行SecurityFilter.doFilter()中chain.doFilter()之后的部分;

(6)执行EncodingFilter.doFilter()中chain.doFilter()之后的部分;

说的简单点就是filter将按照在web.xml文件中的声明顺序调用。

过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。
要特别注意过滤链的执行顺序问题,像EncodingFilter就一定要放在所有Filter之前(在web.xml文件中),这样才能确保在使用请求中的数据前设置正确的编码。
6.filter的详细配置
我们已经了解了filter的基本用法,还有一些细节配置在特殊情况下起作用。

在servlet-2.3中,Filter会过滤一切请求,包括服务器内部使用forward转发请求和<%@ include file=”/index.jsp”%>的情况。

到了servlet-2.4中Filter默认下只拦截外部提交的请求,forward和include这些内部转发都不会被过滤,但是有时候我们需要forward的时候也用到Filter,这样就需要如下配置。

<filter>
    <filter-name>TestFilter</filtername>
    <filter-class>sam.TestFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>TestFilter</filtername>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>EXCEPTION</dispatcher>
</filter-mapping>

这样TestFilter就会过滤所有状态下的请求。如果我们没有进行设置,默认使用的就是REQUEST。而EXCEPTION是在isErrorPage=”true”的情况下出现的,这个用处不多,看一下即可。

这里FORWARD是解决request.getDispatcher(“index.jsp”).forward(request, response);无法触发Filter的关键,配置上这个以后再进行forward的时候就可以触发过滤器了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值