寫一個編碼過濾器

        一個請求: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

相關文章
相關標籤/搜索