如何在jsp页面中获取maven项目的版本号?

30
我正在开发一个由Maven2管理的Java Web应用程序。我们时不时地进行一些更改,并希望发布新版本,当然需要有一个新的版本号。在主页(JSP)中,有类似以下文本: ```html

<b>version:</b> 2.3.3... 

每次我发布新版本时,是否可以只更改<version/>中的内容,并且使用maven ${project.version}自动填充jsp中的版本号?

我尝试过使用maven配置文件,但似乎并没有起作用。

你有什么想法吗?

谢谢。


顺便提一下,我使用资源过滤和Maven配置文件来处理其他配置文件,例如Spring XML文件,它们可以正常工作。但对于JSP文件,无法工作。 - Kent
11个回答

32
您可以使用项目过滤器来处理将JSP复制到目标位置的过程。如果JSP是用${project.version}指定的,并且包含文件夹被指定为过滤器位置,则该值应该在JSP打包时替换进去。
例如,向您的POM中添加以下内容即可启用src/main/resources的过滤:
<resources>
  <resource>
    <directory>src/main/resources</directory>
    <filtering>true</filtering>
  </resource>
</resources>

更新:对于战争打包,您可能需要配置war插件以进行过滤。有关更多详细信息和示例,请参阅war-plugin的documentation中的“Filtering”部分。

基本上,流程是相同的,但它在war插件下定义,因此您会得到类似以下的内容:

<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.0</version>
    <configuration>
      <webResources>
        <resource>
          <directory>src/main/resources</directory>
          <filtering>true</filtering>
        </resource>
      </webResources>
    </configuration>
  </plugin>
</plugins>

很高兴能够帮忙。这适用于在过滤器设置时设置的任何属性。 - Rich Seller
抱歉,刚才我检查了错误的文件,并认为它正在工作。我添加了: <resource> <directory>src/main/webapp</directory> <filtering>true</filtering> </resource> 并在src/main/resources下有一个test.jsp,其中包含${project.version}。当我运行mvn clean package后,版本号未分配给${...}。我做错了什么吗? - Kent
感谢您的评论。 我们的项目结构如下: src/main/webapp/css, images... | src/main/webapp/WEB-INF/jsp/这里是jsps | src/main/resource/属性文件、xml配置文件等 | src/main/java/java.packages.and.sourcecodes | 现在我发现问题是,如果将jsp页面视为资源,那么就有两个资源目录,并且每个目录都有不同的目标输出。:src/main/resources/. -> target/../WEB-INF/classes/. | .../jsp/.jsp ->target/../WEB-INF/jsp/.jsp。 也许资源插件'copy-resources'可以帮忙? - Kent
对于任何试图找出正确答案的人:这是正确的答案。感谢@rich-seller! - Clint Eastwood
War插件的正确配置 https://dev59.com/yWUo5IYBdhLWcg3w1yPH#16776348 - John29
显示剩余2条评论

13

或许有些愚蠢,但我会像这个例子中使用 .properties 文件来代替直接过滤 JSP。


1
最终,我是这样做的。我在现有的属性文件中添加了一个条目,并让mvn填充版本。并添加了一个自动启动的servlet。当应用程序上下文启动时,servlet读取prop文件并设置系统属性,例如“myVersion”,以便jsp可以通过名称检索。使用maven资源插件copy-resources目标也可以工作。但是,我也觉得将jsp过滤为资源不太干净。我们使用apache-tiles进行布局,也就是说,在某些jsp中,已经有了${...}用于tiles。如果一些${}是由maven添加的,则可能会令人困惑。谢谢大家的评论。肯特 - Kent

3

使用 maven-replacer-plugin

将以下代码添加到你的 pom.xml 中:

    <plugin>
        <groupId>com.google.code.maven-replacer-plugin</groupId>
        <artifactId>replacer</artifactId>
        <version>(version)</version>
        <executions>
            <execution>
                <phase>prepare-package</phase>
                <goals>
                    <goal>replace</goal>
                </goals>                    
            </execution>
        </executions>
        <configuration>
            <ignoreMissingFile>true</ignoreMissingFile>
            <file>target/someapp/jsp/helloWorld.jsp</file>
            <outputFile>
                target/someapp/jsp/helloWorld-updated.jsp
            </outputFile>
            <regex>false</regex>
            <token>$BUILD_NUMBER$</token>
            <value>${buildNumber}</value>
        </configuration>
    </plugin>

现在,在指定的文件中,无论出现在哪里,只要有$BUILD_NUMBER$标记,该标记就会被替换。


2

这篇文章已经发布了一段时间,但我希望它能有所帮助。它将会获取从Maven生成的属性:

<%@ page import="java.util.*"%>
<%
    java.io.InputStream inputStream = getServletContext().getResourceAsStream("/META-INF/maven/com.filhetallard.fam.ged/famdox/pom.properties");
    Properties mavenProperties= new Properties();
    mavenProperties.load(inputStream );
    String version = (String) mavenProperties.get("version");
    String name = (String) mavenProperties.get("artifactId");

%><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head> 
    <title>Application <%= name %> v<%= version %></title>

不幸的是,这里有一些缺点:

  • 您必须在代码中明确编写groupId和artifactId
  • 如果直接从target/部署您的Web应用程序到服务器,它将找不到该文件,因为该文件位于maven-archiver目录中,而不是在打包之前的META-INF目录中。

敬礼。


2
我想做同样的事情,但我对任何现有的解决方案都不满意,包括使用Maven过滤方法,这是可以的,但我试图在构建过程中避免修改现有的代码文件,因此我排除了该方法,尽管它是一个合理的方法。
我将我的Maven项目版本号传递到JSP文件的方式基于类似于这里的方法,不同之处在于我没有创建Version.java文件,而是让Maven将版本写入属性文件,例如“version.properties”,如下所示:
version.properties:
app.version = 0.1

例如,您可以让Maven将其放在类路径中,例如在src/main/resources中:

    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.7</version>
    <executions>
          <execution>
            <goals>
              <goal>run</goal>
            </goals>
            <phase>generate-sources</phase>
            <configuration>
            <!-- Idea from link: https://dev59.com/PXE95IYBdhLWcg3wEpzo -->
              <target>
                <property name="resources.dir" value="${project.build.sourceDirectory}/../resources" />
                <property name="version.filename" value="version.properties" />
                <property name="buildtime" value="${maven.build.timestamp}" />
                <echo message="Writing project version string to ${resources.dir}/${version.filename} ..." />
                <echo file="${resources.dir}/${version.filename}" message="app.version = ${project.version}${line.separator}" />
              </target>
            </configuration>
          </execution>
        </executions>
  </plugin>

此外,如果您正在使用Spring Framework 3.x+,则可以添加以下配置以在version.properties中加载属性(如果存在),否则只需显示“v0.0”或其他内容:
@Configuration
@EnableWebMvc
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class WebHomeConfig extends WebMvcConfigurerAdapter implements
    ApplicationContextAware {

  private ApplicationContext _appContext;


  /*
   * (non-Javadoc)
   * 
   * @see
   * org.springframework.context.ApplicationContextAware#setApplicationContext
   * (org.springframework.context.ApplicationContext)
   */
  @Override
  public void setApplicationContext(ApplicationContext appContext)
      throws BeansException {
    _appContext = appContext;
  }

  @Bean
  public ViewResolver getViewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");
    resolver.getAttributesMap().put("appVersion", appVersion);
    return resolver;
  }


  /**
   * Since we don't have any controller logic, simpler to just define
   * controller for page using View Controller. Note: had to extend
   * WebMvcConfigurerAdapter to get this functionality
   * 
   * @param registry
   */
  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/").setViewName("home");
  }

  /**
   * The application version.
   */
  @Value("${app.version:0.0}")
  protected String appVersion;

  @Bean
  public static PropertySourcesPlaceholderConfigurer configurer() {
    PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();

    configurer.setIgnoreResourceNotFound(true);
    configurer.setLocations(new Resource[] {
        new ClassPathResource("version.properties")});
    return configurer;
  }

}

最后,在您的/WEB-INF/views/home.jsp文件中,您可以添加以下内容:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Service Status</title>
    </head>
    <body>
        <h1>Service API</h1>
        <p>The service is up and running! (v${appVersion})</p>
    </body>
</html>

当然,这将呈现为:

服务已经启动运行! (v0.1)

注意:如果您不使用JavaConfig类来配置Spring框架,则可以使用Spring XML配置执行相同的操作。


1

父 pom.xml:

<properties>
        <!-- in my case injected by jenkins build job -->
        <build.version>dev</build.version>
        <build.branch>local</build.branch>
        <build.revision />
 </properties>

资源过滤(这里的占位符将被pom属性值替换)

<resources>
   <resource>
       <directory>src/main/resources</directory>
       <includes>
            <include>conf/version.properties</include>
       </includes>
       <filtering>true</filtering>
   </resource>
</resources>

webContext.xml 中的 Bean 和属性占位符配置:

<context:property-placeholder location="classpath:conf/version.properties"/>

    <bean id="buildVersion" class="de.your.package.cfg.BuildVersion">
        <property name="buildBranch" value="${build_branch}"/>
        <property name="buildVersion" value="${build_version}"/>
        <property name="buildRevision" value="${build_revision}"/>
    </bean>

你的bean看起来像这样:
@Component
public class BuildVersion {

    private String buildBranch;
    private String buildVersion;
    private String buildRevision;

    public String getBuildRevision() {
        return buildRevision;
    }

    public void setBuildRevision(String buildRevision) {
        this.buildRevision = buildRevision;
    }

    public String getBuildVersion() {
        return buildVersion;
    }

    public void setBuildVersion(String buildVersion) {
        this.buildVersion = buildVersion;
    }

    public String getBuildBranch() {
        return buildBranch;
    }

    public void setBuildBranch(String buildBranch) {
        this.buildBranch = buildBranch;
    }

}

这里是您的JSP片段:

<%@ page language="java"
   import="java.util.*,
        org.springframework.context.ApplicationContext,
    org.springframework.web.context.support.WebApplicationContextUtils,
         de.smava.kredithai.cfg.BuildVersion" %>
<%
    ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(pageContext.getServletContext());
    BuildVersion buildVersion = (BuildVersion) applicationContext.getBean("buildVersion");

    String branch = (String) buildVersion.getBuildBranch();
    String version = (String) buildVersion.getBuildVersion();
    String revision = (String) buildVersion.getBuildRevision();

    if (request.getParameter("branch") != null){
        out.println(branch);
    } else if (request.getParameter("version") != null){
        out.println(version);
    } else if (request.getParameter("link") != null){
        out.println("<a href=\"http://your_server_url"+branch+"/"+version+"\" >" + branch + " build " + version + "</a>");
    } else {
        out.println(branch + " build " + version + " rev. " + revision);
    }
%>

1
我会将值传递给 .jsp:


String version = getClass().getPackage().getImplementationVersion();

这将类似于 1.0.0-SNAPSHOT

如果你只得到了空值,你可能需要将类路径添加到 war 的清单中。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.5</version>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
            </manifest>
        </archive>
    </configuration>
</plugin>

为了让类加载器将其拾取。


1

有许多方法可以传递值(如这些评论中所讨论的)。另一种方法(具有其自身的优缺点)是从您的POM文件向清单添加参数:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <archive>
                    <manifestEntries>
                        <Build-Version>${project.version}</Build-Version>
                        <Build-Date>${buildDateTime}</Build-Date>
                        <Build-Number>${buildNumber}</Build-Number>
                        <Build-Revision>${buildRevision}</Build-Revision>
                    </manifestEntries>
                </archive>
            </configuration>
        </plugin>

然后打开并读取清单,在配置期间设置单例bean,或直接在JSP中导入它们:

<%
    String buildVersion;
    String buildDate;
    String buildRevision;
    String buildNumber;
    Attributes attributes;
    String version = "";
    InputStream in = null;

    // Get manifest attributes
    try {
        Manifest manifest;

        in = pageContext.getServletContext().getResourceAsStream("/META-INF/MANIFEST.MF");
        manifest = new Manifest(in);
        attributes = manifest.getMainAttributes();
    } catch (Exception ex) {
        attributes = new Attributes();
        attributes.put(new Attributes.Name("Build-Version"), "None (Inplace Deployment)");
    } finally {
        if (in != null) {
            in.close();
        }
    }
    buildVersion = attributes.getValue("Build-Version");
    buildDate = attributes.getValue("Build-Date");
    buildRevision = attributes.getValue("Build-Revision");
    buildNumber = attributes.getValue("Build-Number");
%>

其中一个优点是,这些信息也作为易于查找的文档出现在清单中。其中一个缺点是需要打开并阅读清单文件。


1

4
我尝试了这个插件,文档非常不完善,存在许多错误,并且似乎没有维护。 - damd

0

你可以在你的JSP文件中使用这个(我的例子中是template.jsp)

<head>
<meta name="Historia Social Unica version:${version}" />

然后在您项目的pom.xml中,您必须激活过滤:

<resources>
  <resource>
    <includes>
       <include>template.jsp</include>
    </includes>
    <directory>src/main/webapp/jsp/template</directory>
    <targetPath>jsp/template/</targetPath>
    <filtering>true</filtering>
  </resource>
 </resources>
</build>

当您替换变量版本后,即可获得您的JSP。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接