Untuk apa perpustakaan sumber daya JSF dan bagaimana menggunakannya?

228

JSF <h:outputStylesheet>, <h:outputScript>dan <h:graphicImage>komponen memiliki libraryatribut. Apa ini dan bagaimana ini harus digunakan? Ada banyak contoh di web yang menggunakannya sebagai berikut dengan konten / jenis file yang umum css, jsdan img(atau image) sebagai nama pustaka tergantung pada tag yang digunakan:

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

Bagaimana ini bermanfaat? The librarynilai dalam contoh-contoh tampaknya hanya mengulangi apa pun yang sudah diwakili oleh nama tag. Untuk <h:outputStylesheet>itu didasarkan pada nama tag sudah jelas bahwa itu mewakili "perpustakaan CSS". Apa bedanya dengan yang berikut yang juga hanya bekerja dengan cara yang sama?

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

Juga, output HTML yang dihasilkan sedikit berbeda. Diberikan jalur konteks /contextnamedan FacesServletpemetaan pada pola URL *.xhtml, yang pertama menghasilkan HTML berikut dengan nama perpustakaan sebagai parameter permintaan:

<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="" />

Sementara yang terakhir menghasilkan HTML berikut dengan nama perpustakaan tepat di jalur 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="" />

Pendekatan yang terakhir masuk ke belakang juga lebih masuk akal daripada pendekatan sebelumnya. Bagaimana sebenarnya libraryatribut itu bermanfaat?

BalusC
sumber

Jawaban:

256

Sebenarnya, semua contoh di web di mana konten umum / jenis file seperti "js", "css", "img", dll digunakan sebagai nama perpustakaan yang menyesatkan .

Contoh dunia nyata

