OK,这一节我们学习目前流行的前端框架 BootStrap:https://www.bootcss.com/
学习如何使用 BootStrap 构建高大上的网站:https://v3.bootcss.com/css/
我们下载“用于生产环境的 BootStrap”。下载好之后,解压。把文件夹粘贴到项目的 static 目录下。
因为我们需要 thymeleaf 模板引擎,所以需要把客户端的 html 文件放在模板的目录下。在 templates 目录下创建 consumer 目录,用来存放客户端的 html 文件。
同时,在 templates 目录下创建 index.html 文件,这是用户端的首页。index.html 代码如下:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title th:text="${title}+'-好来屋在线影院'"></title>
<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"/>
<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap-theme.min.css"/>
<link rel="stylesheet" href="/static/css/movie.css"/>
</head>
<body>
<div class="container">
<!-- 栅格占满12个 -->
<div class="row">
<!-- 引入 common目录下的 head 文件 id=headId 的内容 -->
<div th:include="consumer/common/head::#headId"></div>
</div>
<!-- 栅格占满12个 -->
<div class="row">
<!-- 引入 common目录下的 menu 文件 id=menuId 的内容 -->
<div th:include="consumer/common/menu::#menuId"></div>
</div>
<div class="row">
<!-- 栅格占 8 个 -->
<div class="col-md-8">
<!-- 引入后台返回 key=mainPage 的 mainPageKey 的内容 -->
<div th:include="${mainPage}::${mainPageKey}"></div>
</div>
<!-- 栅格占 4 个 -->
<div class="col-md-4">
<div class="data_list">
<div class="data_list_movieName">
<img src="/static/images/movie_icon.png"/>
最新电影
</div>
<div class="datas">
<ul>
<li th:each="latestMovie:${latestMovieList}">
<span><a th:href="'/consumerMovie/'+${latestMovie.id}" target="_blank"
th:title="${latestMovie.movieName}" th:text="${latestMovie.movieName}">
</a></span></li>
</ul>
</div>
</div>
<!-- 最新电影动态 -->
<div class="data_list">
<div class="data_list_movieName">
<img src="/static/images/dynamic_icon.png"/>
最新电影动态信息
</div>
<div class="datas">
<ul>
<li th:each="dynamicInfo:${movieDynamicList}"><span>
<!-- 在新窗口打开电影具体信息 -->
<a th:href="'/consumerMovie/'+${dynamicInfo.movieId}" target="_blank"
th:title="${dynamicInfo.dynamic}"
th:text="${dynamicInfo.dynamic}">
</a></span></li>
</ul>
</div>
</div>
</div>
</div>
<!-- 底部信息 -->
<div class="row">
<div th:include="consumer/common/foot::#footId"></div>
</div>
<a class="bshareDiv" href="http://www.bshare.cn/share">分享按钮</a><script type="text/javascript" charset="utf-8" src="http://static.bshare.cn/b/buttonLite.js#uuid=&style=3&fs=4&textcolor=#fff&bgcolor=#06C&text=分享到"></script>
</div>
</body>
</html>
说明:
1、.container 类用于固定宽度并支持响应式布局的容器
2、Bootstrap 提供了一套响应式、移动设备优先的流式栅格系统,随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列。
3、EL 表达式从后台返回的数据取值,所以后台定义的返回参数需要与表达式的属性匹配。
数据从请求中获取
4、<img src="/static/images/dynamic_icon.png"/> 小图标可以根据自己的喜欢去下载16×16的。https://www.easyicon.net/
5、接下来我们完善引入的公共页面,如图:
6、注意到有一个地方我们采用如下形式:
这是获取后台动态返回的数据,可能是热门电影列表,可能是某个电影详情,可能是电影查询列表。。。
OK,我们先在 consumer 目录下创建 common 目录:
然后,在 common 目录下创建 foot.html、 head.html 、 menu.html 三个文件。注意 id 要与 index.html 里定义的一致。
head.html 代码:
<meta charset="UTF-8"/>
<div id="headId">
<div class="col-md-4">
<a href="/"><img alt="好来屋在线影院" src="/static/images/logo.png"/></a>
</div>
<div class="col-md-8">
</div>
</div>
menu.html 代码:
<meta charset="UTF-8"/>
<div id="menuId">
<div class="col-md-12" style="padding-top: 10px">
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/"><font color="black">首页</font></a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1" >
<ul class="nav navbar-nav">
<li><a href="/consumerMovie/list/1">收录电影</a></li>
<li><a href="/consumerMovie/dynamic/list/1">电影动态信息</a></li>
</ul>
<!-- 查询电影 -->
<form action="/consumerMovie/search" class="navbar-form navbar-right" role="search" method="post">
<div class="form-group" >
<input type="text" id="q" name="movieName" th:value="${movie == null?'':movie.movieName}"
class="form-control" placeholder="请输入您要搜索的电影名"/>
</div>
<button type="submit" class="btn btn-default">搜索</button>
</form>
</div>
</div>
</nav>
</div>
</div>
说明:
1、这是顶部的菜单样式,在搜索框里判断是否有电影信息,有则把电影名称赋值到文本输入框中(三目表达式的使用)。
2、此外还有“收录电影”、“电影动态信息”、“首页”等接口等待开发
foot.html 代码:
<meta charset="UTF-8"/>
<div id="footId">
<div class="col-md-12" >
<div align="center" style="padding-top: 120px" >
Copyright © biandan 版权所有。仅供学习使用,禁止商用。
</div>
</div>
</div>
然后,我们再根据 index.html 里的代码,创建一个 movie.css 文件,这是调整页面布局的文件,位置在 static 目录下:
首先,创建 css 目录:
movie.css 代码如下:
body{
padding-top: 10px;
padding-bottom: 40px;
}
.data_list{
border: 1px solid #E5E5E5;
padding: 10px;
background-color: #FDFDFD;
margin-top: 0px;
margin-bottom: 10px;
}
.data_list .data_list_movieName{
font-size: 15px;
font-weight: bold;
border-bottom: 1px solid #E5E5E5;
padding-bottom: 10px;
padding-top: 5px;
}
/* 标题的小图标 */
.data_list .data_list_movieName img{
margin-top: 1px;
vertical-align: top;
}
/* 数据集合 */
.data_list .datas{
padding: 5px;
}
/* 热门电影 ,实际项目中最好能自动设置高度*/
.data_list .imageDatas{
height: 1300px;
}
/* 电影列表内容,实际项目开发中最好能自动设置高度 */
.data_list .lImageDatas{
height: 1300px;
}
.data_list .datas ul {
list-style-type: none;
padding-left: 15px;
}
.data_list .datas ul li {
margin-top: 10px;
}
.data_list .datas .imageUl{
margin-left: 20px;
}
.data_list .datas .imageUl li {
float: left;
margin-right: 25px;
}
.data_list .datas .imageUl .imageLi {
height: 250px;
}
.data_list .datas .imageUl .imageLi p{
overflow: hidden;
text-align: center;
padding-top: 4px;
}
.data_list .data_list_movieName .datas{
padding: 5px;
}
/* 电影主图的宽、高参数 */
.data_list .datas .indexMovie{
width: 140px;
height: 198px;
}
.data_list .movie_movieName{
margin-top:20px;
text-align: center;
}
.data_list .movie_createTime{
text-align: center;
}
.data_list .movie_content{
margin-top:20px;
padding-bottom: 30px;
}
.data_list .movie_lastAndNextPage{
border-top:1px dotted black;
padding: 10px;
}
OK,接下来,我们先创建一个 API 接口,用来处理进入首页 “/” 的请求。
我们在 controller 层创建 consumer 包,用来归类存放客户端的请求。
在 consumer 包下创建类:IndexMovieController,用来处理客户端请求首页。代码如下(还没有业务逻辑,仅先看效果):
package com.movie.controller.consumer;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* @author biandan
* @signature 让天下没有难写的代码
* @create 2019-12-01 下午 5:01
*/
@Controller
public class IndexMovieController {
//请求首页
@RequestMapping("/")
public String index(HttpServletRequest request) {
ModelAndView view = new ModelAndView();
view.addObject("title", "首页");
view.addObject("mainPage", "consumer/indexMovie");
view.addObject("mainPageKey", "#keyId");
view.setViewName("index");//返回 index.html 页面
return view;
}
}
说明:
1、这里使用的是 SpringMVC ,所以需要注解 @Controller 而不是 @RestController
2、mainPage:这里指向 consumer 目录下的 indexMovie.html ,我们还需要创建这个文件。
3、mainPageKey = keyId,所以 indexMovie.html 需要有一个 id = keyI 的代码。
接下来,我们在前端 consumer 目录下创建 indexMovie.html 文件,代码如下:
<meta charset="UTF-8"/>
<div id="keyId">
<div class="data_list">
<div class="data_list_movieName">
<img src="/static/images/hot_icon.png" />
热门电影推荐</div>
<div class="datas imageDatas">
<ul class="imageUl" >
<li class="imageLi" th:each="hotMovie:${hotMovieList}">
<a th:href="'/consumerMovie/'+${hotMovie.id}" target="_blank" th:title="${hotMovie.movieName}">
<img class="indexMovie" th:src="'/movieImages/'+${hotMovie.imageName}" />
<p th:text="${hotMovie.movieName}"></p>
</a>
</li>
</ul>
</div>
</div>
</div>
说明:
1、通过 EL 表达式获取后台返回的数据时,需要对应属性字段。
2、图片的路径需要增加 /movieImages/ ,这是我们在 WebConfig 类里配置的虚拟访问路径(参照之前博客)。
OK,我们启动服务,看下效果,浏览器直接输入地址:http://localhost:8080/
OK,接下来,我们就是提供 API 接口,把数据查询出来。