如何创建子资源@Path没有前导斜杠的JAX-RS服务

Mat*_*att 5 java jax-rs path mime-types

我创建了一个JAX-RS服务(MyService),它有许多子资源,每个子资源都是MySubResource的子类.选择的子资源类是根据MyService路径中给出的参数选取的,例如:

@Path("/") @Provides({"text/html", "text/xml"}) 
public class MyResource {
  @Path("people/{id}") public MySubResource getPeople(@PathParam("id") String id) {
    return new MyPeopleSubResource(id);
  }
  @Path("places/{id}") public MySubResource getPlaces(@PathParam("id") String id) {
    return new MyPlacesSubResource(id);
  }
}
Run Code Online (Sandbox Code Playgroud)

其中MyPlacesSubResource和MyPeopleSubResource都是MySubResource的子类.

MySubResource定义为:

public abstract class MySubResource {
  protected abstract Results getResults();

  @GET public Results get() { return getResults(); }

  @GET @Path("xml") 
  public Response getXml() {
    return Response.ok(getResults(), MediaType.TEXT_XML_TYPE).build();  
  }

  @GET @Path("html") 
  public Response getHtml() {
    return Response.ok(getResults(), MediaType.TEXT_HTML_TYPE).build();  
  }
}
Run Code Online (Sandbox Code Playgroud)

结果由相应的MessageBodyWriters处理,具体取决于响应的mimetype.

虽然这可以产生像/ people/Bob/html或/ people/Bob/xml这样的路径,我真正想要的是/people/Bob.html或/people/Bob.xml

有谁知道如何完成我想做的事情?

Pet*_*ter 7

老话题,但这是我最近使用Jersey解决的问题; 也许它会帮助别人.

Jersey支持通过使用请求过滤器将接受的内容类型指定为URI中的文件扩展名.Jersey提供了一个UriConnegFilter(URI内容协商过滤器)对象,您可以将其扩展为将特定扩展名转换为内容类型.然后,将该过滤器作为初始参数包含在Jersey应用程序中.

由于这一切听起来都很模糊,这是我项目的一个具体例子:

我希望能够在URL的末尾解释".json"和".xml",这意味着客户端分别需要JSON格式或XML格式的内容.为此,我这样扩展UriConnegFilter:

package my.filter.package;

import com.sun.jersey.api.container.filter.UriConnegFilter;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.core.MediaType;


public class MediaTypeFilter extends UriConnegFilter {
  private static final Map<String, MediaType> mappedMediaTypes = new HashMap<String, MediaType>(2);

  static {
    mappedMediaTypes.put("json", MediaType.APPLICATION_JSON_TYPE);
    mappedMediaTypes.put("xml", MediaType.APPLICATION_XML_TYPE);
  }

  public MediaTypeFilter() {
    super(mappedMediaTypes);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,因为我使用Jersey作为Servlet,我添加MediaTypeFilter到我的web.xml:

<servlet>
  <servlet-name>My Jersey Servlet</servlet-name>
  <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
  <init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>my.resource.package</param-value>
  </init-param>
  <init-param>
    <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
    <param-value>com.sun.jersey.api.container.filter.LoggingFilter;
                 my.filter.package.MediaTypeFilter;
                 com.sun.jersey.api.container.filter.PostReplaceFilter;
                 com.sun.jersey.api.container.filter.GZIPContentEncodingFilter</param-value>
  </init-param>
  <init-param>
    <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
    <param-value>com.sun.jersey.api.container.filter.GZIPContentEncodingFilter;
                 com.sun.jersey.api.container.filter.LoggingFilter</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
Run Code Online (Sandbox Code Playgroud)

有了这个,Jersey会将URI上的扩展名转换为指定的媒体类型,并删除扩展名.这适用于根资源和子资源,因为它在整个URI上运行.对于您的特定示例,/people/Bob.xml将成为/ people/Bob,Accept请求中的标头将更改为"application/xml"(覆盖任何现有Accept标头).

心连心,

-Peter