zoukankan      html  css  js  c++  java
  • IDEA项目搭建十四——Web站点Controller基类及布局页静态资源设计

    一、简介

    站点搭建完成后,编写页面时一般会有如下几个需求

    1、嵌套静态页面时有很大一部分通用代码,如css、js这部分可以使用thymeleaf的局部片段代码块组成

    2、这些静态资源默认放在程序中,但后期可能会为了节省服务器系统资源做动静分离,或架在CDN上,所以需要有独立的静态资源站点设计,目前我是单独搭建了nginx做静态资源站

    3、编写Controller时有一部分的公用代码可以提出BaseController基类来提供,简化子类代码,统一代码规范

    根据这几个需求,设计如下解决方案

    二、代码

    先看一下我的项目结构,静态资源站存放纯公用的资源,各站点又提供了各自的私有资源存放

    1、首先需要动态配置静态资源站URL,所以我们使用Enum来实现

    SysConfigEnum枚举类,其中http://localhost:8800是我搭建nginx做静态服务器地址,我们站点多了一点,大家可以简化

    /**
     * 程序枚举
     */
    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;
            }
        }
    }

    2、有一个Model实体来标明当前站点的静态资源Url和Ver

    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();
        }
    }

    3、静态资源的信息准备好后我们要把它写在每个页面上,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);
        }
    
    }

    4、子类继承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";
        }
    }

    5、后台完成了,前台渲染页面时的公用部分使用 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>

    6、其他页面引入布局页的代码块

    <!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>

    好,到此这个解决方案就完成了,如有什么不足还望指点

  • 相关阅读:
    spring
    SpringMVC 配置与使用
    基本MVC2模式创建新闻网站
    EL表达式
    JavaBeans介绍
    JSP简介
    Cookie与Session的异同
    过滤器的使用
    session的使用
    最长回文子串
  • 原文地址:https://www.cnblogs.com/taiyonghai/p/9415062.html
Copyright © 2011-2022 走看看