Jsf 2 如何对jar中的资源使用JSF版本控制

Jsf 2 如何对jar中的资源使用JSF版本控制,jsf-2,jar,resources,versioning,Jsf 2,Jar,Resources,Versioning,PF 3.5.10、Mojarra 2.1.21、omnifaces 1.5 我有一个JSF库(只有css文件)。此库位于.jar文件中。css将包含在xhtml中 在html中,它被呈现为以下内容:localhost:8080/cms/javax.faces.resource/css/mycss.css.jsf?ln=mylib primefaces的CSS文件渲染为: localhost:8080/cms/javax.faces.resource/primefaces.js.jsf?ln=

PF 3.5.10、Mojarra 2.1.21、omnifaces 1.5

我有一个JSF库(只有css文件)。此库位于.jar文件中。css将包含在xhtml中

在html中,它被呈现为以下内容:
localhost:8080/cms/javax.faces.resource/css/mycss.css.jsf?ln=mylib

primefaces的CSS文件渲染为:
localhost:8080/cms/javax.faces.resource/primefaces.js.jsf?ln=primefaces&v=3.5.10


请注意末尾的库版本(&3.5.10)。我怎么能做同样的事?我应该在Manifest.mf中编写版本吗。或者如何在jar文件中使用jsf版本控制?

不幸的是,这是不可能的。JAR中的资源不支持库版本控制

您基本上有两种选择:

  • 使用简单而难看的方法,将服务器的启动时间作为查询字符串。考虑到您正在使用OmniFaces,您可以使用其内置的
    {startup}
    托管bean引用应用程序范围中的
    java.util.Date
    实例:

    <h:outputStylesheet ... name="some.css?#{startup.time}" />
    <h:outputScript ... name="some.js?#{startup.time}" />
    
    或者,如果您碰巧已经使用OmniFaces,则可以更简单:

    public class YourVersionResourceHandler extends DefaultResourceHandler {
    
        public YourVersionResourceHandler(ResourceHandler wrapped) {
            super(wrapped);
        }
    
        @Override
        public Resource decorateResource(Resource resource) {
            if (resource == null || !"mylib".equals(resource.getLibraryName())) {
                return resource;
            }
    
            return new RemappedResource(resource, resource.getRequestPath() + "&v=1.0");
        }
    
    }
    
    无论哪种方式,要让它运行,请在JAR的
    /META-INF/faces config.xml
    中注册为

    <application>
        <resource-handler>com.example.MyVersionResourceHandler</resource-handler>
    </application>
    
    
    com.example.MyVersionResourceHandler
    

  • 您还可以使用项目版本,并将其附加为资源文件的版本号。这可以使用
    maven-war插件来完成。
    maven-war插件将在构建期间查看您的页面,并替换已定义的属性

    下面的示例演示如何配置
    maven-war插件
    ,以过滤您的webapp资源,从而注入自定义属性
    asset.version

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" ...>
      ...
    
      <properties>
        <asset.version>${project.version}</asset.version>    
      </properties>
    
      ...
    
      <build>
        <plugins>
          ...
    
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.3</version>
            <configuration>
    
              <nonFilteredFileExtensions>
                <nonFilteredFileExtension>gif</nonFilteredFileExtension>
                <nonFilteredFileExtension>ico</nonFilteredFileExtension>
                <nonFilteredFileExtension>jpg</nonFilteredFileExtension>
                <nonFilteredFileExtension>png</nonFilteredFileExtension>
                <nonFilteredFileExtension>pdf</nonFilteredFileExtension>
              </nonFilteredFileExtensions>
    
              <failOnMissingWebXml>false</failOnMissingWebXml>
    
              <webResources> 
                <webResource>
                  <directory>${basedir}/src/main/webapp</directory> 
                  <filtering>true</filtering> 
                </webResource>
              </webResources> 
    
            </configuration>
          </plugin>
    
          ...
        </plugins>
      </build>
    
    </project>
    
    结果(就我而言)如下:

    <script type="text/javascript" src="/context-path/javax.faces.resource/js/libs/pure/pure-min.css.xhtml?v=1.0.15-SNAPSHOT"></script>
    
    
    
    @Balusc回应说“好吧,不是bug,而是疏忽和规范失败”。似乎部署在库中的css资源无法使用mojarra 2.2.14进行版本控制。是这样吗?我尝试使用自定义ResourceHandler实现您的解决方案,但getWrapped()返回的资源。createResource(resourceName,libraryName)始终返回null。createResource()似乎试图用path/META-INF/resources/查找库的资源(如css/layout.css),但它缺少版本

    为了解决这个问题,我在自定义ResourceHandler上重写了createResource方法,该方法扩展了Omnifaces DefaultResourceHandler,以向resourceName添加版本前缀

    @Override
    public Resource createResource(String resourceName, String libraryName) {
        if (libraryName != null && libraryName.equals(LIBRARY_NAME)) {
            if (!resourceName.startsWith(version)) {
                resourceName = version + "/"+resourceName;
            }
        }
        return super.createResource(resourceName, libraryName);
    }
    
    通过此解决方案,生成的链接如下所示

    <link type="text/css" rel="stylesheet" href="/javax.faces.resource/1_0_3/css/layout.css?ln=common&amp;v=1_0_3"/>
    
    
    
    对于outputStylesheet声明

    <h:outputStylesheet library="common" name="css/layout.css" />
    
    
    

    我不确定这是否是最好的解决方法。

    可能重复的否,我认为这不是重复,因为问题是关于jar文件的。在罐子里,这是不同的。见巴卢斯回答:谢谢!非常有用的回答。你在1
    {startup}
    中的想法很好。因此,客户端css将始终更新,您不能忘记更改版本。另一个问题:是否可以将这个ResourceHandler放在jar文件中并从那里使用它?所以每个jar都是独立的。是的,将类放入jar中,并将其注册到jar的
    /META-INF/faces config.xml
    。答案的底部也提到了这一点,因为你错过了它。和往常一样,回答得很好。但是,我发现com.sun.faces.application.resource.ResourceImpl将对具有版本信息的库使用v参数。所以我对这个伟大的例子做了一个小小的改变,改变了参数名。我正在使用优秀的生成一个git提交哈希,参数名为gch。@raupach:这是一个技术限制。几年后,如果你碰巧已经使用了OmniFaces,那么现在你再来看看如何用更少的代码来实现它:@marcel:好吧,不是bug,但是疏忽和规范失败了。看到了,很好!非常感谢。使用Maven是一个有趣的解决方案。不幸的是,我们没有这样做。
    @Override
    public Resource createResource(String resourceName, String libraryName) {
        if (libraryName != null && libraryName.equals(LIBRARY_NAME)) {
            if (!resourceName.startsWith(version)) {
                resourceName = version + "/"+resourceName;
            }
        }
        return super.createResource(resourceName, libraryName);
    }
    
    <link type="text/css" rel="stylesheet" href="/javax.faces.resource/1_0_3/css/layout.css?ln=common&amp;v=1_0_3"/>
    
    <h:outputStylesheet library="common" name="css/layout.css" />