OK,这一节我们开发 API 接口,把需要的数据返回给客户端。
我们先来解决:
1、indexMovie.html 里的热门电影接口数据
2、index.html 文件里的相关接口,如截图:
实际的流程是这样:
用户请求首页(即地址栏请求“/”)的时候,会进入到 IndexMovieController 这个类的 “/” 请求中,然后我们查询对应的数据,返回到 index.html (即 view 视图),thymeleaf 模板就可以获取到数据了。
修改 IndexMovieController 请求类,完整代码:
package com.movie.controller.consumer;
import com.movie.entity.MovieDynamicEntity;
import com.movie.entity.MovieInfoEntity;
import com.movie.manage.MovieDynamicManage;
import com.movie.manage.MovieInfoManage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* @author biandan
* @signature 让天下没有难写的代码
* @create 2019-12-01 下午 5:01
*/
@Controller
public class IndexMovieController {
//注入电影信息的接口对象
@Autowired
private MovieInfoManage movieInfoManage;
//注入电影动态信息的接口对象
@Autowired
private MovieDynamicManage movieDynamicManage;
//请求首页
@RequestMapping("/")
public ModelAndView index(HttpServletRequest request) {
//查询热门电影
List<MovieInfoEntity> hotMovieList = movieInfoManage.getHotMovieList();
//查询最新电影(右边信息栏)
List<MovieInfoEntity> latestMovieList = movieInfoManage.latestMovieList();
//查询最新电影动态信息(右边信息栏)
List<MovieDynamicEntity> movieDynamicList = movieDynamicManage.movieDynamicList();
ModelAndView view = new ModelAndView();
view.addObject("title", "首页");
view.addObject("mainPage", "consumer/indexMovie");
view.addObject("mainPageKey", "#keyId");
view.addObject("hotMovieList",hotMovieList);
view.addObject("latestMovieList",latestMovieList);
view.addObject("movieDynamicList",movieDynamicList);
view.setViewName("index");//返回 index.html 页面
return view;
}
}
注意:我们的 view 对象在方法 addObject 里的 key,要对应前端的 key,一字不漏。否则无法对应到数据。
接下来,我们需要修改 MovieInfoManage、MovieDynamicManage 两个接口,增加对应的方法:
MovieInfoManage 接口增加代码:
//查询热门电影
List<MovieInfoEntity> getHotMovieList();
//查询最新电影
List<MovieInfoEntity> latestMovieList();
MovieDynamicManage 接口增加代码:
//查询最新电影动态信息
List<MovieDynamicEntity> movieDynamicList();
对应的,它们的实现类也要实现上述的方法。
MovieInfoManageImpl 实现类增加代码,注意我们默认查询的记录数,定义在实现类上,可以根据实际需要修改数字大小:
private static int HOT_SIZE = 20;//热门电影查询前 20 条记录
private static int MSG_SIZE = 10;//列表信息查询 10 条记录
//查询热门电影
@Override
public List<MovieInfoEntity> getHotMovieList(){
List<MovieInfoEntity> list = new ArrayList<>();
try{
list = movieInfoService.getHotMovieList(HOT_SIZE);
}catch (Exception e){
e.printStackTrace();
}
return list;
}
//查询最新电影
@Override
public List<MovieInfoEntity> latestMovieList(){
List<MovieInfoEntity> list = new ArrayList<>();
try{
list = movieInfoService.latestMovieList(MSG_SIZE);
}catch (Exception e){
e.printStackTrace();
}
return list;
}
MovieDynamicManageImpl 实现类增加代码:
private static int MSG_SIZE = 10;//列表信息查询 10 条记录
//查询最新电影动态信息
@Override
public List<MovieDynamicEntity> movieDynamicList(){
List<MovieDynamicEntity> list = new ArrayList<>();
try{
list = movieDynamicService.movieDynamicList(MSG_SIZE);
}catch (Exception e){
e.printStackTrace();
}
return list;
}
对应的,它们的 Service 类也要增加对应的方法:
MovieInfoService 增加代码:
//查询热门电影
@Transactional(readOnly = true)
public List<MovieInfoEntity> getHotMovieList(int size){
return movieInfoDao.getHotMovieList(size);
}
//查询最新电影
@Transactional(readOnly = true)
public List<MovieInfoEntity> latestMovieList(int size){
return movieInfoDao.latestMovieList(size);
}
MovieDynamicService 增加代码:
//查询最新电影动态信息
@Transactional(readOnly = true)
public List<MovieDynamicEntity> movieDynamicList(Integer size){
return movieDynamicDao.movieDynamicList(size);
}
对应的,它们的 DAO 层也要增加代码:
MovieInfoDao 增加代码:
//查询热门电影
List<MovieInfoEntity> getHotMovieList(@Param("size") int size);
//查询最新电影
List<MovieInfoEntity> latestMovieList(@Param("size") int size);
MovieDynamicDao 增加代码:
//查询最新电影动态信息
List<MovieDynamicEntity> movieDynamicList(Integer size);
最后,它们的 mapper 文件也要增加对应的查询方法。
MovieInfoEntityMapper.xml 增加代码:
<!-- 查询热门电影 -->
<select id="getHotMovieList" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select *
from movie_info
where hot = 1
order by id desc
limit 0,#{size,jdbcType=INTEGER}
</select>
<!-- 查询最新电影 -->
<select id="latestMovieList" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select *
from movie_info
order by id desc
limit 0,#{size,jdbcType=INTEGER}
</select>
MovieDynamicEntityMapper.xml 增加代码:
<!-- 查询电影动态 -->
<select id="movieDynamicList" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select d.*,i.movie_name
from movie_dynamic as d
LEFT JOIN movie_info as i
ON d.movie_id = i.id
order by d.id desc
limit 0,#{size,jdbcType=INTEGER}
</select>
OK,我们代码编写完成,启动服务测试效果:http://localhost:8080/
OK,我们已经搞定了首页的信息。
接下来,我们继续开发 API 接口:点击电影查看详情的接口,即 indexMovie.html 文件的 a 链接,以及 index.html 里的电影动态信息链接。
OK,我们新建一个类:ConsumerMovieController,用来处理点击电影详情的请求,放在 consumer 包下:
package com.movie.controller.consumer;
import com.movie.entity.MovieDynamicEntity;
import com.movie.entity.MovieInfoEntity;
import com.movie.manage.MovieDynamicManage;
import com.movie.manage.MovieInfoManage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
/**
* @author biandan
* @signature 让天下没有难写的代码
* @create 2019-12-01 下午 4:59
*/
@RestController
@RequestMapping(value = "/consumerMovie")
public class ConsumerMovieController {
@Autowired
private MovieInfoManage movieInfoManage;
@Autowired
private MovieDynamicManage movieDynamicManage;
//根据id查询电影详细信息
@RequestMapping("/{id}")
public ModelAndView view(@PathVariable("id") Integer id){
//根据电影 id 查询电影信息
MovieInfoEntity movie = movieInfoManage.selectById(id);
///构造分页信息,根据当前电影 id 获取上一个电影、下一个电影的信息
String pageCode = movieInfoManage.getPageCode(id);
//查询最新电影(右边信息栏)
List<MovieInfoEntity> latestMovieList = movieInfoManage.latestMovieList();
//查询最新电影动态信息(右边信息栏)
List<MovieDynamicEntity> movieDynamicList = movieDynamicManage.movieDynamicList();
//查询该对应对应的动态信息(电影信息下面)
List<MovieDynamicEntity> dynamicList = movieDynamicManage.dynamicList(id);
ModelAndView view = new ModelAndView();
view.addObject("pageCode", pageCode);
view.addObject("title", movie.getMovieName());
view.addObject("mainPage", "consumer/view");
view.addObject("mainPageKey", "#mId");
view.addObject("movie", movie);
view.addObject("latestMovieList",latestMovieList);
view.addObject("movieDynamicList",movieDynamicList);
view.addObject("dynamicList",dynamicList);
view.setViewName("index");
return view;
}
}
说明:
1、mainPage 和 mainPageKey 这里指定的值,对应 view.html 和 id=mId 需要我们创建。
2、pageCode 是我们的分页信息,可以查看 BootStrap 文档:https://www.runoob.com/bootstrap/bootstrap-pagination.html
这里我们使用最简单的分页
<ul class="pager">
<li><a href="#">Previous</a></li>
<li><a href="#">Next</a></li>
</ul>
3、我们还要新增一个接口,用于查询该电影对应的动态信息。
//查询该对应对应的动态信息(电影信息下面)
List<MovieDynamicEntity> dynamicList = movieDynamicManage.dynamicList(id);
OK,接下来,我们先在前端的 consumer 目录下创建 view.html
<meta charset="UTF-8"/>
<div id="mId">
<div class="data_list">
<div class="data_list_movieName">
<img src="/static/images/movie_icon.png"></img>
电影详细信息</div>
<div>
<div class="movie_movieName"><h3><strong th:text="${movie.movieName}"></strong></h3></div>
</div>
<div class="movie_createTime">
发布时间:<font th:text="${#dates.format(movie.createTime,'yyyy-MM-dd')}"></font>
</div>
<div class="movie_content" th:utext="${movie.movieContent}"></div>
<div class="movie_lastAndNextPage">
<ul class="pager" th:utext="${pageCode}"></ul>
</div>
</div>
<div class="data_list">
<div class="data_list_movieName">
<img src="/static/images/list_icon.png"/>
电影动态信息列表</div>
<div>
<table class="table">
<thead>
<tr>
<th>序号</th>
<th>动态信息</th>
<th>发布日期</th>
</tr>
</thead>
<tbody>
<tr th:each="dynamicInfo,sequence:${dynamicList}">
<th scope="row" th:text="${sequence.index+1}"></th>
<td>
<a th:href="${dynamicInfo.movieUrl}" th:text="${dynamicInfo.dynamic}"
th:title="${dynamicInfo.dynamic}" target="_blank"></a>
</td>
<td th:text="${#dates.format(dynamicInfo.createTime,'yyyy-MM-dd')}" ></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
说明:
这个属性要对应后台返回的属性值,否则无法找到数据。以及下面的分页信息。
我们来处理一下分页的:
MovieInfoManage 增加方法;
//根据当前电影 id 获取上一个电影、下一个电影的信息
String getPageCode(Integer id);
MovieInfoManageImpl 实现类增加方法:
//根据当前电影 id 获取上一个电影、下一个电影的信息
@Override
public String getPageCode(Integer id){
String pageCode = null;
try{
//查询上一个电影信息
MovieInfoEntity lastInfoEnity = movieInfoService.getLastEntity(id);
//查询下一个电影信息
MovieInfoEntity nextInfoEnity = movieInfoService.getNextEntity(id);
//构建分页
pageCode = PageCodeUtil.getPageCode(lastInfoEnity,nextInfoEnity);
}catch (Exception e){
e.printStackTrace();
}
return pageCode;
}
这里我们需要一个我们自己的工具类 PageCodeUtil,创建在 util 包下,代码如下,具体逻辑自行理解:
package com.movie.util;
import com.movie.entity.MovieInfoEntity;
/**
* 构造分页对象
* @author biandan
* @signature 让天下没有难写的代码
* @create 2019-12-03 下午 11:01
*/
public class PageCodeUtil {
/**
* 构造分页对象方法
* @param lastEntity 上一个电影信息实体
* @param nextEntity 下一个电影信息实体
* @return
*/
public static String getPageCode(MovieInfoEntity lastEntity, MovieInfoEntity nextEntity) {
StringBuilder builder = new StringBuilder();
if (lastEntity == null || lastEntity.getId() == null) {
builder.append("<p>上一部:没有了</p>");
} else {
builder.append("<p>上一部:<a href='/consumerMovie/" + lastEntity.getId() + "'>" + lastEntity.getMovieName() + "</a></p>");
}
if (nextEntity == null || nextEntity.getId() == null) {
builder.append("<p>下一部:没有了</p>");
} else {
builder.append("<p>下一部:<a href='/consumerMovie/" + nextEntity.getId() + "'>" + nextEntity.getMovieName() + "</a></p>");
}
return builder.toString();
}
}
MovieInfoService 类增加2个方法:
//根据 id 查询上一个电影信息
@Transactional(readOnly = true)
public MovieInfoEntity getLastEntity(Integer id){
return movieInfoDao.getLastEntity(id);
}
//根据 id 查询下一个电影信息
@Transactional(readOnly = true)
public MovieInfoEntity getNextEntity(Integer id){
return movieInfoDao.getNextEntity(id);
}
MovieInfoDao 增加2个方法:
//根据 id 查询上一个电影信息
MovieInfoEntity getLastEntity(Integer id);
//根据 id 查询下一个电影信息
MovieInfoEntity getNextEntity(Integer id);
MovieInfoEntityMapper.xml 增加两个查询方法:
<!-- 根据 id 查询上一个电影信息,注意左尖括号的使用 -->
<select id="getLastEntity" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select id, movie_name, movie_title, hot, image_name, movie_content,create_time
from movie_info
<where>
<![CDATA[ id < #{id,jdbcType=INTEGER} ]]>
</where>
order by id desc
limit 0,1
</select>
<!-- 根据 id 查询下一个电影信息 -->
<select id="getNextEntity" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select id, movie_name, movie_title, hot, image_name, movie_content,create_time
from movie_info
where id > #{id,jdbcType=INTEGER}
order by id asc
limit 0,1
</select>
说明:
1、mapper 文件里不允许使用 < 尖括号,会被误以为是html 的符号,需要使用 <![CDATA[ ]]> 包装起来
2、查询上一个、下一个电影的 id 逻辑,一个是把 id 倒序排,然后取最大的;另一个是 id 顺序排,取最小的值。
接下来讲解查询某个电影动态信息的 API 接口:
MovieDynamicManage 增加方法:
//查询该对应对应的动态信息(电影信息下面)
List<MovieDynamicEntity> dynamicList(Integer id);
MovieDynamicManageImpl 实现类:
//查询该对应对应的动态信息(电影信息下面)
@Override
public List<MovieDynamicEntity> dynamicList(Integer id){
List<MovieDynamicEntity> list = new ArrayList<>();
try{
list = movieDynamicService.dynamicList(id);
}catch (Exception e){
e.printStackTrace();
}
return list;
}
MovieDynamicService 增加方法:
//查询该对应对应的动态信息(电影信息下面)
@Transactional(readOnly = true)
public List<MovieDynamicEntity> dynamicList(Integer id){
return movieDynamicDao.dynamicList(id);
}
MovieDynamicDao 增加方法:
//查询该对应对应的动态信息(电影信息下面)
List<MovieDynamicEntity> dynamicList(Integer id);
MovieDynamicEntityMapper.xml 增加方法:
<!-- 查询该对应对应的动态信息(电影信息下面) -->
<select id="dynamicList" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select d.*,i.movie_name
from movie_dynamic as d
LEFT JOIN movie_info as i
ON d.movie_id = i.id
where d.movie_id = #{id,jdbcType=INTEGER}
</select>
OK,我们启动服务,测试:http://localhost:8080/
效果出来了:
为了直观的看到效果,我们可以去数据库 movie_dynamic 修改一些动态信息,对应具体的电影的,如下图;
效果如下图:
OK,我们的测试成功。如果电脑链接网络,还可以看视频,快和你的朋友分享喜悦吧!perfect!