16

PF 3.5.10,Mojarra 2.1.21,全脸 1.5

我有一个 JSF 库(仅包含 css 文件)。该库位于 .jar 文件中。css 将包含在 xhtml 中 <h:outputStylesheet library="mylib" name="css/mycss.css">

在 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?

4

3 回答 3

26

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

你基本上有两个选择:

  1. 以简单而丑陋的方式来做,包括服务器的启动时间作为查询字符串。鉴于您使用的是 OmniFaces,您可以使用其内置#{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}" />
    

    更新:尽管如此,这不适用于<h:outputStylesheet>. 另请参阅:https ://github.com/javaserverfaces/mojarra/issues/3945或https://github.com/javaee/javaserverfaces-spec/issues/1395

    虽然它适用,<h:outputScript>但它有一个非常相似的错误报告,很快就实施了https://github.com/javaserverfaces/mojarra/issues/1216

  2. 和 PrimeFaces 一样,创建一个自定义ResourceHandler.

    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");
        }
    
    }
    

    无论哪种方式,要使其运行,请将其注册为<resource-handler>JAR /META-INF/faces-config.xml

    <application>
        <resource-handler>com.example.MyVersionResourceHandler</resource-handler>
    </application>
    
于 2013-08-09T11:54:04.680 回答
3

您还可以使用您的项目版本并将其附加为资源文件的版本号。这可以使用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>

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

下面是一个使用 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>
于 2014-07-04T16:10:30.820 回答
0

@Balusc 回应说“好吧,不是错误,而是监督和规范失败”。似乎部署在库中的 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" />

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

于 2017-01-19T17:40:55.257 回答