显示图书类别
说明:
(1) 本篇博客的任务:在首页显示图书类别;
(2) 本篇博客说明:
● 本篇博客是:基于【SSM+Mybatis-Plus】开发的第一个案例,所以在阐述的时候略显啰嗦;后面我们在开发其他功能时,会反复使用到本篇博客的SOP ;
● 本篇博客有任何迷糊或者忘记的地方,都可以快速参考以前的博客,都有很详细的阐述;
为了防止干扰,把前面几篇博客创建的测试与演示用的内容删除了;
一:编码前,先了解一下情况;
1.明确任务:在首页显示图书类别;
2.看一下前端的初始情况;
3.看一下底层的数据表;
二:正式编码开发;
1.开发【实体类】,与底层数据表对应;
在和数据表交互的时候,我们一般需要先创建与之对应的实体类;
Category实体类:
说明:
(1) 实体类属性最好按照驼峰命名规则比照着数据表的字段名来写;然后,因为我们要通过Mybatis-Plus来查,所以在类上使用Mybatis-Plus的注解;
(2) 为了打印Category类对象时,更好的看到对象的内容,所以我们重写了toString()方法;
2.开发【Mapper接口】;
创建操作category图书分类表的Mapper接口;
Mapper接口:
说明:
(1) 我们要使用Mybatis- Plus,所以其继承了BaseMapper;同时,这个Mapper接口,使用来服务于category表的,即其增删改查的对象是Category对象,所以设置BaseMapper接口的泛型为Category;
3.开发mapper接口对应的【xml】;
定义了接口,就要有与之对应的xml;
category.xml:
说明:
(1) mapper.xml的xml声明内容,没必要记忆,需要的时候过来复制就行了;
(2) category.xml内容说明;
4.开发【Service】,调用Dao层功能,并根据业务需要编写逻辑代码;
自从接触Spring后,一直在强调接口的重要性,也在一致强调面向接口编程;通过接口,可以隐藏底层类的创建细节,提高程序的可扩展和易维护性;即,在实际开发时,service部分,一般会先定义接口,然后再创建具体的实现类;
CategoryService接口:
说明:
(1) 在CategoryService接口中,定义selectAll()方法;这个方法的目的就是查询category表的所有内容;
有了CategoryService接口后,就要编写该接口的实现;
CategoryServiceImpl实现类:
说明:
(1) 类内容说明;(如果有不明白,或者模糊的地方,去前面相关的博客去查就是了)
(2) 关于事务的内容可以参考【Spring】专栏中的内容;然后目前有两点感觉:
● 在使用声明式事务时,【注解方式】似乎比【配置方式】更好点;因为【注解方式】更加灵活,更加能基于当下情况灵活设置;
● 具体一个类的事务传播方式设置成什么,需要看这个类的内容;如果一个类大部分是查询方法,那么这个类的事务传播方式完全可以设为“NOT_SUPPORTED”,然后如果类中有增删改的方法需要开启事务,那么在该类上再额外设置就好了;
(插).及时的单元测试;
以前就说过,及时的单元测试很有必要。我们写好了Dao层和Service层,可以测试一下;
CategoryServiceImplTest:
说明:
(1) 测试类说明;
(2) 运行结果;;
5.开发【Controller】,调用service,然后将数据放入到当前请求中与模板引擎组合;
Controller控制器是承上启下的组件;
BookController类:
说明:
(1) 这个Controller类的主要作用就是调用Service获得数据,并渲染到index.ftl这个前端文件上,并将页面推到响应中,以便浏览器显示;
(2) 类内容说明;
(3) 如果还有不明白的地方,可以快速参考【SpringMVC】中的相关内容;
6.前端文件:模板引擎读取数据,完成界面渲染,产生HTML;
index.ftl:
说明:
(1) index.ftl我们修改的内容;
(2) index.ftl获取数据;
一个老生常谈的地方:新引入依赖后,如有需要,记得添加到发布中去;
7.启动Tomcat,测试运行,观察效果;
然后访问【localhost/】;
效果:是OK的;
图书分页查询
说明:
(1) 本篇博客任务:图书分页查询:首页加载时,先默认显示第一页数据:Dao和Service部分;
(2) 本篇博客内容:图书分页查询的Dao和Service部分;其主要知识点就是Mybatis-Plus的分页查询;包括:
● Mybatis-Plus的分页查询方法:BaseMapper接口中的selectPage()方法的简介;
● IPage分页对象简述;
● IPage的三个常用方法的引入:【List<Book records = pageObject.getRecords();//获取当前页的数据】,【pageObject.getPages();//获取总页数】,【pageObject.getTotal();//获取总记录数】
● 然后,还提到了创建【接口实现类】的快捷方式:【Alt+Enter】;
我们在【2 【Mybatis-Plus】和【SSM】整合;(重要!!!)】中配置了Mybatis-Plus的分页插件,这可以帮助我们进行分页处理;
PS:在介绍Mybatis的时候,【分页插件PageHelper】也介绍了Mybatis的一款分页插件PageHelper;
因为我们分页查询,查的就是图书,所以底层就是book表;
一:正式编码开发;
1.开发实体类:Book类,与底层book表对应;
Book实体类:
说明:
(1) 里面的知识点,在【显示图书类别】已经详细阐述过了,这儿就不重复啰嗦了;
(2) 写类属性的时候,一定要比照着数据表的字段名,按照驼峰命名的规则去写;别写错了;
2.开发Mapper接口:BookMapper;
BookMapper接口:
说明:
(1) BookMapper接口继承Mybatis-Plus的BaseMapper接口;
(2) 后面测试的时候,发现这儿报了错;原因是没有指定<Book>这个泛型;可以参考[【org.apache.ibatis.binding.BindingException:Invalid bound statement (not found)】异常;](https://blog.csdn.net/csucsgoat/article/details/122033404”【org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)】异常;”)】;
3.开发mapper接口对应的xml:book.xml;
book.xml:
说明:
(1) book.xml的命名空间,要对应上BookMapper接口;
至此,底层的操作数据库的Dao的代码就写好了;然后,就是基于Mybatis-Plus解决分页的问题了;图书分页查询的逻辑代码,我们要在Service中完成;
4.开发service,调用Dao层代码;利用Mybatis-Plus分页插件,编写分页查询逻辑;
(1)BookService接口:定义一个用于分页查询的方法;
说明:
(0) Mybatis-Plus的BaseMapper接口中的selectPage()方法就是分页查询方法,该方法返回的就是IPage分页对象;
(1) IPage是Mybatis-Plus提供的分页对象;IPage分页对象中包含了【当前查询出来的、当前页的、数据】,也包含了一系列与分页相关的信息;比如【总页数】等;
(2) IPage在使用的时候,使用了泛型;这儿的是<Book>,意思是查询出来每一条数据都是一个Book对象;
(3) BookService接口中定义的这个分页查询的方法,其返回值是Mybatis-Plus提供的IPage分页对象
(2)BookServiceImpl实现类;(演示了创建实现类的快捷键方式:Alt+Enter)
这样以后,接口的实现类就得到了:
BookServiceImpl:
说明:
(1) 类内容说明;
(2) Page类可以认为是IPage接口的实现类;
(插).及时的单元测试;
(1)测试类与测试结果;
【Alt+Insert】快捷键生成测试用例;上次是在【显示图书类别】,这儿就不啰嗦了;
BookServiceImplTest测试类:
说明:
(1) IPage的三个常用方法,这儿演示了一下;
(2) 测试运行结果:
(2)Mybatis-Plus分页时,底层SQL的执行过程分析;
可以看到,其首先根据在继承BaseMapper接口配置泛型时配置的Book实体类,拼接字段;然后,在最后有个LIMIT,第一个?代表本次查询的起始位置,后面的?代表本次查询的数据数;
至此,图书分页查询的Dao和Service部分已经写好了;接下来就是如何将这些图书分页数据,动态的加载到页面中;即,就是Controller和前端部分的内容了;
Ajax动态加载图书信息
说明:
(1) 本篇博客任务:图书分页查询:首页加载时,先默认显示第一页数据:Controller部分;前端开发了一部分;
(2)本篇博客前端内容说明:
● 因为,我们希望,在第一次加载index.ftl这个首页时,首页上就默认加载第一页的图书;所以对于这个业务场景来说,我们把这个ajax请求的<script>写在了<head>中,即写在了页面就绪函数中;
● 本篇博客的一个重点是:前端通过Ajax向后端发起请求,然后服务器返回了一些JSON数据,如果我们想把这些JSON数据显示在页面上:就需要,把这些JSON数据转换为HTML,然后动态的加载到对应的数据容器中;(这是在日常开发中,比较普遍采取的做法)
(3) 有关Ajax的内容,可以参考【附加Ajax总结】这篇汇总博客;
1.分析:【前端页面逻辑】与【后台Controller】开发分析:前端通过【Ajax的方式】来和后端交互比较好;
上面我们已经在Service和Dao部分,实现了图书分页查询;然后Service返回的是IPage分页对象;
接下来的任务就是开发Controller和前端了;
(1) 如果前端不使用Ajax的方式来和后端交互:
● 那么,前端就是采用传统的方式来和后端交互了;这也意味着,【图书信息】是随着【index.ftl这个首页的加载】而同时生成的;此时,每当我们点击【点击加载更多】后,为了显示新加载的图书信息,就需要刷新整个index.ftl首页;
● 由此来看,这种方式不太好;
(2) 如果前端使用Ajax的方式来和后端交互:
● 此时当我们点击【点击加载更多】后,index.ftl这个首页不用刷新,Ajax动态加载是在页面进行局部刷新的;
● 即,前端使用Ajax的方式来和后端交互,更加友好;
● 虽然,为了使用Ajax会比较麻烦一些;(我们需要通过JavaScript,来控制请求的提交,和,返回数据的处理)
(3) 有关Ajax的内容,可以参考【附加Ajax总结】这篇汇总博客;
2.开发Controller:调用Service层的分页查询方法,并向前端返回JSON;
BookController:这儿新增的是selectBook()图书分页查询方法;
说明:
(1) 调用service的方法,首先需要注入service对象;
(2) selectBook()方法说明;
(3) 当我们Controller中的方法是直接产生响应文本时(可以通过在方法上使用@ResponseBody注解,或者,在Controller类上使用@RestController注解),因为Spring
MVC中配置了jackson,所以其可以自动把【方法返回的实体对象】序列化为【JSON字符串】;即,上面方法返回的IPage对象,其会自动把IPage对象序列化为JSON字符串;
可以参考
●【ModelAndView对象】
●【RestController注解与路径变量】
●【JSON序列化】;
(4) 此时,重启Tomcat,然后请求selectBook()这个方法;
3.index.ftl前端文件,利用Ajax动态获取后端的JSON数据,组织数据;(只开发了一半)
(1)index.ftl首页文件分析;
(2)利用Ajax与后端交互;
在index.ftl中,使用<script>块,增加一个页面就就绪函数;
说明:
(0) 我们这儿修改或新增的内容为:在<head>中,通过<script>增加了一个页面就绪函数;
(1) 因为我们使用Ajax,而这儿我们是通过jQuery来帮助开发ajax代码;所以,首先需要确认,在index.ftl中引入了jQuery;
(2) 因为,我们希望,在第一次加载index.ftl这个首页时,首页上就默认加载第一页的图书;所以,我们把这个ajax请求的<script>写在了<head>中,即写在了页面就绪函数中;
(3) ajax请求代码分析;
如果,启动Tomcat,通过Localhost这个url去访问首页时,上面编写的页面就绪函数,会去访问localhost/book;我们可以看一下IPage对象的Json数据;
(4) ajax请求代码分析:前端通过Ajax向后端发起请求,然后服务器返回了一些JSON数据,如果我们想把这些JSON数据显示在页面上:就需要,把这些JSON数据转换为HTML,然后动态的加载到对应的数据容器中;(这是在日常开发中,比较普遍采取的做法)
(5) 启动Tomcat,观察效果;
(6) 现存问题:
● 前端通过Ajax向后端发起请求,然后服务器返回了一些JSON数据,如果我们想把这些JSON数据显示在页面上:就需要,把这些JSON数据转换为HTML,然后动态的加载到对应的数据容器中;(这是在日常开发中,比较普遍采取的做法)
● 但是,上面的做法比较笨;如果HTML比较复杂,我们在如上面那样在script中拼接HTML,就会很麻烦;
● 为此,我们引入了一个新的小技术:JS的模板引擎:Art-Template;
● 在下篇博客中,我们会演示利用JS的模板引擎,完成负责页面的构建;
JS模板引擎Art-Template入门
说明:
(1) 本篇博客任务:图书分页查询:首页加载时,先默认显示第一页数据:前端部分剩余内容开发(利用Art-Template技术);
(2) 本篇博客合理性说明:【图书分页查询】中,前端通过Ajax向后端发起请求,然后服务器返回了一些JSON数据,我们想把这些JSON数据显示在页面上】→【就需要,把这些JSON数据转换为HTML,然后动态的加载到对应的数据容器中;(这是在日常开发中,比较普遍采取的做法)】→【但是,如果我们在script中拼接HTML,就会很麻烦】→【因此,我们引入了一个新的小技术:JS的模板引擎:Art-Template】;
(3) 本篇博客内容:
● Art-Template简介;利用Art-Template模板引擎,完成【将JSON数据转成HTML的工作】;
● 引入了星型评分插件raty,并进行了简单使用;
一:Art-Template简介;
1.Art-Template引入;
说明:
(1) Art-Template:基于腾讯开源的JS模板引擎;其是一款高性能的JavaScript模板引擎;
(2) Art-Template主要目的:高效的基于模板,生成复杂的HTML片段;
(3) 如在【上篇博客】中:
● 如果是简单的HTML,我们直接拼接字符串就行了,此时完全用不到Art-Template这把牛刀;
● 但是,如果HTML比较复杂时,可以使用Art-Template来帮助我们;
2.Art-Template官网简述;
二:Art-Template使用演示;(接着开发上篇博客【SSM开发书评网13】的内容)
1.第一步:引入Art-Template引擎的js文件;
2.第二步:定义模板;
在<head>中,定义模板:
说明:
(1) 首先,在<head>中创建<script>,然后把从<div id=“bookList”中复制的HTML片段,复制进这个<script>块中,然后再做的修改;
(2) 修改前后,内容的变化:
(3) 数据从哪儿来的?:
(4) 模板说明;
3.第三步:使用模板,利用template()方法使其与数据结合,生成新的HTML;
在前端通过ajax接收到后端传过来的JSON数据后,通过template方法,将模板和数据结合,生成新的HTML;然后,我们把HTML追加到对应的容器中,就可以了;
说明:
(1) 上面是使用模板,将数据和模板结合,生成HTML,并将HTML追加到<div id=“bookList这个盛放图书的容器中去;
(2) 那么,此时我们就可以将div id=“bookList中原先的写死的那些HTML给删除了;
(3) 此时的index.ftl:
启动Tomcat,演示,观察结果;
三:上面的程序存在【星星评价不能正常显示】的问题:由此引出:星级评分组件:raty;
1.问题演示;
“星星”的产生方式:星级评分组件raty;我们需要了解raty组件,并在项目中设置,已达到星星随评分改变而改变的目的;
2.星级评分组件:raty简介;
我们这儿选择浏览的是raty的jq22的中文版;自然,raty在GitHub上也有的;
raty是一款基于jQuery的星级评分插件;
然后,raty的使用办法;
3.在项目中,使用raty插件,完成星级评分;
(1)首先,引入raty的css和js;
(2)在页面的head的script块中,设置raty图片的位置;
这儿涉及了script的一些内容,自己有点模糊,因此写了一篇博客,做了一点总结和说明;可以参考下【附加script代码写在head或body中的区别页面就绪函数的作用简述】中的内容;
(3)确定raty星型插件的容器:然后在这个容器中,设置了raty的属性【data-score】;
说明:
(1) 我们把<span中原先静态写死的图片给删了;
(4)把【raty星型插件的容器】初始化为与之对应的星型评价组件;
此时的index.ftl:
(5)效果,启动Tomcat,观察效果;
至此,【加载首页index.ftl时,就默认加载第一页数据】就开发完了;接下来的任务就是点击【点击加载更多】按钮后,会加载后续的分页内容了;
点击加载更多按钮开发
说明:
(1) 本篇博客任务:图书分页查询:每次点击【点击加载更多】,就查询下一页的数据;如果所有数据全部查完,就显示【没有其他数据了】;
(2) 本篇博客内容:
● 本篇博客的内容,其主要知识点依旧是Mybatis-Plus的分页查询;只是前几篇博客是分页查询的第一页,本篇博客是分页查询的第二、三……页;
● 本篇博客还介绍了【通过页面就绪函数,捕捉按钮的单击事件】,【隐藏域这个小tips的使用】,【代码的及时重构思想】等;(虽然,这些内容,在以前都遇到过……)
一:【点击加载更多……】开发;
1.正式开发;
index.ftl:
说明:
(0) 我们这儿就是编写了一个页面就绪函数,来捕捉“btnMore”这个按钮的单击事件;
(1) 代码逻辑说明:主要内容就是:给【点击加载更多……】绑定单击事件;编写单击事件;然后就是积累下这种解决业务的编程套路;
(2) 现存的一些小问题:
为此,我们可以对代码进行重构和梳理;(对代码及时进行重构和梳理,是个不错的习惯)
2.重构梳理代码;
重构后的index.ftl:
说明:
(1) 重构说明;
(2) 启动Tomcat后,实测没问题;
至此默认首页大部分功能已经完成了,但是还有两个地方需要开发:【按类别筛选】和【按热度或按评分进行排序】;这两个部分内容,在下篇博客中介绍;
类别、热度、评分查询
说明:
(1) 本篇博客任务:【按类别筛选】和【按热度或按评分进行排序】;
(2) 本篇博客内容:
● 用到了QueryWrapper查询构造器的orderByDesc(“字段名”)的倒序排序的查询条件设置;
● 在前端中,灵活使用“隐藏域”进行存值等操作,可以帮助开发;
● 我们在条件判断,或者前后端传值的时候:增加非空的判断,能够提高程序的健壮性;
● 本篇博客的,按条件动态查询的套路,还是非常值得参考的;
其实,这儿按类别查询,其本质还是基于前面几篇博客的分页查询,只是增加了图书类别和按热度|按评分这些条件;
一:【图书类别超链接】和【按热度|按评分超链接】高亮效果切换,前端设置;
当我们点击【图书类别超链接】和【按热度|按评分超链接】后,我们应该把本次点击的超连接设置为高亮,同时其他超链接设置为灰色;这是前端显示的问题,所以我们只需要设置一下前端就可以了;
1.高亮效果说明;
对于这些高亮标签的切换,需要通过JavaScript来实现;
2.高亮效果实现;
可以看到其SOP是:先移除全部的高亮效果,然后设置基础颜色,然后再把本次点击的超链接设置为高亮;
启动Tomcat,观察其效果,结果是OK的;
二:【图书类别】和【按热度|按评分】开发;
我们点击了【图书类别超链接】和【按热度|按评分超链接】,也就意味着我们选择了某个查询条件,那么我们就要根据这个查询条件去后端查询数据;
1.Service层开发:设置“图书类别”和“按热度|按评分”的条件查询;
(1)首先,在BookService接口的paging()方法中,增加【图书分类编号】和【排序方式】两个参数;
BookService接口:
说明:
(1) 修改的内容:
(2)然后,去修改BookService接口的实现类,BookServiceImpl类;我们需要添加参数,并根据新增的参数,添加查询条件;
BookServiceImpl类:
说明:
(1) 修改的内容:
(2) “图书类别”的一点说明;
(3) “按热度|按评分”的一点说明;
(4) 其中用到了QueryWrapper查询构造器的orderByDesc(“字段名”)的倒序排序的查询条件设置;
(3)然后,去修改BookServiceImpl类的测试类,看些Service层开发的是否OK;
说明:
(1) 测试结果:
2.Controller层开发:设置“图书类别”和“按热度|按评分”的条件查询;
BookController类:
说明:
(1) 方法增加“图书类别”和“按热度|按评分”参数;而这些参数,是需要前台界面传过来的;
3.前端开发:根据前端界面点击的不同,给后端发送不同的参数;
index.ftl:
说明:
(1.1) 因为我们在调用后端查询方法时,需要传递“图书类别”和“按热度|按评分”参数,所以(还是前面遇到的开发策略)我们埋了两个隐藏域,用来保存这两个参数;
(1.2) 然后,当我们点击了界面上的图书类别或者按热度|按评分后,我们需要及时的调整对应隐藏域的值;
可以看到,默认情况下,两个隐藏域的数值分别是-1和quantity;当我们点击图书分类和按热度|按评分后,隐藏域的数值也会相应的发生变化;
(2) 然后,我们把隐藏域的“图书类别”和“按热度|按评分”数据,随着ajax请求发送给后端;
(3) 然后,当我们点击“图书类别”和“按热度|按评分”超链接的时候,应该去调用loadMore()方法;并且参数设置为了true,表示一切按照新的条件,重头开始查询;(
PS:这儿其实更多是对于这种业务场景的,一种在业务层面上的解决方案;以后,自己开发遇到这种场景时,可以考虑采用这种解决方案 )
(5) 然后,既然我们当点击“图书类别”和“按热度|按评分”超链接的时候,一切按照新的条件,重头开始查询;又因为我们知道div id=“bookList”容器是盛放图书信息的,而且我们采用的是向这个容器中追加的方式;所以,如果我们是一切重头开始查询的话,我们应该先清空这个容器;( PS:这儿其实更多是对于这种业务场景的,一种在业务层面上的解决方案;以后,自己开发遇到这种场景时,可以考虑采用这种解决方案 )
(6) 启动Tomcat,观察效果,发现其是OK的;
(7) 这儿的代码和编程套路,还是比较重要的;
至此,【图书列表分页及查询】部分就开发完了,接下来就是开发【图书详情页】了;
图书详情页开发之读取图书信息
说明:
(1) 本篇博客任务:在首页,点击某个图书后,进入该图书的详情页;然后,本篇博客只完成了上面的图书简介;(下面的短评,在下篇博客介绍)
(2) 本篇博客需要注意的点:
● 开发完Service部分后,养成及时测试的好习惯;
● 我们在使用资源时,最好使用绝对路径,而不要使用相对路径;(自然不排除,个别场景需要使用相对路径)
零:前置说明和分析;
1.把detail.ftl详情页的前端文件,引入;
2.主要任务分析;
通过上面分析可以看出,这儿主要的任务是:【当点击首页的某本书,会后端发起“/book/该图书的id”】→【为此,后端就要编写一个,按照图书的id,去查book图书表,获取图书对象的功能逻辑】;
一:正式开发;
1.开发实体类,与底层数据表对应;
图书详情的信息存储在book表中;
2.开发【Mapper接口】;
3.开发mapper接口,对应的【xml】;
4.开发service,调用Dao层代码,完成图书详情的查询;
(1)BookService接口,定义一个【根据图书编号,查询图书对象】的方法;
在BookService接口中,增加一个【根据图书编号,查询图书对象】的方法;
(2)BookServiceImpl实现类,去实现 【根据图书编号,查询图书对象】方法;
在BookServiceImpl实现类中,我们要去实现 【根据图书编号,查询图书对象】方法;
5.开发Controller,调用Service层的代码;渲染数据,跳转到detail.ftl详情页;
在BookController类中,新增显示详情页的方法:showDedail()方法;
说明:
(1) showDetail()方法和前端的对应关系;
(2) 其中,用到了路径变量,Spring MVC的路径变量,是在【获取路径变量@PathVariable】中第一次介绍和说明的;如有需要,可以快速参考;
(3) 此时的效果:启动Tomcat,观察效果;
然后,放开断点:
(4) 解决(3)中css,js等资源不存在的问题:建议使用绝对路径,而不是相对路径;
问题分析:
解决策略:建议使用绝对路径;
Tomcat重新加载后,效果如下:
此时,只是完成了跳转到detail.ftl页面的功能,detail.ftl页面里面的数据还是写死的,我们需要去detail.ftl中去动态获取后端添加到响应中的数据;
6.detail.ftl前端文件,获取数据;
设置的地方如下:
此时的效果:启动Tomcat,观察效果:数据填充的没问题;
此时图书详情页的有关【图书详情信息】的图书介绍部分已经OK了,但是图书详情页,还有与短评相关的部分,后面我们需要开发这部分内容;
注:图片无法显示请关闭防盗链:
在head下添加代码
图书详情页开发之显示评论列表
说明:
(1) 本篇博客任务:在首页,点击某个图书后,进入该图书的详情页;然后,本篇博客要完成的是,显示下面的短评部分;
(2) 本篇博客:
● 一个和 【JS模板引擎Art-Template入门】对比时,业务逻辑和处理方式的对比和分析;
● 一个新知识,或者说是一个骚操作 : Mybatis-Plus的【@TableField(exist = false)所谓关联查询时,给对象附加对象的策略:这可以让如Evaluation对象去承载evaluation表中没有对应字段的属性;
零:前置分析和说明;
1.图书的评论信息在evaluation表中;
一:正式开发;
1.开发实体类,与底层数据表对应;
因为我们要操作evaluation表,所以需要创建一个实体类以应对该表;
Evaluation实体类:
说明:
(1) 这个没什么好说的,前面介绍过好多次了,保证属性和evaluation表的表字段名一致,别写错就行了;
(2) Date类型的属性,其类型是【java.util.Date】,别弄错了;
2.开发【Mapper接口】;
EvaluationMapper接口:
说明:
(1) 千万别忘记书写泛型;
3.开发mapper接口,对应的【xml】;
evaluation.xml:
说明:
(1) 设置好对应关系就行了;
4.开发service,调用Dao层代码,完成图书短评的查询工作;
(1)EvaluationService接口;
在EvaluationService接口中,定义一个根据图书编号,查询图书短评的方法;
(2)EvaluationServiceImpl实现类;
说明:
(1) 前面说过,【Alt+Enter】可以快速生成接口的实现类;
(2) 其中用到的东西,在前面多次遇到过,这儿再啰嗦一下;
5.开发Controller,调用Service层的代码;渲染数据,跳转到detail.ftl详情页;
6.1.detail.ftl前端文件,获取短评数据:其实是,获取短评数据的大部分内容;(这儿前端在获取数据的时候,有一个关于业务场景的分析和比对,比较重要!!!)
这些写死的<div,都一样,只是里面写死的信息不一样,我们删的只剩一个;
说明:
(1) 我们修改的内容:
其中,FreeMarker设置日期格式可以快速参考【FreeMarker基本语法-取值】;
(2)一个疑问:(比较重要)
● 问题: 在【JS模板引擎Art-Template入门】中,我们开发首页时,首页的图书信息,我们是这样做的:【前提,我们首先设置一个<div>容器,把这个容器作为盛放图书信息的容器】→【首先,当后端的图书数据过来后,这些数据是List】→【遍历这些List,每获取一条图书数据,就通过Art-Template定义模板,把这条数据渲成HTML片段】→【然后,把这端HTML,追加到那个容器中】;:为什么在前面显示图书信息这篇博客中,我们这样做;而,在这儿,我们显示短评信息时,我们直接<#list>遍历显示就行了?
● 个人理解:
首先,在前面显示图书信息的那篇博客中,首页上我们每次点击【点击加载更多…】按钮,就在首页上多显示一点数据;即显示图书信息时,图书信息不是一次就显示完的,,所以,我们定义了一个Art-Template模板,每次新图书数据来的时候,就通过这个模板生成一段HTML,然后把这段HTML追加到显示图书的容器中;
然后,本篇博客的显示短评信息,就是一锤子买卖,一次就能把某本图书的所有短评信息全部加载过来;自然,为了解决这个需求,完全不需要定义Art-Template模板,只要<#list>遍历数据,显示就行了;
● 总结: 通过,这个不同业务情况下的不同的处理策略;应该能够帮助自己提升业务开发和业务决策能力;
6.2.detail.ftl前端文件,获取短评数据:其实是,获取短评数据的会员昵称;(遇到了 Mybatis-Plus的【@TableField(exist = false),这可以让如Evaluation对象去承载evaluation表中没有对应字段的属性;:新知识,比较重要!!! )
(1)需求说明;
【如何在获取评论数据时,一起获取该条评论对应的会员昵称信息】,是这儿要解决的问题;
这种类似的场景,似乎在前面介绍Mybatis对象关联查询时,遇到过类似的需求场景;但是,看下
【MyBatis多表级联查询】这篇博客后,就能快速了解Mybatis的关联对象查询到底是什么;
然后,Mybatis的对象关联查询,和这儿使用Mybatis-Plus的解决策略,是不同的;
(2)开发查询member会员表的Dao层;
因为会员信息存储在member表中,所以我们要创建操作member表的一套内容,如下:
至此,我们有了可以获取到member表信息的,Dao层的内容;
(3)利用Mybatis-Plus的【@TableField(exist = false),在Evaluation中添加Member属性;
这是关键一步:(先别纠结为什么这么做,先看着;;;一会就能明白)
(4) 在EvaluationServiceImpl中,调用member的Dao层代码,以给Evaluation的Member属性赋值;
然后,我们就能在EvaluationServiceImpl类中,分别调用【操作book表的Dao】和【操作member表的Dao】,以获取【Book对象】和【Member对象】,然后把这两个对象在赋值为Evaluation对象;
这样以后,每一条短评Evaluation对象,其Book属性和Member属性就有了正确的值,我们在detail.ftl中就能获取到该条短评的对应的会员的昵称了;
(5)在detail.ftl中,就可以获取Member信息,即获取会员昵称了;
(下图很容易理解,我就不啰嗦了)
(6)此时的效果;
启动Tomcat,观察效果:OK没问题;
至此,我们就完成了显示某本图书短评的功能;不过这儿仅仅是显示短评;至于给短评点赞、写短评这些内容在后面介绍;
而且想要点赞短评或写短评,需要用户登录;所以,后面会先介绍会员的注册和登录功能;