<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

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

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

    頁(yè)面布局分為包含布局和層次布局,包含布局,一般通過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都是指包含本頁(yè)面的部分。被包含的文件的被包含部分需要加上屬性: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)頁(yè)部分。以前的做法有用ajax的,有用iframe的,還有用javabean獲取后傳給前端的。thymeleaf這種處理方式相對(duì)合理。采用dom這種方式,需要templateEngine.addTemplateResolver(urlTemplateResolver());

    包含語(yǔ)法的模板文件和片段都可以通過表達(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請(qǐng)求的時(shí)候,后端返回的視圖為片段的內(nèi)容。

    包含布局,由于是在每個(gè)頁(yè)面包含公共代碼,因此natural特性沒有影響,不過如果一旦需要切換包含另外的公共部分或者改變統(tǒng)一頁(yè)面布局模式,那么包含布局就顯得力不從心。層次布局,目前流行的有Tiles和sitemesh,一般是將布局等公用部分放在parent里面,顯示時(shí)將每個(gè)子頁(yè)面的具體內(nèi)容融合到parent里面來對(duì)外展現(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)。
    針對(duì)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:測(cè)試類:
    @Controller
    class SigninController {
     
        @Layout(value = "layouts/blank")
        @RequestMapping(value = "signin")
        String signin() {
            return "signin/signin";
        }
    }
    5:測(cè)試布局模板頁(yè)面:
    <!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:測(cè)試內(nèi)容模板頁(yè)面:
    <!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 不做浮躁的人 閱讀(7697) 評(píng)論(1)  編輯  收藏

    FeedBack:
    # re: 頁(yè)面布局備忘
    2016-06-06 19:56 | Nicl

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


    網(wǎng)站導(dǎo)航:
     

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

    常用鏈接

    留言簿(9)

    隨筆分類(31)

    隨筆檔案(75)

    文章分類(1)

    文章檔案(3)

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 伊伊人成亚洲综合人网7777| 大学生高清一级毛片免费| 亚洲午夜激情视频| 国产精品亚洲lv粉色| 日韩激情淫片免费看| 亚洲av无码国产综合专区| 91网站免费观看| 97se亚洲国产综合自在线| 精品久久久久久久久免费影院| 亚洲无人区视频大全| 日本在线高清免费爱做网站| 亚洲制服丝袜在线播放| 国内精品乱码卡1卡2卡3免费| 亚洲国产午夜精品理论片在线播放 | 免费网站看av片| 亚洲av无码一区二区乱子伦as | 亚洲va久久久噜噜噜久久天堂| 久草免费福利视频| 99久久亚洲精品无码毛片| 日韩免费精品视频| 国产亚洲精品仙踪林在线播放| 久久久精品国产亚洲成人满18免费网站 | 国产免费伦精品一区二区三区 | 免费jlzzjlzz在线播放视频| 男人和女人高潮免费网站| 亚洲人成色77777| 亚州免费一级毛片| 亚洲第一第二第三第四第五第六| 亚洲高清无码在线观看| 久久中文字幕免费视频| 亚洲成年网站在线观看| 日韩亚洲国产综合久久久| 免费观看久久精彩视频| 亚洲一区二区三区播放在线| 扒开双腿猛进入爽爽免费视频 | 最近免费中文字幕中文高清| 亚洲精品视频在线免费| 国产成人青青热久免费精品| 成在线人免费无码高潮喷水| 亚洲免费视频网址| 国产亚洲?V无码?V男人的天堂|