仅在Java Filter中更改ContentType或CharacterEncoding如果ContentType === JSON

Bra*_*rks 5 java content-type filter jersey-2.0

我正在尝试确保来自基于Jersey的java应用程序的所有JSON响应都在其ContentType标头中附加了UTF-8字符编码参数.

所以,如果它是一个JSON响应,我想响应报头的Content-Type

Content-Type:application/json; charset = 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为"application/json"时设置字符编码.我发现response.getContentType()方法总是返回null,除非我先调用chain.doFilter.但是如果我在此之后尝试更改字符编码,它似乎总是会被覆盖.

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()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

我见过其他类似的问题,但他们似乎都没有这个问题.我已经尝试将我的过滤器注册为第一个,最后一个过滤器没有运气.

Bra*_*rks 7

感谢这个页面上的其他答案,我找到了一种方法来做到这一点......非常接近他们的建议,但事实证明我能够让它工作的唯一方法是覆盖"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
    }
}
Run Code Online (Sandbox Code Playgroud)


bok*_*oky 5

这不会以这种方式工作。

当您调用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!
}
Run Code Online (Sandbox Code Playgroud)

编辑: ct.toUpperCase().startsWith("application/json")更改为ct.toLowerCase().startsWith("application/json").