Dokumentasi AsliBagian keduaBagian ketigaDaftar isi:
1. Integrasi Thymeleaf dengan Spring
2. Dialek SpringStandard
3. Tampilan dan Lihat Penyelesai
3.1 Tampilan dan Lihat Penyelesai dalam Spring MVC
3.2 Tampilan dan Lihat Penyelesai dalam Thymeleaf
4. Manajer Pemula Benih Thyme Spring
4.1 Konsep
4.2 Lapisan bisnis
4.3 Konfigurasi Spring MVC
4.4 Pengendali
4.5 Mengkonfigurasi Layanan Konversi
5 Tampilkan Data Pemula Benih
6 Membuat Formulir
6.1 Memproses objek perintah
6.2 Masukan
6.3 Bidang kotak centang
6.4 Bidang Tombol Radio
6,5 Dropdown / Daftar pemilih
6.6 Bidang dinamis
7 Verifikasi dan pesan kesalahan
7.1 Kesalahan bidang
7.2 Semua kesalahan
7.3 Kesalahan global
7.4 Menampilkan kesalahan di luar formulir
7.5 Objek Kesalahan Kaya
8 Ini masih prototipe!
9 Layanan Konversi
9.1 Konfigurasi
9.2 Sintaks braket ganda
9.3 Penggunaan dalam formulir
9.4 # konversi objek konversi
10 Rendering fragmen templat Templat templat (AJAX dll)
10.1 Mendefinisikan Fragmen dalam View Bean
10.2 Mendefinisikan fragmen dalam nilai pengembalian controller
11 Fitur Integrasi Tingkat Lanjut
11.1 Integrasi dengan RequestDataValueProcessor
11.1 Membangun URI menjadi Pengontrol
12 Spring WebFlow integrasi
12.2 Cuplikan AJAX di Spring WebFlow
Panduan ini menjelaskan bagaimana
Thymeleaf dapat diintegrasikan dengan Spring Framework, terutama (tetapi tidak hanya) Spring MVC.
Perhatikan bahwa Thymeleaf memiliki integrasi untuk versi 3.x dan 4.x dari Framework Spring dan lebih tinggi, disediakan oleh dua perpustakaan terpisah yang disebut thymeleaf-spring3 dan thymeleaf-spring4. Pustaka ini dikemas dalam file .jar yang terpisah (thymeleaf-spring3- {version} .jar dan thymeleaf-spring4- {version} .jar) dan harus ditambahkan ke jalur kelas Anda untuk menggunakan integrasi Thymeleaf Spring dalam aplikasi Anda.
Sampel kode dan contoh aplikasi dalam panduan ini menggunakan Spring 4.x dan integrasi Thymeleaf yang sesuai, tetapi isi teks ini juga berlaku untuk Spring 3.x. Jika aplikasi Anda menggunakan Spring 3.x, yang harus Anda lakukan adalah mengganti paket org.thymeleaf.spring4 dengan org.thymeleaf.spring3 dalam contoh kode.
1. Integrasi Thymeleaf dengan Spring
Thymeleaf menawarkan serangkaian integrasi Spring yang memungkinkannya digunakan sebagai pengganti JSP yang berfungsi penuh dalam aplikasi Spring MVC.
Integrasi ini memungkinkan Anda untuk:
- Buat pemetaan ke metode dalam objek pola Spring MVC Controller Anda yang dikelola oleh Thymeleaf, sama seperti Anda melakukannya dengan JSP.
- Gunakan Spring Expression Language (Spring EL) alih-alih OGNL di templat Anda.
- Buat formulir di templat Anda yang sepenuhnya terintegrasi dengan komponen dan formulir dukungan formulir Anda, termasuk penggunaan editor properti, layanan konversi, dan penanganan kesalahan validasi.
- Tampilkan pesan internasionalisasi dari file pesan yang dikelola oleh Spring (melalui objek MessageSource biasa).
- Temukan pola Anda menggunakan mekanisme resolusi sumber daya asli Spring.
Harap dicatat bahwa untuk sepenuhnya memahami tutorial ini, Anda harus terlebih dahulu melalui
tutorial "
Menggunakan Thymeleaf ", yang menjelaskan dialek standar secara rinci.
2. Dialek SpringStandard
Untuk mencapai integrasi yang lebih mudah dan lebih baik, Thymeleaf menyediakan dialek yang secara khusus mengimplementasikan semua fungsi yang diperlukan untuk bekerja dengan benar dengan Spring.
Dialek khusus ini didasarkan pada dialek Thymeleaf standar dan diimplementasikan dalam kelas org.thymeleaf.spring4.dialect.SpringStandardDialect, yang sebenarnya berasal dari org.thymeleaf.standard.StandardDialect.
Selain semua fungsi yang sudah ada dalam dialek standar dan, karenanya, diwariskan, SpringStandard Dialect menawarkan fungsi spesifik berikut:
- Menggunakan Spring Expression Language (Spring EL atau SpEL) sebagai bahasa ekspresi variabel, bukan OGNL. Karenanya, semua ekspresi $ {...} dan * {...} akan dievaluasi oleh mesin bahasa ekspresi Spring. Perhatikan juga bahwa dukungan kompiler Spring EL (Spring 4.2.4+) tersedia.
- Akses ke komponen apa pun dalam konteks aplikasi Anda menggunakan sintaks SpringEL: $ {@ myBean.doSomething ()}
- Atribut baru untuk memproses formulir: th: bidang , th: kesalahan, dan th: errorclass , kecuali untuk yang baru : implementasi objek , yang memungkinkan Anda untuk menggunakannya untuk memilih perintah formulir.
- Metode objek dan ekspresi adalah # themes.code (...) , yang setara dengan tag kustom JSP spring: theme .
- Objek dan metode ekspresi, # mvc.uri (...) , yang setara dengan fungsi pegas JSP : mvcUrl (...) (hanya di Spring 4.1+).
Perhatikan bahwa dalam kebanyakan kasus, Anda tidak boleh menggunakan dialek ini secara langsung di objek TemplateEngine biasa sebagai bagian dari konfigurasinya. Jika Anda tidak memiliki kebutuhan integrasi khusus dengan Spring, Anda harus membuat instance kelas template baru yang secara otomatis melakukan semua langkah konfigurasi yang diperlukan:
org.thymeleaf.spring4.SpringTemplateEngine .
Contoh konfigurasi kacang:
@Bean public SpringResourceTemplateResolver templateResolver(){
Atau menggunakan konfigurasi Spring berbasis XML:
<bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver"> <property name="prefix" value="/WEB-INF/templates/" /> <property name="suffix" value=".html" /> <property name="templateMode" value="HTML" /> <property name="cacheable" value="true" /> </bean> <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine"> <property name="templateResolver" ref="templateResolver" /> <property name="enableSpringELCompiler" value="true" /> </bean>
3. Tampilan dan Lihat Penyelesai
3.1 Tampilan dan Lihat Penyelesai dalam Spring MVC
Spring MVC memiliki dua antarmuka yang sesuai dengan inti sistem templatnya:
- org.springframework.web.servlet.View
- org.springframework.web.servlet.ViewResolver
Lihat halaman model dalam aplikasi kami dan memungkinkan Anda untuk mengubah dan menentukan sebelumnya perilaku mereka dengan mendefinisikannya sebagai komponen kacang. Tampilan bertanggung jawab untuk membuat antarmuka HTML yang sebenarnya, sebagai aturan, untuk mengeksekusi beberapa jenis mesin template, misalnya Thymeleaf.
ViewResolvers adalah objek yang bertanggung jawab untuk mendapatkan objek
View untuk operasi dan lokal tertentu. Biasanya, pengontrol meminta ViewResolvers untuk meneruskan tampilan dengan nama tertentu (string yang dikembalikan oleh metode controller), dan kemudian semua cara untuk menyelesaikan tampilan dalam aplikasi dieksekusi dalam rantai yang dipesan sampai salah satu dari mereka dapat menyelesaikan tampilan ini, dalam hal ini objek View dikembalikan dan kontrol ditransfer ke sana. untuk rendering HTML.
Harap perhatikan bahwa tidak semua halaman dalam aplikasi kami harus didefinisikan sebagai tampilan, tetapi hanya mereka yang perilakunya kami ingin non-standar atau disesuaikan dengan cara khusus (misalnya, dengan menghubungkan beberapa komponen khusus ke dalamnya). Jika ViewResolver diminta untuk tampilan yang tidak memiliki kacang yang sesuai (yang merupakan kasus umum), tampilan baru dibuat ad hoc dan dikembalikan.Konfigurasi JSP + JSTL ViewResolver pada aplikasi Spring MVC dari masa lalu tampak seperti ini:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsps/" /> <property name="suffix" value=".jsp" /> <property name="order" value="2" /> <property name="viewNames" value="*jsp" /> </bean>
Sekilas sifat-sifatnya sudah cukup untuk mengetahui bagaimana itu dikonfigurasi:
- viewClass menetapkan kelas instance Lihat. Ini diperlukan untuk pengenal JSP, tetapi tidak sama sekali ketika kita bekerja dengan Thymeleaf.
- Awalan dan sufiks berfungsi sama dengan atribut dengan nama yang sama di objek Thymeleaf TemplateResolver.
- order menetapkan urutan di mana ViewResolver akan diminta dalam rantai.
- viewNames memungkinkan Anda untuk menentukan (dengan wildcard) nama-nama tampilan yang akan diselesaikan oleh ViewResolver ini.
3.2 Tampilan dan Lihat Penyelesai dalam Thymeleaf
Thymeleaf menawarkan implementasi untuk dua antarmuka yang disebutkan di atas:
- org.thymeleaf.spring4.view.ThymeleafView
- org.thymeleaf.spring4.view.ThymeleafViewResolver
Kedua kelas ini akan bertanggung jawab untuk menangani templat Thymeleaf sebagai hasil dari eksekusi pengendali.
Konfigurasi dari Resolver Thymeleaf View sangat mirip dengan JSP:
@Bean public ThymeleafViewResolver viewResolver(){ ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setTemplateEngine(templateEngine());
... atau dalam XML:
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver"> <property name="templateEngine" ref="templateEngine" /> <property name="order" value="1" /> <property name="viewNames" value="*.html,*.xhtml" /> </bean>
Parameter
templateEngine , tentu saja, adalah objek SpringTemplateEngine yang kita definisikan di bab sebelumnya. Dua lainnya (
order dan
viewNames ) adalah opsional dan memiliki arti yang sama seperti di JSP ViewResolver, yang kita lihat sebelumnya.
Harap perhatikan bahwa kami tidak memerlukan parameter awalan atau sufiks, karena sudah ditentukan dalam Penyelesai Templat (yang, pada gilirannya, diteruskan ke Mesin Templat).
Tetapi bagaimana jika kita ingin mendefinisikan
kacang View dan
menambahkan beberapa variabel statis ke dalamnya ? Mudah, cukup tentukan prototipe untuk itu:
@Bean @Scope("prototype") public ThymeleafView mainView() { ThymeleafView view = new ThymeleafView("main");
Setelah melakukan ini, Anda dapat meminta komponen ini dengan memilihnya berdasarkan nama (dalam hal ini mainView).
4. Manajer Pemula Benih Thyme Spring
Kode sumber untuk contoh-contoh yang ditunjukkan dalam bab ini dan bab selanjutnya dari panduan ini dapat ditemukan di repositori
GitHub Spring Seyme Seed Starter Manager .
4.1 Konsep
Mengenai Thymeleaf, kami adalah penggemar berat thyme, dan setiap musim semi kami menyiapkan starter kit kami dengan tanah yang bagus dan benih favorit kami, tanam di bawah matahari Spanyol dan dengan sabar menunggu tanaman baru kami tumbuh.
Tetapi tahun ini, kami lelah menempelkan label pada wadah benih awal untuk mengetahui biji apa yang ada di setiap sel wadah, jadi kami memutuskan untuk menyiapkan aplikasi menggunakan Spring MVC dan
Thymeleaf untuk membantu kami membuat katalog pemula kami:
Spring Thyme SeedStarter Manager .

Mirip dengan aplikasi Good Thymes Virtual Grocery yang kami kembangkan dalam tutorial Menggunakan Thymeleaf, STSM memungkinkan kami untuk mendemonstrasikan aspek terpenting dari mengintegrasikan Thymeleaf sebagai mesin templat untuk Spring MVC.
4.2 Lapisan bisnis
Kita akan membutuhkan lapisan bisnis yang sangat sederhana untuk aplikasi kita. Pertama-tama, mari kita lihat objek model kita:

Beberapa kelas layanan yang sangat sederhana akan menyediakan metode bisnis yang diperlukan. Seperti:
@Service public class SeedStarterService { @Autowired private SeedStarterRepository seedstarterRepository; public List<SeedStarter> findAll() { return this.seedstarterRepository.findAll(); } public void add(final SeedStarter seedStarter) { this.seedstarterRepository.add(seedStarter); } }
Dan:
@Service public class VarietyService { @Autowired private VarietyRepository varietyRepository; public List<Variety> findAll() { return this.varietyRepository.findAll(); } public Variety findById(final Integer id) { return this.varietyRepository.findById(id); } }
4.3 Konfigurasi Spring MVC
Selanjutnya, kita perlu
mengonfigurasi konfigurasi Spring MVC untuk aplikasi, yang akan mencakup tidak hanya artefak Spring MVC standar, seperti sumber daya pemrosesan atau anotasi pemindaian, tetapi juga membuat
mesin Templat dan
View Resolver .
@Configuration @EnableWebMvc @ComponentScan public class SpringWebConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware { private ApplicationContext applicationContext; public SpringWebConfig() { super(); } public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } @Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { super.addResourceHandlers(registry); registry.addResourceHandler("/images/**").addResourceLocations("/images/"); registry.addResourceHandler("/css/**").addResourceLocations("/css/"); registry.addResourceHandler("/js/**").addResourceLocations("/js/"); } @Bean public ResourceBundleMessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("Messages"); return messageSource; } @Override public void addFormatters(final FormatterRegistry registry) { super.addFormatters(registry); registry.addFormatter(varietyFormatter()); registry.addFormatter(dateFormatter()); } @Bean public VarietyFormatter varietyFormatter() { return new VarietyFormatter(); } @Bean public DateFormatter dateFormatter() { return new DateFormatter(); } @Bean public SpringResourceTemplateResolver templateResolver(){
4.4 Pengendali
Tentu saja, kita juga memerlukan pengontrol untuk aplikasi kita. Karena STSM hanya akan berisi satu halaman web dengan daftar nilai awal dan formulir untuk menambahkan yang baru, kami hanya akan menulis satu kelas kontroler untuk semua interaksi server:
@Controller public class SeedStarterMngController { @Autowired private VarietyService varietyService; @Autowired private SeedStarterService seedStarterService; ... }
Sekarang mari kita lihat apa yang bisa kita tambahkan ke kelas controller ini.
Atribut modelPertama, kita akan menambahkan beberapa atribut model yang akan kita butuhkan di halaman:
@ModelAttribute("allTypes") public List<Type> populateTypes() { return Arrays.asList(Type.ALL); } @ModelAttribute("allFeatures") public List<Feature> populateFeatures() { return Arrays.asList(Feature.ALL); } @ModelAttribute("allVarieties") public List<Variety> populateVarieties() { return this.varietyService.findAll(); } @ModelAttribute("allSeedStarters") public List<SeedStarter> populateSeedStarters() { return this.seedStarterService.findAll(); }
Metode yang dipetakanDan sekarang bagian terpenting dari pengontrol, metode yang dipetakan: satu untuk menampilkan halaman formulir, dan yang lainnya untuk menangani penambahan objek
SeedStarter baru.
@RequestMapping({"/","/seedstartermng"}) public String showSeedstarters(final SeedStarter seedStarter) { seedStarter.setDatePlanted(Calendar.getInstance().getTime()); return "seedstartermng"; } @RequestMapping(value="/seedstartermng", params={"save"}) public String saveSeedstarter( final SeedStarter seedStarter, final BindingResult bindingResult, final ModelMap model) { if (bindingResult.hasErrors()) { return "seedstartermng"; } this.seedStarterService.add(seedStarter); model.clear(); return "redirect:/seedstartermng"; }
4.5 Mengkonfigurasi Layanan Konversi
Untuk memberikan pemformatan sederhana untuk objek
Date serta objek
Variety di lapisan tampilan kami, kami mengonfigurasi aplikasi kami sehingga objek Spring
ConversionService dibuat dan diinisialisasi (extensible
WebMvcConfigurerAdapter ) menggunakan beberapa objek pemformatan yang kami butuhkan.
Lihat lagi:
@Override public void addFormatters(final FormatterRegistry registry) { super.addFormatters(registry); registry.addFormatter(varietyFormatter()); registry.addFormatter(dateFormatter()); } @Bean public VarietyFormatter varietyFormatter() { return new VarietyFormatter(); } @Bean public DateFormatter dateFormatter() { return new DateFormatter(); }
Pemformat pegas adalah implementasi dari antarmuka
org.springframework.format.Formatter . Untuk informasi lebih lanjut tentang cara kerja infrastruktur konversi Spring, lihat dokumen di
spring.io .
Mari kita lihat
DateFormatter yang memformat tanggal sesuai dengan string format yang ada di kunci
date.format dari
Messages.properties kami:
public class DateFormatter implements Formatter<Date> { @Autowired private MessageSource messageSource; public DateFormatter() { super(); } public Date parse(final String text, final Locale locale) throws ParseException { final SimpleDateFormat dateFormat = createDateFormat(locale); return dateFormat.parse(text); } public String print(final Date object, final Locale locale) { final SimpleDateFormat dateFormat = createDateFormat(locale); return dateFormat.format(object); } private SimpleDateFormat createDateFormat(final Locale locale) { final String format = this.messageSource.getMessage("date.format", null, locale); final SimpleDateFormat dateFormat = new SimpleDateFormat(format); dateFormat.setLenient(false); return dateFormat; } }
VarietyFormatter secara otomatis mengkonversi antara objek
Variety kami dan cara kami ingin menggunakannya dalam formulir kami (terutama oleh nilai-nilai bidang
id mereka):
public class VarietyFormatter implements Formatter<Variety> { @Autowired private VarietyService varietyService; public VarietyFormatter() { super(); } public Variety parse(final String text, final Locale locale) throws ParseException { final Integer varietyId = Integer.valueOf(text); return this.varietyService.findById(varietyId); } public String print(final Variety object, final Locale locale) { return (object != null ? object.getId().toString() : ""); } }
Kami akan mempelajari lebih lanjut tentang bagaimana alat pemformatan ini memengaruhi cara kami menampilkan data kami di masa mendatang.