рдкрд╣рд▓рд╛ рднрд╛рдЧрджреВрд╕рд░рд╛ рднрд╛рдЧ7 рд╕рддреНрдпрд╛рдкрди рдФрд░ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢
рд╣рдорд╛рд░реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рдлрд╝реЙрд░реНрдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЙрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реВрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рддреНрдпрд╛рдкрди рд╕рдВрджреЗрд╢ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдЙрд╕рдиреЗ рдХрд┐рдП рд╣реИрдВред
Thymeleaf рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрдИ рдЯреВрд▓ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ:
# рдлреАрд▓реНрдбреНрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ,
th: рдПрд░рд░ рдФрд░
th: рдПрд░рд░рдХреНрд▓рд╛рд╕ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдореЗрдВ рдХрдИ рдХрд╛рд░реНрдпред
7.1 рдлрд╝реАрд▓реНрдб рддреНрд░реБрдЯрд┐рдпрд╛рдБ
рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рд╣рдо рдХрд┐рд╕реА рддреНрд░реБрдЯрд┐ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ CSS рд╡рд░реНрдЧ рдХреЛ рдлрд╝реАрд▓реНрдб рдореЗрдВ рдХреИрд╕реЗ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
<input type="text" th:field="*{datePlanted}" th:class="${#fields.hasErrors('datePlanted')}? fieldError" />
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ,
# рдлрд╝реАрд▓реНрдб.рд╣реИрд╕рд░реНрд╕ (...) рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдлрд╝реАрд▓реНрдб рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ (
рджрд┐рдирд╛рдВрдХрд┐рдд ) рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдмреВрд▓рд┐рдпрди рдорд╛рди рджреЗрддрд╛ рд╣реИ рдЬреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕рддреНрдпрд╛рдкрди рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВред
рд╣рдо рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рд╕рднреА рддреНрд░реБрдЯрд┐рдпрд╛рдБ рднреА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рджреЛрд╣рд░рд╛ рд╕рдХрддреЗ рд╣реИрдВ:
<ul> <li th:each="err : ${#fields.errors('datePlanted')}" th:text="${err}" /> </ul>
рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХреЗ рдмрдЬрд╛рдп, рд╣рдо
рд╡реЗрдВ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
: рддреНрд░реБрдЯрд┐рдпрд╛рдБ , рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╡рд┐рд╢реЗрд╖рддрд╛ рдЬреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЪрдпрдирдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рд╕рднреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╕реВрдЪреА рдмрдирд╛рддреА рд╣реИ, рдЬрд┐рд╕реЗ <br /> рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
<input type="text" th:field="*{datePlanted}" /> <p th:if="${#fields.hasErrors('datePlanted')}" th:errors="*{datePlanted}">Incorrect date</p>
рддреНрд░реБрдЯрд┐-рдЖрдзрд╛рд░рд┐рдд CSS рд╕реНрдЯрд╛рдЗрд▓рд┐рдВрдЧ:
th: рдПрд░рд░рдХреНрд▓рд╛рд╕рдЙрджрд╛рд╣рд░рдг рд╣рдордиреЗ рдКрдкрд░ рджреЗрдЦрд╛, рдЗрдирдкреБрдЯ рдлреЙрд░реНрдо рдХреЗ рд▓рд┐рдП рд╕реАрдПрд╕рдПрд╕ рд╡рд░реНрдЧ рдХреА рд╕реНрдерд╛рдкрдирд╛, рдпрджрд┐ рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВ, рддреЛ рдпрд╣ рдмрд╣реБрдд рдЖрдо рд╣реИ рдХрд┐ рдерд╛рдЗрдореЗрд▓реНрдл рд╕рдЯреАрдХ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╡рд┐рд╢реЗрд╖рддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ:
th: errorclass ред
рдкреНрд░рдкрддреНрд░ рдлрд╝реАрд▓реНрдб рдЯреИрдЧ (рдЗрдирдкреБрдЯ, рдЪрдпрди, рдЯреЗрдХреНрд╕рд╛рд░рд┐рдпрд╛ ...) рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ, рдпрд╣ рдХрд┐рд╕реА рднреА рдореМрдЬреВрджрд╛
рдирд╛рдо рдпрд╛
рд╡реЗрдВ рд╕реЗ рдлрд╝реАрд▓реНрдб рдХрд╛ рдирд╛рдо рдЬрд╛рдБрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдкрдврд╝реЗрдЧрд╛
: рдлрд╝реАрд▓реНрдб рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ рдПрдХ рд╣реА рдЯреИрдЧ рдореЗрдВ, рдФрд░ рдлрд┐рд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕реАрдПрд╕рдПрд╕ рд╡рд░реНрдЧ рдХреЛ рдЯреИрдЧ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ, рдпрджрд┐ рдРрд╕рд╛ рдХреЛрдИ рдлрд╝реАрд▓реНрдб рд╣реИ рдХреЛрдИ рд╕рдВрдмрдВрдзрд┐рдд рддреНрд░реБрдЯрд┐рдпрд╛рдБ рд╣реИрдВ:
<input type="text" th:field="*{datePlanted}" class="small" th:errorclass="fieldError" />
рдпрджрд┐
рджрд┐рдирд╛рдВрдХрд┐рдд рдореЗрдВ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВ, рддреЛ рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:
<input type="text" id="datePlanted" name="datePlanted" value="2013-01-01" class="small fieldError" />
7.2 рд╕рднреА рддреНрд░реБрдЯрд┐рдпрд╛рдВ
рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рд╣рдо рдлреЙрд░реНрдо рдореЗрдВ рд╕рднреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ? рд╣рдореЗрдВ рдмрд╕ рд╕реНрдерд┐рд░рд╛рдВрдХ '
* ' рдпрд╛ '
рд╕рднреА ' (рдЬреЛ рд╕рдорддреБрд▓реНрдп рд╣реИрдВ) рдХреЗ рд╕рд╛рде
# рдлрд╝реАрд▓реНрдб.рд╣реИрд╕рд░реНрд╕ (...) рдФрд░
# рдлрд╝реАрд▓реНрдбреНрд╕ред рд╡реЗрд░рд░реНрд╕ (...) рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
<ul th:if="${#fields.hasErrors('*')}"> <li th:each="err : ${#fields.errors('*')}" th:text="${err}">Input is incorrect</li> </ul>
рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ, рд╣рдо рд╕рднреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрди рдкрд░ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ...
<ul> <li th:each="err : ${#fields.errors('*')}" th:text="${err}" /> </ul>
... рдФрд░ рдПрдХ рд╕рд╛рдЭрд╛ рд╕реВрдЪреА рднреА рдмрдирд╛рдПрдВ <br />:
<p th:if="${#fields.hasErrors('all')}" th:errors="*{all}">Incorrect date</p>
рдЕрдВрдд рдореЗрдВ, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐
# рдлрд╝реАрд▓реНрдб.рд╣реИрд╕рд░реНрд╕ ('*') # рдлрд╝реАрд▓реНрдбреНрд╕ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред
рдПрдиреАрдпрд░рд░реНрд╕ () , рдФрд░
# рдлрд╝реАрд▓реНрдбреНрд╕ред рд╡реЗрд░рд░реНрд╕ ('*') # рдлрд╝реАрд▓реНрдбреНрд╕.рдСрд▓рд░реНрд╕ () рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдкрд╕рдВрдж рдХрд┐рдП рдЧрдП рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
<div th:if="${#fields.hasAnyErrors()}"> <p th:each="err : ${#fields.allErrors()}" th:text="${err}">...</p> </div>
7.3 рд╡реИрд╢реНрд╡рд┐рдХ рддреНрд░реБрдЯрд┐рдпрд╛рдВ
рд╡рд╕рдВрдд рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рддреАрд╕рд░реА рдкреНрд░рдХрд╛рд░ рдХреА рддреНрд░реБрдЯрд┐ рд╣реИ: рд╡реИрд╢реНрд╡рд┐рдХ рддреНрд░реБрдЯрд┐рдпрд╛рдВред рдпреЗ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВ рдЬреЛ рдлреЙрд░реНрдо рдореЗрдВ рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреНрд╖реЗрддреНрд░ рд╕реЗ рдЬреБрдбрд╝реА рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА рдореМрдЬреВрдж рд╣реИрдВред
Thymeleaf рдЗрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рддрдХ рдкрд╣реБрдБрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ
рд╡реИрд╢реНрд╡рд┐рдХ рдирд┐рд░рдВрддрд░рддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ:
<ul th:if="${#fields.hasErrors('global')}"> <li th:each="err : ${#fields.errors('global')}" th:text="${err}">Input is incorrect</li> </ul>
<p th:if="${#fields.hasErrors('global')}" th:errors="*{global}">Incorrect date</p>
... рд╕рд╛рде рд╣реА рд╕рдорддреБрд▓реНрдп рд╕рд╣рд╛рдпрдХ рд╡рд┐рдзрд┐рдпрд╛рдБ
# рдлрд╝реАрд▓реНрдбреНрд╕ .hasGlobalErrors () рдФрд░
# рдлрд╝реАрд▓реНрдбреНрд╕ .globalErrors () :
7.4 рд░реВрдкреЛрдВ рдХреЗ рдмрд╛рд╣рд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдирд╛
рдлрд╝реЙрд░реНрдо рд╕рддреНрдпрд╛рдкрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЪреБрдирд┐рдВрджрд╛ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ (
* {...} ) рдХреЗ рдмрдЬрд╛рдп рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ (
$ {...} ) рдХреЗ рдмрд╛рд╣рд░ рднреА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдлреЙрд░реНрдо рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдШрдЯрдХ рдХреЗ рдирд╛рдо рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрд╕рд░реНрдЧ:
<div th:errors="${myForm}">...</div> <div th:errors="${myForm.date}">...</div> <div th:errors="${myForm.*}">...</div> <div th:if="${#fields.hasErrors('${myForm}')}">...</div> <div th:if="${#fields.hasErrors('${myForm.date}')}">...</div> <div th:if="${#fields.hasErrors('${myForm.*}')}">...</div> <form th:object="${myForm}"> ... </form>
7.5 рдЕрдореАрд░ рддреНрд░реБрдЯрд┐ рд╡рд╕реНрддреБрдУрдВ
Thymeleaf рдЧреБрдг
рдлрд╝реАрд▓реНрдб рдирд╛рдо (рд╕реНрдЯреНрд░рд┐рдВрдЧ),
рд╕рдВрджреЗрд╢ (рд╕реНрдЯреНрд░рд┐рдВрдЧ) рдФрд░
рд╡реИрд╢реНрд╡рд┐рдХ (рдмреВрд▓рд┐рдпрди) рдХреЗ рд╕рд╛рде рдмреАрди рдШрдЯрдХреЛрдВ (рд╕рд░рд▓ рддрд╛рд░ рдХреЗ рдмрдЬрд╛рдп) рдХреЗ рд░реВрдк рдореЗрдВ рдлрд╛рд░реНрдо рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
рдпреЗ рддреНрд░реБрдЯрд┐рдпрд╛рдВ
# рдлрд╝реАрд▓реНрдбреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИрдВред
рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ () рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╡рд┐рдзрд┐:
<ul> <li th:each="e : ${#fields.detailedErrors()}" th:class="${e.global}? globalerr : fielderr"> <span th:text="${e.global}? '*' : ${e.fieldName}">The field name</span> | <span th:text="${e.message}">The error message</span> </li> </ul>
8 рдпрд╣ рдЕрднреА рднреА рдПрдХ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рд╣реИ!
рд╣рдорд╛рд░рд╛ рдЖрд╡реЗрджрди рддреИрдпрд╛рд░ рд╣реИред рд▓реЗрдХрд┐рди рдЖрдЗрдП рдПрдХ рдФрд░ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВред html рдкреЗрдЬ рд╣рдордиреЗ рдмрдирд╛рдпрд╛ ...
рдерд╛рдЗрдореЗрд▓рдл рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рд╕реБрдЦрдж рдкрд░рд┐рдгрд╛рдо рдпрд╣ рд╣реИ рдХрд┐ рдЗрди рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдмрд╛рдж рдЬреЛ рд╣рдордиреЗ рдЕрдкрдиреЗ HTML рдореЗрдВ рдЬреЛрдбрд╝реЗ рд╣реИрдВ, рд╣рдо рдЕрднреА рднреА рдЗрд╕ HTML рдХреЛ рдПрдХ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рд╣рдо рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдПрдХ
рдкреНрд░рд╛рдХреГрддрд┐рдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рд╣реИ )ред рдЪрд▓рд┐рдП рдмрд┐рдирд╛ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЛ рд▓реЙрдиреНрдЪ рдХрд┐рдП рд╕реАрдзреЗ рдЕрдкрдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ
seedstartermng.html рдЦреЛрд▓реЗрдВ:

