2015-07-20 67 views
2

我正在使用Jersey 2.19。我想支持我的API的兩個版本。爲此,我想要有兩條主要路徑:/api/v1/api/v2。我想要兩個包com.test.v1(帶有v1 API資源)和com.test.v2(帶有v2 API資源)。在JAX-RS/Jersey中添加java包的資源路徑段?

我知道如何定義整個應用程序的路徑,我將在我的ResourceConfig類上使用@ApplicationPath('api')。但是,我將如何定義包com.test.v1資源所在的/v1命名空間,以及包com.test.v2資源所在的/v2命名空間?目前,除了在每個@Path註釋中添加「v1」和「v2」前綴之外,我沒有其他選擇,例如:每個資源的前綴@Path('v1/something')@Path('v2/something')。這是很多冗餘。

有沒有更好的方法?

回答

3

下面是一種完成此方法的概念驗證。我從來沒有使用過這個,所以我不能提供任何證明任何維護性問題的可能性,或者可能不符合大型項目的要求。我只是在一個簡單的項目上測試過。

它基本上使用澤西的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.stackoverflow.jersey.v1", "v1"); 
     packageAppenders.put("com.stackoverflow.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; 
    } 
} 

可能比它的價值更麻煩。我不知道。你可以成爲法官。

+0

我會接受你的答案,因爲它回答我的原始問題。我最終採取了不同的路徑,請看我的答案。 – wujek

+0

@wujek是的我完全忘了這麼做。我會繼續並接受你自己的答案。它更有意義。 –

3

最後我決定只配置和部署2個Jersey servlet。 API的V1在module_v1中,V2在module_v2中,並且我有兩個包含2個ResourceConfig的servlet。第一個資源配置定義路徑'v1',第二個'v2',它們都是相對於'api'的根。這工作得很好,並允許簡單刪除任何版本。