中文乱码解决方案 之 过滤器的应用

一提到中文乱码,肯定又是愁死一大批的开发人士,不论学生做的简单的测试,还是公司做的项目,乱码都是如影随形。下面就讲解一下过滤器是怎么处理乱码的。

 乱码的处理方式有很多,在我们讲解JSP内置对象的时候,request对象中提到过记住那个处理乱码的操作,忘记的同学可以去下面的连接回顾一下

http://zhaoyuqiang.blog.51cto.com/6328846/1132142

过滤器是Servlet的一种

 前面的文章讲解的是简单的Servlet,其实Servlet的一共分为三种:

1. 简单Servlet(之前讲解的都是) 是作为一种程序所必须的开发结构保存下来的,它属于程序的一部分;

2.过滤Servlet 也就是我们所说的过滤器了,它是以组件的形式在程序中运行的

3. 监听Servlet 和过滤Servlet是一样的,我们将在以后学习

什么是过滤器

在说过滤器之前先要明白一个问题,过滤器是以组件的形式存在的,它是一个Servlet,但是它使用的是接口而不是简单Servlet中 HttpServlet类了。这个接口就是Filter.

javax.servlet包中有个Filter接口,那么根据此接口的特点就可以发现,此接口的主要功能是完成公共协议操作的。

  过滤器是以一种组件的形式绑定到WEB应用程序中的,与其他的WEB应用程序组件不同的是,过滤器是采用了“链”的方式进行处理的。如下图所示;

过滤器的实现











以上是三个方法,也间接的反应出了他的生命周期

一个简单的过滤器

package Fileter;
import java.io.*;
import javax.servlet.*;
public class SimpleFilter implements Filter{
    public void init(FilterConfig config)throws ServletException{
        String initParam=config.getInitParameter("ref");//取得初始化参数
        System.out.println("**过滤器初始化,初始化参数="+initParam);
    }
    public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
                throws IOException,ServletException{//执行过滤
     chain.doFilter(request, response);//将请求继续传递
        }
    public void destroy(){
        System.out.println ("**过滤器销毁");
    }
}

过滤器完成之后肯定也要开始进行配置操作,需要注意的是,如果一个web.xml文件中既有普通的配置又有过滤器的配置的话,应该先写过滤器的配置

<filter>
  <filter-name>simple</filter-name>
  <filter-class>Fileter.SimpleFilter</filter-class>
  <init-param>
     <param-name>ref</param-name>
     <param-value>hello world</param-value>
  </init-param>
</filter>
<filter-mapping>
   <filter-name>simple</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

注意:

1. 在此处配置的url-pattern表示的是一个过滤路径,现在既然是“/”则表示的是对一个目录中的全部内容进行过滤

     2.FilterChain表示把请求向下传递,如果后面还有过滤器,则继续过滤,如果没有则直接到目的地

    3.过滤器不需要任何的配置就可以在服务器启动的时候自动的完成初始化操作。如上图中红色的区域是在服务器启动的时候就执行了。

在这里举一个非常典型的形象例子来说明过滤器的执行过程吧!

AB是两个人,CD是两个强盗 ,A到底B需要经过一座山,当A走到山顶的时候,强盗自动出来抢劫A,注意是自动的。这个时候A可能被杀,可能被抢劫后放了A,于是A继续走,如果后面还有强盗D,则A继续被D抢劫了一遍,然后才到达目的地B

映射到程序中就是,A请求想要到底B请求,需要经过过滤器CD,在A传递到B的过程中,过滤器C首先自动出来对A进行过滤操作, FilterChain表示的是把请求向下传递,也就是强盗C抢劫A后将A向下放行,如果后面还有过滤器D,则继续进行过滤。

问题:这个时候大家会不会想,当A到底B后,A不能一直都住在B的家里啊,那么AB家中返回又会怎么样呢?映射到我们的程序中就是AB是一个请求的过程,之后B要响应A的请求。

实际上A回去的时候还得被抢劫一次,也就是说,过滤器实际上是执行4次的,来的时候几次,回去的时候也是几次。

  与Servlet一样,过滤器本身也可以对多个路径执行过滤,例如;

<filter>
  <filter-name>simple</filter-name>
  <filter-class>Fileter.SimpleFilter</filter-class>
  <init-param>
     <param-name>ref</param-name>
     <param-value>hello world</param-value>
  </init-param>
</filter>
<filter-mapping>
   <filter-name>simple</filter-name>
   <url-pattern>/jsp/login/*</url-pattern>
</filter-mapping>

这个表示对jsp文件夹下的login文件进行过滤,只要符合要求,是可以对任意指定的文件进行过滤的。

 明白了过滤器的是实现原理了,我相信大家都应该猜到乱码是怎么用过滤器来处理的了吧。  

从实际上来讲过滤器在开发中的使用最频繁的两种操作是:编码过滤和登录验证。

中文乱码处理(过滤器)

 对于编码肯定是所有页面都要使用的,而且只要是页面都要写编码:requestSetCharacterEncoding()方法进行编码的设置

package Fileter;
import java.io.*;
import javax.servlet.*;
public class Encoding implements Filter{
    private String charSet; //设置字符编码
    public void init(FilterConfig config)throws ServletException{
        this.charSet=config.getInitParameter("charset");//取得初始化参数
    }
    public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
                throws IOException,ServletException{//执行过滤
     request.setCharacterEncoding(this.charSet);//设置统一编码
    }
    public void destroy(){
    }
}

<filter>
  <filter-name>encoding</filter-name>
  <filter-class>Fileter.encoding</filter-class>
  <init-param>
     <param-name>charset</param-name>
     <param-value>utf-8</param-value>
  </init-param>
</filter>
<filter-mapping>
   <filter-name>encoding</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

在本程序中,在初始化操作时候,通过FilterConfig中的getInitParameter()取得了一个配置得的初始化参数,此参数的内容是一个指定的过滤编码,然后在doFilter()方法中执行request.setCharacterEncoding()操作

之后,只要是页面的提交,就会经过这个过滤器,而这个过滤器的功能就是统一字符编码。这样就避免了在每个页面中都写requestSetCharacterEncoding()这个方法了。

登录验证(提一下)

    登录验证也是一个很重要的内容,因为在很多情况下都需要通过session完成登录验证的操作,但是如果每个页面都编写重复的session属性的判断,那么就变得相当的复杂,而且维护也不方便,所以可以对一些需要限制的地方采用登录的验证操作。

    这里需要注意的是,session本身是属于HTTP协议的范畴,但是doFilter()方法中定义的是ServletRequest类型的对象,那么要想取得session,则必须进行向下转型,将ServletRequest变为HttpServletRequest接口对象,才能通过getSession()方法取得session 对象。

package Fileter;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class SimpleFilter implements Filter{
    public void init(FilterConfig config)throws ServletException{
    }
    public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
                throws IOException,ServletException{//执行过滤
       HttpServletRequest req=(HttpServletRequest)request;
       HttpSession ses=req.getSession();
       if(ses.getAttribute("userid")!=null){
           chain.doFilter(request, response);
       }else{
           request.getRequestDispatcher("login.jsp").forward(request, response);
       }
    }
    public void destroy(){
    }
}

<filter>
  <filter-name>session</filter-name>
  <filter-class>Fileter.session</filter-class>
</filter>
<filter-mapping>
   <filter-name>session</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

你可能感兴趣的:(web开发,filter,过滤器)