一、简介

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

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>

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

IDEA项目搭建十四——Web站点Controller基类及布局页静态资源设计的更多相关文章

  1. IDEA项目搭建十二——站点用户登录会话实现

    一.简介 前两天写了一篇用户登录会话设计的脑图,这次就把这个引入到项目中实现,总体来说需要几步先罗列一下: 1.需要一个Cookie工具类用于读写cookie 2.需要一个Cache工具类用于在服务端 ...

  2. Spring+SpringMVC+MyBatis深入学习及搭建(十四)——SpringMVC和MyBatis整合

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7010363.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十三)--S ...

  3. Scala学习十四——模式匹配和样例类

    一.本章要点 match表达式是更好的switch,不会有意外调入下一个分支 如果没有模式能够匹配,会抛出MatchError,可以用case _模式避免 模式可以包含一个随意定义的条件,称做守卫 你 ...

  4. 『PyTorch』第十四弹_torch.nn.Module类属性

    nn.Module基类的构造函数: def __init__(self): self._parameters = OrderedDict() self._modules = OrderedDict() ...

  5. 第一步 使用sencha touch cmd 4.0 创建项目、打包(加入全局变量、公用类、自定义扩展、资源文件)

    参考资料: http://www.cnblogs.com/qqloving/archive/2013/04/25/3043606.html http://www.admin10000.com/docu ...

  6. MVC Controller 基类中的Request

    今天在测试自己MVC程序的时候发现之前写代码的一个BUG,需求是每个页面要获取当前URL链接中包含的城市ID,我把获取url的方法写到了Controller的基类BaseController(Base ...

  7. MVC Controller 基类 BaseController 中的 Request

    今天修复mvc中的一个bug,需求是每个页面要获取当前URL链接中 host首是否正确,我把获取url的方法写到了Controller的基类BaseController(BaseController继 ...

  8. 深入浅出的webpack构建工具--webpack4+vue+router项目架构(十四)

    阅读目录 一:vue-router是什么? 二:vue-router的实现原理 三:vue-router使用及代码配置 四:理解vue设置路由导航的两种方法. 五:理解动态路由和命名视图 六:理解嵌套 ...

  9. SSH项目搭建(四)——Maven的pom.xml配置

    史上最全的maven的pom.xml文件详解: https://www.cnblogs.com/qq765065332/p/9238135.html 下面的节点有不理解是啥意思的可以到上面链接的文章里 ...

随机推荐

  1. lazy-init 懒加载的艺术

    懒加载是一种加载方式,加载单例对象一般有两种方式,一是在启动时就立即创建好,另一种则是在需要用到的时候再去加载即懒加载.懒加载一般会针对单例场景,且一般是针对在加载消耗较大费时,且不一定会用到的场景. ...

  2. vmware中nat模式中使用静态ip后无法上网的问题

    在/etc/network/interfaces中添加静态ip auto eth0iface eth0 inet staticaddress 192.168.31.133netmask 255.255 ...

  3. Java核心技术及面试指南面试题,基本数据类型、封装类和运算操作的面试题

    2.1.5.1说说&和&&的区别,以及|与||的区别. &和|是位运算符,不怎么用,而&&和||是逻辑运算符,一般用在if,while,for等条件判断 ...

  4. vue 解决无法设置滚动位置的问题

    问题描述 在实现锚点定位的时候发现无法设置滚动条的位置. 在Vue中,使用 document.body.scrollTop=952 无法设置滚动条的高度. document.body.scrollTo ...

  5. Android--Service之AIDL传递系统基本类型数据

    前言 前面讲解了Service的一些基本内容.但是对于绑定服务传递数据,只局限于本地服务,无法使用服务进行跨进程间的交互.如果需要用到跨进程交互的话,需要用到一个新的技术-AIDL,这篇博客就针对AI ...

  6. [android学习]__使用百度地图开放api编写地图定位app

    前言 在前面我已经记录关于如何使用百度地图api,以及如何配置相关的androidstudio配置了,接下来将记录如何使用百度地图api开发简单的地图定位apk,我将决定不定期持续更新本篇笔记,在每个 ...

  7. 图片预览(适用于IE6,9,10,Firefox)

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  8. linux 命令 — 文件相关

    使用文件相关命令 dd 用来生成任意大小的文件 dd if=/dev/zero of=junk.data bs=1m count=1 生成一个1m大小的文件,里面全部使用0填充 if: 指定输入文件, ...

  9. 获取完全一样的数据库,包括表与表之间的外键关系,check,default表结构脚本

    今天公司给了一个任务,某一个项目由于数据过大,造成Sql Server 2012 的运行占用很大内存,于是要把之前的不常用的数据分开.要求写个脚本,要求: 1.能获取原来数据库中的表结构,主键一致.表 ...

  10. AspectJ在Spring中的使用

    在上一篇AspectJ的入门中,简单的介绍了下AspectJ的使用,主要是以AspectJ的example作为例子.介绍完后也留下了几个问题:1)我们在spring中并没有看到需要aspectj之类的 ...