我需要实现一个使用第一个查询参数来标识操作的Web服务,即客户端调用将类似于:http://localhost:8080/ws/operation?info或http://localhost:8080/ws/operation?create&name=something。
http://localhost:8080/ws/operation?info
http://localhost:8080/ws/operation?create&name=something
似乎我无法使用@Path注释来区分方法,因为区别特征在于查询参数。以下示例也引发了异常:
package com.example.ws; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.QueryParam; @Path("/operation") public class Operation { @GET public String info(@QueryParam("info") String info) { return "info"; } @GET public String create(@QueryParam("create") String create) { return "create"; } }
有没有一种方法可以根据查询参数指定要使用的方法?还是我真的必须定义一种方法并在其中检查是否设置了某些查询参数?
我认为Claudio是正确的-您可以使用Jersey,但是您将自己处理查询参数,因为它仅在路径上匹配。
您可以注入UriInfo并从中提取查询参数:
@Path("/operation") public class Operation { @Context protected UriInfo info; @GET public String operation() { if (info.getQueryParameters().containsKey("create")) // do stuff else if (info.getQueryParameters().containsKey("info")) // other stuff } }
@Path("/operation") public class Operation { @Context protected UriInfo info; @GET public String operation() { if (info.getQueryParameters().containsKey("create")) // do stuff else if (info.getQueryParameters().containsKey("info")) // other stuff }
}
您可以从Jersey切换到另一个框架。我相信Spring 可以根据查询参数路由到多种方法。
如您所述,也许您可以编写一些更标准的内容,然后将请求重新映射到该标准。例如,您可以使用Servlet过滤器或前端服务器(如Apache httpd或nginx)来修改请求。
从资源的角度考虑这些操作是在做什么?客户帐户,电影,股票交易等。出于争论的缘故,我们将其称为“ Foo”。您可能会使用类似以下的内容:
@Path("/foo") public class FooResource { @Context protected UriInfo info; @GET @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Foo getById(@QueryParam("id") int id) { // get Foo by id Foo = .... // return an instance of Foo and let Jersey convert it to XML // or JSON depending on the "Accept" header that the client sent return foo; } @POST @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response create(Foo instance) { // let Jersey deserialize the request body from JSON or XML. // save the instance however you want int id = fooService.save(instance); // return a 204 "created" with a "Location" header URI location = info.getAbsolutePathBuilder().path(“{id}”).build(id); return Response.created(location).build(); } }
@Path("/foo") public class FooResource { @Context protected UriInfo info; @GET @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Foo getById(@QueryParam("id") int id) { // get Foo by id Foo = .... // return an instance of Foo and let Jersey convert it to XML // or JSON depending on the "Accept" header that the client
sent return foo; }
@POST @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Response create(Foo instance) { // let Jersey deserialize the request body from JSON or XML. // save the instance however you want int id = fooService.save(instance); // return a 204 "created" with a "Location" header URI location =
info.getAbsolutePathBuilder().path(“{id}”).build(id); return Response.created(location).build(); }
听起来您的URI结构是由其他人强制执行的,因此这可能不是您的选择。如果您继续使用当前的URI结构,则应注意一个主要陷阱。
根据HTTP 1.1规范,GET请求应该是幂等的。您当前的设计似乎正在使用GET请求创建新的服务器端实例。可能会损坏…中间代理或Web浏览器可能会缓存对GET请求的响应,并阻止创建新实例。