Java 通过工件版本向后兼容

Java 通过工件版本向后兼容,java,xml,maven,Java,Xml,Maven,我正在用三个maven项目开发一个RESTful Web应用程序。这是我的maven设置(从一些细节中删除) 客户端(第二版): com.mycompany.app:app model:2.0中的类Foo package com.mycompany.app.model.v2; public class Foo { private String name; private int age; } 在第一个版本中,一切正常,因为webapp只依赖com.mycompany.app:

我正在用三个maven项目开发一个RESTful Web应用程序。这是我的maven设置(从一些细节中删除)

客户端(第二版):

com.mycompany.app:app model:2.0中的类Foo

package com.mycompany.app.model.v2;

public class Foo {
    private String name;
    private int age;
}
在第一个版本中,一切正常,因为webapp只依赖com.mycompany.app:app model:1.0。 在第二个版本中,maven决定只依赖com.mycompany.app:app model:2.0。 这是正常的行为,我理解为什么在正常情况下这是件好事。 然而我的Backwords compapility代码(在服务器中)希望使用com.mycompany.app:app model:1.0中的类,因为该版本中发布的客户端使用这些类。 新客户端(版本2.0)的代码希望使用com.mycompany.app:app model:2.0类

我相信有一种方法可以欺骗maven同时依赖这两种方法,但是如何做到呢? 通常当我在这种情况下结束时,我的大脑会发出警报,我解决问题的方式通常会有问题。 但我似乎找不到另一种方法,它不包括其他“更大”的缺点:(
Idees any?

问题比Maven更严重。默认情况下,JVM只会加载一个类的一个版本。如果有两个版本的
com.mycompany.app.model.ModelObject
(例如)在程序的类路径上,当一个类请求
ModelObject
时,类加载器将输出并加载它找到的第一个类

我在公共web服务中看到的一种处理方法是根据其版本命名所有类。例如,版本1模型类可以放在包
com.mycompany.app.model_1
中,版本2模型类可以放在
com.mycompany.app.model_2
中。您(和客户端)不过,在这种情况下,最终可能会编写相当多的额外代码

可能更简单的方法是只为您要支持的模型的每个版本托管一个单独的webapp,webapp路径基于模型版本。因此,在这种情况下,版本1 webapp可能托管在
http://app.mycompany.com/webapp_1/...
和版本2位于
http://app.mycompany.com/webapp_2/...
。(web服务器为每个webapp使用单独的类加载器,因此webapp_1和webapp_2可以使用同一类的不同版本。)


(如果你喜欢冒险,你也可以尝试在一个webapp中为每个模型版本设置自己的类加载器。不过,我不知道我是否推荐这样做。)问题比Maven更严重。默认情况下,JVM将只加载一个类的一个版本。如果程序的类路径上有两个版本的
com.mycompany.app.model.ModelObject
(例如),当其中一个类请求
ModelObject
,则类加载器将退出并加载找到的第一个版本

我在公共web服务中看到的一种处理方法是根据其版本命名所有类。例如,版本1模型类可以放在包
com.mycompany.app.model_1
中,版本2模型类可以放在
com.mycompany.app.model_2
中。您(和客户端)不过,在这种情况下,最终可能会编写相当多的额外代码

可能更简单的方法是只为您要支持的模型的每个版本托管一个单独的webapp,webapp路径基于模型版本。因此,在这种情况下,版本1 webapp可能托管在
http://app.mycompany.com/webapp_1/...
和版本2位于
http://app.mycompany.com/webapp_2/...
。(web服务器为每个webapp使用单独的类加载器,因此webapp_1和webapp_2可以使用同一类的不同版本。)

(如果你喜欢冒险,你也可以尝试在一个webapp中为每个模型版本设置自己的类加载器。不过,我不知道我是否推荐这样做。)

您可以使用将这些工件复制到项目中的一个目录中。复制同一工件的多个版本应该是可以的。尽管这对根据这些不同版本编译代码没有帮助(您可能需要手动配置其他类路径)

或者只需更改每个版本的工件ID。

您可以使用将这些工件复制到项目中的一个目录中。复制同一工件的多个版本应该是可以的。尽管这对针对这些不同版本编译代码没有帮助(您可能需要将附加类路径配置为手写)


或者只需更改每个版本的工件ID。

所以,回答我自己的问题,这就是我提出的。我认为这是一个非常简单的问题,没有太多的开箱即用

最初我有3件艺术品:

  • com.mycompany.app:app客户端
  • com.mycompany.app:应用程序模型
  • com.mycompany.app:app webapp
最后我又介绍了一件工艺品:

  • com.mycompany.app:app依赖于
此工件唯一的工作是将所有已发布的模型工件捆绑到一个可靠的工件中。为此,我遵循Esko的建议并使用maven插件:

  • 插件:maven依赖插件
目标是解包。这将所有的.class文件放在目标下的一个目录中,因为我确保每个模型版本都在一个唯一的包中生成类,所以它运行良好,没有任何覆盖。我只包含了.class文件,省略了所有其他文件(MANIFEST.MF、pom.xml和pom.properties)

在那之后,trix很简单。我所要做的就是向工件添加一个资源,因为它不包含任何其他源,所以它成为了一个新的可靠工件。很好

现在,为了让所有这些都按我想要的方式工作,我在我的webapp工件中将新工件声明为一个依赖项,允许我访问模型所有版本中的所有类
<project>
    <groupId>com.mycompany.app</groupId>
    <artifactId>app-model</artifactId>
    <version>2.0</version>
</project>
...
<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <configuration>
        <generatePackage>com.mycompany.app.model.v2</generatePackage>
    </configuration>
</plugin>
<project>
    <groupId>com.mycompany.app</groupId>
    <artifactId>app-webapp</artifactId>
    <version>2.0</version>
    ...
    <dependency>
        <groupId>com.mycompany.app</groupId>
        <artifactId>app-model</artifactId>
        <version>1.0</version>
    </dependency>
    <dependency>
        <groupId>com.mycompany.app</groupId>
        <artifactId>app-model</artifactId>
        <version>2.0</version>
    </dependency>
</project>
package com.mycompany.app.model.v1;

public class Foo {
    private String name;
}
package com.mycompany.app.model.v2;

public class Foo {
    private String name;
    private int age;
}
<project>

  <groupId>com.mycompany.app</groupId>
  <artifactId>app-depend</artifactId>
  <version>2.0</version>
  <packaging>jar</packaging>

  <build>
    <resources>
      <resource>
        <!-- this is where 'unpack' puts the files -->
        <directory>${project.build.directory}/dependency</directory>
        <filtering>false</filtering>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.5.1</version>
        <executions>
          <execution>
            <id>unpack</id>
            <!-- we must do the 'unpack' before the building the jar -->
            <phase>generate-sources</phase>
            <goals>
              <goal>unpack</goal>
            </goals>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>com.mycompany.app</groupId>
                  <artifactId>app-model</artifactId>
                  <version>1.0</version>
                  <type>jar</type>
                  <includes>com/mycompany/app/model/v1/**</includes>
                </artifactItem>
                <artifactItem>
                  <groupId>com.mycompany.app</groupId>
                  <artifactId>app-model</artifactId>
                  <version>2.0</version>
                  <type>jar</type>
                  <includes>com/mycompany/app/model/v2/**</includes>
                </artifactItem>
                <!-- future releases will go here -->
              </artifactItems>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

</project>