應用一:解決tomcat下中文亂碼問題(先來個簡單的)
在tomcat下,我們通常這樣來解決中文亂碼問題:
過濾器代碼:
- package filter;
- import java.io.*;
- import javax.servlet.*;
- import javax.servlet.http.*;
- import wrapper.GetHttpServletRequestWrapper;
- public class ContentTypeFilter implements Filter {
- private String charset = "UTF-8";
- private FilterConfig config;
- public void destroy() {
- System.out.println(config.getFilterName()+"被銷毀");
- charset = null;
- config = null;
- }
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- //設置請求響應字符編碼
- request.setCharacterEncoding(charset);
- response.setCharacterEncoding(charset);
- HttpServletRequest req = (HttpServletRequest)request;
- System.out.println("----請求被"+config.getFilterName()+"過濾");
- //執(zhí)行下一個過濾器(如果有的話,否則執(zhí)行目標servlet)
- chain.doFilter(req, response);
- System.out.println("----響應被"+config.getFilterName()+"過濾");
- }
- public void init(FilterConfig config) throws ServletException {
- this.config = config;
- String charset = config.getServletContext().getInitParameter("charset");
- if( charset != null && charset.trim().length() != 0)
- {
- this.charset = charset;
- }
- }
- }
web.xml中過濾器配置:
- <!--將采用的字符編碼配置成應用初始化參數(shù)而不是過濾器私有的初始化參數(shù)是因為在JSP和其他地方也可能需要使用-->
- <context-param>
- <param-name>charset</param-name>
- <param-value>UTF-8</param-value>
- </context-param>
- <filter>
- <filter-name>ContentTypeFilter</filter-name>
- <filter-class>filter.ContentTypeFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>ContentTypeFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
request.setCharacterEncoding(charset); 必須寫在第一次使用request.getParameter()之前,這樣才能保證參數(shù)是按照已經(jīng)設置的字符編碼來獲取。
response.setCharacterEncoding(charset);必須寫在PrintWriter out = request.getWriter()之前,這樣才能保證out按照已經(jīng)設置的字符編碼來進行字符輸出。
通過過濾器,我們可以保證在Servlet或JSP執(zhí)行之前就設置好了請求和響應的字符編碼。
但是這樣并不能完全解決中文亂碼問題:
對于post請求,無論是“獲取參數(shù)環(huán)節(jié)”還是“輸出環(huán)節(jié)"都是沒問題的;
對于get請求,"輸出環(huán)節(jié)"沒有問題,但是"獲取參數(shù)環(huán)節(jié)"依然出現(xiàn)中文亂碼,所以在輸出時直接將亂碼輸出了。
原因是post請求和get請求存放參數(shù)位置是不同的:
post方式參數(shù)存放在請求數(shù)據(jù)包的消息體中。get方式參數(shù)存放在請求數(shù)據(jù)包的請求行的URI字段中,以?開始以param=value¶me2=value2的形式附加在URI字段之后。而request.setCharacterEncoding(charset); 只對消息體中的數(shù)據(jù)起作用,對于URI字段中的參數(shù)不起作用,我們通常通過下面的代碼來完成編碼轉(zhuǎn)換:
- String paramValue = request.getParameter("paramName");
- paramValue = new String(paramValue.trim().getBytes("ISO-8859-1"), charset);
但是每次進行這樣的轉(zhuǎn)換實在是很麻煩,有沒有統(tǒng)一的解決方案呢?
解決方案1: 在tomcat_home\conf\server.xml 中的Connector元素中設置URIEncoding屬性為合適的字符編碼
- <Connector port="8080" protocol="HTTP/1.1"
- connectionTimeout="20000"
- redirectPort="8443"
- URIEncoding="UTF-8"
- />
這樣做的缺點是,同一個tomcat下的其他應用也將受到影響。而其每次部署時都需要類修改配置也很麻煩。
解決方案2:自定義請求包裝器包裝請求,將字符編碼轉(zhuǎn)換的工作添加到getParameter()方法中
- package wrapper;
- import java.io.UnsupportedEncodingException;
- import java.net.URLDecoder;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletRequestWrapper;
- public class GetHttpServletRequestWrapper extends HttpServletRequestWrapper {
- private String charset = "UTF-8";
- public GetHttpServletRequestWrapper(HttpServletRequest request) {
- super(request);
- }
- /**
- * 獲得被裝飾對象的引用和采用的字符編碼
- * @param request
- * @param charset
- */
- public GetHttpServletRequestWrapper(HttpServletRequest request,
- String charset) {
- super(request);
- this.charset = charset;
- }
- /**
- * 實際上就是調(diào)用被包裝的請求對象的getParameter方法獲得參數(shù),然后再進行編碼轉(zhuǎn)換
- */
- public String getParameter(String name) {
- String value = super.getParameter(name);
- value = value == null ? null : convert(value);
- return value;
- }
- public String convert(String target) {
- System.out.println("編碼轉(zhuǎn)換之前:" + target);
- try {
- return new String(target.trim().getBytes("ISO-8859-1"), charset);
- } catch (UnsupportedEncodingException e) {
- return target;
- }
- }
- }
修改過濾器的doFilter方法 代碼如下:
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- //設置請求響應字符編碼
- request.setCharacterEncoding(charset);
- response.setCharacterEncoding(charset);
- //新增加的代碼
- HttpServletRequest req = (HttpServletRequest)request;
- if(req.getMethod().equalsIgnoreCase("get"))
- {
- req = new GetHttpServletRequestWrapper(req,charset);
- }
- System.out.println("----請求被"+config.getFilterName()+"過濾");
- //傳遞給目標servlet或jsp的實際上時包裝器對象的引用,而不是原始的HttpServletRequest對象
- chain.doFilter(req, response);
- System.out.println("----響應被"+config.getFilterName()+"過濾");
- }
這樣一來,在servlet中調(diào)用包裝器的getParameters方法來獲取參數(shù),就已經(jīng)完成了字符編碼的轉(zhuǎn)換過程,我們就不需要在每次獲取參數(shù)時來進行字符編碼轉(zhuǎn)換了。
其實用動態(tài)代理來實現(xiàn)可能更好,這里只是我講課時的一個例子,用來介紹HttpServletRequestWrapper,不對之處,敬請指教,以免誤人子弟啊。
源代碼示例工程:http://www.aygfsteel.com/Files/whistler/demo.rar
學軟件開發(fā),到蜂鳥科技!
超強的師資力量 、完善的課程體系 、超低的培訓價格 、真實的企業(yè)項目。
網(wǎng)址:
電話:
鄭州軟件開發(fā)興趣小組群: