如何在子资源@Path不加斜杠的情况下创建JAX-RS服务 [英] How to create a JAX-RS service where the sub-resource @Path doesn't have a leading slash

查看:79
本文介绍了如何在子资源@Path不加斜杠的情况下创建JAX-RS服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've created a JAX-RS service (MyService) that has a number of sub resources, each of which is a subclass of MySubResource. The sub resource class being chosen is picked based on the parameters given in the MyService path, for example:

@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);
  }
}

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

where MyPlacesSubResource and MyPeopleSubResource are both sub-classes of MySubResource.

MySubResource定义为:

MySubResource is defined as:

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();  
  }
}

结果由相应的MessageBodyWriters处理,具体取决于响应的模仿类型.

Results is processed by corresponding MessageBodyWriters depending on the mimetype of the response.

虽然这行得通,但会导致类似/people/Bob/html或/people/Bob/xml的路径,而我真正想要的是/people/Bob.html或/people/Bob.xml

While this works it results in paths like /people/Bob/html or /people/Bob/xml where what I really want is /people/Bob.html or /people/Bob.xml

有人知道如何完成我想做的事吗?

Does anybody know how to accomplish what I want to do?

推荐答案

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

Old topic, but this is something I solved recently using Jersey; perhaps it'll help someone else.

Jersey支持通过使用请求过滤器将接受的内容类型指定为URI中的文件扩展名.泽西岛提供了 (URI内容协商筛选器)对象,可将特定扩展名转换为内容类型.然后,您将该过滤器作为Jersey应用程序的初始参数添加.

Jersey supports specifying the accepted content type as a file extension in the URI through the use of request filters. Jersey supplies a UriConnegFilter (URI Content Negotiation Filter) object that you extend to translate specific extensions to content types. You then include that filter as an initial parameter to the Jersey application.

由于所有内容都含糊不清,因此这是我的项目中的一个具体示例:

Since that all sounds so vague, here's a concrete example from my project:

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

I wanted to be able to interpret ".json" and ".xml" at the end of the URL as meaning that the client wanted JSON-formatted or XML-formatted content, respectively. To that end, I extended UriConnegFilter like so:

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);
  }
}

然后,由于我将Jersey用作Servlet,因此我在Web.xml中添加了MediaTypeFilter:

Then, since I am using Jersey as a Servlet, I added MediaTypeFilter to my 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>

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

With that in place, Jersey translates the extension on the URI into the specified media type, and removes the extension. This works for root resources and sub-resources because it operates on the whole URI. For your particular example, /people/Bob.xml would become /people/Bob and the Accept header in the request would be changed to "application/xml" (overriding any existing Accept header).

hth

-彼得

这篇关于如何在子资源@Path不加斜杠的情况下创建JAX-RS服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