IDEA項目搭建十四——Web站點Controller基類及佈局頁靜態資源設計

1、簡介

站點搭建完成後,編寫頁面時通常會有以下幾個需求javascript

一、嵌套靜態頁面時有很大一部分通用代碼,如css、js這部分能夠使用thymeleaf的局部片斷代碼塊組成css

二、這些靜態資源默認放在程序中,但後期可能會爲了節省服務器系統資源作動靜分離,或架在CDN上,因此須要有獨立的靜態資源站點設計,目前我是單獨搭建了nginx作靜態資源站html

三、編寫Controller時有一部分的公用代碼能夠提出BaseController基類來提供,簡化子類代碼,統一代碼規範java

根據這幾個需求,設計以下解決方案jquery

 

2、代碼

先看一下個人項目結構,靜態資源站存放純公用的資源,各站點又提供了各自的私有資源存放nginx

一、首先須要動態配置靜態資源站URL,因此咱們使用Enum來實現web

SysConfigEnum枚舉類,其中http://localhost:8800是我搭建nginx作靜態服務器地址,咱們站點多了一點,你們能夠簡化spring

/**
 * 程序枚舉
 */
public interface SysConfigEnum {
    /**
     * 動態站點地址
     */
    enum SiteUrl {
        AdminBase(""),
        AgentBase(""),

        AdminFlight(""),
        AgentFlight(""),

        AdminHotel(""),
        AgentHotel(""),

        private String url;

        SiteUrl(String value) {
            this.url = value;
        }

        public String getUrl() {
            return this.url;
        }
    }

    /**
     * 靜態資源地址
     */
    enum StaticUrl {
        Common("http://localhost:8800/content/", "20180801"),
        PlatformAdmin("http://localhost:8800/content/admin/content/", "20180801"),
        PlatformAgent("http://localhost:8800/content/agent/content/", "20180801"),
        ProductBaseAdmin("/admin/content/", "20180801"),
        ProductBaseAgent("/agent/content/", "20180801"),
        ProductFlightAdmin("/admin/content/", "20180801"),
        ProductFlightAgent("/agent/content/", "20180801"),
        ProductHotelAdmin("/admin/content/", "20180801"),
        ProductHotelAgent("/agent/content/", "20180801");

        private String url;
        private String ver;

        StaticUrl(String url, String ver) {
            this.url = url;
            this.ver = ver;
        }

        public String getUrl() {
            return this.url;
        }

        public String getVer() {
            return "?v=" + this.ver;
        }
    }
}

二、有一個Model實體來標明當前站點的靜態資源Url和Verbootstrap

StaticModel實體裏面標明瞭Common全局通用靜態資源,Platform平臺通用靜態資源,Product產品站點內部靜態資源安全

get、set方法作了一點修改,因爲屬性類型是枚舉,set直接設置,get時拆分開,便於作擴展

/**
 * 靜態資源實體
 */
public class StaticModel {

    private SysConfigEnum.StaticUrl common;
    private SysConfigEnum.StaticUrl platform;
    private SysConfigEnum.StaticUrl product;

    public void setCommon(SysConfigEnum.StaticUrl common) {
        this.common = common;
    }

    public void setPlatform(SysConfigEnum.StaticUrl platform) {
        this.platform = platform;
    }

    public void setProduct(SysConfigEnum.StaticUrl product) {
        this.product = product;
    }

    public String getCommonUrl() {
        return this.common.getUrl();
    }

    public String getCommonVer() {
        return this.common.getVer();
    }

    public String getPlatformUrl() {
        return this.platform.getUrl();
    }

    public String getPlatformVer() {
        return this.platform.getVer();
    }

    public String getProductUrl() {
        return this.product.getUrl();
    }

    public String getProductVer() {
        return this.product.getVer();
    }
}

三、靜態資源的信息準備好後咱們要把它寫在每一個頁面上,action到page由model來傳遞,那咱們就要在每個action時都設置一下這個model,那咱們新建一個BaseController基類來實現

Model、ModelMap、Map<>都是同一個BindingAwareModelMap實例,因此我是用了Model,你們也能夠各自更換

在基類中提供request、response、model來給子類使用,簡化子類單獨注入的操做,@ModelAttribute註解的方法,會在每個action執行以前執行【多個ModelAttribute之間沒有執行順序是亂序的】

import com.ysl.ts.common.StaticModel;
import com.ysl.ts.common.SysConfigEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Controller基類Admin
 * @author TaiYongHai
 */
public class BaseController {

    //request是線程安全的,能夠自動注入
    @Autowired
    private HttpServletRequest request;
    //response是非線程安全的,使用本地線程控制
    private ThreadLocal<HttpServletResponse> response = new ThreadLocal<>();
    //model是非線程安全的,使用本地線程控制
    private ThreadLocal<Model> model = new ThreadLocal<>();
 
    /*
    HttpServletRequest req
    HttpServletResponse res
    Model m
    action方法中的這些參數Servlet會自動幫你填充
     */

    /**
     * 獲取Request
     * @return
     */
    protected final HttpServletRequest getRequest() {
        return this.request;
    }

