Thư viện tài nguyên JSF để làm gì và nên sử dụng nó như thế nào?


228

JSF <h:outputStylesheet>, <h:outputScript><h:graphicImage>các thành phần có một librarythuộc tính. Cái này là gì và nên dùng cái này như thế nào? Có rất nhiều ví dụ trên web mà sử dụng nó như sau với kiểu nội dung phổ biến / tập tin css, jsimg(hoặc image) như tên thư viện tùy thuộc vào thẻ được sử dụng:

<h:outputStylesheet library="css" name="style.css" />
<h:outputScript library="js" name="script.js" />
<h:graphicImage library="img" name="logo.png" />

Nó hữu ích như thế nào? Các librarygiá trị trong những ví dụ dường như được chỉ lặp đi lặp lại bất cứ điều gì đã được đại diện bởi các tên thẻ. Đối với một <h:outputStylesheet>tên dựa trên tên thẻ đã rõ ràng rằng nó đại diện cho một "thư viện CSS". Điều gì khác biệt với những điều sau đây cũng chỉ hoạt động theo cùng một cách?

<h:outputStylesheet name="css/style.css" />
<h:outputScript name="js/script.js" />
<h:graphicImage name="img/logo.png" />

Ngoài ra, đầu ra HTML được tạo ra là một chút khác nhau. Đưa ra một đường dẫn ngữ cảnh /contextnameFacesServletánh xạ trên một mẫu URL của *.xhtml, cái trước tạo ra HTML sau với tên thư viện là tham số yêu cầu:

<link rel="stylesheet" type="text/css" href="/contextname/javax.faces.resource/style.css.xhtml?ln=css" />
<script type="text/javascript" src="/contextname/javax.faces.resource/script.js.xhtml?ln=js"></script>
<img src="/contextname/javax.faces.resource/logo.png.xhtml?ln=img" alt="" />

Trong khi cái sau tạo ra HTML sau với tên thư viện chỉ trong đường dẫn của URI:

<link rel="stylesheet" type="text/css" href="/contextname/javax.faces.resource/css/style.css.xhtml" />
<script type="text/javascript" src="/contextname/javax.faces.resource/js/script.js.xhtml"></script>
<img src="/contextname/javax.faces.resource/img/logo.png.xhtml" alt="" />

Cách tiếp cận thứ hai làm cho nhận thức muộn cũng có ý nghĩa hơn so với cách tiếp cận trước đây. Làm thế nào chính xác là librarythuộc tính sau đó hữu ích?

Câu trả lời:


256

Trên thực tế, tất cả các ví dụ trên web trong đó loại nội dung / tệp phổ biến như "js", "css", "img", v.v ... được sử dụng làm tên thư viện là sai lệch .

Ví dụ thế giới thực

