在 JAX-RS/Jersey 中为 java 个包添加资源路径段?
Add resource path segment for java packages in JAX-RS/Jersey?
我正在使用 Jersey 2.19。我想支持我的 API 的两个版本。为此,我希望有两条主要路径:/api/v1
和 /api/v2
。我想要两个包 com.test.v1
(具有 v1 API 资源)和 com.test.v2
(具有 v2 API 资源)。
我知道如何为整个应用程序定义路径,我只会在 ResourceConfig
class 上使用 @ApplicationPath('api')
。但是,我如何定义包 com.test.v1
资源位于 /v1
命名空间中,而包 com.test.v2
资源位于 /v2
命名空间中?目前,除了在每个 @Path
注释中添加 'v1' 和 'v2' 前缀外,我没有其他选择,例如:每个资源的 @Path('v1/something')
或 @Path('v2/something')
前缀。这是很多冗余。
有没有更好的方法?
下面是实现此目的的一种方法的概念验证。我从未使用过它,所以我无法真正提供任何可维护性问题的证明,这些可维护性问题可能会或可能不会出现在大型项目中。我刚刚测试了一个简单的项目。
它基本上使用 Jersey 的 Programmatic resource building API 将版本附加到原始路径。
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.server.model.ModelProcessor;
import org.glassfish.jersey.server.model.Resource;
import org.glassfish.jersey.server.model.ResourceModel;
@Provider
public class VersioningModelProcessor implements ModelProcessor {
private Map<String, String> packageAppenders = new HashMap<>();
{
packageAppenders.put("com.Whosebug.jersey.v1", "v1");
packageAppenders.put("com.Whosebug.jersey.v2", "v2");
}
@Override
public ResourceModel processResourceModel(ResourceModel model, Configuration config) {
// Create new resourc model.
ResourceModel.Builder newModelBuilder = new ResourceModel.Builder(false);
for (final Resource resource: model.getResources()) {
// Look for the package
String path = resource.getPath();
Class handlerClass = resource.getHandlerClasses().iterator().next();
String pkg = handlerClass.getPackage().getName();
// Match the packge to our map of packages
if (packageAppenders.containsKey(pkg)) {
// append the version
String version = packageAppenders.get(pkg);
path = version + "/" + path.replace("/", "");
Resource.Builder resourceBuilder = Resource.builder(resource);
resourceBuilder.path(path);
Resource newResource = resourceBuilder.build();
System.out.println(newResource.toString());
// add the new resource with the new path.
newModelBuilder.addResource(newResource);
} else {
// Do nothing. Just add the resource as normal
newModelBuilder.addResource(resource);
}
}
return newModelBuilder.build();
}
@Override
public ResourceModel processSubResource(ResourceModel model, Configuration config) {
return model;
}
}
可能麻烦多于它的价值。我不知道。你可以当裁判。
最后我决定只配置和部署 2 个 Jersey servlet。 API 的 V1 在 module_v1 中,V2 在 module_v2 中,我有两个带有 2 个 ResourceConfig 的 servlet。第一个资源配置定义路径 'v1',第二个 'v2',它们都相对于 'api' 的根目录。这工作得很好,允许简单地删除任何版本。
我正在使用 Jersey 2.19。我想支持我的 API 的两个版本。为此,我希望有两条主要路径:/api/v1
和 /api/v2
。我想要两个包 com.test.v1
(具有 v1 API 资源)和 com.test.v2
(具有 v2 API 资源)。
我知道如何为整个应用程序定义路径,我只会在 ResourceConfig
class 上使用 @ApplicationPath('api')
。但是,我如何定义包 com.test.v1
资源位于 /v1
命名空间中,而包 com.test.v2
资源位于 /v2
命名空间中?目前,除了在每个 @Path
注释中添加 'v1' 和 'v2' 前缀外,我没有其他选择,例如:每个资源的 @Path('v1/something')
或 @Path('v2/something')
前缀。这是很多冗余。
有没有更好的方法?
下面是实现此目的的一种方法的概念验证。我从未使用过它,所以我无法真正提供任何可维护性问题的证明,这些可维护性问题可能会或可能不会出现在大型项目中。我刚刚测试了一个简单的项目。
它基本上使用 Jersey 的 Programmatic resource building API 将版本附加到原始路径。
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.server.model.ModelProcessor;
import org.glassfish.jersey.server.model.Resource;
import org.glassfish.jersey.server.model.ResourceModel;
@Provider
public class VersioningModelProcessor implements ModelProcessor {
private Map<String, String> packageAppenders = new HashMap<>();
{
packageAppenders.put("com.Whosebug.jersey.v1", "v1");
packageAppenders.put("com.Whosebug.jersey.v2", "v2");
}
@Override
public ResourceModel processResourceModel(ResourceModel model, Configuration config) {
// Create new resourc model.
ResourceModel.Builder newModelBuilder = new ResourceModel.Builder(false);
for (final Resource resource: model.getResources()) {
// Look for the package
String path = resource.getPath();
Class handlerClass = resource.getHandlerClasses().iterator().next();
String pkg = handlerClass.getPackage().getName();
// Match the packge to our map of packages
if (packageAppenders.containsKey(pkg)) {
// append the version
String version = packageAppenders.get(pkg);
path = version + "/" + path.replace("/", "");
Resource.Builder resourceBuilder = Resource.builder(resource);
resourceBuilder.path(path);
Resource newResource = resourceBuilder.build();
System.out.println(newResource.toString());
// add the new resource with the new path.
newModelBuilder.addResource(newResource);
} else {
// Do nothing. Just add the resource as normal
newModelBuilder.addResource(resource);
}
}
return newModelBuilder.build();
}
@Override
public ResourceModel processSubResource(ResourceModel model, Configuration config) {
return model;
}
}
可能麻烦多于它的价值。我不知道。你可以当裁判。
最后我决定只配置和部署 2 个 Jersey servlet。 API 的 V1 在 module_v1 中,V2 在 module_v2 中,我有两个带有 2 个 ResourceConfig 的 servlet。第一个资源配置定义路径 'v1',第二个 'v2',它们都相对于 'api' 的根目录。这工作得很好,允许简单地删除任何版本。