首页 文章

如何在jar中使用JSF版本控制资源

提问于
浏览
11

PF 3.5.10,Mojarra 2.1.21,omnifaces 1.5

我有一个JSF库(仅限css文件) . 该库位于.jar文件中 . css将包含在带有 <h:outputStylesheet library="mylib" name="css/mycss.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-versioning?

3 回答

  • 3

    遗憾的是,这是不可能的 . JAR中的资源不支持库版本控制 .

    你基本上有两个选择:

    • 以简单和丑陋的方式做到这一点,包括使用OmniFaces的服务器's startup time as query string. Given that you',您可以在应用程序范围内使用其内置 #{startup} 托管bean引用 java.util.Date 实例:
    <h:outputStylesheet ... name="some.css?#{startup.time}" />
    <h:outputScript ... name="some.js?#{startup.time}" />
    

    或者您可能已将该版本作为某个应用程序变量 .

    <h:outputStylesheet ... name="some.css?v=#{app.version}" />
    <h:outputScript ... name="some.js?v=#{app.version}" />
    

    Update :尽管如此,这对 <h:outputStylesheet> 无效 . 另见:https://github.com/javaserverfaces/mojarra/issues/3945https://github.com/javaee/javaserverfaces-spec/issues/1395

    它适用于 <h:outputScript> ,它有一个非常简单的错误报告,很快就实现了https://github.com/javaserverfaces/mojarra/issues/1216

    public class MyVersionResourceHandler extends ResourceHandlerWrapper {
    
        private ResourceHandler wrapped;
    
        public MyVersionResourceHandler(ResourceHandler wrapped) {
            this.wrapped = wrapped;
        }
    
        @Override
        public Resource createResource(String resourceName) {
            return createResource(resourceName, null, null);
        }
    
        @Override
        public Resource createResource(String resourceName, String libraryName) {
            return createResource(resourceName, libraryName, null);
        }
    
        @Override
        public Resource createResource(String resourceName, String libraryName, String contentType) {
            final Resource resource = super.createResource(resourceName, libraryName, contentType);
    
            if (resource == null) {
                return null;
            }
    
            return new ResourceWrapper() {
    
                @Override
                public String getRequestPath() {
                    return super.getRequestPath() + "&v=1.0";
                }
    
                @Override // Necessary because this is missing in ResourceWrapper (will be fixed in JSF 2.2).
                public String getResourceName() {
                    return resource.getResourceName();
                }
    
                @Override // Necessary because this is missing in ResourceWrapper (will be fixed in JSF 2.2).
                public String getLibraryName() {
                    return resource.getLibraryName();
                }
    
                @Override // Necessary because this is missing in ResourceWrapper (will be fixed in JSF 2.2).
                public String getContentType() {
                    return resource.getContentType();
                }
    
                @Override
                public Resource getWrapped() {
                    return resource;
                }
            };
        }
    
        @Override
        public ResourceHandler getWrapped() {
            return wrapped;
        }
    
    }
    

    或者,如果您碰巧已经使用过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 中将其注册为 <resource-handler> .

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

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

    以下示例说明如何配置 maven-war-plugin 以过滤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>
    

    然后可以在您的JSF文件中使用 asset.version 属性 .

    以下是使用JSF 2.2测试的示例:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE html>
    <html ...
          xmlns:jsf="http://xmlns.jcp.org/jsf">
    
    ...
    <script jsf:name="js/libs/pure/pure-min.css?v=${project.version}" />
    

    结果(在我的情况下)将是以下内容:

    <script type="text/javascript" src="/context-path/javax.faces.resource/js/libs/pure/pure-min.css.xhtml?v=1.0.15-SNAPSHOT"></script>
    
  • 19

    @Balusc回复说“好吧,不是一个bug,但监督和规范失败” . 似乎在库中部署的css资源无法使用mojarra 2.2.14进行版本控制 . 这样对吗?我尝试使用自定义ResourceHandler实现您的解决方案,但getWrapped()返回的资源.createResource(resourceName,libraryName)始终返回null . 似乎createResource()尝试使用路径/ 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" />
    

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

相关问题