// 直接寫入中文
response.getWriter().write("您好中國hello");
// 瀏覽器顯示:?好?國hello (或亂碼)
Servlet 規範默認響應編碼為 ISO-8859-1,不支持中文。瀏覽器接收到字節流後,若無明確編碼聲明,會嘗試自動檢測或按默認編碼解碼,導致中文亂碼。
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("您好中國hello");
原理:setContentType 同時設置 HTTP 響應頭 Content-Type: text/html;charset=UTF-8 和內部編碼,瀏覽器據此正確解碼。
response.setCharacterEncoding("UTF-8"); // 設置 Writer 編碼
response.setHeader("Content-Type", "text/html;charset=UTF-8"); // 設置響應頭
response.getWriter().write("您好中國hello");
注意:必須在 getWriter() 前調用,否則無效。
String content = "您好中國hello";
byte[] data = content.getBytes(StandardCharsets.UTF_8);
response.setContentType("text/html;charset=UTF-8");
response.setContentLength(data.length);
try (OutputStream os = response.getOutputStream()) {
os.write(data);
}
適用場景:二進制數據輸出、需精確控制字節長度、避免 Writer 緩衝區干擾。
@Controller
public class HelloController {
@GetMapping("/hello")
@ResponseBody
public String hello() {
return "您好中國hello"; // 自動應用 StringHttpMessageConverter (默認 UTF-8)
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List> converters) {
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
stringConverter.setWriteAcceptCharset(false); // 防止雙重 charset 聲明
converters.add(0, stringConverter); // 優先級最高
}
}
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
chain.doFilter(req, resp);
}
}
| 響應類型 | Content-Type 示例 | 關鍵點 |
|---|---|---|
| HTML 頁面 | text/html;charset=UTF-8 | Meta 標簽 <meta charset="UTF-8"> 雙重保障 |
| JSON API | application/json;charset=UTF-8 | Spring MVC @ResponseBody 自動處理 |
| XML 數據 | application/xml;charset=UTF-8 | XML 聲明 <?xml version="1.0" encoding="UTF-8"?> |
| 文件下載 | application/octet-stream | 文件名編碼 URLEncoder.encode(filename, "UTF-8") |
| 圖片/二進制 | image/jpeg, image/png | 無字符編碼問題,直接輸出字節流 |
request.setCharacterEncoding("UTF-8") 只影響請求體解碼 (POST 表單),不影響響應getWriter() 後設置編碼無效,Writer 已按默認編碼創建getWriter() 和 getOutputStream() 會拋出 IllegalStateException解決響應中文亂碼核心:在獲取輸出流前,明確設置 Content-Type 包含 charset=UTF-8。推薦使用 response.setContentType("text/html;charset=UTF-8") 一步到位。Spring MVC 項目通過配置 StringHttpMessageConverter 或 @ResponseBody 自動處理,舊項目加全局過濾器統一攔截設置。牢記「先設置編碼,再獲取流」原則,徹底告別亂碼。