Servlet Filter实现全站统一编码,解决中文乱码问题

在开发 Web 项目时,解决中文乱码问题是不可避免的。在前面所学的知识中,解决乱码的通常做法是在 Servlet 程序中设置编码方式,但是,当多个 Servlet 程序都需要设置编码方式时,就会书写大量重复的代码。

为了解决这一问题,我们可以在 Filter 中对获取到的请求和响应消息进行编码处理,这样就可以实现全站编码方式的统一。本节将分步骤演示如何使用 Filter 实现全站编码的统一。

1)编写 form.jsp 页面

在 filterDemo01 项目的 WebContent 目录中编写一个 form.jsp 页面,该页面用于提交用户登录的表单信息,如下所示。

  1. <%@ page language="java" contentType="text/html; charset=utf-8"
  2. pageEncoding="utf-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  4. "http://www.w3.org/TR/html4/loose.dtd">
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  8. <title>用户登录</title>
  9. </head>
  10. <center>
  11. <h3>用户登录</h3>
  12. </center>
  13. <body style="text-align:center;">
  14. <a href="<%=request.getContextPath()%>/CharacterServlet?name=张三&password=1234">
  15. 单击超链接登录
  16. </a>
  17. <form action="<%=request.getContextPath()%>/CharacterServlet" method="post">
  18. <table border="1" width="600px" cellpadding="0" cellspacing="0" align="center">
  19. <tr>
  20. <td height="30" align="center">用户名:</td>
  21. <td>&nbsp;<input type="text" name="name" /></td>
  22. </tr>
  23. <tr>
  24. <td height="30" align="center">密&nbsp;码</td>
  25. <td>&nbsp;<input type="password" name="password" /></td>
  26. </tr>
  27. <tr>
  28. <td height="30" colspan="2" align="center">
  29. <input type="submit" value="登录"/>
  30. &nbsp;&nbsp;&nbsp;&nbsp;
  31. <input type="reset" value="重置" />
  32. </td>
  33. </tr>
  34. </table>
  35. </form>
  36. </body>
  37. </html>

在 form.jsp 中,第 14~16 行代码是一个请求方式为 GET 的超链接;第 17~35 行代码是一个 POST 提交方式 form 表单。

2)创建 Servlet

在 filterDemo01 项目的 com.mengma.filter 包中创建一个名称为 CharacterServlet 的 Servlet 类,该类用于获取用户输入的请求参数,并将参数输出到控制台,其代码如下所示。

  1. package com.mengma.filter;
  2. import java.io.IOException;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. public class CharacterServlet extends HttpServlet {
  8. public void doGet(HttpServletRequest request, HttpServletResponse response)
  9. throws ServletException, IOException {
  10. System.out.println(request.getParameter("name"));
  11. System.out.println(request.getParameter("password"));
  12. }
  13. public void doPost(HttpServletRequest request, HttpServletResponse response)
  14. throws ServletException, IOException {
  15. doGet(request, response);
  16. }
  17. }

3)创建过滤器

在 filterDemo01 项目的 com.mengma.filter 包中创建一个名称为 CharacterFilter 的 Filter 类,该类用于拦截用户的请求访问,并实现全站编码的统一,其具体实现代码如下所示。

  1. package com.mengma.filter;
  2. import java.io.IOException;
  3. import java.io.UnsupportedEncodingException;
  4. import javax.servlet.Filter;
  5. import javax.servlet.FilterChain;
  6. import javax.servlet.FilterConfig;
  7. import javax.servlet.ServletException;
  8. import javax.servlet.ServletRequest;
  9. import javax.servlet.ServletResponse;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletRequestWrapper;
  12. import javax.servlet.http.HttpServletResponse;
  13. public class CharacterFilter implements Filter {
  14. public void init(FilterConfig fConfig) throws ServletException {
  15. }
  16. public void doFilter(ServletRequest req, ServletResponse res,
  17. FilterChain chain) throws IOException, ServletException {
  18. HttpServletRequest request = (HttpServletRequest) req;
  19. HttpServletResponse response = (HttpServletResponse) res;
  20. // 拦截所有的请求,解决全站中文乱码,指定request和response的编码
  21. request.setCharacterEncoding("utf-8"); // 只对消息体有效
  22. response.setContentType("text/html;charset=utf-8");
  23. // 对 request 进行包装
  24. CharacterRequest characterRequest = new CharacterRequest(request);
  25. chain.doFilter(characterRequest,response);
  26. }
  27. public void destroy() {
  28. }
  29. }
  30. // 继承默认包装类 HttpServletRequestWrapper
  31. class CharacterRequest extends HttpServletRequestWrapper {
  32. private HttpServletRequest request;
  33. public CharacterRequest(HttpServletRequest request) {
  34. super(request);
  35. this.request = request;
  36. }
  37. // 子类继承父类一定会覆写一些方法,此处用于重写getParameter()方法
  38. public String getParameter(String name) {
  39. // 调用被包装对象getParameter()方法,获得请求参数
  40. String value = super.getParameter(name);
  41. if (value == null) {
  42. return null;
  43. }
  44. String method = super.getMethod(); // 判断请求方式
  45. if ("get".equalsIgnoreCase(method)) {
  46. try {
  47. value = new String(value.getBytes("iso-8859-1"), "utf-8");
  48. } catch (UnsupportedEncodingException e) {
  49. throw new RuntimeException(e);
  50. }
  51. }
  52. return value; // 解决乱码后返回结果
  53. }
  54. }

在 CharacterFilter 中,针对请求的方式不同,采用了不同的乱码解决方式。其中,由于 POST 方式的请求参数存放在消息体中,所以通过 setCharacterEncoding() 方法进行设置,而 GET 方式的请求参数存放在消息头中,通过 HttpServletRequestWrapper 类对 HttpServletRequest 类进行包装,并通过重写 getParameter() 的方式设置 GET 方式提交参数的编码。

需要注意的是,由于要拦截用户访问资源的所有请求,因此需要将 CharacterFilter 映射信息中 <filter-mapping> 元素拦截的路径设置为“/*”,如下所示:

  1. <filter>
  2. <filter-name>CharacterFilter</filter-name>
  3. <filter-class>com.mengma.filter.CharacterFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>CharacterFilter</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>

4)运行项目并查看结果

启动 Tomcat 服务器,在浏览器的地址栏中输入地址 http://localhost:8080/filterDemo01/form.jsp,此时,浏览器窗口中会显示一个用户登录的表单,在这个表单中输入用户名“张三”和密码“1234”,如图 1 所示。


图 1 运行结果

单击图 1 中的【登录】按钮提交表单,此时,MyEclipse 控制台显示的结果如图 2 所示。


图 2 控制台窗口

从图 2 中可以看出,form.jsp 表单中输入的信息已经显示在了控制台窗口中,而且中文的用户名也没有出现乱码。需要注意的是,由于 form.jsp 表单的提交方式是 POST,因此可以说明使用 CharacterFilter 类可以解决 POST 提交方式的中文乱码问题。

接下来验证 GET 方式提交表单的乱码问题是否可以解决。单击图 1 中的“单击超链接登录”链接后(这种提交方式相当于 GET 方式提交信息),MyEclipse 控制台窗口显示的结果同样如图 2 所示。因此可以说明,使用 CharacterFilter 类可以解决 GET 提交方式的中文乱码问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智慧浩海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值