学科分类
目录
Java Web

Filter实现统一全站编码

在Web开发中,经常会遇到中文乱码问题,按照前面所学的知识,解决乱码的通常做法都是在Servlet程序中设置编码方式,但是,如果多个Servlet程序都需要设置编码方式,势必会书写大量重复的代码。

为了解决上面的问题,我们可以在Filter中对获取到的请求和响应消息进行编码,从而统一全站的编码方式。接下来,分步骤讲解如何使用Filter实现统一全站的编码,具体如下:

(1)编写form.jsp页面

在chapter04工程的WebContent根目录中,编写一个form.jsp页面,用于提交用户登录的表单信息,如例1所示。

例1 form.jsp

 1  <%@ page language="java" contentType="text/html; charset=utf-8"

 2  pageEncoding="utf-8" import="java.util.*"

 3  %>

 4  <html>

 5  <head></head>

 6  <center>

 7    <h3>用户登录</h3>

 8  </center>

 9  <body style="text-align: center;">

 10   <a href="<%=request.getContextPath()%>/CharacterServlet?name=

 11         传智播客&password=123456">点击超链接登录</a>

 12   <form action="<%=request.getContextPath()%>/CharacterServlet"

 13     method="post">

 14     <table border="1" width="600px" cellpadding="0" cellspacing="0"

 15       align="center">

 16       <tr>

 17         <td height="30" align="center">用户名:</td>

 18         <td>&nbsp;<input type="text" name="name" /></td>

 19       </tr>

 20       <tr>

 21         <td height="30" align="center">&nbsp; 码:</td>

 22         <td>&nbsp;<input type="password" name="password" /></td>

 23       </tr>

 24       <tr>

 25         <td height="30" colspan="2" align="center">

 26          <input type="submit"value="登录" />&nbsp;&nbsp;&nbsp;&nbsp; 

 27          <input type="reset"value="重置" /></td>

 28       </tr>

 29     </table>

 30   </form>

 31 </body>

 32 <html>

(2)编写CharacterServlet.java程序

在chapter04工程的cn.itcast.chapter04.servlet包中,编写一个CharacterServlet.java程序,该程序用于获取用户输入的请求参数,并将参数输出到控制台,如例2所示。

例2 CharacterServlet.java

 1  package cn.itcast.chapter04.servlet;

 2  import java.io.IOException;

 3  import javax.servlet.*;

 4  import javax.servlet.http.*;

 5  public class CharacterServlet extends HttpServlet {

 6    public void doGet(HttpServletRequest request, HttpServletResponse

 7        response)throws ServletException, IOException {

 8      System.out.println(request.getParameter("name"));

 9      System.out.println(request.getParameter("password"));

 10   }

 11   public void doPost(HttpServletRequest request, HttpServletResponse 

 12       response)throws ServletException, IOException {

 13     doGet(request, response);

 14   }

 15 }

(3)编写CharacterFilter.java过滤器

CharacterFilter类用于拦截用户的请求访问,实现统一全站编码的功能。但是,由于请求方式post和get解决乱码方式的不同,post方式的请求参数存放在消息体中,可以通过setCharacterEncoding()方法进行设置,而get方式的请求参数存放在消息头中,必须得通过获取URI参数才能进行设置。如果每次单独对get请求方式进行处理,势必会很麻烦,为此,可以通过HttpServletRequestWrapper类对HttpServletRequest进行包装,通过重写getParameter()的方式来设置get方式提交参数的编码,CharacterFilter类的实现代码如例3所示。

例3 CharacterFilter.java

 1  package cn.itcast.chapter04.filter;

 2  import java.io.*;

 3  import javax.servlet.*;

 4  import javax.servlet.http.*;

 5  public class CharacterFilter implements Filter {

 6    public void init(FilterConfig filterConfig) throws ServletException {

 7    }

 8    public void doFilter(ServletRequest req, ServletResponse resp,

 9        FilterChain chain) throws IOException, ServletException {

 10     HttpServletRequest request = (HttpServletRequest) req;

 11     HttpServletResponse response = (HttpServletResponse) resp;

 12     // 拦截所有的请求 解决全站中文乱码

 13     // 指定 request 和 response 的编码

 14     request.setCharacterEncoding("utf-8"); // 只对消息体有效

 15     response.setContentType("text/html;charset=utf-8");

 16     // 在放行时 应该给目标资源一个request对象 让目标资源调用 

 17      // getParameter时调到我们写的getParameter

 18     // 对request进行包装

 19     CharacterRequest characterRequest = new CharacterRequest(request);

 20     chain.doFilter(characterRequest, response);

 21   }

 22   public void destroy() {

 23   }

 24 }

 25 // 针对 request 对象进行包装

 26 // 继承 默认包装类HttpServletRequestWrapper

 27 class CharacterRequest extends HttpServletRequestWrapper {

 28   public CharacterRequest(HttpServletRequest request) {

 29     super(request);

 30   }

 31   // 子类继承父类一定会覆写一些方法,此处用于重写getParamter()方法

 32   public String getParameter(String name) {

 33     // 调用 被包装对象的getParameter()方法 获得请求参数

 34     String value = super.getParameter(name);

 35     if (value == null)

 36       return null;

 37     // 判断请求方式

 38     String method = super.getMethod();

 39     if ("get".equalsIgnoreCase(method)) {

 40       try {

 41          value = new String(value.getBytes("iso-8859-1"), "utf-8");

 42       } catch (UnsupportedEncodingException e) {

 43         throw new RuntimeException(e);

 44       }

 45     }

 46     // 解决乱码后返回结果

 47     return value;

 48   }

 49 }

在web.xml文件中,配置CharacterFilter过滤器,由于要拦截用户访问资源的所有请求,因此将<filter-mapping>元素拦截的路径设置为“/*”,具体代码如下:

<filter>

  <filter-name>CharacterFilter</filter-name>

  <filter-class>

     cn.itcast.chapter04.filter.CharacterFilter

  </filter-class>

</filter>

<filter-mapping>

  <filter-name>CharacterFilter</filter-name>

  <url-pattern>/*</url-pattern>

</filter-mapping>

(4)访问form.jsp页面

重新启动Web服务器,打开IE浏览器,在地址栏中输入http://localhost:8080/chapter04/form.jsp,此时,浏览器窗口中会显示一个用户登录的表单,在这个表单中输入用户名传智播客、密码123456,如图1所示。

图1 运行结果

点击图1界面中的登录按钮来提交表单,此时,控制台窗口显示的结果如图2所示。

图2 控制台窗口

从图2可以看出,在form.jsp表单中输入的用户名和密码都正确的显示在控制台窗口,而且中文的用户名也没有出现乱码问题。需要注意的是,form.jsp表单的提交方式是post,因此可以说明使用post提交表单可以解决中文乱码问题,表单的提交方式还有一种是get,接下来就验证get方式提交表单的乱码问题能否解决。

(5)使用超连接访问form.jsp页面

点击图1界面中的“点击超链接登录”提交表单,这种提交方式相当于get方式提交表单,此时,控制台窗口显示的结果如图3所示。

图3 控制台窗口

从图3可以看出,get方式提交表单与post方式提交表单的效果是一样的,同样不会出现乱码问题。因此,可以说明使用Filter过滤器可以方便的完成统一全站编码的功能。

需要注意的是,针对response对象,Servlet API也提供了对应的包装类HttpServletResponseWrapper,它的用法与HttpServletRequestWrapper类似,在此不再进行举例介绍了。

点击此处
隐藏目录