Để bắt đầu, chúng ta hãy xem các triển khai JSF hiện tại như MojarraMyFaces và các thư viện thành phần JSF như PrimeFacesOmniFaces sử dụng nó như thế nào. Không ai trong số họ sử dụng các thư viện tài nguyên theo cách này. Họ sử dụng nó (dưới vỏ bọc, bằng @ResourceDependencyhoặc UIViewRoot#addComponentResource()) theo cách sau:

<h:outputScript library="javax.faces" name="jsf.js" />
<h:outputScript library="primefaces" name="jquery/jquery.js" />
<h:outputScript library="omnifaces" name="omnifaces.js" />
<h:outputScript library="omnifaces" name="fixviewstate.js" />
<h:outputScript library="omnifaces.combined" name="[dynamicname].js" />
<h:outputStylesheet library="primefaces" name="primefaces.css" />
<h:outputStylesheet library="primefaces-aristo" name="theme.css" />
<h:outputStylesheet library="primefaces-vader" name="theme.css" />

Rõ ràng là về cơ bản nó đại diện cho tên thư viện / mô-đun / chủ đề chung nơi tất cả các tài nguyên đó thường thuộc về.

Xác định dễ dàng hơn

Bằng cách này, việc xác định và phân biệt các tài nguyên đó thuộc về và / hoặc đến từ đâu dễ dàng hơn nhiều. Hãy tưởng tượng rằng bạn primefaces.csstình cờ có một tài nguyên trong ứng dụng web của riêng bạn trong đó bạn đang ghi đè / hoàn thiện một số CSS mặc định của PrimeFaces; nếu PrimeFaces không sử dụng tên thư viện cho riêng mình primefaces.css, thì tên riêng của PrimeFaces sẽ không được tải, mà thay vào đó là tên do ứng dụng web cung cấp, sẽ phá vỡ giao diện.

Ngoài ra, khi bạn đang sử dụng một tùy chỉnh ResourceHandler, bạn cũng có thể áp dụng kiểm soát chi tiết hơn đối với các tài nguyên đến từ một thư viện cụ thể khi libraryđược sử dụng đúng cách. Nếu tất cả các thư viện thành phần sẽ sử dụng "js" cho tất cả các tệp JS của họ, làm thế nào để ResourceHandlerphân biệt nếu nó đến từ một thư viện thành phần cụ thể? Ví dụ là OmniFaces CombinedResourceHandlerGraphicResourceHandler; kiểm tra createResource()phương thức trong đó thư viện được kiểm tra trước khi ủy quyền cho trình xử lý tài nguyên tiếp theo trong chuỗi. Bằng cách này, họ biết khi nào để tạo ra CombinedResourcehoặc GraphicResourcecho mục đích.

Đáng chú ý là RichFaces đã làm sai. Nó hoàn toàn không sử dụng bất kỳ lớp nào libraryvà đã homebrew một lớp xử lý tài nguyên khác trên nó và do đó không thể xác định được tài nguyên RichFaces theo lập trình. Đó chính xác là lý do tại sao OmniFaces CombinedResourceHander phải giới thiệu một bản hack dựa trên phản chiếu để làm cho nó hoạt động bằng mọi cách với tài nguyên RichFaces.

Ứng dụng web của riêng bạn

Ứng dụng web của riêng bạn không nhất thiết cần một thư viện tài nguyên. Bạn tốt nhất chỉ nên bỏ qua nó.

<h:outputStylesheet name="css/style.css" />
<h:outputScript name="js/script.js" />
<h:graphicImage name="img/logo.png" />

Hoặc, nếu bạn thực sự cần phải có một cái, bạn có thể đặt cho nó một tên chung hợp lý hơn, như "mặc định" hoặc một số tên công ty.

<h:outputStylesheet library="default" name="css/style.css" />
<h:outputScript library="default" name="js/script.js" />
<h:graphicImage library="default" name="img/logo.png" />

Hoặc, khi các tài nguyên dành riêng cho một số mẫu Facelets chính, bạn cũng có thể đặt tên cho mẫu đó để dễ liên hệ với nhau hơn. Nói cách khác, nó nhiều hơn cho mục đích tự làm tài liệu. Ví dụ: trong một /WEB-INF/templates/layout.xhtmltệp mẫu:

<h:outputStylesheet library="layout" name="css/style.css" />
<h:outputScript library="layout" name="js/script.js" />

Và một /WEB-INF/templates/admin.xhtmltệp mẫu:

<h:outputStylesheet library="admin" name="css/style.css" />
<h:outputScript library="admin" name="js/script.js" />

Để biết ví dụ trong thế giới thực, hãy kiểm tra mã nguồn giới thiệu OmniFaces .

Hoặc, khi bạn muốn chia sẻ cùng một tài nguyên trên nhiều ứng dụng web và đã tạo một dự án "chung" cho điều đó dựa trên ví dụ tương tự như trong câu trả lời này , lần lượt được nhúng như JAR trong webapp /WEB-INF/lib, sau đó cũng tham chiếu nó như thư viện (tên là miễn phí cho sự lựa chọn của bạn; các thư viện thành phần như OmniFaces và PrimeFaces cũng hoạt động theo cách đó):

<h:outputStylesheet library="common" name="css/style.css" />
<h:outputScript library="common" name="js/script.js" />
<h:graphicImage library="common" name="img/logo.png" />

Phiên bản thư viện

Một ưu điểm chính khác là bạn có thể áp dụng phiên bản thư viện tài nguyên theo đúng cách trên các tài nguyên được cung cấp bởi ứng dụng web của riêng bạn (điều này không hoạt động đối với các tài nguyên được nhúng trong JAR). Bạn có thể tạo một thư mục con trực tiếp trong thư mục thư viện với tên trong \d+(_\d+)*mẫu để biểu thị phiên bản thư viện tài nguyên.

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

Khi sử dụng đánh dấu này:

<h:outputStylesheet library="default" name="css/style.css" />
<h:outputScript library="default" name="js/script.js" />
<h:graphicImage library="default" name="img/logo.png" />

Điều này sẽ tạo ra HTML sau với phiên bản thư viện làm vtham số:

<link rel="stylesheet" type="text/css" href="/contextname/javax.faces.resource/css/style.css.xhtml?ln=default&amp;v=1_0" />
<script type="text/javascript" src="/contextname/javax.faces.resource/js/script.js.xhtml?ln=default&amp;v=1_0"></script>
<img src="/contextname/javax.faces.resource/img/logo.png.xhtml?ln=default&amp;v=1_0" alt="" />

Vì vậy, nếu bạn đã chỉnh sửa / cập nhật một số tài nguyên, thì tất cả những gì bạn cần làm là sao chép hoặc đổi tên thư mục phiên bản thành một giá trị mới. Nếu bạn có nhiều thư mục phiên bản, thì JSF ResourceHandlersẽ tự động phục vụ tài nguyên từ số phiên bản cao nhất, theo quy tắc đặt hàng số.

Vì vậy, khi sao chép / đổi tên resources/default/1_0/*thư mục thành resources/default/1_1/*như sau:

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

Sau đó, ví dụ đánh dấu cuối cùng sẽ tạo ra HTML sau:

<link rel="stylesheet" type="text/css" href="/contextname/javax.faces.resource/css/style.css.xhtml?ln=default&amp;v=1_1" />
<script type="text/javascript" src="/contextname/javax.faces.resource/js/script.js.xhtml?ln=default&amp;v=1_1"></script>
<img src="/contextname/javax.faces.resource/img/logo.png.xhtml?ln=default&amp;v=1_1" alt="" />

Điều này sẽ buộc webbrowser yêu cầu tài nguyên trực tiếp từ máy chủ thay vì hiển thị tài nguyên có cùng tên từ bộ đệm, khi lần đầu tiên URL với tham số thay đổi được yêu cầu. Bằng cách này, các endusers không bắt buộc phải làm mới cứng (Ctrl + F5, v.v.) khi họ cần lấy tài nguyên CSS / JS đã cập nhật.

Xin lưu ý rằng phiên bản thư viện là không thể đối với các tài nguyên được đính kèm trong tệp JAR. Bạn sẽ cần một tùy chỉnh ResourceHandler. Xem thêm Cách sử dụng phiên bản JSF cho các tài nguyên trong jar .

Xem thêm:


2
Có thể sử dụng EL cho thư viện? Vì vậy, nếu tôi muốn có một tài nguyên / mặc định và một tài nguyên / cảm giácFroggyToday, tôi có thể làm một cái gì đó như thư viện = "# {someL LibraryHere}" ánh xạ một số Thư viện vào thư viện đã chọn của tôi và không phải phụ thuộc vào việc đổi tên thư mục tài nguyên thành phiên bản cao hơn mỗi lần Tôi muốn thay đổi chúng.
gebuh

Khi bạn nói library = admin hoặc libray = layout, những thư mục (admin và layout) đó có trong thư mục tài nguyên không?
Koray Tugay

Ừm Balus rất thú vị. Tôi đang gặp vấn đề trong một ứng dụng web nơi tệp theme.css trống khi tải. Điều này chỉ xảy ra sau khi tái cấu trúc khác nhau (trong JBOSS EAP). Url css giống như thế này: /javax.faces.resource/css/theme.css.xhtml?ln=default&v=3_3_0_130416 và nó được khai báo theo cách này: <h: outputSty Meateet library = "default" name = "css / theme. css "đích =" đầu "/>. Có lẽ vấn đề này liên quan đến các vấn đề phiên bản?
Ricardo Vila

2
Các ký tự được phép cho giá trị của libraryhoặc một cái gì đó liên quan đến nó có thay đổi giữa mojarra 2.2.5 (2.2.5-jbossorg-3, wildfly 8.0) và 2.2.11 (2.2.11-jbossorg-1) không? Tôi dường như không thể tìm thấy bất cứ điều gì trong các bản phát hành. Xem stackoverflow.com/questions/35719808/
Mạnh

3
Cảm ơn @BalusC. Thật không may, ngay cả Hướng dẫn Java EE 7 của Oracle cũng đưa ra ví dụ sai bằng cách sử dụng tên thư viện csstrong chương 8.6 Tài nguyên web và thực hiện sai với css và hình ảnh trong ứng dụng ví dụ đoánnumber-jsf .
Jesper
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.