    /**
     * 注入Response
     * @param res
     */
    @ModelAttribute
    private void setResponse(HttpServletResponse res) {
        this.response.set(res);
    }

    /**
     * 獲取Response
     * @return
     */
    protected final HttpServletResponse getResponse() {
        return response.get();
    }

    /**
     * 注入Model
     * @param m
     */
    @ModelAttribute
    private void setModel(Model m) {
        this.model.set(m);
    }

    /**
     * 獲取Model
     * (Model、ModelMap、Map<>將使用BindingAwareModelMap做爲模型對象的實現,
     * 都是同一個BindingAwareModelMap實例,因此都共享同一份數據)
     * @return
     */
    protected final Model getModel() {
        return model.get();
    }

    //@ModelAttribute註解的方法,會在每個action執行以前執行【多個ModelAttribute之間沒有執行順序是亂序的】
    //設置靜態資源參數
    @ModelAttribute
    private void setStaticParams(Model m) {
        StaticModel staticModel = new StaticModel();
        staticModel.setCommon(SysConfigEnum.StaticUrl.Common);
        staticModel.setPlatform(SysConfigEnum.StaticUrl.PlatformAdmin);
        staticModel.setProduct(SysConfigEnum.StaticUrl.ProductBaseAdmin);
        //存入Model中
        m.addAttribute("yslTsStatic", staticModel);
    }

}

四、子類繼承BaseController能夠直接使用提供的model等對象

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
@RequestMapping("/admin/home")
@Component("AdminHome")
public class HomeController extends BaseController {

    @RequestMapping("/index")
    public String index() {
        //直接使用基類提供的對象
        HttpServletRequest request = super.getRequest();
        HttpServletResponse response = super.getResponse();
        Model model = super.getModel();
        return "/admin/home/index";
    }
}

五、後臺完成了,前臺渲染頁面時的公用部分使用 th:fragment 佈局代碼塊來實現

<html xmlns:th="http://www.thymeleaf.org">
    <!-- header 放在<head>標籤內,並在其下方寫css -->
    <div th:fragment="header" th:remove="tag">
        <div th:replace="~{/admin/layout/fragments :: metaLib}"></div>
        <div th:replace="~{/admin/layout/fragments :: cssLib}"></div>
        <div th:replace="~{/admin/layout/fragments :: cssAssist}"></div>
    </div>
    <!-- footer 放在<body>標籤內,並在其下方寫js -->
    <div th:fragment="footer" th:remove="tag">
        <div th:replace="~{/admin/layout/fragments :: jsLib}"></div>
        <div th:replace="~{/admin/layout/fragments :: jsAssist}"></div>
    </div>

    <!-- 引入變量包 -->
    <!--/*@thymesVar id="yslTsStatic" type="com.ysl.ts.common.StaticModel"*/-->
    <!-- meta信息 -->
    <div th:fragment="metaLib" th:remove="tag">
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta http-equiv="x-ua-compatible" content="ie=edge">
        <meta name="renderer" content="webkit"/>
        <meta name="Author" content="EB.Group"/>
    </div>
    <!-- 引入css -->
    <div th:fragment="cssLib" th:remove="tag">
        <link rel="icon" th:href="@{${yslTsStatic.getCommonUrl()}+'img/favicon.ico'+${yslTsStatic.getCommonVer()}}" type="image/x-icon"/>        
        <link rel="stylesheet" th:href="@{${yslTsStatic.getCommonUrl()}+'css/bootstrap.min.css'+${yslTsStatic.getCommonVer()}}"/>        
    </div>
    <!-- 全局css -->
    <div th:fragment="cssAssist" th:remove="tag">
        <style>
            body {
                overflow: hidden;
            }
        </style>
    </div>
    <!-- 引入js -->
    <div th:fragment="jsLib" th:remove="tag">
        <script type="text/javascript" th:src="@{${yslTsStatic.getCommonUrl()}+'js/jquery-1.9.1.min.js'+${yslTsStatic.getCommonVer()}}"></script>        
        <script type="text/javascript" th:src="@{${yslTsStatic.getPlatformUrl()}+'js/ysl-ts-common.js'+${yslTsStatic.getPlatformVer()}}"></script>
    </div>
    <!-- 全局js -->
    <div th:fragment="jsAssist" th:remove="tag">        
        <script type="text/javascript">
            console.log("jsAssist");
        </script>
    </div>

</html>

六、其餘頁面引入佈局頁的代碼塊

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>管理後臺</title>
    <div th:replace="~{/admin/layout/fragments :: header}"></div>
    <!-- 從這裏如下寫頁面獨立的css -->
</head>
<body>

<h1>歡迎</h1>

<div th:replace="~{/admin/layout/fragments :: footer}"></div>
<!-- 每一個頁面能夠引入本身獨有的js -->
<script type="text/javascript" th:src="@{${yslTsStatic.getProductUrl()}+'js/test.js'+${yslTsStatic.getProductVer()}}"></script>
<!-- 從這裏如下寫頁面獨立的js -->
<script type="text/javascript">
    console.log("page js");
</script>
</body>
</html>

好,到此這個解決方案就完成了,若有什麼不足還望指點

相關文章
相關標籤/搜索