【任务目标】
在web开发中,经常会遇到中文乱码问题,按照我们前面所学的知识,解决乱码的通常做法都是在Servlet程序中设置编码方式,但是如果多个Servlet程序都需要设置编码方式,势必会书写大量的代码。为了解决上面的问题,可以在Filter中获取到的请求和响应消息进行编码,从而统一全站的编码方式。
【实现步骤】
1.编写form.jsp页面
在chapter08项目的WebContent目录中,编写一个form.jsp页面,该页面用于提交用户登陆的表单信息,代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" import="java.util.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<center>
<h3>用户登录</h3>
</center>
<body style="text-align: center;">
<a href="<%=request.getContextPath()%>/CharacterServlet?name=传智播客&password=123456">单击超链接登录</a>
<form action="<%=request.getContextPath()%>/CharacterServlet"
method="post">
<table border="1" width="600px" cellpadding="0" cellspacing="0"
align="center">
<tr>
<td height="30" align="center">用户名:</td>
<td> <input type="text" name="name" />
</td>
</tr>
<tr>
<td height="30" align="center">密 码:</td>
<td> <input type="password" name="password" />
</td>
</tr>
<tr>
<td height="30" colspan="2" align="center">
<input type="submit" value="登录" />
<input type="reset" value="重置" />
</td>
</tr>
</table>
</form>
</body>
在上述代码中,第10~11行是一个超链接,请求方式为GET方式;第12—32行代码是一个Form表单,它的提交方式被设置为POST方式。
2.创建Servlet
在chapter08项目的cn.itcast.chapter08.filter包中,编写一个CharacterServlet类,该类用于获取用户输入的请求参数,并将参数输出到控制台,代码如下:
package cn.itcast.chapter08.filter;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
public class CharacterServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println(request.getParameter("name"));
System.out.println(request.getParameter("password"));
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
3.创建过滤器
在chapter08 项目的cn.itcast.chapter08.filter包中,编写一个ChapterFifer该类用于拦截用户的请求访问,实现统一全站编码的功能。 只是针对请求的方式不同,解决乱码的方式也不同。其中,POST方式的请求参数存放在消息体中,,可以通过,setCharaterEncoding()方法进行设置:而GET方式的请求参数存放在消息头中,必须得通过获取URI参数才能进行设置。如果每次单独对GET请求方式进行处理,势必会很麻烦。为此,可以通过HttpServletRequestWrapper类对HttpServletRequest进行包装,通过重写getParameter()的方式来设置GET方式提交参数的编码,CharacterFilter类的实现代码如下所示:
package cn.itcast.chapter08.filter;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class CharacterFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// 拦截所有的请求 解决全站中文乱码
// 指定 request 和 response 的编码
request.setCharacterEncoding("utf-8"); // 只对消息体有效
response.setContentType("text/html;charset=utf-8");
// 对request进行包装
CharacterRequest characterRequest = new CharacterRequest(request);
chain.doFilter(characterRequest, response);
}
public void destroy() {
}
}
// 继承 默认包装类HttpServletRequestWrapper
class CharacterRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
public CharacterRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
// 子类继承父类一定会覆写一些方法,此处用于重写getParamter()方法
public String getParameter(String name) {
// 调用被包装对象的getParameter()方法,获得请求参数
String value = super.getParameter(name);
if (value == null)
return null;
// 判断请求方式
String method = super.getMethod();
if ("get".equalsIgnoreCase(method)) {
try {
value = new String(value.getBytes("iso-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
// 解决乱码后返回结果
return value;
}
}
4.配置映射信息
在web.xml文件中,配置CharacterServlet和CharacterFilter的映射信息。由于要拦截用户访问资源的所有请求,因此,将ChapterFilter的映射信息。由于要拦截用户访问资源的所有请求,因此,将ChapterFilter映射信息中“filter-mapping”元素拦截的路径设置为“/*”代码如下:
<servlet>
<description></description>
<display-name>CharacterServlet</display-name>
<servlet-name>CharacterServlet</servlet-name>
<servlet-class>cn.itcast.chapter08.filter.CharacterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CharacterServlet</servlet-name>
<url-pattern>/CharacterServlet</url-pattern>
</servlet-mapping>
<filter>
<filter-name>CharacterFilter</filter-name>
<filter-class>cn.itcast.chapter08.filter.CharacterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
5.项目启动,测试结果
启动Tomact服务器,打开浏览器,在地址栏输入地址“http://localhost:10081/chapter/form.jsp”此时,浏览器窗口会显示一个用户登陆的表单,在这个表单中输入用户名“张荣博”,密码“123456”如下图所示:
单击上图中的【登录】按钮来提交表单,此时,控制台窗口显示的结果如下图所示:
从上图可以看出,在form.jsp表单中输入的用户名和密码都正确的显示在控制台窗口,而且中文的用户名也没有出现乱码问题,需要注意的是,form.jsp表单的提交方式是POST。因此,可以说明使用POST提交表单可以解决中文乱码的问题。表单的提交方式还有一种是GET,接下来验证GET方式提交表单的乱码问题能否解决。
单击第一幅图中的“单击超链接登陆”链接来提交表单,这种提交方式相当于GET方式提交表单,此时,控制台窗口显示的结果如下图所示:
从上图我们可以看出,GET方式提交表单与POST方式提交表单的效果是一致的,同样不会出现乱码问题,因此,可以说明使用Filter过滤器可以方便地完成统一全站编码的功能。