java - ContainerRequestFilter 返回实体的错误内容类型

标签 java jackson jax-rs cxf

我想对每个请求进行全局检查。因此,我使用 ContainerRequestFilter (没有 @PreMatching )并抛出 WebApplicationException如果检查未通过,则响应包含错误实体。

我的问题是,响应的内容类型与 Accept 不匹配请求的 header 。但是,如果我在资源中抛出相同的异常,响应将包含正确的内容类型。

代码:

我的实体:

@XmlRootElement(namespace = "http://www.mycompany.com/test")
@XmlAccessorType(value = XmlAccessType.FIELD)
public class TestEntity {

    public TestEntity() {
        this.key = "error";
    }

    @XmlElement
    private String key;
}

我的过滤器:

@Named
public class TestFilter implements ContainerRequestFilter {
    private boolean globalError = true;

    public void filter(final ContainerRequestContext requestContext) throws IOException {
        if (globalError) {
            throw new WebApplicationException(Response.status(422).entity(new TestEntity()).build());
        }
    } 
}

我的资源:

@Named
public class TestResource {

    @GET
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public void find() {
        throw new WebApplicationException(Response.status(422).entity(new TestEntity()).build());
    }
}

我的 CXF 配置:

<jaxrs:server address="/rest/v1" id="test">
    <jaxrs:serviceBeans>
        <ref bean="testResource" />
    </jaxrs:serviceBeans>
    <jaxrs:providers>
        <bean class="org.apache.cxf.jaxrs.provider.JAXBElementProvider" />
        <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider" />
        <ref bean="testFilter" />
    </jaxrs:providers>
</jaxrs:server>

测试:

请求:

GET http://localhost:8080/test-webapp/services/rest/v1/ HTTP/1.1
Accept-Encoding: gzip,deflate
Accept: application/json
Host: localhost:8080
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

响应globalError=true:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:testEntity xmlns:ns2="http://www.mycompany.com/test">
      <key>error</key>
</ns2:testEntity>

响应 globalError=false:

{"key":"error"}

问题:

为什么响应不同?我该如何修复它?

最佳答案

似乎ContainerRequestFilter的默认响应构建器不使用接受 header 来覆盖响应内容类型。需要将内容类型添加到Response

throw new WebApplicationException(Response.status(422).type("applicati‌​on/json").entity(new TestEntity()).build()

获得所需行为的一个选项是在异常响应中设置 .type 之前检查 header (使用 requestContext.abortWith() 而不是引发异常)

这是一个设置application/json(如果在 header 中找到)或返回默认类型的示例

public class TestFilter implements ContainerRequestFilter {
    private boolean globalError = true;

    private String typeFromHeaders(ContainerRequestContext requestContext){
        List<String> acceptHeaders = requestContext.getHeaders().get("Accept");
        if (acceptHeaders != null){         
            for (String acceptHeader: acceptHeaders){
                if (acceptHeader.indexOf(MediaType.APPLICATION_JSON)>=0){
                    return MediaType.APPLICATION_JSON;
                }   
            }
        }
        return null;
    }
    public void filter(final ContainerRequestContext requestContext) throws IOException {
        if (globalError) {
            requestContext.abortWith(
                    Response.status(422).type(typeFromHeaders(requestContext)).entity(new TestEntity()).build());
        }
    } 
}

关于java - ContainerRequestFilter 返回实体的错误内容类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40328055/

相关文章:

Java Spring + MongoTemplate 无法检索对象列表

Java Controller 未将 JSON 转换为实体

java - jackson 多态性: Nested Subtypes

java - 如何处理 jersey jax rs 中的横切问题

javax.ws.rs.ProcessingException,在 Payara Server 5 中找不到内容类型 application/json 类型的 writer

java - android studio Sqlite 数据库 java.lang.IllegalStateException : getDatabase called recursively

java - 列出目录中与文件掩码(又名模式或 Glob)匹配的所有文件

java - Java 类 java.util.ArrayList 的消息体编写器

Java套接字通信——提高速度

java - Json Deserializer - 如何从父 JSON 对象获取数据