Servlet 使用 RequestDispatcher.forward() 轉發至 JSP 時,頁面顯示中文亂碼。單獨存取 JSP 正常,僅透過 Servlet 轉發時發生。
在呼叫 response.getWriter() 取得 PrintWriter 之前,若未先設定回應編碼,Servlet 容器會預設使用 ISO-8859-1 編碼。一旦 PrintWriter 建立,後續再設定編碼已無效果。
在 任何 取得輸出流操作之前,務必先設定編碼:
// 必須在 response.getWriter() 之前呼叫
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 之後才能取得 PrintWriter
PrintWriter out = response.getWriter();
@WebServlet("/forwardDemo")
public class ForwardServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// ✅ 正確順序:先設定編碼
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
// 設定轉發屬性
req.setAttribute("message", "中文測試訊息");
// 轉發
RequestDispatcher rd = req.getRequestDispatcher("/result.jsp");
rd.forward(req, resp);
// ❌ 錯誤示範:若在 forward 後才設定編碼已無效
// resp.setCharacterEncoding("UTF-8");
}
}
建議在 Filter 中統一設定請求/回應編碼,避免各 Servlet 重複撰寫:
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
chain.doFilter(req, resp);
}
}
確保 JSP 頁面頂部包含:
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
亂碼核心在於 編碼設定時機:必須在取得輸出流 (getWriter() 或 getOutputStream()) 之前 完成。養成「先設定編碼,再取得流」的習慣,或使用 Filter 統一處理,可徹底杜絕此類問題。