Untuk memulai, mari kita lihat bagaimana implementasi JSF yang ada seperti Mojarra dan MyFaces dan pustaka komponen JSF seperti PrimeFaces dan OmniFaces menggunakannya. Tidak ada yang menggunakan perpustakaan sumber daya dengan cara ini. Mereka menggunakannya (di bawah selimut, dengan @ResourceDependencyatau UIViewRoot#addComponentResource()) dengan cara berikut:

<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" />

Seharusnya menjadi jelas bahwa itu pada dasarnya mewakili perpustakaan umum / modul / nama tema di mana semua sumber daya itu milik umum.

Identifikasi yang lebih mudah

Dengan cara ini, lebih mudah untuk menentukan dan membedakan dari mana sumber daya itu berasal dan / atau berasal. Bayangkan bahwa Anda memiliki primefaces.csssumber daya di webapp Anda sendiri di mana Anda mengganti / menyelesaikan beberapa CSS default dari PrimeFaces; jika PrimeFaces tidak menggunakan nama pustaka untuk namanya sendiri primefaces.css, maka PrimeFaces sendiri tidak akan dimuat, tetapi yang disediakan webapp, yang akan merusak tampilan.

Selain itu, ketika Anda menggunakan kebiasaan ResourceHandler, Anda juga dapat menerapkan kontrol yang lebih baik terhadap sumber daya yang berasal dari perpustakaan tertentu bila librarydigunakan dengan cara yang benar. Jika semua pustaka komponen akan menggunakan "js" untuk semua file JS mereka, bagaimana akan ResourceHandlerpernah membedakan jika itu berasal dari pustaka komponen tertentu? Contohnya adalah OmniFaces CombinedResourceHandlerdan GraphicResourceHandler; periksa createResource()metode di mana perpustakaan diperiksa sebelum mendelegasikan ke penangan sumber daya berikutnya dalam rantai. Dengan cara ini mereka tahu kapan harus membuat CombinedResourceatau GraphicResourceuntuk tujuan itu.

Perlu dicatat bahwa RichFaces melakukan kesalahan. Itu tidak menggunakan librarysama sekali dan homebrewed lapisan penanganan sumber daya lain di atasnya dan karena itu mustahil untuk mengidentifikasi sumber daya RichFaces secara pemrograman Itulah alasan mengapa OmniFaces CombinedResourceHander harus memperkenalkan hack berbasis refleksi untuk membuatnya tetap bekerja dengan sumber daya RichFaces.

Aplikasi web Anda sendiri

Aplikasi web Anda sendiri tidak perlu perpustakaan sumber daya. Anda sebaiknya menghilangkannya.

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

Atau, jika Anda benar-benar perlu memilikinya, Anda bisa memberinya nama umum yang lebih masuk akal, seperti "default" atau beberapa nama perusahaan.

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

Atau, ketika sumber daya khusus untuk beberapa templat Facelets master, Anda juga bisa memberikannya nama templat, sehingga lebih mudah untuk saling berhubungan. Dengan kata lain, ini lebih untuk keperluan dokumenter sendiri. Misalnya dalam /WEB-INF/templates/layout.xhtmlfile templat:

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

Dan /WEB-INF/templates/admin.xhtmlfile templat:

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

Untuk contoh dunia nyata, periksa kode sumber showcase OmniFaces .

Atau, ketika Anda ingin berbagi sumber daya yang sama di beberapa webapps dan telah membuat proyek "umum" untuk itu berdasarkan pada contoh yang sama seperti pada jawaban ini yang pada gilirannya tertanam sebagai JAR di webapp /WEB-INF/lib, kemudian juga rujuk sebagai pustaka (nama gratis untuk pilihan Anda; pustaka komponen seperti OmniFaces dan PrimeFaces juga berfungsi seperti itu):

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

Versi perpustakaan

Keuntungan utama lainnya adalah Anda dapat menerapkan versi perpustakaan sumber daya dengan cara yang benar pada sumber daya yang disediakan oleh aplikasi web Anda sendiri (ini tidak bekerja untuk sumber daya yang tertanam dalam JAR). Anda dapat membuat subfolder anak langsung di folder perpustakaan dengan nama dalam \d+(_\d+)*pola untuk menunjukkan versi perpustakaan sumber daya.

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

Saat menggunakan markup ini:

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

Ini akan menghasilkan HTML berikut dengan versi pustaka sebagai vparameter:

<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="" />

Jadi, jika Anda telah mengedit / memperbarui beberapa sumber daya, maka yang perlu Anda lakukan hanyalah menyalin atau mengganti nama folder versi menjadi nilai baru. Jika Anda memiliki beberapa folder versi, maka JSF ResourceHandlerakan secara otomatis menyajikan sumber daya dari nomor versi tertinggi, sesuai dengan aturan pemesanan numerik.

Jadi, ketika menyalin / mengganti nama resources/default/1_0/*folder menjadi resources/default/1_1/*seperti berikut:

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

Maka contoh markup terakhir akan menghasilkan HTML berikut:

<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="" />

Ini akan memaksa browser web untuk meminta sumber daya langsung dari server alih-alih menunjukkan yang dengan nama yang sama dari cache, ketika URL dengan parameter yang diubah diminta untuk pertama kalinya. Dengan cara ini pengguna akhir tidak perlu melakukan penyegaran keras (Ctrl + F5 dan sebagainya) ketika mereka perlu mengambil sumber CSS / JS yang diperbarui.

Harap dicatat bahwa versi perpustakaan tidak dimungkinkan untuk sumber daya yang terlampir dalam file JAR. Anda akan membutuhkan kebiasaan ResourceHandler. Lihat juga Cara menggunakan versi JSF untuk sumber daya dalam toples .

Lihat juga:

BalusC
sumber
2
Apakah mungkin menggunakan EL untuk perpustakaan? Jadi jika saya ingin memiliki sumber daya / default dan sumber daya / feelingFroggyToday saya bisa melakukan sesuatu seperti library = "# {someLibraryHere}" memetakan someLibraryHere ke perpustakaan pilihan saya dan tidak harus bergantung pada penggantian nama direktori sumber daya ke versi yang lebih tinggi setiap kali Saya ingin mengubahnya.
gebuh
Ketika Anda mengatakan library = admin atau libray = layout, apakah itu folder (admin dan layout) di folder resources?
Koray Tugay
Umm. Balus sangat menarik. Saya menghadapi masalah di aplikasi web tempat file theme.css kosong saat memuat. Ini hanya terjadi setelah berbagai penukaran (dalam JBOSS EAP). URL css seperti ini: /javax.faces.resource/css/theme.css.xhtml?ln=default&v=3_3_0_130416 dan dinyatakan dengan cara ini: <h: perpustakaan outputStylesheet = "default" name = "css / theme. css "target =" head "/>. Mungkin masalah ini terkait dengan masalah versi?
Ricardo Vila
2
Apakah karakter yang diizinkan untuk nilai libraryatau sesuatu yang terkait dengannya berubah antara mojarra 2.2.5 (2.2.5-jbossorg-3, wildfly 8.0) dan 2.2.11 (2.2.11-jbossorg-1)? Sepertinya saya tidak dapat menemukan apa pun di releasenotes. Lihat stackoverflow.com/questions/35719808/…
Kukeltje
3
Terima kasih @BalusC. Sayangnya bahkan Java EE 7 Tutorial Oracle sendiri memberikan contoh yang salah dengan menggunakan nama perpustakaan cssdi bab 8.6 Sumber Daya Web dan melakukannya dengan css dan gambar yang salah dalam aplikasi contoh guessnumber-jsf .
Jesper