解决乱码setCharacterEncoding("UTF-8")不生效的问题
今天在写拦截器的时候,如果判断用户未登录,直接返回一个错误码,提醒用户登录。
但是在前端接收的提示信息中,结果是
{code: "58888", msg: "???"}
这里的???应该是请登录
检查一下工具类,发现工具类里面是设置过编码
public static void writeJson(HttpServletResponse response , Object content ) throws IOException {
try(PrintWriter out = response.getWriter()){
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding("UTF-8");
String returnText = JSONObject.toJSONString(content, SerializerFeature.DisableCircularReferenceDetect);
out.write(returnText);
out.flush();
}
}
然后又检查了一下,页面上的response headers的信息
编码集变成了 ISO-8859-1
说明代码里,设置编码集的代码没有生效。
点进源码看看到底为啥没生效。
public void setCharacterEncoding(final String charset) {
// writer != null , 就不会再设置编码集了
if (insideInclude || responseStarted() || writer != null || isCommitted()) {
return;
}
charsetSet = charset != null;
this.charset = charset;
if (contentType != null) {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, getContentType());
}
}
如果writer对象不是空,就不会再设置编码集。
所以response.setCharacterEncoding("UTF-8");
代码要在response.getWriter()
之前调用,不然编码不会生效。
顺便再看一下getWriter() 方法都干了啥?
public PrintWriter getWriter() throws IOException {
if (writer == null) {
// 如果编码没有set,设置编码
// getCharacterEncoding() 如果web-app,container都没有设置编码集,就默认ISO_8859_1
if (!charsetSet) {
//servet 5.5
setCharacterEncoding(getCharacterEncoding());
}
if (responseState == ResponseState.STREAM) {
throw UndertowServletMessages.MESSAGES.getOutputStreamAlreadyCalled();
}
responseState = ResponseState.WRITER;
createOutputStream();
final ServletPrintWriter servletPrintWriter = new ServletPrintWriter(servletOutputStream, getCharacterEncoding());
writer = ServletPrintWriterDelegate.newInstance(servletPrintWriter);
}
return writer;
}
public String getCharacterEncoding() {
if (charset != null) {
return charset;
}
// first check, web-app context level default response encoding
if (servletContext.getDeployment().getDeploymentInfo().getDefaultResponseEncoding() != null) {
return servletContext.getDeployment().getDeploymentInfo().getDefaultResponseEncoding();
}
// now check the container level default encoding
if (servletContext.getDeployment().getDeploymentInfo().getDefaultEncoding() != null) {
return servletContext.getDeployment().getDeploymentInfo().getDefaultEncoding();
}
// if no explicit encoding is specified, this method is supposed to return ISO-8859-1 as per the
// expectation of this API
return StandardCharsets.ISO_8859_1.name();
}
综上所述,编码集要在getWriter()
之前设置,不然就会有乱码的问题