首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

解決 HttpServletResponse 響應中文亂碼問題的三種方案

     編輯:Java 相關知識

問題現象

// 直接寫入中文
response.getWriter().write("您好中國hello");
// 瀏覽器顯示:?好?國hello (或亂碼)

根因分析

Servlet 規範默認響應編碼為 ISO-8859-1,不支持中文。瀏覽器接收到字節流後,若無明確編碼聲明,會嘗試自動檢測或按默認編碼解碼,導致中文亂碼。

三種解決方案 (按推薦順序)

方案一:設置響應頭 Content-Type (最完整、推薦)

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() 前調用,否則無效。

方案三:使用 OutputStream 手動編碼 (底層控制)

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 緩衝區干擾。

Spring MVC 中的最佳實踐

1. @Controller 返回 String 直接輸出

@Controller
public class HelloController {
    @GetMapping("/hello")
    @ResponseBody
    public String hello() {
        return "您好中國hello"; // 自動應用 StringHttpMessageConverter (默認 UTF-8)
    }
}

2. 全局配置 HttpMessageConverter

@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); // 優先級最高
    }
}

3. 過濾器統一設置 (舊項目兼容)

@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-8Meta 標簽 <meta charset="UTF-8"> 雙重保障
JSON APIapplication/json;charset=UTF-8Spring MVC @ResponseBody 自動處理
XML 數據application/xml;charset=UTF-8XML 聲明 <?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
  • ✅ 統一在項目入口 (Filter/Interceptor/全局配置) 設置 UTF-8,避免分散在各 Controller

總結

解決響應中文亂碼核心:在獲取輸出流前,明確設置 Content-Type 包含 charset=UTF-8。推薦使用 response.setContentType("text/html;charset=UTF-8") 一步到位。Spring MVC 項目通過配置 StringHttpMessageConverter 或 @ResponseBody 自動處理,舊項目加全局過濾器統一攔截設置。牢記「先設置編碼,再獲取流」原則,徹底告別亂碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved