用response得到輸出流,即response.getOuptStream(); 返回值為ServletOutputStream 對象,即JSP的out對象,要么用response得到輸出對象PrintWriter即response.getWriter()。
Java代碼
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
PrintWriter pw = response.getWriter();
response.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8");
pw.print("中文");
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
PrintWriter pw = response.getWriter();
response.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8");
pw.print("中文");
}
輸出亂碼。為什么呢,已經設置了字符編碼啊?難道設置的無效。
在API中找到方法說明:
Java代碼
PrintWriter getWriter() throws IOException
Returns a PrintWriter object that can send character text to the client. The PrintWriter uses the character encoding returned by getCharacterEncoding().
If the response's character encoding has not been specified as described in getCharacterEncoding (i.e., the method just returns the default value ISO-8859-1), getWriter updates it to ISO-8859-1.
PrintWriter getWriter() throws IOException
Returns a PrintWriter object that can send character text to the client. The PrintWriter uses the character encoding returned by getCharacterEncoding().
If the response's character encoding has not been specified as described in getCharacterEncoding (i.e., the method just returns the default value ISO-8859-1), getWriter updates it to ISO-8859-1.
就是講,在返回一個PrintWriter對象的時候,charactor encoding就已經確定了,就已經設置好了字符集了。什么時候設置的呢? setCharacterEncoding方法的實現時發現如下代碼:
Java代碼
public void setCharacterEncoding(String charset) {
if (isCommitted())
return;
// Ignore any call from an included servlet
if (included)
return;
// Ignore any call made after the getWriter has been invoked
// The default should be used
if (usingWriter)
return;
coyoteResponse.setCharacterEncoding(charset);
isCharacterEncodingSet = true;
}
public void setCharacterEncoding(String charset) {
if (isCommitted())
return;
// Ignore any call from an included servlet
if (included)
return;
// Ignore any call made after the getWriter has been invoked
// The default should be used
if (usingWriter)
return;
coyoteResponse.setCharacterEncoding(charset);
isCharacterEncodingSet = true;
}
其中usingWriter 標志為getPrinteWriter方法中設定,可見其控制邏輯為一旦返回了PrintWriter,本函數即不再生效。
ServletOutputStream out = response.getOutputStream();
out.print("中文");
//情況1:正常,瀏覽器按utf-8方式查看
//response.setContentType("text/html; charset=utf-8");
//情況2:瀏覽器缺省按簡體中文查看,手動設為utf-8方式查看正常
//response.setCharacterEncoding("utf-8");
說明:這種方式不僅不需要在調用getOutputStream()之前設定字符集,甚至在print輸出后設定都有效。
///情況三:在tomcat的server.xml中找到Connector的位置,並添加URIEncoding="UTF-8:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"URIEncoding="UTF-8"/>
結論:
1.在servlet中輸出中文,如果采用PrintWriter方式,需要在調用getPrintWriter()之前調用setContentType 或者 setCharacterEncoding;采用ServletOutputStream方式,不受此限。
2.setContentType 和 setCharacterEncoding兩方法中設定characterEncoding的方法對服務器效果一致,不需要反復調用。在輸出文本內容時,采用response.setContentType("text/html; charset=utf-8");似乎更為方便。
3.PrintWriter自身並沒有處理編碼的職責,它還是應該看成一個裝飾器比較好:它就是為了輸出更方便而設計的,提供print、println、printf等便利方法。要設置編碼的話,可以在它的底層Writer上設置:(這里以OutputStreamWriter為底層Writer),參考:
Java代碼
new PrintWriter(new OutputStreamWriter(new FileOutputStream("yourfilepath"), "UTF-8"));
new PrintWriter(new OutputStreamWriter(new FileOutputStream("yourfilepath"), "UTF-8"));