在Java Web开发中,HttpServlet是处理客户端请求的核心组件。当浏览器通过表单向服务器提交数据时,通常会使用GET或POST方法,而服务端需要在对应的doGet或doPost方法中获取字段并规避中文乱码。理解容器对两种请求参数的解析机制,是写出健壮接口的前提。

一、HttpServlet中GET与POST的基础处理
HttpServlet提供了doGet和doPost两个 protected 方法,分别响应HTTP的GET和POST请求。当表单的method属性为get时,所有参数会附着在URL后面,以查询字符串形式传输;当method为post时,参数放在请求体(request body)中。开发者通常会在这两个方法里调用HttpServletRequest的getParameter方法读取数据。
下面是一个最基础的Servlet示例,它同时重写了doGet与doPost,并在其中获取表单中的两个字段。注意此时尚未处理编码,仅展示获取方式:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FormServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// GET请求参数从URL查询字符串获取
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("GET username=" + username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// POST请求参数从请求体获取
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("POST username=" + username);
}
}
上述代码在纯英文环境下可以正常工作,但一旦表单中包含中文,且未设置编码,打印出的username就会出现乱码。这是因为Servlet容器在解析参数时采用了默认字符集,而浏览器提交时使用的往往是UTF-8。
二、POST请求的中文乱码处理
对于POST请求,参数位于请求体,Servlet规范要求在第一次调用getParameter之前,通过request.setCharacterEncoding("UTF-8")来告知容器以何种编码解析 body。如果调用顺序靠后,容器已经按默认ISO-8859-1解析过,设置将失效。
修正后的doPost方法如下,我们在方法开头立即设置编码,再获取参数,这样中文就能正确读取:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 必须在getParameter之前设置
req.setCharacterEncoding("UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("POST username=" + username);
}
这种方式的优点是简单直接,缺点是每个Servlet都要写一遍,且容易遗漏。在真实项目中,更推荐用Filter统一处理,在过滤器中对所有请求设置编码,避免重复代码。此外,响应给浏览器的内容也应设置resp.setContentType("text/html;charset=UTF-8"),保证输出不乱码。
三、GET请求的中文乱码成因与解决
GET请求的参数在URL中,其解码发生在容器解析HTTP行阶段,并不受setCharacterEncoding影响。以Tomcat为例,默认使用ISO-8859-1解码查询字符串,因此即便在doGet里设置request编码,读出的中文仍是乱码。
一种兼容旧项目的做法是手动转码:先将参数按ISO-8859-1还原为字节,再用UTF-8重构字符串。示例如下:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String raw = req.getParameter("username");
// 先按ISO-8859-1取字节,再用UTF-8构造
String username = new String(raw.getBytes("ISO-8859-1"), "UTF-8");
System.out.println("GET username=" + username);
}
更彻底的方案是修改Tomcat的server.xml,在Connector节点增加URIEncoding="UTF-8"属性,让容器直接以UTF-8解析GET参数。这样代码中无需手动转码,可读性与维护性更好。但需注意,该配置对所有应用生效,团队应达成共识。
四、统一编码的实践建议
为避免在每一个Servlet中反复处理,可编写一个EncodingFilter,在chain.doFilter之前设置请求与响应编码。web.xml中配置该过滤器拦截所有路径,即可全局生效。
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class EncodingFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
chain.doFilter(req, resp);
}
public void init(FilterConfig f) {}
public void destroy() {}
}
不过过滤器只能解决POST体编码,GET参数仍依赖服务器配置或手动转码。因此在架构层面,建议将Tomcat的URIEncoding设好,并在前端表单声明accept-charset="UTF-8",形成端到端一致。这样业务代码只需专注参数使用,不必被乱码分散注意力。
五、常见误区与小结
不少初学者以为setCharacterEncoding能解决所有乱码,结果在GET接口中依旧报错,其根源正是忽略了URL解码时机。另外,使用<form>标签时若未指定method,浏览器默认发GET,也容易引发 confusion。理清GET与POST在Servlet中的参数位置与解码规则,才能写出稳定的表单处理接口。
综上,POST靠request编码设置加过滤器,GET靠服务器URIEncoding或手动转码,两者配合并统一前端字符集,中文表单数据便可顺畅抵达后台逻辑。
HttpServletGET_POST中文乱码处理修改时间:2026-08-08 16:45:30