实现会员交互功能
阅读状态变更
首先,在com.ql.reader.entity包下创建阅读状态实体类
package com.ql.reader.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Date;
/**
* 会员阅读状态实体
*/
@TableName("member_read_state")
public class MemberReadState {
@TableId(type = IdType.AUTO)
private Long rsId;
private Long bookId;
private Long memberId;
private Integer readState;
private Date createTime;
public Long getRsId() {
return rsId;
}
public void setRsId(Long rsId) {
this.rsId = rsId;
}
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public Long getMemberId() {
return memberId;
}
public void setMemberId(Long memberId) {
this.memberId = memberId;
}
public Integer getReadState() {
return readState;
}
public void setReadState(Integer readState) {
this.readState = readState;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
然后在com.ql.reader.mapper包下创建mapper接口
package com.ql.reader.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ql.reader.entity.Category;
import com.ql.reader.entity.MemberReadState;
public interface MemberReadStateMapper extends BaseMapper<MemberReadState> {
}
在src/main/resources/mappers目录下创建member_read_state.xml映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ql.reader.mapper.MemberReadStateMapper">
</mapper>
然后打开MemberService.java添加获得阅读状态方法,并在MemberServiceImpl.java添加相应方法实现。
/**
* 获得阅读状态
* @param memberId 会员编号
* @param bookId 图书编号
* @return 阅读状态对象
*/
public MemberReadState selectMemberReadState(Long memberId, Long bookId);
/**
* 获得阅读状态
*
* @param memberId 会员编号
* @param bookId 图书编号
* @return 阅读状态对象
*/
public MemberReadState selectMemberReadState(Long memberId, Long bookId) {
QueryWrapper<MemberReadState> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("book_id", bookId);
queryWrapper.eq("member_id", memberId);
MemberReadState memberReadState = memberReadStateMapper.selectOne(queryWrapper);
return memberReadState;
}
打开BookController.java,在展示图书细节方法里添加获取会员阅读状态的代码逻辑
@GetMapping("/book/{id}")
public ModelAndView showDetail(@PathVariable("id") Long id, HttpSession session){
Book book = bookService.selectById(id);
List<Evaluation> evaluationList = evaluationService.selectByBookId(id);
Member member = (Member) session.getAttribute("loginMember");
ModelAndView mav = new ModelAndView("/detail");
if(member!=null){
//获取会员阅读状态
MemberReadState memberReadState = memberService.selectMemberReadState(member.getMemberId(), id);
mav.addObject("memberReadState", memberReadState);
}
mav.addObject("book", book);
mav.addObject("evaluationList", evaluationList);
return mav;
}
运行项目测试。
更新会员阅读状态
打开MemberService.java添加更新阅读状态方法,并在MemberServiceImpl.java添加相应方法实现。
/**
* 更新阅读状态
* @param memberId 会员编号
* @param bookId 图书编号
* @param readState 阅读状态
* @return 阅读状态对象
*/
public MemberReadState updateMemberReadState(Long memberId, Long bookId, Integer readState);
/**
* 更新阅读状态
*
* @param memberId 会员编号
* @param bookId 图书编号
* @param readState 阅读状态
* @return 阅读状态对象
*/
public MemberReadState updateMemberReadState(Long memberId, Long bookId, Integer readState) {
QueryWrapper<MemberReadState> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("book_id", bookId);
queryWrapper.eq("member_id", memberId);
MemberReadState memberReadState = memberReadStateMapper.selectOne(queryWrapper);
//无则新增,有则更新
if(memberReadState==null){
memberReadState = new MemberReadState();
memberReadState.setMemberId(memberId);
memberReadState.setBookId(bookId);
memberReadState.setReadState(readState);
memberReadState.setCreateTime(new Date());
memberReadStateMapper.insert(memberReadState);
}else{
memberReadState.setReadState(readState);
memberReadStateMapper.updateById(memberReadState);
}
return memberReadState;
}
打开BookController.java,添加更新想看/看过阅读状态方法
/**
* 更新想看/看过阅读状态
* @param memberId 会员id
* @param bookId 图书id
* @param readState 阅读状态
* @return 处理结果
*/
@PostMapping("/update_read_state")
@ResponseBody
public Map updateReadState(Long memberId, Long bookId, Integer readState){
Map result = new HashMap();
try {
memberService.updateMemberReadState(memberId, bookId, readState);
result.put("code", "0");
result.put("msg", "success");
}catch (BussinessException e){
e.printStackTrace();
result.put("code", e.getCode());
result.put("msg", e.getMsg());
}
return result;
}
运行项目测试
写短评
首先打开MemberService.java添加新增短评方法,并在MemberServiceImpl.java里添加相应方法实现。
/**
* 发布新的短评
* @param memberId 会员编号
* @param bookId 图书编号
* @param score 评分
* @param content 短评内容
* @return 短评对象
*/
public Evaluation evaluate(Long memberId, Long bookId, Integer score, String content);
/**
* 发布新的短评
*
* @param memberId 会员编号
* @param bookId 图书编号
* @param score 评分
* @param content 短评内容
* @return 短评对象
*/
public Evaluation evaluate(Long memberId, Long bookId, Integer score, String content) {
Evaluation evaluation = new Evaluation();
evaluation.setMemberId(memberId);
evaluation.setBookId(bookId);
evaluation.setScore(score);
evaluation.setContent(content);
evaluation.setState("enable");
evaluation.setEnjoy(0);
evaluation.setCreateTime(new Date());
evaluationMapper.insert(evaluation);
return evaluation;
}
然后打开MemberController.java添加新增短评调用方法
@PostMapping("/evaluate")
@ResponseBody
public Map evaluate(Long memberId, Long bookId, Integer score, String content){
Map result = new HashMap();
try {
memberService.evaluate(memberId, bookId, score, content);
result.put("code", "0");
result.put("msg", "success");
}catch (BussinessException e){
e.printStackTrace();
result.put("code", e.getCode());
result.put("msg", e.getMsg());
}
return result;
}
前端代码为detail.ftl中短评代码部分
<script>
...
$(function () {
<#if !loginMember ??>
...
$("#btnEvaluation").click(function(){
// 转换为星型组件
$("#score").raty({});
// 显示短评对话框
$("#dlgEvaluation").modal("show");
})
// 评论对话框提交数据
$("#btnSubmit").click(function(){
// 获取评分
var score = $("#score").raty("score");
var content = $("#content").val();
if(score == 0 || $.trim(content) == ""){
return;
}
$.post("/evaluate" , {
score : score,
bookId : ${book.bookId},
memberId : ${loginMember.memberId},
content : content
},function(json){
if(json.code == "0"){
// 刷新当前页面
window.location.reload();
}
},"json")
})
</#if>
})
</script>
运行项目测试
短评点赞
首先打开MemberService.java添加新增短评点赞方法,并在MemberServiceImpl.java里添加相应方法实现。
/**
* 短评点赞
* @param evaluationId 短评编号
* @return 短评对象
*/
public Evaluation enjoy(Long evaluationId);
/**
* 短评点赞
*
* @param evaluationId 短评编号
* @return 短评对象
*/
public Evaluation enjoy(Long evaluationId) {
Evaluation evaluation = evaluationMapper.selectById(evaluationId);
evaluation.setEnjoy(evaluation.getEnjoy()+1);
evaluationMapper.updateById(evaluation);
return evaluation;
}
然后打开MemberController.java添加新增短评点赞调用方法
@PostMapping("/enjoy")
@ResponseBody
public Map enjoy(Long evaluationId){
Map result = new HashMap();
try {
Evaluation evaluation = memberService.enjoy(evaluationId);
result.put("code", "0");
result.put("msg", "success");
result.put("evaluation", evaluation);
}catch (BussinessException e){
e.printStackTrace();
result.put("code", e.getCode());
result.put("msg", e.getMsg());
}
return result;
}
前端代码为detail.ftl中短评点赞代码部分
<script>
...
// 评论点赞
$("*[data-evaluation-id]").click(function(){
debugger
var evaluationId = $(this).data("evaluation-id");
$.post("/enjoy",{evaluationId:evaluationId},function(json){
if(json.code == "0"){
$("*[data-evaluation-id='" + evaluationId + "'] span").text(json.evaluation.enjoy);
}
},"json")
})
...
</script>
运行项目测试
Spring Task定时任务
Spring Task是Spring 3.0后推出的定时任务模块。
Spring Task的职责是按周期后台自动执行任务。
Spring Task可利用Cron表达式实现灵活的定时处理。
Cron表达式实例
第一行为每分钟的0秒执行任务。
第二行为2000年的每小时的前五分钟每0秒和30秒执行任务。
第三行为每周三的9点到18点的每个小时的整点执行任务。
利用Spring-Task自动计算图书评分
打开book.xml文件添加更新图书评分的sql语句
<update id="updateEvaluation">
update book b set evaluation_score = (
select ifnull(avg(score), 0) from evaluation where book_id = b.book_id and state = 'enable'
),evaluation_quantity = (
select ifnull(count(*), 0) from evaluation where book_id = b.book_id and state = 'enable'
)
</update>
然后打开BookMapper.java添加对应的方法
public interface BookMapper extends BaseMapper<Book> {
/**
* 更新图书评分、评价数量
*/
public void updateEvaluation();
}
然后打开BookService.java添加更新图书评分、评价数量方法,并在在BookServiceImpl.java添加方法实现
/**
* 更新图书评分、评价数量
*/
public void updateEvaluation();
/**
* 更新图书评分、评价数量
*/
@Transactional
public void updateEvaluation() {
bookMapper.updateEvaluation();
}
Spring Task底层依赖包含在spring-context依赖里,所以不需要额外引入依赖。
打开applicationContext.xml添加Spring Task配置
<!--开启Spring Task定时任务的注解模式-->
<task:annotation-driven/>
然后在com.ql.reader.task包下创建ComputeTask.java编写自动计算任务代码
package com.ql.reader.task;
import com.ql.reader.service.BookService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 完成自动计算任务
*/
@Component
public class ComputeTask {
@Resource
private BookService bookService;
//任务调度
@Scheduled(cron = "0 * * * * ?")
public void updateEvaluation(){
bookService.updateEvaluation();
System.out.println("已更新所有图书评分");
}
}
运行项目,登录并打开一个书籍评分为:
添加评分为:
添加完等下一分钟看到调度任务已执行,刷新页面,此时该书评分已变。