Operasi Biasa FreeMarker

1. Pengenalan

FreeMarker adalah mesin templat, ditulis di Java, dan dikelola oleh Apache Foundation. Kita dapat menggunakan Bahasa Templat FreeMarker, juga dikenal sebagai FTL, untuk menghasilkan banyak format berdasarkan teks seperti halaman web, e-mel, atau fail XML.

Dalam tutorial ini, kita akan melihat apa yang dapat kita lakukan di luar kotak dengan FreeMarker, walaupun perhatikan bahawa ia cukup dapat dikonfigurasi dan bahkan dapat disatukan dengan baik dengan Spring.

Mari kita mulakan!

2. Gambaran Keseluruhan Pantas

Untuk menyuntik kandungan dinamik di halaman kami, kami perlu menggunakan sintaks yang difahami oleh FreeMarker :

  • $ {…} Dalam templat akan diganti dalam output yang dihasilkan dengan nilai sebenar ungkapan di dalam kurungan keriting - kami sebut sebagai interpolasi ini - beberapa contohnya ialah $ {1 + 2 } dan $ {variableName}
  • Tag FTL adalah seperti tag HTML (tetapi mengandungi # atau @ ) dan FreeMarker menafsirkannya, misalnya
  • Komen di FreeMarker bermula dengan <# - dan diakhiri dengan ->

3. Tanda Sertakan

Arahan FTL include adalah cara untuk kita mengikuti prinsip KERING dalam aplikasi kita. Kami akan menentukan kandungan berulang dalam fail dan menggunakannya semula di templat FreeMarker yang berbeza dengan tag sertakan tunggal .

Salah satu kes penggunaan adalah ketika kita ingin memasukkan bahagian menu di dalam banyak halaman. Pertama, kita akan menentukan bahagian menu di dalam fail - kita akan memanggilnya menu.ftl - dengan kandungan berikut:

Dashboard Add new endpoint

Dan di halaman HTML kami, mari sertakan menu yang dibuat.ftl :

Dashboard page

Dan kami juga boleh memasukkan FTL dalam serpihan kami, yang sangat bagus.

4. Menangani Kewujudan Nilai

FTL akan menganggap sebarang nilai nol sebagai nilai yang hilang. Oleh itu, kita perlu lebih berhati-hati dan menambah logik untuk menangani nol di dalam templat kita.

Kita boleh menggunakan ?? pengendali untuk memeriksa sama ada atribut, atau harta bersarang, wujud. Hasilnya adalah boolean:

${attribute??}

Oleh itu, kami telah menguji atribut untuk nol, tetapi itu tidak selalu mencukupi. Sekarang mari kita tentukan nilai lalai sebagai pengganti untuk nilai yang hilang ini. Untuk melakukan ini, kita memerlukan ! pengendali ditempatkan selepas nama pemboleh ubah:

${attribute!'default value'}

Dengan menggunakan kurungan bulat, kita dapat membungkus banyak atribut bersarang.

Sebagai contoh, untuk memeriksa sama ada atribut itu ada dan mempunyai harta bersarang dengan harta bersarang yang lain, kami membungkus semuanya:

${(attribute.nestedProperty.nestedProperty)??}

Akhirnya, dengan menyatukan semuanya, kami dapat memasukkannya di antara kandungan statik:

Testing is student property exists: ${student???c}

Using default value for missing student: ${student!'John Doe'}

Wrapping student nested properties: ${(student.address.street)???c}

Sekiranya pelajar itu batal , kita akan melihat:

Testing is student property exists: false

Using default value for missing student: John Doe

Wrapping student nested properties: false

Perhatikan arahan tambahan ? C yang digunakan selepas ?? . Kami melakukannya untuk menukar nilai boolean menjadi rentetan yang dapat dibaca oleh manusia.

5. Tag If-Else

Struktur kawalan terdapat di FreeMarker, dan tradisional jika-mungkin mungkin biasa:

Walaupun cabang-cabang elseif dan lain - lain adalah pilihan, syarat-syarat mesti dipastikan menjadi nilai boolean.

Untuk membantu penilaian kami, kami mungkin akan menggunakan salah satu:

  • x == y untuk diperiksa adalah x sama dengan y
  • x! = y untuk kembali benar hanya jika x berbeza dari y
  • x lt y bermaksud bahawa x mestilah lebih kecil daripada y - kita juga boleh menggunakan < bukannya lt
  • x gt y dinilai menjadi benar hanya jika x lebih besar daripada y - kita boleh menggunakan > bukannya gt
  • x lte y menguji jika x kurang daripada atau sama dengan y - alternatif untuk lte ialah <=
  • x gte y menguji jika x lebih besar daripada atau sama dengan y - alternatif gte adalah> =
  • x ?? untuk memeriksa kewujudan x
  • urutan? seqContains (x) mengesahkan kewujudan x di dalam turutan

Sangat penting untuk diingat bahawa FreeMarker menganggap> = dan> sebagai watak penutup untuk tag FTL. Penyelesaiannya adalah dengan membungkus penggunaannya dalam kurungan atau menggunakan gte atau gt sebagai gantinya.

Menyusunnya, untuk templat berikut:

${status.reason}

Missing status!

Kami berakhir dengan kod HTML yang dihasilkan:

404 Not Found

Missing status!

6. Bekas Sub-Pemboleh ubah

Di FreeMarker, kami mempunyai tiga jenis bekas untuk sub-pemboleh ubah:

  • Hash adalah urutan pasangan nilai-kunci - kuncinya mesti unik di dalam hash dan kami tidak mempunyai pesanan
  • Urutan adalah senarai di mana kita mempunyai indeks yang berkaitan dengan setiap nilai - fakta yang perlu diperhatikan ialah sub-pemboleh ubah boleh terdiri dari pelbagai jenis
  • Koleksi adalah kes urutan khas di mana kita tidak dapat mengakses ukuran atau mengambil nilai mengikut indeks - kita masih boleh mengulanginya dengan tag senarai !

6.1. Item Pengulangan

Kita boleh melakukan lelaran ke atas bekas dengan dua cara asas. Yang pertama adalah di mana kita melakukan iterasi atas setiap nilai dan mempunyai logik untuk setiap nilai:

Atau, semasa kita mahu melakukan lelaran Hash , mengakses kunci dan nilai:

Bentuk kedua lebih kuat kerana ia juga membolehkan kita menentukan logik yang seharusnya berlaku pada pelbagai langkah dalam lelaran:

The item mewakili nama pembolehubah bergelung, tetapi kita boleh menukar nama kepada apa yang kita mahu. Yang lagi cawangan adalah pilihan.

Sebagai contoh langsung, tentukan templat dengan baik di mana kita menyenaraikan beberapa status:


    
  • ${status}

No statuses available

Ini akan mengembalikan HTML berikut kepada kami apabila bekas kami ["200 OK", "404 Tidak Ditemui", "500 Ralat Pelayan Dalaman"] :


    
  • 200 OK
  • 404 Not Found
  • 500 Internal Server Error

6.2. Pengendalian Item

Hash mempunyai dua fungsi mudah: kunci untuk mendapatkan semula kunci yang terkandung, dan nilai untuk mendapatkan hanya nilai.

Urutan lebih kompleks; kita dapat mengumpulkan fungsi yang paling berguna:

  • pecahkan dan bergabung untuk mendapatkan sub-urutan atau menggabungkan dua urutan
  • membalikkan , mengisih, dan mengisih dengan cara mengubah susunan elemen
  • pertama dan terakhir akan mengambil unsur pertama atau terakhir, masing-masing
  • ukuran mewakili bilangan elemen dalam urutan
  • seqContains , seqIndexOf , atau seqLastIndexOf untuk mencari elemen

7. Pengendalian Jenis

FreeMarker dilengkapi dengan pelbagai fungsi (built-in) yang tersedia untuk bekerja dengan objek. Mari lihat beberapa fungsi yang sering digunakan.

7.1. Pengendalian Rentetan

  • url dan urlPath akan keluar dari rentetan URL, dengan pengecualian bahawa urlPath tidak akan terlepas dari garis miring /
  • jString , jsString, dan jsonString masing-masing akan menerapkan peraturan pelarian untuk Java, Javascript dan JSON
  • capFirst , uncapFirst , huruf besar , huruf kecil dan huruf besar berguna untuk mengubah casing rentetan kami, seperti yang tersirat dengan nama mereka
  • boolean , tarikh , masa , datetime dan nombor adalah fungsi untuk menukar dari rentetan jenis lain

Sekarang mari kita gunakan beberapa fungsi tersebut:

${'//myurl.com/?search=Hello World'?urlPath}

${'Using " in text'?jsString}

${'my value?upperCase}

${'2019-01-12'?date('yyyy-MM-dd')}

Dan output untuk templat di atas adalah:

http%3A//myurl.com/%3Fsearch%3DHello%20World

MY VALUE

Using \" in text

12.01.2019

Semasa menggunakan fungsi tarikh , kami juga melewati pola yang akan digunakan untuk menguraikan objek String. FreeMarker menggunakan format tempatan kecuali dinyatakan sebaliknya , sebagai contoh dalam fungsi rentetan yang tersedia untuk objek tarikh.

7.2. Pengendalian Nombor

  • bulat , lantai dan siling dapat menolong nombor bulat
  • abs akan mengembalikan nilai mutlak nombor
  • rentetan akan menukar nombor menjadi rentetan. Kami juga dapat melewati empat format angka yang telah ditentukan: komputer , mata wang , nombor , atau persen atau menentukan format kami sendiri, seperti [“0. ###”]

Mari lakukan rantaian beberapa operasi matematik:

${(7.3?round + 3.4?ceiling + 0.1234)?string('0.##')}

Dan seperti yang dijangkakan, nilai yang dihasilkan adalah 11.12.

7.3. Pengendalian Tarikh

  • . sekarang mewakili tarikh-tarikh semasa
  • tarikh , masa dan masa dapat mengembalikan bahagian tarikh dan masa objek tarikh-waktu
  • rentetan akan menukar tarikh-tarikh menjadi rentetan - kita juga dapat melepasi format yang diinginkan atau menggunakan yang telah ditentukan sebelumnya

Kita akan mendapatkan masa sekarang dan memformat output ke rentetan yang hanya mengandungi jam dan minit:

${.now?time?string('HH:mm')}

HTML yang dihasilkan adalah:

15:39

8. Pengendalian Pengecualian

Kami akan melihat dua cara untuk menangani pengecualian untuk templat FreeMarker.

Cara pertama adalah dengan menggunakan tag cubaan pemulihan untuk menentukan apa yang harus kita laksanakan dan sekumpulan kod yang harus dilaksanakan sekiranya berlaku kesilapan.

Sintaksnya adalah:

Kedua-dua teg percubaan dan pemulihan adalah wajib. Dalam kes kesilapan, ia gulung semula blok cuba dan akan melaksanakan hanya kod di dalam mendapatkan semula seksyen .

Mengingat sintaks ini, mari kita tentukan templat kita sebagai:

Preparing to evaluate

Attribute is ${attributeWithPossibleValue??}

Attribute is missing

Done with the evaluation

Apabila atributWithPossibleValue hilang, kita akan melihat:

Preparing to evaluate

Attribute is missing

Done with the evaluation

Dan output ketika atributWithPossibleValue wujud adalah:

Preparing to evaluate

Attribute is 200 OK

Done with the evaluation

Cara kedua adalah dengan mengkonfigurasi FreeMarker apa yang harus berlaku sekiranya terdapat pengecualian.

Dengan Spring Boot, kami dengan mudah mengkonfigurasinya melalui fail sifat; berikut adalah beberapa konfigurasi yang tersedia:

  • spring.freemarker.setting.template_exception_handler = tetapkan semula lontarkan pengecualian
  • spring.freemarker.setting.template_exception_handler = debug mengeluarkan maklumat jejak timbunan kepada klien dan kemudian membuang pengecualian semula.
  • spring.freemarker.setting.template_exception_handler = html_debug mengeluarkan maklumat jejak timbunan kepada klien, memformatnya sehingga biasanya akan dapat dibaca dengan baik di penyemak imbas, dan kemudian membuang pengecualian semula.
  • spring.freemarker.setting.template_exception_handler = abaikan melangkau arahan yang gagal, membiarkan templat terus dijalankan.
  • spring.freemarker.setting.template_exception_handler = lalai

9. Kaedah Memanggil

Kadang-kadang kita mahu memanggil kaedah Java dari templat FreeMarker kami. Kita sekarang akan melihat bagaimana melakukannya.

9.1. Ahli Statik

Untuk mula mengakses ahli statik, kita boleh mengemas kini konfigurasi FreeMarker global kita atau menambahkan atribut jenis S taticModels pada model, di bawah statik nama atribut :

model.addAttribute("statics", new DefaultObjectWrapperBuilder(new Version("2.3.28")) .build().getStaticModels());

Mengakses elemen statik adalah lurus ke hadapan.

Pertama, kami mengimport elemen statik kelas kami menggunakan tag penetapan, kemudian memutuskan nama dan, akhirnya, jalan kelas Java.

Inilah cara kami mengimport kelas Matematik dalam templat kami, menunjukkan nilai medan PI statik , dan menggunakan kaedah pow statik :

PI value: ${MathUtils.PI}

2*10 is: ${MathUtils.pow(2, 10)}

HTML yang dihasilkan adalah:

PI value: 3.142

2*10 is: 1,024

9.2. Ahli Kacang

Ahli kacang sangat mudah diakses: gunakan titik (.) Dan itu sahaja!

Untuk contoh seterusnya, kami akan menambahkan objek Rawak ke model kami:

model.addAttribute("random", new Random());

Dalam templat FreeMarker kami, mari menghasilkan nombor rawak:

Random value: ${random.nextInt()}

Ini akan menyebabkan output serupa dengan:

Random value: 1,329,970,768

9.3. Kaedah Tersuai

Langkah pertama untuk menambahkan kaedah khusus adalah mempunyai kelas yang menerapkan antara muka TemplatModelEx Templat FreeMarker dan menentukan logik kami dalam kaedah exec :

public class LastCharMethod implements TemplateMethodModelEx { public Object exec(List arguments) throws TemplateModelException  }

Kami akan menambahkan contoh kelas baru kami sebagai atribut pada model:

model.addAttribute("lastChar", new LastCharMethod());

Langkah seterusnya adalah menggunakan kaedah baru di dalam templat kami:

Last char example: ${lastChar('mystring')}

Akhirnya, output yang dihasilkan adalah:

Last char example: g

10. Kesimpulannya

Dalam artikel ini, kami telah melihat bagaimana menggunakan mesin templat FreeMarker di dalam projek kami. Kami telah memberi tumpuan kepada operasi biasa, bagaimana memanipulasi objek yang berbeza, dan beberapa topik yang lebih maju.

Pelaksanaan semua coretan ini boleh didapati di GitHub.