рдпрд╣рд╛рдБ рдпрд╣ рд╣реИ! рдпрд╣ рдПрдХ рдХрд╛рдордХрд╛рдЬреА рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдирд╣реАрдВ рд╣реИ, рдпрд╣ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреЗрдЯрд╛ рдирд╣реАрдВ рд╣реИ ... рд▓реЗрдХрд┐рди рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╣реА рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рд╣реИ рдЬреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд HTML рдХреЛрдб рд╕реЗ рдмрдирд╛ рд╣реИред
9 рд░реВрдкрд╛рдВрддрд░рдг рд╕реЗрд╡рд╛
9.1 рд╡рд┐рдиреНрдпрд╛рд╕
рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдерд╛рдЗрдорд▓реЗрдл рдЖрд╡реЗрджрди рд╕рдВрджрд░реНрдн рдореЗрдВ рдкрдВрдЬреАрдХреГрдд рдкрд░рд┐рд╡рд░реНрддрди рд╕реЗрд╡рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреНрд▓рд╛рд╕, рдореВрд▓ рд╕реНрдкреНрд░рд┐рдВрдЧ
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(); }
9.2 рдбрдмрд▓ рдмреНрд░реИрдХреЗрдЯ рд╕рд┐рдВрдЯреИрдХреНрд╕
рдХрд┐рд╕реА рднреА рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдмрджрд▓рдиреЗ / рдкреНрд░рд╛рд░реВрдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░реВрдкрд╛рдВрддрд░рдг рд╕реЗрд╡рд╛ рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рдбрдмрд▓ рдХреЛрд╖реНрдардХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
- рдЪрд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП: $ {{...}}
- рдПрдХ рд╡рд┐рдХрд▓реНрдк рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП: * {{...}}
рдЗрд╕рд▓рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрдВрдЯреЗрдЧрд░-рдЯреВ-рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрдирд╡рд░реНрдЯрд░ рджрд┐рдпрд╛ рдЧрдпрд╛, рдЬреЛ рд╣рдЬрд╛рд░реЛрдВ рд╡рд┐рднрд╛рдЬрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдХреЙрдорд╛ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рдпрд╣ рд╣реИ:
<p th:text="${val}">...</p> <p th:text="${{val}}">...</p>
... рдореЗрдВ рдкрд░рд┐рдгрд╛рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:
<p>1234567890</p> <p>1,234,567,890</p>
9.3 рд░реВрдкреЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
рд╣рдордиреЗ рдкрд╣рд▓реЗ рджреЗрдЦрд╛ рдерд╛ рдХрд┐ рд╣рд░
рд╡реЗрдВ: рдлрд╝реАрд▓реНрдб рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣рдореЗрд╢рд╛ рдЯреНрд░рд╛рдВрд╕рдлрд╝реЙрд░реНрдо рд╕реЗрд╡рд╛ рд▓рд╛рдЧреВ рдХрд░реЗрдЧреА, рдЗрд╕рд▓рд┐рдП рдпрд╣:
<input type="text" th:field="*{datePlanted}" />
... рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕рдХреЗ рдмрд░рд╛рдмрд░:
<input type="text" th:field="*{{datePlanted}}" />
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╡рд╕рдВрдд рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдпрд╣ рдПрдХрдорд╛рддреНрд░ рдкрд░рд┐рджреГрд╢реНрдп рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХрд▓ рдмреНрд░реИрдХреЗрдЯ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рд╕реЗрд╡рд╛ рд▓рд╛рдЧреВ рдХреА рдЬрд╛рддреА рд╣реИред
9.4 # рд░реВрдкрд╛рдВрддрд░рдг рд░реВрдкрд╛рдВрддрд░рдг рд╡рд╕реНрддреБ
# рд░реВрдкрд╛рдВрддрд░рдг рд░реВрдкрд╛рдВрддрд░рдг рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдЖрдкрдХреЛ рдЖрд╡рд╢реНрдпрдХ рд░реВрдк рд╕реЗ рд░реВрдкрд╛рдВрддрд░рдг рд╕реЗрд╡рд╛ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ:
<p th:text="${'Val: ' + #conversions.convert(val,'String')}">...</p>
рдЗрд╕ рд╕реЗрд╡рд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╣реИ:
- # рд░реВрдкрд╛рдВрддрд░рдг.рдХреЙрдиреНрд╡рд░реНрдЯ (рдСрдмреНрдЬреЗрдХреНрдЯ, рдХреНрд▓рд╛рд╕) : рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдХрдирд╡рд░реНрдЯ рдХрд░рддрд╛ рд╣реИ
- # рд░реВрдкрд╛рдВрддрд░рдг.рдХреЙрдиреНрд╡рд░реНрдЯ (рдСрдмреНрдЬреЗрдХреНрдЯ, рд╕реНрдЯреНрд░рд┐рдВрдЧ) : рдКрдкрд░ рдХреЗ рд╕рдорд╛рди, рд▓реЗрдХрд┐рди рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рд▓рдХреНрд╖реНрдп рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде (рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ java.langред рдкреИрдХреЗрдЬ рдЫреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ)
рдЯреЗрдореНрдкрд▓реЗрдЯ рдЯреЗрдореНрдкрд▓реЗрдЯ рдЯреБрдХрдбрд╝реЗ (AJAX рдЖрджрд┐) рдХреЗ 10 рдкреНрд░рддрд┐рдкрд╛рджрди рдЯреБрдХрдбрд╝реЗ
Thymeleaf рдЕрдкрдиреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рдХреЗрд╡рд▓ рднрд╛рдЧ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ:
рдЯреБрдХрдбрд╝рд╛ ред
рдпрд╣ рдПрдХ рдЙрдкрдпреЛрдЧреА рдШрдЯрдХ рдЙрдкрдХрд░рдг рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣
AJAX рдХреЙрд▓ рдкрд░ рдЪрд▓рдиреЗ рд╡рд╛рд▓реЗ рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдкрд░ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рдЙрд╕ рдкреГрд╖реНрда рдХреЗ рд▓реЗрдЖрдЙрдЯ рдХреЗ рдЯреБрдХрдбрд╝реЗ рдХреЛ рд▓реМрдЯрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рд▓реЛрдб рд╣реИ (рдЪрдпрди рдХреЛ рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрдЯрди рдХреЛ рдЪрд╛рд▓реВ / рдмрдВрдж ...)ред
рдлреНрд░реИрдЧреНрдореЗрдВрдЯреЗрдб рд░реЗрдВрдбрд░рд┐рдВрдЧ рдХреЛ Thymeleaf рд╕реНрдирд┐рдкреЗрдЯ рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ: рдСрдмреНрдЬреЗрдХреНрдЯ рдЬреЛ
org.thymeleaf.fragment.IFragmentSpec рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред
рдЗрди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиреЛрдВ рдореЗрдВ рд╕рдмрд╕реЗ рдЖрдо рд╣реИ
org.thymeleaf.standard.fragment.StandardDOMSelectorFragmentSpec , рдЬреЛ рдЖрдкрдХреЛ DOM рдЪрдпрдирдХрд░реНрддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреИрд╕реЗ
рд╡реЗрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рд▓реЛрдЧреЛрдВ рдореЗрдВ
рд╢рд╛рдорд┐рд▓ рд╣реИрдВ : th рдпрд╛
: рдмрджрд▓реЗрдВ ред
10.1 рдПрдХ рджреГрд╢реНрдп рдмреАрди рдореЗрдВ рдЯреБрдХрдбрд╝реЗ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛
рд╕реЗрдо рджреЗрдЦреЗрдВ
org.thymeleaf.spring4.view.ThymeleafView рд╡рд░реНрдЧ рдХреЗ рд╕реЗрдо рд╣реИрдВ рдЬреЛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕рдВрджрд░реНрдн рдореЗрдВ рдШреЛрд╖рд┐рдд рд╣реИрдВ (
рдмреАрди рдПрдиреЛрдЯреЗрд╢рди рдпрджрд┐ рдЖрдк рдЬрд╛рд╡рд╛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ)ред рд╡реЗ рдЖрдкрдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдЕрдВрд╢ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ:
@Bean(name="content-part") @Scope("prototype") public ThymeleafView someViewBean() { ThymeleafView view = new ThymeleafView("index");
рдмреАрди рдХреА рдЙрдкрд░реЛрдХреНрдд рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рдпрджрд┐ рд╣рдорд╛рд░рд╛ рдирд┐рдпрдВрддреНрд░рдХ рдПрдХ
рдХрдВрдЯреЗрдВрдЯ-рдкрд╛рд░реНрдЯ (рдЙрдкрд░реЛрдХреНрдд рдмреАрди рдХрд╛ рдирд╛рдо) рджреЗрддрд╛ рд╣реИ ...
@RequestMapping("/showContentPart") public String showContentPart() { ... return "content-part"; }
... Thymeleaf рдХреЗрд╡рд▓ рдЙрдкрд╕рд░реНрдЧ рдФрд░ рдкреНрд░рддреНрдпрдп рд▓рдЧрд╛рдиреЗ рдХреЗ рдмрд╛рдж, рд╕реВрдЪрдХрд╛рдВрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреА
рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдЯреБрдХрдбрд╝рд╛ рд▓реМрдЯреЗрдЧрд╛ - рдЬрд┐рд╕рдХрд╛ рд╕реНрдерд╛рди рд╕рдВрднрд╡рддрдГ
/WEB-INF/templates/index.html рдХреЗ рд╕рдорд╛рди рд╣реЛрдЧрд╛ред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдкрд░рд┐рдгрд╛рдо рдкреВрд░реА рддрд░рд╣ рд╕реЗ
рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдЧрд╛
:: рд╕рд╛рдордЧреНрд░реА :
<!DOCTYPE html> <html> ... <body> ... <div th:fragment="content"> Only this div will be rendered! </div> ... </body> </html>
рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдерд╛рдЗрдорд▓реЗрдл рд▓реЗрдЖрдЙрдЯ рдЪрдпрдирдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рд╣рдо рдХрд┐рд╕реА рднреА
рд╡реЗрдВ рдореЗрдВ рдПрдХ рдЯреБрдХрдбрд╝реЗ рдХреЗ рдмрд┐рдирд╛ рдПрдХ рдЯреБрдХрдбрд╝реЗ рдХрд╛ рдЪрдпрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
: рдЯреБрдХрдбрд╝рд╛ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВред рдЖрдЗрдП
рдЖрдЗрдбреА рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:
@Bean(name="content-part") @Scope("prototype") public ThymeleafView someViewBean() { ThymeleafView view = new ThymeleafView("index");
10.2 рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рд░рд┐рдЯрд░реНрди рд╡реИрд▓реНрдпреВ рдореЗрдВ рдЯреБрдХрдбрд╝реЗ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛
рд╡реНрдпреВ рдмреАрдиреНрд╕ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдЯреБрдХрдбрд╝реЗ рдХреЛ
рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдирд┐рдпрдВрддреНрд░рдХ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЬреИрд╕реЗ
рд╡реЗрдВ рдореЗрдВ: рд╕рдореНрдорд┐рд▓рд┐рдд рдХрд░реЗрдВ рдпрд╛
рд╡реЗрдВ: рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ
рдмрджрд▓реЗрдВ ред
@RequestMapping("/showContentPart") public String showContentPart() { ... return "index :: content"; }
рдмреЗрд╢рдХ, DOM рдЪрдпрдирдХрд░реНрддрд╛рдУрдВ рдХреА рдкреВрд░реА рд╢рдХреНрддрд┐ рдлрд┐рд░ рд╕реЗ рдЙрдкрд▓рдмреНрдз рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдорд╛рдирдХ HTML рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ, рдЬреИрд╕реЗ
id = "рд╕рд╛рдордЧреНрд░реА" рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╣рдорд╛рд░реЗ рдЯреБрдХрдбрд╝реЗ рдХрд╛ рдЪрдпрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
@RequestMapping("/showContentPart") public String showContentPart() { ... return "index :: #content"; }
рдФрд░ рд╣рдо рдорд╛рдкрджрдВрдбреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреИрд╕реЗ:
@RequestMapping("/showContentPart") public String showContentPart() { ... return "index :: #content ('myvalue')"; }
11 рдЙрдиреНрдирдд рдПрдХреАрдХрд░рдг рд╕реБрд╡рд┐рдзрд╛рдПрдБ
11.1 RequestDataValueProcessor рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг
Thymeleaf рд╕реНрдкреНрд░рд┐рдВрдЧ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯрдбреИрдЯрд╛рд╡реИрд▓реНрдпреВрдкреНрд░реЛрд╕реЗрд╕рд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╕рд╛рде рдореВрд▓ рдПрдХреАрдХреГрдд рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЖрдкрдХреЛ рд▓рд┐рдВрдХ URL рдХреЛ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯ рдХрд░рдиреЗ, URL рдмрдирд╛рдиреЗ рдФрд░ рдлрд╝реАрд▓реНрдб рдорд╛рди рдмрдирд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЙрдиреНрд╣реЗрдВ рдорд╛рд░реНрдХрдЕрдк рд░рд┐рдЬрд▓реНрдЯ рдкрд░ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рдкрд╛рд░рджрд░реНрд╢реА рд░реВрдк рд╕реЗ рдЫрд┐рдкреЗ рд╣реБрдП рдлрд╝реАрд▓реНтАНрдб рдлрд╝реАрд▓реНрдб рднреА рд╢рд╛рдорд┐рд▓ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕реБрд░рдХреНрд╖рд╛ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрддреА рд╣реИрдВ, рдЬреИрд╕реЗ: CSRF рдХреЗ рд╡рд┐рд░реБрджреНрдз рд╕реБрд░рдХреНрд╖рд╛ (рдХреНрд░реЙрд╕-рд╕рд╛рдЗрдЯ рдЕрдиреБрд░реЛрдз рдЬрд╛рд▓рд╕рд╛рдЬреА) ред
RequestDataValueProcessor рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕рдВрджрд░реНрдн рдореЗрдВ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣
org.springframework.web.servlet.support.equestDataValueProcessor рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рд╕реЗрдо рдирд╛рдо рдХреЗ рд░реВрдк рдореЗрдВ
requestDataValueProcessor рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:
@Bean public RequestDataValueProcessor requestDataValueProcessor() { return new MyRequestDataValueProcessor(); }
... рдФрд░ Thymeleaf рдЗрд╕реЗ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:
- th: href рдФрд░ th: src call RequestDataValueProcessor.processUrl (...) URL рд░реЗрдВрдбрд░ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ
- th: рдПрдХреНрд╢рди рдХреЙрд▓ RequestDataValueProcessor.processAction (...) рдлреЙрд░реНрдо рдХреА рдПрдХреНрд╢рди рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдФрд░ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╡рд┐рд╢реЗрд╖рддрд╛ <рдлреЙрд░реНрдо> рдЯреИрдЧ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддреА рд╣реИ, рдЬреЛ рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдПрдХрдорд╛рддреНрд░ рдЬрдЧрд╣ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ RequestDataValueProcessor.getExtraHiddenFields (... ) рдФрд░ рд╕рдорд╛рдкрди </ form> рдЯреИрдЧ рд╕реЗ рддреБрд░рдВрдд рдкрд╣рд▓реЗ рдЫрд┐рдкреЗ рд╣реБрдП рдлрд╝реАрд▓реНрдб рдХреЛ рдЬреЛрдбрд╝рддрд╛ рд╣реИ
- th: рдорд╛рди рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ RequestDataValueProcessor.processFormFieldValue (...) рдЙрд╕ рдореВрд▓реНрдп рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛ рддрдм рддрдХ рд╕рдВрджрд░реНрднрд┐рдд рд╣реЛрддрд╛ рд╣реИ, рдЬрдм рддрдХ рдХрд┐ th: рдлрд╝реАрд▓реНрдб рдПрдХ рд╣реА рдЯреИрдЧ рдореЗрдВ рдирд╣реАрдВ рд╣реИ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ th: рдлрд╝реАрд▓реНрдб рдзреНрдпрд╛рди рд░рдЦреЗрдЧреА)
- th: рдлрд╝реАрд▓реНрдб рдХреЙрд▓ рдЙрд╕ рдЕрдиреБрд░реЛрдз рдХрд╛ рдорд╛рди рдЦреАрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП RequestDataValueProcessor.processFormFieldValue (...) рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ (рдпрд╛ рдЯреИрдЧ рдХрд╛ рд╢рд░реАрд░ рдпрджрд┐ рдпрд╣ рд╣реИ рддреЛ рдпрд╣ textarea рд╣реИ)
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдмрд╣реБрдд рдХрдо рдкрд░рд┐рджреГрд╢реНрдп рд╣реИрдВ рдЬрд┐рдирдореЗрдВ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдореЗрдВ RequestDataValueProcessor рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдпрд╣ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╕реБрд░рдХреНрд╖рд╛ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬреЛ рдЖрдк рдкрд╛рд░рджрд░реНрд╢реА рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реНрдкреНрд░рд┐рдВрдЧ рд╕рд┐рдХреНрдпреЛрд░рд┐рдЯреА рдХрд╛ рд╕реАрдПрд╕рдЖрд░рдПрдлред11.1 рдХрдВрдЯреНрд░реЛрд▓рд░реНрд╕ рдХреЛ URI рдмрд┐рд▓реНрдбрд┐рдВрдЧ
рд╕рдВрд╕реНрдХрд░рдг 4.1 рдХреЗ рд╕рд╛рде рд╢реБрд░реВ,
рд╡рд╕рдВрдд рдпреВрдЖрд░рдЖрдИ рдХреЛ рдЬрд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрд┐рдирд╛ рд╡рд┐рдЪрд╛рд░реЛрдВ рд╕реЗ рд╕реАрдзреЗ рдПрдиреЛрдЯреЗрдЯ рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдХреЗ рд▓рд┐рдВрдХ рдмрдирд╛рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЗрди рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдХреЛ рдореИрдк рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
Thymeleaf рдореЗрдВ, рдпрд╣ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐
# mvc.url (...) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдЖрдкрдХреЛ рдирд┐рдпрдВрддреНрд░рдХ рд╡рд░реНрдЧ рдХреЗ рдкреВрдВрдЬреА рдЕрдХреНрд╖рд░реЛрдВ рдореЗрдВ рдирд┐рдпрдВрддреНрд░рдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╡реЗ рд╕реНрдерд┐рдд рд╣реИрдВ, рд╡рд┐рдзрд┐ рдирд╛рдо рдХреЗ рдмрд╛рджред рдпрд╣ JSP рдореЗрдВ рдХрд╕реНрдЯрдо
рд╕реНрдкреНрд░рд┐рдВрдЧ: mvcUrlx (...) рдлрдВрдХреНрд╢рди рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕рдХреЗ рд▓рд┐рдП:
public class ExampleController { @RequestMapping("/data") public String getData(Model model) { ... return "template" } @RequestMapping("/data") public String getDataParam(@RequestParam String type) { ... return "template" } }
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рд╡рд┐рдзрд┐ рд╕рдВрджрд░реНрдн рдмрдирд╛рдПрдВрдЧреЗ:
<a th:href="${(#mvc.url('EC#getData')).build()}">Get Data Param</a> <a th:href="${(#mvc.url('EC#getDataParam').arg(0,'internal')).build()}">Get Data Param</a>
рдЖрдк рдЗрд╕ рддрдВрддреНрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ
http://docs.spring.io/spring-framework/docs/4.1.2.RELEASE/spring-framework-reference/html/mvc.html#mvc-links-to-controllers- рдкрд░ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ
рд╕реЗ-рдмрд╛рд░ рджреЗрдЦрд╛ рдЧрдпрд╛12 рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдмрдлреНрд▓реЛ рдПрдХреАрдХрд░рдг
Thymeleaf + рд╕реНрдкреНрд░рд┐рдВрдЧ рдПрдХреАрдХрд░рдг рдкреИрдХреЗрдЬ рдореЗрдВ рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдмрдлреНрд▓реЛ (2.3+) рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рд╢рд╛рдорд┐рд▓ рд╣реИред
WebFlow рдореЗрдВ рдХреБрдЫ рдШрдЯрдирд╛рдУрдВ (рдкрд░рд┐рд╡рд░реНрддрди) рд╢реБрд░реВ рд╣реЛрдиреЗ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдкреГрд╖реНрда рдХреЗ рдЯреБрдХрдбрд╝реЛрдВ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ AJAX рд╕реБрд╡рд┐рдзрд╛рдПрдБ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдФрд░ Thymeleaf рдХреЗ рд▓рд┐рдП рдЗрди AJAX рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдПрдХ рдФрд░ ViewResolver рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring4.view.AjaxThymeleafViewResolver"> <property name="viewClass" value="org.thymeleaf.spring4.view.FlowAjaxThymeleafView" /> <property name="templateEngine" ref="templateEngine" /> </bean>
... рдФрд░ рдлрд┐рд░ рдЗрд╕
ViewResolver рдХреЛ
WebFlow ViewFactoryCreator рдореЗрдВ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator"> <property name="viewResolvers" ref="thymeleafViewResolver"/> </bean>
рдпрд╣рд╛рдБ рд╕реЗ рдЖрдк рдЕрдкрдиреЗ рд╡реНрдпреВ-рд╕реНрдЯреЗрдЯ рдХреЗ рдореЗрдВ Thymeleaf рдЯреЗрдореНрдкрд▓реЗрдЯреНрд╕ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
<view-state id="detail" view="bookingDetail"> ... </view-state>
рдЙрдкрд░реЛрдХреНрдд рдЙрджрд╛рд╣рд░рдг рдореЗрдВ,
BookDetail рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдПрдХ Thymeleaf рдЯреЗрдореНрдкрд▓реЗрдЯ рд╣реИ, рдЬреЛ TemplateEngine рдореЗрдВ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдП рдЧрдП рдХрд┐рд╕реА рднреА рдЯреЗрдореНрдкрд▓реЗрдЯ рд░рд┐рдЬрд╝реЙрд▓реНрд╡рд░ рдХреЗ рд▓рд┐рдП рд╕рдордЭрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдмрдлреНрд▓реЛ рдореЗрдВ 12.2 AJAX рд╕реНрдирд┐рдкреЗрдЯ
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ рдпрд╣ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕реНрдкреНрд░рд┐рдВрдЧ рд╡реЗрдмрдлреНрд▓реЛ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП AJAX рдЯреБрдХрдбрд╝реЗ рдХреИрд╕реЗ рдмрдирд╛рдПрдВред рдпрджрд┐ рдЖрдк WebFlow рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдПрдХ рд╕реНрдкреНрд░рд┐рдВрдЧ рдПрдорд╡реАрд╕реА рдирд┐рдпрдВрддреНрд░рдХ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рдЬреЛ AJAX рдЕрдиреБрд░реЛрдз рдХрд╛ рдЬрд╡рд╛рдм рджреЗрддрд╛ рд╣реИ рдФрд░ HTML рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдирд┐рдпрдВрддреНрд░рдХ рдХреЛ рдмрдирд╛рдиреЗ рдореЗрдВ рдЙрддрдирд╛ рд╣реА рд╕рд░рд▓ рд╣реИ рдЬреЛ рдПрдХ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдПрдХрдорд╛рддреНрд░ рдЕрдкрд╡рд╛рдж рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рддрд░рд╣ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд░рдЦрддреЗ рд╣реИрдВ " :: "рдирд┐рдпрдВрддреНрд░рдХ" рдЕрдкрдиреЗ рдирд┐рдпрдВрддреНрд░рдХ рд╡рд┐рдзрд┐ рд╕реЗредWebFlow рдЖрдкрдХреЛ рдЗрд╕ рддрд░рд╣ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП <рд░реЗрдВрдбрд░> рдЯреИрдЧ рдХреЗ рд╕рд╛рде AJAX рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ:
<view-state id="detail" view="bookingDetail"> <transition on="updateData"> <render fragments="hoteldata"/> </transition> </view-state>
рдпреЗ рдЯреБрдХрдбрд╝реЗ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ
рд╣реЛрдЯрд▓рдбрд╛рдЯрд╛ )
рдЕрдВрдХ рдХреЗ рд╕рд╛рде рдЕрдВрдХрди рдореЗрдВ рдЗрдВрдЧрд┐рдд рдЯреБрдХрдбрд╝реЗ рдХреА рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рд╕реЗ рдЕрд▓рдЧ рд╕реВрдЪреА рд╣реЛ рд╕рдХрддреА рд╣реИ:
рд╕реБрдЧрдВрдзрд┐рдд :
<div id="data" th:fragment="hoteldata"> This is a content to be changed </div>
рд╣рдореЗрд╢рд╛ рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдЗрди рд╕реНрдирд┐рдкреЗрдЯ рдореЗрдВ рдПрдХ
рдЖрдИрдбреА рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП рддрд╛рдХрд┐ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЪрд▓ рд░рд╣реЗ рд╕реНрдкреНрд░рд┐рдВрдЧ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реАрдЬрд╝ рдорд╛рд░реНрдХрдЕрдк рдХреА рдЬрдЧрд╣ рд▓реЗ рд╕рдХреЗрдВред
рдЖрдк рдбреЛрдо рдЪрдпрдирдХрд░реНрддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ <рд░реЗрдВрдбрд░> рдЯреИрдЧ рднреА рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
<рджреГрд╢реНрдп-рд░рд╛рдЬреНрдп рдЖрдИрдбреА = "рд╡рд┐рд╕реНрддрд╛рд░" рджреГрд╢реНрдп = "рдмреБрдХрд┐рдВрдЧрдбреЗрд▓">
/>
</ рджреЗрдЦреЗрдВ рд░рд╛рдЬреНрдп>
... рдФрд░ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐
рд╡реЗрдВ: рдЯреБрдХрдбрд╝реЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ:
<div id="data"> This is a content to be changed </div>
рдХреЛрдб рдХреЗ рд▓рд┐рдП рдЬреЛ
рдЕрджреНрдпрддрдирдбрд╛рдЯрд╛ рд╕рдВрдХреНрд░рдордг рдЪрд▓рд╛рддрд╛ рд╣реИ, рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
<script type="text/javascript" th:src="@{/resources/dojo/dojo.js}"></script> <script type="text/javascript" th:src="@{/resources/spring/Spring.js}"></script> <script type="text/javascript" th:src="@{/resources/spring/Spring-Dojo.js}"></script> ... <form id="triggerform" method="post" action=""> <input type="submit" id="doUpdate" name="_eventId_updateData" value="Update now!" /> </form> <script type="text/javascript"> Spring.addDecoration( new Spring.AjaxEventDecoration({formId:'triggerform',elementId:'doUpdate',event:'onclick'})); </script>