• Spring MVC视图层:thymeleaf vs. JSP


    本文对比了同一Spring MVC工程中相同页面(一个订阅表单)分别采用Thymeleaf和JSP(包括JSP、JSTL、Spring tag lib)两种方式的实现。

    本文的所有代码来自一个可运行的应用。你可以从文档页面下载该应用程序的源代码。

    Common requirements

    顾客通过一个表单添加到消息列表中,包含下面两个域:

    • Email地址
    • 订阅类型(接收所有邮件、每日摘要)

    要求该页面支持HTML5且完全国际化,国际化信息从Spring框架中配置的MessageSource对象中抽取所有的文本和消息。

    该应用包含两个@Controller,二者含有相同的代码,只是跳转到不同的view:

    • SubscribeJsp用于JSP页面(subscribejsp视图)
    • SubscribeTh用于Thymeleaf页面(subscribeth视图)

    在模型(model)中包含下列类:

    • Subscription:form-backing bean,包含两个域:String email和SubscriptionType subscriptionType。
    • SubscriptionType:一个枚举类型,表单中subscriptionType域的值,可取的值包含ALL_EMAILS和DAILY_DIGEST。

    (本文我们仅关注JSP和Thymeleaf模板代码的讨论。如果你想了解controller代码和Spring配置的实现细节,请自行查看下载包中的源代码)

    使用JSP实现(Doing it with JSP)

    这是页面:

    下面是JSP代码,使用了JSTL(core)和Spring(tags和form) JSP标签库:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %><%@  
    2. taglib prefix="s" uri="http://www.springframework.org/tags" %><%@  
    3. taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@  
    4. page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html>  
    5.    
    6. <html>  
    7.    
    8. <head>  
    9.     <title>Spring MVC view layer: Thymeleaf vs. JSP</title>  
    10.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
    11.     <link rel="stylesheet" type="text/css" media="all" href="<s:url value='/css/thvsjsp.css' />"/>  
    12. </head>  
    13.    
    14. <body>  
    15.    
    16. <h2>This is a JSP</h2>  
    17.    
    18. <s:url var="formUrl" value="/subscribejsp" />  
    19. <sf:form modelAttribute="subscription" action="${formUrl}">  
    20.    
    21.     <fieldset>  
    22.    
    23.         <div>  
    24.             <label for="email"><s:message code="subscription.email" />: </label>  
    25.             <sf:input path="email" />  
    26.         </div>  
    27.         <div>  
    28.             <label><s:message code="subscription.type" />: </label>  
    29.             <ul>  
    30.                 <c:forEach var="type" items="${allTypes}" varStatus="typeStatus">  
    31.                     <li>  
    32.                         <sf:radiobutton path="subscriptionType" value="${type}" />  
    33.                         <label for="subscriptionType${typeStatus.count}">  
    34.                             <s:message code="subscriptionType.${type}" />  
    35.                         </label>  
    36.                     </li>  
    37.                 </c:forEach>  
    38.             </ul>  
    39.         </div>  
    40.    
    41.         <div class="submit">  
    42.             <button type="submit" name="save"><s:message code="subscription.submit" /></button>  
    43.         </div>  
    44.    
    45.     </fieldset>  
    46.    
    47. </sf:form>  
    48.    
    49. </body>  
    50.    
    51. </html>  



    使用Thymeleaf实现(Doing it with Thymeleaf)

    下面使用Thymeleaf实现相同的页面。页面如下:

    下面是Thymeleaf代码:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <!DOCTYPE html>  
    2.    
    3. <html xmlns:th="http://www.thymeleaf.org">  
    4.    
    5. <head>  
    6.     <title>Spring MVC view layer: Thymeleaf vs. JSP</title>  
    7.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
    8.     <link rel="stylesheet" type="text/css" media="all"  
    9.           href="../../css/thvsjsp.css" th:href="@{/css/thvsjsp.css}"/>  
    10. </head>  
    11.    
    12. <body>  
    13.    
    14. <h2>This is a Thymeleaf template</h2>  
    15.    
    16. <form action="#" th:object="${subscription}" th:action="@{/subscribeth}">  
    17.    
    18.     <fieldset>  
    19.    
    20.         <div>  
    21.             <label for="email" th:text="#{subscription.email}">Email: </label>  
    22.             <input type="text" th:field="*{email}" />  
    23.         </div>  
    24.         <div>  
    25.             <label th:text="#{subscription.type}">Type: </label>  
    26.             <ul>  
    27.                 <li th:each="type : ${allTypes}">  
    28.                     <input type="radio" th:field="*{subscriptionType}" th:value="${type}" />  
    29.                     <label th:for="${#ids.prev('subscriptionType')}"  
    30.                            th:text="#{'subscriptionType.'+${type}}">First type</label>  
    31.                 </li>  
    32.                 <li th:remove="all"><input type="radio" /> <label>Second Type</label></li>  
    33.             </ul>  
    34.         </div>  
    35.    
    36.         <div class="submit">  
    37.             <button type="submit" name="save" th:text="#{subscription.submit}">Subscribe me!</button>  
    38.         </div>  
    39.    
    40.     </fieldset>  
    41.    
    42. </form>  
    43.    
    44. </body>  
    45.    
    46. </html>  


    注意事项:

    • 上述代码更加接近HTML——没有奇怪的标签,只是增加了一些有意义的属性。
    • 变量表达式(${...})是Spring EL且在模型属性(model attributes)上执行,星号表达式(*{...})在form backing bean上执行,hash表达式(#{...})用于国际化,link表达式(@{...})重写URL。(如果想深入学习,参考Getting started with the Standard Dialect in 5 minutes)。
    • 这里允许使用原型代码(prototype code):例如,可以把第一个域的标签设置为Email:,而在页面执行时,Thymeleaf会根据subscription.email的值把它替换为国际化的文本。
    • 我们甚至可以添加一个<li>仅仅用于prototype。当Thymeleaf执行页面时将会被删掉。

    改变页面风格(Let's change the page style)

    假象我们写完了页面,但是我们突然想改变一下按钮周围的颜色:从绿色改为淡蓝色。我们不确定那种蓝色更加合适,因此我们需要多次尝试不同的颜色组合。

    下面看一下采用JSP和Thymeleaf的实现方式:

    采用JSP修改页面风格(Changing the page style using JSP)

    第1步:将应用程序部署到开发服务器上,并启动服务器。如果服务器不启动,JSP页面不会渲染,因此这一步是必须的。

    第2步:导航到需要修改的页面。通常情况下,需要修改的页面是该应用程序的所有页面中某一个,很有可能需要点击多个链接、提交多个表单、查询多次数据库后才能跳转到这个页面。

    第3步:打开firebug、dragonfly或其他嵌入浏览器的web开发工具。通过这些工具我们可以修改页面风格,并直接作用到浏览器的DOM上,并显示给我们。

    第4步:修改颜色。尝试多种颜色组合后,确定最合适的颜色。

    第5步:复制修改过的代码,并粘贴到对应的CSS文件中。

    完成!

    采用Thymeleaf修改页面风格(Changing the page style using Thymeleaf)

    第1步:双击.html模板文件,在浏览器中打开它。由于是Thymeleaf模板,它将会正常显示,采用模板/原型(template/prototype)数据(注意订阅类型选项):

    第2步:使用文本编辑器打开.css文件。模板文件在其<link rel="stylesheet" ...>标签中链接了CSS(Thymeleaf在执行模板时会把该标签中的href替换为th:href)。因此对CSS文件的修改会显示在页面中。

    第3步:修改颜色。和采用JSP一样,我们仍然需要尝试多种不同的颜色组合,使用F5刷新页面。

    完成!

    重大区别(That was a big difference)

    步骤数量的差别并不重要(在Thymeleaf的例子中也可以使用firebug)。真正重要的区别在于其复杂性,JSP方式中每一步骤需要花费的精力和时间。采用JSP,就必须部署并启动整个应用程序,这使得JSP不如Thymeleaf方便。

    下列情形将进一步体现上述区别的意义:

    • 开发服务器并不在本地,而是远程服务器。
    • 不仅修改CSS,而且添加或删除了一些HTML代码。
    • 还未实现页面所需的后台逻辑

    最后一点是最重要的一点:如果应用程序仍在开发中,页面展示所需的Java逻辑还未完成的情况下,我们如何给客户展示新的颜色?(或者想让顾客选择颜色)...

    使用JSP作为静态原型不行吗?(And what about trying to use the JSP as a static prototype?)

    你可能会问,我们为什么要那么费事儿的修改JSP,像Thymeleaf一样直接打开JSP不行吗?

    答案是:NO。

    我们可以试一下:我们要把.jsp文件的后缀名改为.html,打开后结果如下图:

    页面哪去了?其实页面还是那个页面。只是为了让页面以JSP的方式执行,我们要添加许多JSP标签和特性。但是改为HTML后,浏览器就无法正确的显示了。

    再一次回顾一下双击Thymeleaf模板打开后的样子:

    完全不是一个级别的了。。。

    Got HTML5?

    在一开始的时候,我们就说了我们的页面是HTML5的。那么为什么不使用一些HTML5表单相关的新特性呢?

    例如,<input type="email" ...>标签可以让浏览器检查输入是否是合法的邮件格式。input标签还添加了一个新属性placeholder,它的值会默然显示在输入框中,焦点移到该输入框时自动消失。

    不错吧?不幸的是,并非所有浏览器都支持(到2011年,Opera 11 和Firefox 4支持),但是我们可以安全的使用这些新特性,因为所有的浏览器在遇到不认识的input type(如email)时会默认把它看做text类型的input,并忽略placeholder属性。

    Doing HTML5 with JSP

    Spring 3.1之前

    Spring MVC的JSP标签库在Spring3.1之前不能完全支持HTML5,因而在此之前不能写email type的input标签:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <input type="email" id="email" name="email" placeholder="your@email" value="" />  


    这是不对的。在Spring MVC中不能这样写JSP input ,因为我们不能正确地把输入绑定到form-backing bean的email属性。为了实现这种功能,需要使用<s:eval/>标签,该标签将完成所有的转换,使纯HTML标签像<sf:email/>标签一样运行:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <input type="email" id="email" name="email" placeholder="your@email"  
    2.        value="<s:eval expression='subscription.email' />" />  



    Spring3.1及之后

    Spring3.1仍然没有<sf:email ...>标签,但是<sf:input ...>标签允许type属性的值为email:

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <sf:input path="email" type="email" />  


    上述代码正确地完成了表单绑定

    Doing HTML5 with Thymeleaf

    Thymeleaf完全支持HTML5(即使是Spring3.0),因而我们只需修改input标签的type属性并添加placeholder属性,即可使用,它将会正确地绑定属性、集成到Spring MVC的属性编辑器,更为重要的是,显示为原型时也能正常显示——这是sf:input标签不支持的——

    [html] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <input type="email" th:field="*{email}" placeholder="your@email" />  


    完成!

  • 相关阅读:
    python-使用pyecharts绘制各省份985学校数量图
    python-将多个表格的信息合并到一个表格中
    python-使用百度AipOcr实现表格文字图片识别
    python安装OCR识别库
    python-一种去掉前后缀获取子串的方法
    python-一种字符串排序方式
    How to write educational schema.
    RabbitMq related
    OPENId是什么, OAUTH 是什么
    使用abp的 redis cache
  • 原文地址:https://www.cnblogs.com/qihuan/p/5013526.html
Copyright © 2020-2023  润新知