不做浮躁的人
          正在行走的人...
          posts - 171,  comments - 51,  trackbacks - 0
          一直在用flex做前端,都習(xí)慣面向?qū)ο蟮慕M件模式裝配ui,最近想做一些基于網(wǎng)頁的以信息展示為主的網(wǎng)站系統(tǒng),我簡稱信息發(fā)布內(nèi)核,內(nèi)核兩字表明我只是想做基本功能,不是做一個(gè)大而全的內(nèi)容發(fā)布系統(tǒng)。首先得考慮的就是頁面的布局模式。頁面的布局模式與所選用的頁面技術(shù)相關(guān),初步計(jì)劃選擇thymeleaf,源于它的natural理念。

          thymeleaf的eclipse插件:https://github.com/thymeleaf/thymeleaf-extras-eclipse-plugin

          頁面布局分為包含布局和層次布局,包含布局,一般通過th:include以及th:replace來實(shí)現(xiàn),include和replace不一樣的是一個(gè)包含在host tag里面,一個(gè)是指替換host tag,thymeleaf的包含布局和jsp的include不同的方面在于,thymeleaf可以包含某個(gè)文件的某一個(gè)部分,而jsp的必須包含整個(gè)文件。比如:<div th:replace="fragments/header :: header">...</div>,fragments/header是指被包含的模板文件,::header的header指被包含模板文件中的被包含部分。可以用this:header或者::header都是指包含本頁面的部分。被包含的文件的被包含部分需要加上屬性:th:fragment="header"

          thymeleaf可以基于dom selector來處理包含,而不用顯示地調(diào)用th:fragment,比如:<div th:include="http://www.thymeleaf.org :: p.notice" >...</div>,那么將會(huì)調(diào)用tag p且.class="notice“的片段,這個(gè)最大的好處就是包含別的網(wǎng)站的網(wǎng)頁部分。以前的做法有用ajax的,有用iframe的,還有用javabean獲取后傳給前端的。thymeleaf這種處理方式相對合理。采用dom這種方式,需要templateEngine.addTemplateResolver(urlTemplateResolver());

          包含語法的模板文件和片段都可以通過表達(dá)式來指定,比如<div th:replace="fragments/footer :: ${#authentication.principal.isAdmin()} ? 'footer-admin' : 'footer'">。

          thymeleaf包含模板也支持參數(shù)包含,比如:
          <div th:fragment="alert (type, message)"
                   class="alert alert-dismissable" th:classappend="'alert-' + ${type}">
                <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
                <span th:text="${message}">Test</span>
              </div>
          表示alert這個(gè)片段有兩個(gè)參數(shù):type和message,那么調(diào)用的時(shí)候:
          <div th:replace="fragments/alert :: alert (type='danger', message=${errorMessage})">...</div>
          參數(shù)化片段提高片段的可重用性.

          題外話,我當(dāng)年特喜歡infoglue的設(shè)計(jì)理念,事過好多年,依稀記得slot和param binding兩個(gè)讓我一直很喜歡的理念,現(xiàn)在的thymeleaf都可以做到。繼續(xù)...

          能夠從spring controller返回片段,比如:
          if (AjaxUtils.isAjaxRequest(requestedWith)) {
                  return SIGNUP_VIEW_NAME.concat(" :: signupForm");
              }
              return SIGNUP_VIEW_NAME;
          當(dāng)用ajax請求的時(shí)候,后端返回的視圖為片段的內(nèi)容。

          包含布局,由于是在每個(gè)頁面包含公共代碼,因此natural特性沒有影響,不過如果一旦需要切換包含另外的公共部分或者改變統(tǒng)一頁面布局模式,那么包含布局就顯得力不從心。層次布局,目前流行的有Tiles和sitemesh,一般是將布局等公用部分放在parent里面,顯示時(shí)將每個(gè)子頁面的具體內(nèi)容融合到parent里面來對外展現(xiàn),優(yōu)點(diǎn)是更好的維護(hù)性,缺點(diǎn)是natural不夠。

          本次信息發(fā)布內(nèi)核采用層次布局模式。兩層模板展現(xiàn),父級(jí)模板負(fù)責(zé)布局展現(xiàn),子級(jí)模板負(fù)責(zé)內(nèi)容展現(xiàn)。
          針對spring mvc和thymeleaf做一下擴(kuò)展:
          1、定義注釋:layout注釋可以用在類和方法上。
          @Target({ElementType.METHOD, ElementType.TYPE})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          public @interface Layout {
              String value() default "";
          }

          2、定義interceptor:
          public class ThymeleafLayoutInterceptor extends HandlerInterceptorAdapter {
           
              private static final String DEFAULT_LAYOUT = "layouts/default";
              private static final String DEFAULT_VIEW_ATTRIBUTE_NAME = "view";
           
              private String defaultLayout = DEFAULT_LAYOUT;
              private String viewAttributeName = DEFAULT_VIEW_ATTRIBUTE_NAME;
           
              public void setDefaultLayout(String defaultLayout) {
                  Assert.hasLength(defaultLayout);
                  this.defaultLayout = defaultLayout;
              }
           
              public void setViewAttributeName(String viewAttributeName) {
                  Assert.hasLength(defaultLayout);
                  this.viewAttributeName = viewAttributeName;
              }
           
              @Override
              public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
                  if (!modelAndView.hasView()) {
                      return;
                  }
                  String originalViewName = modelAndView.getViewName();
                  if (isRedirectOrForward(originalViewName)) {
                      return;
                  }
                  String layoutName = getLayoutName(handler);
                  modelAndView.setViewName(layoutName);
                  modelAndView.addObject(this.viewAttributeName, originalViewName);
              }
           
              private boolean isRedirectOrForward(String viewName) {
                  return viewName.startsWith("redirect:") || viewName.startsWith("forward:");
              }
           
              private String getLayoutName(Object handler) {
                  HandlerMethod handlerMethod = (HandlerMethod) handler;
                  Layout layout = getMethodOrTypeAnnotation(handlerMethod);
                  if (layout == null) {
                      return this.defaultLayout;
                  } else {
                      return layout.value();
                  }
              }
           
              private Layout getMethodOrTypeAnnotation(HandlerMethod handlerMethod) {
                  Layout layout = handlerMethod.getMethodAnnotation(Layout.class);
                  if (layout == null) {
                      return handlerMethod.getBeanType().getAnnotation(Layout.class);
                  }
                  return layout;
              }
          }

          3:配置interceptor:
          @Configuration
          public class WebMvcConfig extends WebMvcConfigurationSupport {
              @Override
              protected void addInterceptors(InterceptorRegistry registry) {
                  registry.addInterceptor(new ThymeleafLayoutInterceptor());
              }
          }

          4:測試類:
          @Controller
          class SigninController {
           
              @Layout(value = "layouts/blank")
              @RequestMapping(value = "signin")
              String signin() {
                  return "signin/signin";
              }
          }
          5:測試布局模板頁面:
          <!DOCTYPE html>
          <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
           
          <head>...</head>
          <body>
          <div th:raplace="fragments/header :: header">
              Header
          </div>
          <div th:replace="${view} :: content">
              Content
          </div>
          <div th:replace="fragments/footer :: footer">
              Footer
          </div>
          </body>
          </html>


          6:測試內(nèi)容模板頁面:
          <!DOCTYPE html>
          <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
           
          <head>...</head>
          <body>
          <div class="container" th:fragment="content">
              <!-- /* Handle the flash message */-->
              <th:block th:if="${message != null}">
                  <div th:replace="fragments/alert :: alert (type=${#strings.toLowerCase(message.type)}, message=${message.message})"> </div>
              </th:block>
              <p>
                  Hello <span th:text="${#authentication.name}">User</span>!
                  Welcome to the Spring MVC Quickstart application!
              </p>
          </div>
          </body>
          </html>
          posted on 2014-02-10 14:00 不做浮躁的人 閱讀(7705) 評論(1)  編輯  收藏

          FeedBack:
          # re: 頁面布局備忘
          2016-06-06 19:56 | Nicl
          eeeee  回復(fù)  更多評論
            

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           

          <2014年2月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          2324252627281
          2345678

          常用鏈接

          留言簿(9)

          隨筆分類(31)

          隨筆檔案(75)

          文章分類(1)

          文章檔案(3)

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 澄迈县| 罗甸县| 西昌市| 洪湖市| 大新县| 隆林| 衡南县| 扎兰屯市| 延边| 孙吴县| 南丹县| 织金县| 托里县| 称多县| 得荣县| 军事| 正宁县| 金昌市| 浦北县| 建阳市| 游戏| 波密县| 成都市| 东方市| 佳木斯市| 昆山市| 建宁县| 邯郸县| 彰武县| 贵溪市| 巴楚县| 文登市| 黑龙江省| 六盘水市| 二连浩特市| 临夏市| 赞皇县| 竹北市| 宜兴市| 漳平市| 平远县|