我想,以确保从位于新泽西州的Java应用程序的所有JSON响应有附加到他们的ContentType标头一个UTF-8字符编码参数。
所以,如果它是一个JSON响应,我想响应头为Content-Type
是
内容类型:应用/ JSON;字符集= UTF-8
EDIT: I know I can do this on a case by case basis, but I'd like to do it globally, so it affects all content responses that have a content type of "application/json".
如果我只是尝试,并设置在我的过滤器中的字符编码,无论内容类型,它工作正常。但我只是想设置的字符编码如果将contentType是“应用/ JSON”。我觉得除非我先打电话chain.doFilter的response.getContentType()方法总是返回null。但是,如果我尝试在此之后改变字符编码,它似乎总是会被覆盖。
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.ws.rs.core.MediaType;
public class EnsureJsonResponseIsUtf8Filter implements Filter
{
private class SimpleWrapper extends HttpServletResponseWrapper
{
public SimpleWrapper(HttpServletResponse response)
{
super(response);
}
@Override
public String getCharacterEncoding()
{
return "UTF-8";
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
chain.doFilter(request, response);
if (response.getContentType() != null && response.getContentType().contains(MediaType.APPLICATION_JSON))
{
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, new SimpleWrapper((HttpServletResponse) response));
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
@Override
public void destroy()
{
}
}
我见过的其他similar questions,但没有人似乎有这个问题。我试着注册我的过滤器,没有运气第一,和最后一个过滤器。
由于此页面上的其他答案,我发现了一个办法做到这一点....非常接近他们被暗示,但事实证明,我能得到它的工作的唯一办法就是越权“的getOutputStream”看看将contentType在这一点上。我已经把这个过滤器链中的第一个过滤器,它似乎很好地工作。
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.ws.rs.core.MediaType;
public class EnsureJsonIsUtf8ResponseFilter implements Filter
{
final String APPLICATION_JSON_WITH_UTF8_CHARSET = MediaType.APPLICATION_JSON + ";charset=" + java.nio.charset.StandardCharsets.UTF_8;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
HttpServletResponse r = (HttpServletResponse) response;
HttpServletResponse wrappedResponse = new HttpServletResponseWrapper(r)
{
@Override
public ServletOutputStream getOutputStream() throws java.io.IOException
{
ServletResponse response = this.getResponse();
String ct = (response != null) ? response.getContentType() : null;
if (ct != null && ct.toLowerCase().startsWith(MediaType.APPLICATION_JSON))
{
response.setContentType(APPLICATION_JSON_WITH_UTF8_CHARSET);
}
return super.getOutputStream();
}
};
chain.doFilter(request, wrappedResponse);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
// This method intentionally left blank
}
@Override
public void destroy()
{
// This method intentionally left blank
}
}
这不会以这种方式工作。
当你调用chain.doFilter(request, response);
你的头已经被刷新,你不能重新设置以后。
你可以做的其实是一个快速和肮脏的伎俩:
public void doFilter(...) {
HttpServletResponse resp = new HttpServletResponseWrapper(response) {
public void setContentType(String ct) {
if(ct!=null && ct.toLowerCase().startsWith("application/json")) {
super.setContentType("application/json;charset=UTF-8");
} else {
super.setContentType(ct);
}
}
}
// Set content type manually to override any potential defaults,
// See if you need it at all
response.setContentType("application/json;charset=UTF-8");
chain.doFilter(request, resp); // Inject our response!
}
编辑:ct.toUpperCase().startsWith("application/json")
改为ct.toLowerCase().startsWith("application/json")
。
使用this answer作为参考解决您的问题,以如下所示的JSON文本进行重新编码:
public void doFilter(...) {
final CharResponseWrapper wrappedResponse =
new CharResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, wrappedResponse);
final String content = wrappedResponse.toString();
final String type = wrappedResponse.getContentType();
if (type != null && type.contains(MediaType.APPLICATION_JSON)) {
// Re-encode the JSON response as UTF-8.
response.setCharacterEncoding("UTF-8");
final OutputStream out = response.getOutputStream();
out.write(content.getBytes("UTF-8"));
out.close();
}
else {
// Otherwise just write it as-is.
final PrintWriter out = response.getWriter();
out.write(content);
out.close();
}
}
这也可以使用ClientFilter
,我刚刚碰到的StackOverflow职位相似的目的是可行的:
有使用ContainerResponseFilter
成功:
public class ContentTypeEncodingFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
String contentType = responseContext.getHeaderString(HttpHeaders.CONTENT_TYPE);
if (contentType == null) {
return;
}
ContentType parsedType = ContentType.parse(contentType);
if (parsedType.getCharset() != null) {
return;
}
ContentType encodedType = parsedType.withCharset(StandardCharsets.UTF_8);
responseContext.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, encodedType.toString());
}
}
不是100%肯定我得到了你想要达到的目标。你想调用后设置页眉字符集
chain.doFilter(request, response)
?
如果这是我怕的情况下,你不能因为很可能在这一点上,那chain.doFilter(请求,响应)已经返回处理请求后,内容的字符集已经被发送到客户端,因此,你不能改变它了。