REST资源版本控制的最佳实践是将版本信息放入HTTP请求的Accept/Content-Type标头中,使URI保持不变.
以下是用于检索系统信息的REST API示例请求/响应:
==>
GET /api/system-info HTTP/1.1
Accept: application/vnd.COMPANY.systeminfo-v1+json
<==
HTTP/1.1 200 OK
Content-Type: application/vnd.COMPANY.systeminfo-v1+json
{
“session-count”: 19
}
Run Code Online (Sandbox Code Playgroud)
请注意,MIME类型中指定了版本.
这是版本2的另一个请求/响应:
==>
GET /api/system-info HTTP/1.1
Accept: application/vnd.COMPANY.systeminfo-v2+json
<==
HTTP/1.1 200 OK
Content-Type: application/vnd.COMPANY.systeminfo-v2+json
{
“uptime”: 234564300,
“session-count”: 19
}
Run Code Online (Sandbox Code Playgroud)
有关更多说明和示例,请参见http://barelyenough.org/blog/tag/rest-versioning/.
是否有可能在基于Java的JAX-RS实现中轻松实现此方法,例如Jersey或Apache CXF?
目标是让几个@Resource类具有相同的@Path值,但是根据MIME类型中指定的实际版本提供请求?
我一般都研究过JAX-RS,特别是Jersey,并没有发现它的支持.泽西岛没有机会以相同的路径注册两个资源.需要实现WebApplicationImpl类的替换以支持它.
你能提出什么建议吗?
注意:需要同时提供同一资源的多个版本.新版本可能会引入不兼容的更改.
我正在使用Jersey JAX-RS客户端(版本2.0).我知道它使用Jackson ObjectMapper来生成和解析JSON.我想使用同一个对象为某些java类生成JSON,以便我可以将它们写入日志.
我知道我可以创建一个新的ObjectMapper实例,但我更愿意请求Jersey客户端给我一个它正在使用的实例.我怎样才能做到这一点?Jersey 2.0知道Jackson,因为它包含一个JacksonFeature类,用于首先配置Jackson功能.
假设我使用@GET方法调用以下Web服务:
@GET
@Path(value = "/user/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUserCache(@PathParam("id") String id, @Context HttpHeaders headers) throws Exception {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("id", id);
SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
Cre8Mapper mapper = session.getMapper(Cre8Mapper.class);
// slow it down 5 seconds
Thread.sleep(5000);
// get data from database
User user = mapper.getUser(map);
if (user == null) {
return Response.ok().status(Status.NOT_FOUND).build();
} else {
CacheControl cc = new CacheControl();
// save data for 60 seconds
cc.setMaxAge(60);
cc.setPrivate(true);
return Response.ok(gson.toJson(user)).cacheControl(cc).status(Status.OK).build();
}
}
Run Code Online (Sandbox Code Playgroud)
为了实验,我在从数据库中获取数据之前5秒放慢当前线程的速度. …
我们使用Spring rest模板和jackson json提供程序来序列化/反序列化json.从我的服务中,我发送一个linkedHashSet,当我收到它时,它会转换为客户端的HashSet.因此我放松了元素的插入顺序.这是针对Set的jackson json提供程序的默认实现吗?有没有其他方法,所以它可以反序列化到正确的实现?我觉得这会很棘手,但你们会非常感激投入.
谢谢
对于REST服务,Jersey vs Jersey(Stand alone)vs Jersey与Grizzly vs Jersey与Tomcat有什么区别?
我可以在不需要服务器的情况下运行Jersey吗?
是否有任何实现javax.ws.rs.core.UriInfo可用于快速创建实例以进行测试.这个界面很长,我只需要测试一下.我不想在这个界面的整个实现上浪费时间.
更新:我想为类似于此的函数编写单元测试:
@GET
@Path("/my_path")
@Produces(MediaType.TEXT_XML)
public String webserviceRequest(@Context UriInfo uriInfo);
Run Code Online (Sandbox Code Playgroud) 我正在使用的API决定接受UUID作为Base32编码的字符串,而不是UUID.fromString()期望的标准十六进制,破折号分隔格式.这意味着我不能简单地写@QueryParam UUID myUuid为方法参数,因为转换会失败.
我正在解决这个问题,通过使用不同的fromString转换器编写自定义对象以与Jersey @QueryString和@FormParam注释一起使用.我希望能够访问fromString方法中的转换上下文,以便我可以提供更好的错误消息.现在,我所能做的就是以下几点:
public static Base32UUID fromString(String uuidString) {
final UUID uuid = UUIDUtils.fromBase32(uuidString, false);
if (null == uuid) {
throw new InvalidParametersException(ImmutableList.of("Invalid uuid: " + uuidString));
}
return new Base32UUID(uuid);
}
Run Code Online (Sandbox Code Playgroud)
我希望能够公开哪个参数具有无效的UUID,因此我记录的异常和返回的用户错误非常清楚.理想情况下,我的转换方法会有一个额外的参数用于细节,如下所示:
public static Base32UUID fromString(
String uuidString,
String parameterName // New parameter?
) {
final UUID uuid = UUIDUtils.fromBase32(uuidString, false);
if (null == uuid) {
throw new InvalidParametersException(ImmutableList.of("Invalid uuid: " + uuidString
+ …Run Code Online (Sandbox Code Playgroud) 我正在考虑从使用JAX RS的Apache CXF RS切换到Spring MVC REST,并看到Spring MVC REST当前处理ETag的方式存在一些问题.也许我不理解正确,或者有更好的方法来实现JAX RS目前正在做的事情?
使用Apache CXF RS,在REST服务内部评估上次修改时间戳和ETag的条件(条件评估实际上非常复杂,请参阅RFC 2616第14.24和14.26节,所以我很高兴这对我来说是完成的).代码看起来像这样:
@GET
@Path("...")
@Produces(MediaType.APPLICATION_JSON)
public Response findBy...(..., @Context Request request) {
... result = ...fetch-result-or-parts-of-it...;
final EntityTag eTag = new EntityTag(computeETagValue(result), true);
ResponseBuilder builder = request.evaluatePreconditions(lastModified, eTag);
if (builder == null) {
// a new response is required, because the ETag or time stamp do not match
// ...potentially fetch full result object now, then:
builder = Response.ok(result);
} else {
// a new response is not needed, …Run Code Online (Sandbox Code Playgroud) jax-rs ×10
java ×6
rest ×5
jersey ×4
jackson ×2
annotations ×1
clojure ×1
etag ×1
grizzly ×1
http ×1
http-caching ×1
jersey-2.0 ×1
json ×1
spring ×1
spring-mvc ×1
unit-testing ×1
versioning ×1
web-services ×1