What is the JSF resource library for and how should it be used?

后端 未结 1 501
暗喜
暗喜 2020-11-21 05:09

The JSF , and components have a library attribute. What is this and how should this be u

1条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-21 05:35

    Actually, all of those examples on the web wherein the common content/file type like "js", "css", "img", etc is been used as library name are misleading.

    Real world examples

    To start, let's look at how existing JSF implementations like Mojarra and MyFaces and JSF component libraries like PrimeFaces and OmniFaces use it. No one of them use resource libraries this way. They use it (under the covers, by @ResourceDependency or UIViewRoot#addComponentResource()) the following way:

    
    
    
    
    
    
    
    
    

    It should become clear that it basically represents the common library/module/theme name where all of those resources commonly belong to.

    Easier identifying

    This way it's so much easier to specify and distinguish where those resources belong to and/or are coming from. Imagine that you happen to have a primefaces.css resource in your own webapp wherein you're overriding/finetuning some default CSS of PrimeFaces; if PrimeFaces didn't use a library name for its own primefaces.css, then the PrimeFaces own one wouldn't be loaded, but instead the webapp-supplied one, which would break the look'n'feel.

    Also, when you're using a custom ResourceHandler, you can also apply more finer grained control over resources coming from a specific library when library is used the right way. If all component libraries would have used "js" for all their JS files, how would the ResourceHandler ever distinguish if it's coming from a specific component library? Examples are OmniFaces CombinedResourceHandler and GraphicResourceHandler; check the createResource() method wherein the library is checked before delegating to next resource handler in chain. This way they know when to create CombinedResource or GraphicResource for the purpose.

    Noted should be that RichFaces did it wrong. It didn't use any library at all and homebrewed another resource handling layer over it and it's therefore impossible to programmatically identify RichFaces resources. That's exactly the reason why OmniFaces CombinedResourceHander had to introduce a reflection-based hack in order to get it to work anyway with RichFaces resources.

    Your own webapp

    Your own webapp does not necessarily need a resource library. You'd best just omit it.

    
    
    
    

    Or, if you really need to have one, you can just give it a more sensible common name, like "default" or some company name.

    
    
    
    

    Or, when the resources are specific to some master Facelets template, you could also give it the name of the template, so that it's easier to relate each other. In other words, it's more for self-documentary purposes. E.g. in a /WEB-INF/templates/layout.xhtml template file:

    
    
    

    And a /WEB-INF/templates/admin.xhtml template file:

    
    
    

    For a real world example, check the OmniFaces showcase source code.

    Or, when you'd like to share the same resources over multiple webapps and have created a "common" project for that based on the same example as in this answer which is in turn embedded as JAR in webapp's /WEB-INF/lib, then also reference it as library (name is free to your choice; component libraries like OmniFaces and PrimeFaces also work that way):

    
    
    
    

    Library versioning

    Another main advantage is that you can apply resource library versioning the right way on resources provided by your own webapp (this doesn't work for resources embedded in a JAR). You can create a direct child subfolder in the library folder with a name in the \d+(_\d+)* pattern to denote the resource library version.

    WebContent
     |-- resources
     |    `-- default
     |         `-- 1_0
     |              |-- css
     |              |    `-- style.css
     |              |-- img
     |              |    `-- logo.png
     |              `-- js
     |                   `-- script.js
     :
    

    When using this markup:

    
    
    
    

    This will generate the following HTML with the library version as v parameter:

    
    
    
    

    So, if you have edited/updated some resource, then all you need to do is to copy or rename the version folder into a new value. If you have multiple version folders, then the JSF ResourceHandler will automatically serve the resource from the highest version number, according to numerical ordering rules.

    So, when copying/renaming resources/default/1_0/* folder into resources/default/1_1/* like follows:

    WebContent
     |-- resources
     |    `-- default
     |         |-- 1_0
     |         |    :
     |         |
     |         `-- 1_1
     |              |-- css
     |              |    `-- style.css
     |              |-- img
     |              |    `-- logo.png
     |              `-- js
     |                   `-- script.js
     :
    

    Then the last markup example would generate the following HTML:

    
    
    
    

    This will force the webbrowser to request the resource straight from the server instead of showing the one with the same name from the cache, when the URL with the changed parameter is been requested for the first time. This way the endusers aren't required to do a hard refresh (Ctrl+F5 and so on) when they need to retrieve the updated CSS/JS resource.

    Please note that library versioning is not possible for resources enclosed in a JAR file. You'd need a custom ResourceHandler. See also How to use JSF versioning for resources in jar.

    See also:

    • JSF resource versioning
    • JSF2 Static resource caching
    • Structure for multiple JSF projects with shared code
    • JSF 2.0 specification - Chapter 2.6 Resource Handling

    0 讨论(0)
提交回复
热议问题