الوثائق الأصليةالجزء الثانيالجزء الثالثجدول المحتويات:
1. التكامل مع الزعتر مع الربيع
2. لهجة SpringStandard
3. المشاهدات وعرض حل
3.1 وجهات النظر ومشاهدة القرارات في الربيع MVC
3.2 طرق العرض و الحل في Thymeleaf
4. مدير زنبق بذور الربيع
4.1 مفهوم
4.2 طبقة العمل
4.3 الربيع MVC التكوين
4.4 تحكم
4.5 تكوين خدمة التحويل
5 عرض بيانات بداية البذور
6 إنشاء نماذج
6.1 معالجة كائن الأوامر
6.2 المدخلات
6.3 حقول خانة الاختيار
6.4 حقول زر الراديو
6.5 محددات القائمة المنسدلة
6.6 الحقول الديناميكية
7 رسائل التحقق والخطأ
7.1 أخطاء المجال
7.2 كل الأخطاء
7.3 الأخطاء العالمية
7.4 عرض الأخطاء خارج النماذج
7.5 كائنات خطأ غني
8 هذا لا يزال نموذجا أوليا!
9 خدمة التحويل
9.1 التكوين
9.2 بناء جملة قوس مزدوج
9.3 استخدم في النماذج
9.4 # كائن تحويل التحويلات
10 تقديم أجزاء من أجزاء قالب القالب (أجاكس إلخ)
10.1 تعريف الشظايا في حبة المشاهدة
10.2 تحديد الشظايا في القيمة المرجعة لوحدة التحكم
11 ميزات التكامل المتقدمة
11.1 التكامل مع RequestDataValueProcessor
11.1 بناء URIs إلى وحدات التحكم
12 ربيع التكامل WebFlow
12.2 مقتطفات AJAX في Spring WebFlow
يشرح هذا الدليل كيف يمكن دمج
Thymeleaf مع Spring Framework ، خاصةً (ولكن ليس فقط) Spring MVC.
لاحظ أن Thymeleaf يحتوي على تكامل للإصدارات 3.x و 4.x من Spring Framework والإصدارات الأحدث ، والتي توفرها مكتبتان منفصلتان تسمى thymeleaf-spring3 و thymeleaf-spring4. يتم حزم هذه المكتبات في ملفات .jar منفصلة (thymeleaf-spring3- {version} .jar و thymeleaf-spring4- {version} .jar) ويجب إضافتها إلى مسار الفصل الدراسي الخاص بك لاستخدام تكامل Thymeleaf Spring في التطبيق الخاص بك.
تستخدم نماذج التعليمات البرمجية وتطبيقات العينات في هذا الدليل Spring 4.x وتكاملات Thymeleaf المقابلة لها ، ولكن محتويات هذا النص تنطبق أيضًا على Spring 3.x. إذا كان التطبيق الخاص بك يستخدم Spring 3.x ، كل ما عليك فعله هو استبدال الحزمة org.thymeleaf.spring4 بـ org.thymeleaf.spring3 في أمثلة التعليمات البرمجية.
1. التكامل مع الزعتر مع الربيع
تقدم Thymeleaf مجموعة من تكامل Spring التي تسمح باستخدامها كبديل JSP كامل الميزات في تطبيقات Spring MVC.
ستتيح لك هذه الدمج ما يلي:
- قم بإجراء مناظرة للطرق في كائنات Spring MVC Controller للأنماط التي يتحكم فيها Thymeleaf ، تمامًا كما تفعل مع JSP.
- استخدم Spring Expression Language (Spring EL) بدلاً من OGNL في القوالب الخاصة بك.
- قم بإنشاء نماذج في القوالب الخاصة بك متكاملة تمامًا مع مكونات وفواتير دعم النموذج ، بما في ذلك استخدام برامج تحرير الخصائص وخدمات التحويل ومعالجة الأخطاء في التحقق من الصحة.
- عرض رسائل التدويل من ملفات الرسائل التي يديرها Spring (عبر كائنات MessageSource العادية).
- ابحث عن الأنماط باستخدام آليات تحليل موارد Spring الأصلية.
يرجى ملاحظة أنه من أجل فهم هذا البرنامج التعليمي بشكل كامل ، يجب عليك أولاً
الاطلاع على البرنامج التعليمي "
Using Thymeleaf " ، الذي يوضح بالتفصيل اللهجة القياسية.
2. لهجة SpringStandard
لتحقيق التكامل الأسهل والأفضل ، يوفر Thymeleaf لهجة تقوم على وجه التحديد بتنفيذ جميع الوظائف اللازمة للعمل بشكل صحيح مع Spring.
تستند هذه اللهجة الخاصة إلى لهجة Thymeleaf القياسية ويتم تنفيذها في فئة org.thymeleaf.spring4.dialect.SpringStandardDialect ، والتي يتم اشتقاقها فعليًا من org.thymeleaf.standard.StandardDialect.
بالإضافة إلى جميع الوظائف الموجودة بالفعل في اللهجة القياسية ، وبالتالي ، الموروثة ، يقدم SpringStandard Dialect الوظائف المحددة التالية:
- استخدام Spring Expression Language (Spring EL أو SpEL) كلغة تعبير متغير ، وليس OGNL. لذلك ، سيتم تقييم كل التعبيرات $ {...} و * {...} بواسطة محرك لغة تعبير Spring. لاحظ أيضًا أن دعم مترجم Spring EL (إصدار الربيع 4.2.4+) متاح.
- الوصول إلى أي مكونات في سياق التطبيق الخاص بك باستخدام بناء جملة SpringEL: $ {@ myBean.doSomething ()}
- سمات جديدة لمعالجة النموذج: th: field ، th: error ، و th: errorclass ، باستثناء تطبيق th: object الجديد ، الذي يسمح لك باستخدامه لتحديد أمر النموذج.
- أسلوب الكائن والتعبير هو # themes.code (...) ، وهو ما يعادل علامة JSP spring: custom theme .
- أسلوب الكائن والتعبير ، # mvc.uri (...) ، المكافئ لوظيفة JSP spring المخصصة : mvcUrl (...) (فقط في Spring 4.1+).
لاحظ أنه في معظم الحالات ، يجب ألا تستخدم هذه اللهجة مباشرة في كائن TemplateEngine عادي كجزء من التكوين الخاص بها. إذا لم يكن لديك احتياجات تكامل خاصة مع Spring ، فيجب عليك بدلاً من ذلك إنشاء مثيل لفئة قالب جديدة تقوم تلقائيًا بتنفيذ جميع خطوات التكوين الضرورية:
org.thymeleaf.spring4.SpringTemplateEngine .
مثال تكوين الفول:
@Bean public SpringResourceTemplateResolver templateResolver(){
أو باستخدام تكوين Spring المستندة إلى 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. المشاهدات وعرض حل
3.1 وجهات النظر ومشاهدة القرارات في الربيع MVC
يحتوي Spring MVC على واجهتين تتوافق مع جوهر نظام القوالب الخاص به:
- org.springframework.web.servlet.View
- org.springframework.web.servlet.ViewResolver
يمكنك عرض صفحات النماذج في تطبيقاتنا وتتيح لك تغيير سلوكها وتحديده مسبقًا عن طريق تعريفها كمكونات فاصوليا. المشاهدات هي المسؤولة عن تقديم واجهة HTML الحقيقية ، كقاعدة عامة ، لتنفيذ نوع من محرك القالب ، على سبيل المثال Thymeleaf.
ViewResolvers هي كائنات مسؤولة عن الحصول على
عرض الكائنات لعملية معينة
ولغة . عادةً ما تطلب وحدات التحكم من ViewResolvers إعادة توجيه العرض باسم محدد (السلسلة التي يتم إرجاعها بواسطة طريقة التحكم) ، ثم يتم تنفيذ جميع وسائل حل طريقة العرض في التطبيق في سلسلة مرتبة حتى يتمكن أحدهم من حل طريقة العرض هذه ، وفي هذه الحالة يتم إرجاع كائن العرض ويتم نقل عنصر التحكم إليه لتقديم HTML.
يرجى ملاحظة أنه لا ينبغي تعريف كل الصفحات في تطبيقاتنا على أنها طرق عرض ، ولكن فقط الصفحات التي نريد أن يكون سلوكها غير قياسي أو مخصصًا بطريقة خاصة (على سبيل المثال ، من خلال ربط بعض المكونات الخاصة به). إذا تم طلب ViewResolver لطريقة عرض لا تحتوي على فاصوليا مقابلة (وهي حالة شائعة) ، يتم إنشاء طريقة عرض جديدة مخصصة ويتم إرجاعها.بدا تكوين JSP + JSTL ViewResolver النموذجي في تطبيق Spring MVC من الماضي كما يلي:
<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>
نظرة سريعة على خصائصه تكفي لمعرفة كيفية تكوينها:
- تقوم viewClass بتعيين فئة عرض المثيلات. يعد هذا ضروريًا لمعرّف JSP ، ولكن ليس على الإطلاق عندما نعمل مع Thymeleaf.
- تعمل البادئة واللاحقة بشكل مشابه للسمات التي تحمل الاسم نفسه في كائنات Thymeleaf TemplateResolver.
- يعيّن الترتيب الترتيب الذي سيُطلب فيه ViewResolver في السلسلة.
- تتيح لك viewNames تحديد (باستخدام أحرف البدل) أسماء طرق العرض التي سيتم حل ViewResolver هذه.
3.2 طرق العرض و الحل في Thymeleaf
تقدم ثيميليف تطبيقات للواجهتين المذكورة أعلاه:
- org.thymeleaf.spring4.view.ThymeleafView
- org.thymeleaf.spring4.view.ThymeleafViewResolver
ستكون هاتان الفئتان مسؤولتان عن التعامل مع قوالب Thymeleaf نتيجة لتنفيذ وحدات التحكم.
تكوين Resolver Thymeleaf View مشابه جدًا لـ JSP:
@Bean public ThymeleafViewResolver viewResolver(){ ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setTemplateEngine(templateEngine());
... أو في 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>
المعلمة
templateEngine ، بالطبع ، هي كائن SpringTemplateEngine الذي حددناه في الفصل السابق. الآخران (
ترتيب و
viewNames ) اختياري ولهما نفس المعنى كما هو الحال في JSP ViewResolver ، الذي رأيناه سابقًا.
يرجى ملاحظة أننا لسنا بحاجة إلى معلمات بادئة أو لاحقة ، لأنها محددة بالفعل في "محلل القوالب" (والتي بدورها يتم تمريرها إلى "محرك القوالب").
ولكن ماذا لو أردنا تحديد
حبة عرض وإضافة بعض المتغيرات الساكنة إليها ؟ سهل ، فقط حدد النموذج الأولي لذلك:
@Bean @Scope("prototype") public ThymeleafView mainView() { ThymeleafView view = new ThymeleafView("main");
بعد القيام بذلك ، يمكنك طلب هذا المكون عن طريق تحديده حسب الاسم (في هذه الحالة عرض رئيسي).
4. مدير زنبق بذور الربيع
يمكن العثور على الكود المصدري للأمثلة الموضحة في هذا الفصل والفصول اللاحقة من هذا الدليل في مستودع
إدارة GitHub Spring Seyme Seed Starter Manager .
4.1 مفهوم
فيما يتعلق بالزعتر ، نحن من عشاق الزعتر ، وكل ربيع نعد مجموعاتنا المبتدئة بتربة جيدة وبذورنا المفضلة ، ونزرعها تحت أشعة الشمس الإسبانية وننتظر بصبر نمو نباتاتنا الجديدة.
لكن هذا العام ، لقد سئمنا من لصق الملصقات على حاويات البذور الأولية لمعرفة ما هي البذور الموجودة في كل خلية من خلايا الحاوية ، لذلك قررنا إعداد التطبيق باستخدام Spring MVC و
Thymeleaf لمساعدتنا في
التسويق للمبتدئين لدينا:
Spring Thyme SeedStarter Manager .

على غرار تطبيق Good Thymes Virtual Grocery الذي قمنا بتطويره في البرنامج التعليمي باستخدام Thymeleaf ، تتيح لنا STSM إظهار أهم جوانب دمج Thymeleaf كمحرك قوالب لـ Spring MVC.
4.2 طبقة العمل
سنحتاج إلى طبقة أعمال بسيطة جدًا لتطبيقنا. بادئ ذي بدء ، دعونا ننظر إلى الأشياء النموذجية لدينا:

سيوفر فصلان بسيطان من الخدمة طرق العمل الضرورية. مثل:
@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); } }
و:
@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 الربيع MVC التكوين
بعد ذلك ، نحتاج
إلى تكوين تهيئة Spring MVC للتطبيق ، والتي لن تشمل فقط التحف القياسية لـ Spring MVC ، مثل معالجة الموارد أو مسح التعليقات التوضيحية ، ولكن أيضًا إنشاء مثيل لـ
Template Engine و
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 تحكم
بالطبع ، نحن بحاجة أيضًا إلى وحدة تحكم لتطبيقنا. نظرًا لأن STSM سوف تحتوي على صفحة ويب واحدة فقط مع قائمة بالقيم الأولية ونموذج لإضافة قيم جديدة ، سنكتب فئة تحكم واحدة فقط لجميع تفاعلات الخادم:
@Controller public class SeedStarterMngController { @Autowired private VarietyService varietyService; @Autowired private SeedStarterService seedStarterService; ... }
الآن دعونا نرى ما يمكننا إضافته إلى فئة وحدة التحكم هذه.
سمات النموذجأولاً ، سنضيف بعض سمات النموذج التي سنحتاجها على الصفحة:
@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(); }
طرق المعينةوالآن الجزء الأكثر أهمية من وحدة التحكم ، الأساليب المعينة: واحد لعرض صفحة النموذج ، والآخر للتعامل مع إضافة كائنات
SeedStarter جديدة.
@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 تكوين خدمة التحويل
لتوفير تنسيق بسيط لكائنات
التاريخ وكذلك كائنات
متنوعة في طبقة العرض الخاصة بنا ، قمنا بتكوين تطبيقنا بحيث تم إنشاء كائن Spring
ConversionService وتهيئته (
WebMvcConfigurerAdapter ) القابل للتوسيع باستخدام زوجين من كائنات التنسيق التي نحتاجها.
انظر مرة أخرى:
@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(); }
التنسيقات الربيعية هي
تطبيقات للواجهة
org.springframework.format.Formatter . لمزيد من المعلومات حول كيفية عمل البنية الأساسية للتحويل Spring ، راجع المستندات في
spring.io .
دعونا نلقي نظرة على
DateFormatter الذي يقوم بتنسيق التواريخ وفقًا لسلسلة التنسيق الموجودة في مفتاح
date.format الخاص
برسائلنا. الخصائص :
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 تلقائيًا بين كائنات
Variety الخاصة بنا والطريقة التي نريد استخدامها بها في
أشكالنا (بشكل أساسي بواسطة قيم حقول
معرفهم ):
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() : ""); } }
سنتعلم المزيد عن كيفية تأثير أدوات التنسيق هذه على طريقة عرضنا لبياناتنا في المستقبل.