使用Filter实现统一编码

【任务目标】
在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>&nbsp;<input type="text" name="name" />
				</td>
			</tr>
			<tr>
				<td height="30" align="center">密 &nbsp; 码:</td>
				<td>&nbsp;<input type="password" name="password" />
				</td>
			</tr>
			<tr>
				<td height="30" colspan="2" align="center">
				<input type="submit" value="登录" />
				 &nbsp;&nbsp;&nbsp;&nbsp;
				<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”如下图所示:
使用Filter实现统一编码
单击上图中的【登录】按钮来提交表单,此时,控制台窗口显示的结果如下图所示:
使用Filter实现统一编码

从上图可以看出,在form.jsp表单中输入的用户名和密码都正确的显示在控制台窗口,而且中文的用户名也没有出现乱码问题,需要注意的是,form.jsp表单的提交方式是POST。因此,可以说明使用POST提交表单可以解决中文乱码的问题。表单的提交方式还有一种是GET,接下来验证GET方式提交表单的乱码问题能否解决。
单击第一幅图中的“单击超链接登陆”链接来提交表单,这种提交方式相当于GET方式提交表单,此时,控制台窗口显示的结果如下图所示:
使用Filter实现统一编码
从上图我们可以看出,GET方式提交表单与POST方式提交表单的效果是一致的,同样不会出现乱码问题,因此,可以说明使用Filter过滤器可以方便地完成统一全站编码的功能。

上一篇:css样式控制网页页面整体变灰色代码


下一篇:F5发布100Gbps刀片设备 为5G网络打好前站