Java Restlet内容类型协商

Java Restlet内容类型协商,java,mime-types,content-type,restlet,media-type,Java,Mime Types,Content Type,Restlet,Media Type,API通常支持各种形式的内容协商:AcceptHTTP头请求,content-TypeHTTP头请求(尽管我认为不符合标准),以及从文件扩展名派生期望的类型。我希望我的Restlet REST API能够支持所有这些,我正在寻求帮助,以了解如何做到这一点 我的第一个努力是看看Restlet是否支持它。我使用的是Jackson扩展,因此我创建了一个简单的应用程序,它将/foo路由到一个服务器资源,该服务器资源返回一个映射 当我简单地与/foo建立GET HTTP URL连接(la)时,我得到了XM

API通常支持各种形式的内容协商:
Accept
HTTP头请求,
content-Type
HTTP头请求(尽管我认为不符合标准),以及从文件扩展名派生期望的类型。我希望我的Restlet REST API能够支持所有这些,我正在寻求帮助,以了解如何做到这一点

我的第一个努力是看看Restlet是否支持它。我使用的是Jackson扩展,因此我创建了一个简单的应用程序,它将
/foo
路由到一个
服务器资源
,该服务器资源返回一个
映射

当我简单地与
/foo
建立GET HTTP URL连接(la)时,我得到了XML。我希望这个默认值是JSON。这就是问题所在如何设置默认的JSON类型?

当我对
/foo.xml
/foo.json
进行相同的HTTP URL连接调用时,我得到一个404。这是问题之二如何使用文件扩展名来表示预期的媒体类型?

因为我在Servlet容器中运行,所以我当前的方法是包装
HttpServletRequest
,如果没有文件扩展名,则将
Accept
HTTP头设置为
application/json
。这是一个目前正在解决问题1的黑客。然而,我一直无法扩展这种方法,以摆脱问题2中的404


Restlet使许多其他事情变得简单,我假设我遗漏了一些东西——有一些配置问题,我可以在某个地方进行调整,使它做正确的事情。我在API文档中看到了关于这一点的提示,但没有什么明显的。那么这是什么配置呢?

最简单的方法是在应用程序的路由器前面添加一个自定义过滤器,以执行以下操作:

  • 如果接受的媒体类型列表为空(
    request.clientInfo.acceptedMediaTypes
    ),请设置默认媒体类型。标题Accept的值在此处设置。在执行服务器资源之前设置它很重要,这样在从bean到表示的转换过程中就可以考虑到这一点

    Filter preferencesFilter = new Filter(getContext()) {
        protected int beforeHandle(Request request, Response response) {
            if (request.getClientInfo().getAcceptedMediaTypes().isEmpty()) {
                request.getClientInfo().accept(MediaType.APPLICATION_JSON);
            } else if ((request.getClientInfo().getAcceptedMediaTypes().size() == 1)
                && (request.getClientInfo().getAcceptedMediaTypes().get(0).getMetadata().equals(MediaType.ALL))) {
                request.getClientInfo().accept(MediaType.APPLICATION_JSON);
            }
            return super.beforeHandle(request, response);
        }            
    }
    
    作为信息,当指定no-accept媒体类型时,Restlet使用注册媒体的第一个转换器来实际构建响应内容。在您的案例中,它似乎就是XML

  • 检测提供的扩展以推断您的情况下相应的可接受媒体类型。Restlet的
    TunnelService
    允许对请求进行预处理,以支持使用扩展进行内容协商等功能。您只需按如下所述进行配置:

    public class MyApplication extends Application {
        public MyApplication() {
            getTunnelService().setExtensionsTunnel(true);
        }
    
        @Override
        public Restlet createInboundRoot() {
            (...)
        }
    }
    
否则,在使用Restlet时不应该依赖servlet API。servlet扩展只应被视为在servlet容器中嵌入Restlet应用程序的适配器

它在以下地址为您的用例添加了一个示例项目:

希望它能帮助你,
Thierry

如果您想查看我使用的代码库,这里是:“否则,在使用Restlet时应该依赖servlet API。”您的意思是,“否则,在使用Restlet时不应该依赖servlet API吗?”?