写一个编码过滤器

        一个请求:http://localhost:8080/FilterTest/ServletTest?name=%E4%B8%AD%E6%96%87 传送到Web服务器是不带编码的,可是web容器解码是有默认处理的编码,Tomcat就是用"ISO-8859-1"解码的,而后将请求交给相应的Servlet类处理。html

        因此咱们能够写一个过滤器,在请求传给相应的Servlet类处理以前改变其编码。java

下面是一个简单的Demo。web

代码:数组

package cn.xiaol.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @date 建立时间:2016年10月15日 下午11:15:10
 * @Description TODO
 */
public class ServletTest extends HttpServlet {
	
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String name = req.getParameter("name");
		System.out.println("GET后台打印:" + name);
		resp.getWriter().println("GET前台打印" + name);
	}

	
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String name = req.getParameter("name");
		System.out.println("POST后台打印:" + name);
		resp.getWriter().println("POST前台打印" + name);
	}
}

web.xml:服务器

<servlet>
		<servlet-name>ServletTest</servlet-name>
		<servlet-class>cn.xiaol.servlet.ServletTest</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>ServletTest</servlet-name>
		<url-pattern>/ServletTest</url-pattern>
	</servlet-mapping>

请求后的结果:app

GET????涓枃

接下来,咱们写一个过滤器:ide

package cn.xiaol.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * @date 建立时间:2016年10月16日 上午12:51:10
 * @Description 编码过滤器
 */
public class CharSetFilter implements Filter {
	// 默认编码为UTF-8
	private String charset = "UTF-8";

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 处理响应编码,不设置的话,后台打印显示中文,可是返回到前台的是乱码
		response.setContentType("text/html;charset=UTF-8");
		HttpServletRequest req = (HttpServletRequest) request;
		if (req.getMethod().equalsIgnoreCase("GET")) {
			if (!(req instanceof RequestWrapper)) {
				// 处理Get请求编码
				// 用装饰者request替换了本来的request,执行过滤链
				req = new RequestWrapper(req, charset);
			}
		} else {
			// 处理Post请求编码
			req.setCharacterEncoding(charset);
		}
		// 用装饰者request替换了本来的request,执行过滤链
		chain.doFilter(req, response);
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		// 从web.xml中读取编码信息
		String charset = config.getInitParameter("charset");
		// 若是不为空就替换咱们默认的UTF-8
		if (charset != null && !charset.isEmpty()) {
			this.charset = charset;
		}
	}

}

        全部的request进来后,先判断是否是GET请求,若是不是就直接设置编码,放行。不然就替换成装饰模式的RequestWrapper。之因此要替换成RequestWrapper,是由于RequestWrapper做为装饰者,它的大部分方法咱们都不重写,只重写其中咱们想要改变的方法。post

下面是RequestWrapper的代码:this

package cn.xiaol.filter;

import java.io.UnsupportedEncodingException;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * @date 建立时间:2016年10月16日 上午12:09:12
 * @Description 这是使用装饰模式后的request类
 */
public class RequestWrapper extends HttpServletRequestWrapper {
	// 存放传进来的HttpServletRequest对象
	private HttpServletRequest request;
	// 编码格式
	private String charset;

	/**
	 * 为了方便设置编码格式,增长一个编码格式入参
	 * 
	 * @param request
	 * @param charset
	 */
	public RequestWrapper(HttpServletRequest request, String charset) {
		// 把引用传一份给父类,由于父类也是一个装饰者,实现了咱们不想重写的方法
		super(request);
		this.request = request;
		this.charset = charset;
	}

	@Override
	public String getParameter(String key) {
		String value = request.getParameter(key);
		if (value == null)// 若是value为null就返回null
			return null;
		try {
			// Get请求的时候实际上是没有带编码格式的,是Web服务器,也就是Tomcat默认采用了ISO-8859-1
			// 因此先用ISO-8859-1取数据,再转为UTF-8
			return new String(value.getBytes("ISO-8859-1"), charset);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public Map getParameterMap() {
		Map<String, String[]> map = request.getParameterMap();
		if (map == null) {
			return map;
		}
		for (String key : map.keySet()) {// 遍历全部的key
			String[] values = map.get(key);// 获得key的value字符串数组
			for (int i = 0; i < values.length; i++) {// 遍历value字符串数组,设置编码
				try {
					values[i] = new String(values[i].getBytes("ISO-8859-1"), charset);
				} catch (UnsupportedEncodingException e) {
					throw new RuntimeException(e);
				}
			}
		}
		return map;
	}
}

        这里重写了getParameter和getParameterMap方法,由于咱们须要用这些方法得到前台传入的参数。编码

web.xml:

<filter>
		<filter-name>CharsetFilter</filter-name>
		<filter-class>cn.xiaol.filter.CharSetFilter</filter-class>
		<!-- init-param初始化参数能够不给,由于在Filter中设置了默认编码为UTF-8 -->
		<init-param>
			<param-name>charset</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharsetFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

请求后的结果:

GET前台打印中文

        最后在这里提一下,get请求是将数据放入rul中,而后对中文进行UTF-8编码,再进行ISO-8859-1编码(为了缩短字符),然传给Web服务器。因此RequestWrapper中将传入参数先用ISO-8859-1编码getBytes获得byte数组,再用UTF-8转为String。

        而post请求,是把数据进行UTF-8编码而后放在http请求体中传给服务器,因此CharSetFilter中,直接req.setCharacterEncoding("UTF-8")就能够正确显示中文了。

下面给出完整的Demo:

http://pan.baidu.com/s/1gfmcPQ7

相关文章
相关标签/搜索