自定义内容协商处理扩展和与泽西的“接受”标头

时间:2014-10-05 21:46:56

标签: java rest jersey

我有这个资源(简化):

@Path("/cars{extension:(\\.(xml|json))?}")
public class Cars {

    @GET
    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
    public Response searchCars(@PathParam("extension") String extension) {
        System.out.println("extension: " + extension);
        //...
        return Response.status(200).entity(output).build();
    }
}

我希望,例如(但业务逻辑可以更改),如果扩展名为xml则返回xml响应,如果扩展名为json则返回Json,无论标题为“Accept”是什么。 事情是默认情况下我想使用Accept标头,但让我们说一些虚拟人想要使用Ajax访问我的Web服务并且对标题知之甚少,我想通过添加适当的扩展来为他轻松做事。
通过该片段,我可以获得扩展(如果有),但我不知道如何相应地更改策略。

谢谢!

修改
所以我找到了一些东西,我可以使用Response.ResponseBuilder中的.type(),如:

Response.ResponseBuilder responseBuilder = Response.status(200).entity(output);
if ([some test about extention or header])
    responseBuilder.type(MediaType.APPLICATION_XML);
// other tests

我不知道这是否是正确的方法,但这意味着我需要为所有路径处理它......

1 个答案:

答案 0 :(得分:0)

我会为此使用ContainerResponseFilter,因此您不会为每条路径使用它。

首先检查扩展名 - 也就是假人喜欢的MediaType。

比检查您的服务是否可接受所请求的MediaType。如果没有,我会说假人运气不好;)

示例代码 [jersey 2.x]

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.List;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;

@Provider
public class EntityResponseFilter implements ContainerResponseFilter {

    @Override
    public void filter( ContainerRequestContext reqc , ContainerResponseContext resc ) throws IOException {
        MediaType mediaType = this.getMediaTypeFromExtentionOrHeader(); // TODO
        List<MediaType> mediaTypes = reqc.getAcceptableMediaTypes();
        if( mediaTypes.contains(mediaType) ) {   
            resc.setEntity( resc.getEntity(), new Annotation[0], mediaType );
        }
        // ...
    }
}

希望这在某种程度上有所帮助:)