分布式架构搭建拉勾教育PC站-后端


1、项目架构

1.1 项目介绍

  • 拉勾教育PC站,是提供给我们学员观看技术视频的网站
  • 学员使用手机号注册登录后,可以选择适合自己的课程,并观看课程视频,当然,有免费的课程,也有vip专属课程

1.2 页面原型展示

访问:http://edufront.lagou.com/

用户名:15510792995 密码:111111

image-20220112201515640

1.3 技术选型

1.3.1 前端技术选型

image-20220112201539195

1.3.2 后端技术选型

image-20220112201553869

1.4 项目开发环境

  • 开发工具
    • 后端: IDEA 2019
    • 前端: VS code
    • 数据库客户端工具: SQLYog
  • 开发环境
    • JDK 11
    • Maven 3.6.3
    • MySQL 5.7
    • Zookeeper 3.6.0
    • Dubbo 2.5.7
    • Redis 5.0.4

2、开发后端服务接口

  • 我们采用前后端分离的开发模式,先开发后端服务接口,测试成功,再开发前端vue界面,最后进行前后端联调,项目上线

2.1 项目结构与命名

  • 单一架构

image-20220112201733273

  • 分布式架构:

image-20220112201750937

  • 后端项目架构,我们采用dubbo的生产者和消费者的理论,创建服务提供方和服务消费方两个工程,通过maven聚合工程来搭建,模块划分如下:
    • 服务提供
      • lagou-edu-parent:pom聚合父工程,统一依赖设置
      • lagou-edu-entity:jar工程,封装实体类
      • lagou-edu-dao:jar工程,封装与数据库打交道的部分
      • lagou-edu-service:web工程,暴露服务的接口和实现
    • 服务消费
      • lagou-edu-web:web工程,接收前端工程发来的请求,远程调用服务并消费

2.1.2 URL命名

  • 查询:http://localhost:8002/course/getList --- get开头
  • 保存:http://localhost:8002/course/saveXx --- save开头
  • 更新:http://localhost:8002/course/updateXx --- update开头

2.1.3 接口响应格式

/**
  数据传输对象
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ResponseDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    private int state;  // 操作状态
    private String message;  // 状态描述
    private T content;  // 相应内容
}

2.1.4 pom.xml


    5.0.6.RELEASE


    
    
        org.springframework
        spring-context
        ${spring.version}
    
    
        org.springframework
        spring-beans
        ${spring.version}
    
    
        org.springframework
        spring-webmvc
        ${spring.version}
    
    
        org.springframework
        spring-jdbc
        ${spring.version}
    
    
        org.springframework
        spring-aspects
        ${spring.version}
    
    
        org.springframework
        spring-test
        ${spring.version}
        test
    
    
    
        org.mybatis
        mybatis
        3.2.8
    
    
        org.mybatis
        mybatis-spring
        1.3.2
    
    
    
        com.alibaba
        druid
        1.0.9
    
    
    
        mysql
        mysql-connector-java
        5.1.32
    
    
    
        com.alibaba
        dubbo
        2.5.7
    
    
    
        org.apache.zookeeper
        zookeeper
        3.4.6
    
     
    
        com.github.sgroschupf
        zkclient
        0.1
    
    
        javassist
        javassist
        3.11.0.GA
    
    
    
        com.alibaba
        fastjson
        1.2.47
    
    
    
        junit
        junit
        4.12
        test
    
    
    
        org.springframework.data
        spring-data-redis
        2.3.2.RELEASE
    
    
    
        redis.clients
        jedis
        3.1.0
    
    
    
        com.fasterxml.jackson.core
        jackson-databind
        2.9.8
    

2.1.5 初始化数据库

  • 数据库设计文档V1.0.pdf
  • edu.sql

2.1 用户模块

  • 实体类的编写没有任意技术含量,而且还浪费时间,传说中的“老牛活”
  • 使用一个插件可以快速生成 entity,dao,service,mapper等文件
  • 生成“老牛活”代码的解决方案有很多种:企业中比较常见的还有“mybatis的逆向工程(自学)”

image-20220112202300137

2.1.1 用户登录/注册

image-20220112202319831

  • lagou-edu-entity

lombok小辣椒,使用注解取代原来冗余的get和set,空构造,全参数构造



    org.projectlombok
    lombok
    1.18.12
    provided

@Data  //get和set都全部生成了
@AllArgsConstructor //生成全参数的构造方法
@NoArgsConstructor //生成空构造方法
@ToString // 生成toString方法
public class User implements Serializable {
    private static final long serialVersionUID = -89788707895046947L;
    /**
    * 用户id
    */
    private Integer id;
  • lagou-edu-dao

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>


    
    
        
    

spring-dao.xml

<?xml version="1.0" encoding="UTF-8"?>

    
    
    
    
        
        
        
        
        
    
    
    
        
        
    
    
    
        
    
    
    
    
        
    
 
<?xml version="1.0" encoding="UTF-8"?>


    
        
        
        
        
        
        
        
        
        
        
        
        
        
    
    

@Service
public interface UserDao {
   /**
    * @param phone 手机号
    * @param password 密码
    * @return 用户对象
    */
   User login(@Param("phone") String phone, @Param("password") String password);
}
// 测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/spring-dao.xml" })
public class TestUser {
    @Autowired
    private UserDao userDao;
    
    @Test
    public void login(){
        User user = userDao.login("1101", "123");
        System.out.println("user = " + user);
    }
}
  • lagou-edu-service

spring-service.xml

<?xml version="1.0" encoding="UTF-8"?>

    
    
    
    
    
    
    
    
        
    
    
        
        
    

<?xml version="1.0" encoding="UTF-8"?>

    
        org.springframework.web.context.ContextLoaderListener
    
    
        contextConfigLocation
        classpath*:spring/spring-*.xml
    

// 测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring/spring-*.xml" })
public class TestUser {
    @Autowired
    private UserService userService;
    
    @Test
    public void login(){
        User user = userService.login("110", "123");
        System.out.println("user = " + user);
    }
}

tomcat插件

war

    
        
            org.apache.tomcat.maven
            tomcat7-maven-plugin
            
                8001
                /
            
            
                
                    
                    package
                    
                        run
                    
                
            
        
    

  • lagou-edu-web

spring-consumer.xml

<?xml version="1.0" encoding="UTF-8"?>

    
    
        
            
                
                
                    
                        WriteMapNullValue
                        WriteDateUseDateFormat
                    
                
            
        
    
    
    
    
    
    
    

<?xml version="1.0" encoding="UTF-8"?>

    
    
        charset
        org.springframework.web.filter.CharacterEncodingFilter
        
            encoding
            utf-8
        
        
            forceEncoding
            true
        
    
    
        charset
        /*
    
    
    
        corsFitler
        com.thetransactioncompany.cors.CORSFilter
    
    
        corsFitler
        /*
    
    
        springMVC
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            classpath:spring/spring-consumer.xml
        
    
    
        springMVC
        /
        

tomcat插件

war

    
        
            org.apache.tomcat.maven
            tomcat7-maven-plugin
            
                8002
                /
            
            
                
                    
                    package
                    
                        run
                    
                
            
        
    

2.2 课程模块

2.2.1 全部课程

  • 课程:Java从小白到大神 (course) -------> 起点老师:拉勾网高级讲师 (teacher
    • 第一章:初识 (course_section
      • 01 什么是java (course_lesson
      • 02 jdk的介绍与安装
    • 第二章:应用
      • 01 什么是数据类型
      • 02 什么是变量

course 1:1 teacher
course 1:N course_section
course_section 1:N course_lesson
course_lesson1:N course_media

image-20220112203108385

  • lagou-edu-entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Course implements Serializable {
    private Teacher teacher; // 一门课程对应一个讲师
    private List courseSections; //一门课程对应多个章节
    private ActivityCourse activityCourse;// 一门课做一个活动
    // 省略
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseSection implements Serializable {
    private List courseLessons; // 一章对应多个小节
    // 省略
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseLesson implements Serializable {
    private CourseMedia courseMedia; // 一小节课对应一个视频
    // 省略
}
  • lagou-edu-dao
<?xml version="1.0" encoding="UTF-8"?>


    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
            
            
            
            
            
            
            
            
        
        
        
            
            
            
            
            
            
            
            
            
            
            
            
            
        
        
        
            
            
            
            
 			
            
            
            
            
            
            
                
                
                
                
                
                
                
                
                
                
                
                
                
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
					
                    
                    
                
            
        
    
    
        select
    c.id c_id,`course_name`,`brief`,`price`,`price_tag`,`discounts`,`discounts_tag`,
    `course_description_mark_down`,`course_description`,`course_img_url`,`is_new`,
    `is_new_des`,`last_operator_id`,`auto_online_time`,c.create_time c_create_time,
    c.update_time c_update_time,c.is_del c_is_del,`total_duration`,`course_list_img`,
    c.status c_status,`sort_num`,`preview_first_field`,`preview_second_field`,`sales`,
    t.id t_id,t.course_id t_course_id,`teacher_name`,`position`,t.description t_description,
    t.create_time t_create_time,t.update_time t_update_time,t.is_del t_is_del,
    cs.id cs_id,cs.course_id cs_course_id,`section_name`,cs.description cs_description,
    cs.create_time cs_create_time,cs.update_time cs_update_time,`is_de`,cs.order_num cs_order_num ,
    cs.status cs_status,
    cl.id cl_id,cl.course_id cl_course_id,cl.section_id cl_section_id,`theme`,cl.duration cl_duration,
    `is_free`,cl.create_time cl_create_time,cl.update_time cl_update_time,cl.is_del cl_is_del,cl.order_num 		cl_order_num,
    cl.status cl_status,
    cm.id cm_id,cm.course_id cm_course_id,cm.section_id cm_section_id,cm.lesson_id cm_lesson_id,
    `cover_image_url`,cm.duration cm_duration,`file_edk`,`file_size`,`file_name`,`file_dk`,cm.create_time 		cm_create_time,
    cm.update_time cm_update_time,cm.is_del cm_is_del,`duration_num`,`file_id`,
    ac.id ac_id,ac.course_id ac_course_id,`begin_time`,`end_time`,`amount`,`stock`,ac.status ac_status,
    ac.is_del ac_is_del,`remark`,ac.create_time ac_create_time,`create_user`,ac.update_time ac_update_time,
    `update_user`
    from activity_course ac right join course c on  c.id = ac.course_id
        inner join teacher t on c.id = t.course_id
        inner join course_section cs on c.id = cs.course_id
        inner join course_lesson cl on cl.section_id = cs.id
        left join course_media cm on cm.lesson_id = cl.id
    
    

package mapper;
import com.lagou.entity.Course;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public interface CourseDao {
    /**
     * 查询全部课程信息
     * @return
     */
    List getAllCourse();
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/spring-dao.xml" })
public class TestCourse {
    @Autowired
    private CourseDao courseDao;
    @Test
    public void getAllCourse(){
        List list = courseDao.getAllCourse();
        for(Course course : list){
            //if( course.getId().toString() .equals("8") ){ //查询第8门课
                String flag = course.getActivityCourse()!=null ? "【火爆活动中】":"";
                System.out.println("课程:"+flag + course.getId() +"->"+ course.getCourseName());
                for(CourseSection cs : course.getCourseSections() ){
                    System.out.println("\t\t章节" + cs.getId() +"--->" + cs.getSectionName());
                    for(CourseLesson cl : cs.getCourseLessons()){
                        if(cl.getCourseMedia() != null){
                            System.out.println("\t\t\t小节" + cl.getId() 
                                               +"--->" + cl.getTheme() 
                                               +",视频:" + cl.getCourseMedia().getFileId() 
                                               +",时长:【"+ cl.getCourseMedia().getDuration()+"】");
                        }else{
                            System.out.println("\t\t\t小节" + cl.getId() 
                                               +"--->" + cl.getTheme()+",视频:【待上传】,时长:【00:00】");
                        }
                    }
                }
            //}
        }
    }
}
  • lagou-edu-service
package com.lagou.course;
import com.lagou.entity.Course;
import java.util.List;
public interface CourseService {
    /**
     * 查询全部课程信息
     * @return
     */
    List getAllCourse();
}
package com.lagou.course.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.lagou.course.CourseService;
import com.lagou.entity.Course;
import mapper.CourseDao;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Service
public class CourseServiceImpl implements CourseService {
    @Autowired
    private CourseDao courseDao;
    public List getAllCourse() {
        return courseDao.getAllCourse();
    }
}
  • lagou-edu-web
package com.lagou.course;
import com.lagou.entity.Course;
import java.util.List;
public interface CourseService {
    /**
     * 查询全部课程信息
     * @return
     */
    List getAllCourse();
}
package com.lagou.course.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.lagou.course.CourseService;
import com.lagou.entity.Course;
import com.lagou.entity.User;
import com.lagou.entity.UserDTO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("course")
public class CourseController {
    @Reference // 远程消费
    private CourseService courseService;
    @GetMapping("getAllCourse")
    public List getAllCourse() {
        List list = courseService.getAllCourse();
        return list;
    }
}

2.2.2 已购课程

image-20220112204021764

  • lagou-edu-entity (同上)
  • lagou-edu-dao

@Service
public interface CourseDao {
    /**
     * 查询已登录用户购买的全部课程信息
     * @return
     */
    List getCourseByUserId(@Param("userId") String userId);
}
  • lagou-edu-service
public interface CourseService {
    /**
     * 查询已登录用户购买的全部课程信息
     * @return
     */
    List getCourseByUserId(String userId);
}
@Service
public class CourseServiceImpl implements CourseService {
    @Autowired
    private CourseDao courseDao;
    public List getCourseByUserId(String userId) {
        return courseDao.getCourseByUserId(userId);
    }
}
  • lagou-edu-web
public interface CourseService {
    /**
     * 查询已登录用户购买的全部课程信息
     * @return
     */
    List getCourseByUserId(String userId);
}
@RestController
@RequestMapping("course")
public class CourseController {
    @Reference // 远程消费
    private CourseService courseService;
    @GetMapping("getCourseByUserId/{userid}")
    public List getCourseByUserId( @PathVariable("userid") String userid 
) {
        List list = courseService.getCourseByUserId(userid);
        return list;
    }
}

2.2.3 课程详情

image-20220112204247072

  • lagou-edu-entity (同上)
  • lagou-edu-dao

@Service
public interface CourseDao {
    /**
     * 查询某门课程的详细信息
     * @param courseid 课程编号
     * @return
     */
    Course getCourseById(@Param("courseid") Integer courseid);
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/spring-dao.xml"})
public class TestCourse {
    @Autowired
    private CourseDao courseDao;
    @Test
    public void getCourseById() {
        Course course = courseDao.getCourseById(7);
        String flag = course.getActivityCourse() != null ? "【火爆活动中】" : "";
        System.out.println("课程:" + flag + course.getId() + "->" + course.getCourseName());
        for (CourseSection cs : course.getCourseSections()) {
            System.out.println("\t\t章节" + cs.getId() + "--->" + cs.getSectionName());
            for (CourseLesson cl : cs.getCourseLessons()) {
                if (cl.getCourseMedia() != null) {
                    System.out.println("\t\t\t小节" + cl.getId() + "--->" + cl.getTheme() 
                                       + ",视频:" + cl.getCourseMedia().getFileId() 
                                       + ",时长:【" + cl.getCourseMedia().getDuration() + "】");
                } else {
                System.out.println("\t\t\t小节" + cl.getId() + "--->" + cl.getTheme() 
                                   + ",视频:【待上传】,时长:【00:00】");
                }
            }
        }
    }
}
  • lagou-edu-service
public interface CourseService {
    Course getCourseById(Integer courseid);
}
@Service // 暴露服务
public class CourseServiceImpl implements CourseService {
    public Course getCourseById(Integer courseid) {
        return courseDao.getCourseById(courseid);
    }
}
  • lagou-edu-web
public interface CourseService {
    /**
     * 查询某门课程的详细信息
     * @param courseid 课程编号
     * @return
     */
    Course getCourseById(Integer courseid);
}
@RestController
@RequestMapping("course")
public class CourseController {
    @Reference // 远程消费
    private CourseService courseService;
    @GetMapping("getCourseById/{courseid}")
    public Course getCourseById(@PathVariable("courseid")Integer courseid) {
        Course course = courseService.getCourseById(courseid);
        return course;
    }
}

2.2.4 课程播放

image-20220112204509714

2.3 订单模块

2.3.1 购买/生成订单

image-20220112204529656

  • lagou-edu-dao

insert  into `user_course_order`(`order_no`,`user_id`,`course_id`,`activity_course_id`,
    `source_type`,`status`,`create_time`,ùpdate_time`,ìs_del`)
values(#{orderNo},#{user_id},#{course_id},#{activity_course_id},
     #{source_type},0,sysdate(),sysdate(),0)

@Service
public interface OrderDao {
    /**
     * 生成订单
     * @param orderNo 订单编号
     * @param user_id 用户编号
     * @param course_id 课程编号
     * @param activity_course_id 活动课程编号
     * @param source_type 订单来源类型
     */
    void saveOrder(@Param("orderNo")String orderNo,
                   @Param("user_id")String user_id,
                   @Param("course_id")String course_id,
                   @Param("activity_course_id")Stringactivity_course_id,
                   @Param("source_type")String source_type);
}
  • lagou-edu-service
public interface OrderService {
    /**
     * 生成订单
     * @param orderNo 订单编号
     * @param user_id 用户编号
     * @param course_id 课程编号
     * @param activity_course_id 活动课程编号
     * @param source_type 订单来源类型
     */
    void saveOrder(String orderNo, String user_id, String course_id,
                   String activity_course_id, String source_type);
}
@Service //暴露服务
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    public void saveOrder(String orderNo, String user_id, String course_id, 
                          String activity_course_id, String source_type) {
        orderDao.saveOrder(orderNo, user_id, course_id, activity_course_id, source_type);
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring/spring-*.xml" })
public class TestOrder {
    @Autowired
    private OrderService orderService;
    @Test
    public void saveOrder(){
        String orderNo= UUID.randomUUID().toString();
        String user_id = "100030011";
        String course_id = "7";
        String activity_course_id = "0"; // 0表示,本课程没有活动
        String source_type = "1";
       
 orderService.saveOrder(orderNo,user_id,course_id,activity_course_id,source_type
);
    }
}
  • lagou-edu-web
public interface OrderService {
    /**
     * 生成订单
     * @param orderNo 订单编号
     * @param user_id 用户编号
     * @param course_id 课程编号
     * @param activity_course_id 活动课程编号
     * @param source_type 订单来源类型
     */
    void saveOrder(String orderNo, String user_id, String course_id,
                   String activity_course_id, String source_type);
}
@RestController
@RequestMapping("order")
public class OrderController {
    @Reference // 远程消费
    private OrderService orderService;
    @GetMapping("saveOrder/{userid}/{courseid}/{acid}/{stype}")
    public String saveOrder(@PathVariable("userid")String user_id , 
                            @PathVariable("courseid")String course_id,
                            @PathVariable("acid")String activity_course_id,
                            @PathVariable("stype")String source_type) {
        String orderNo = UUID.randomUUID().toString();
        orderService.saveOrder(orderNo, user_id, course_id, activity_course_id, source_type);
        return orderNo;
    }
}

2.3.2 订单操作

image-20220112204747147

  • lagou-edu-dao
<?xml version="1.0" encoding="UTF-8"?>


    
        
        
        
        
        
        
        
        
        
        
    
    
        update user_course_order set status = #{status} where order_no = #{orderNo} and is_del = 0
    
    
        update user_course_order set is_del= 1 where order_no = #{orderNo}
    
    

@Service
public interface OrderDao {
    /**
     * 修改订单状态
     * @param orderNo 订单编号
     * @param status 订单状态 0已创建 10已支付 20已完成 30已取消 40已过期
     * @return 受影响的行数
     */
    Integer updateOrder( @Param("orderNo") String orderNo,@Param("status") int status );
    /**
     * 删除订单
     * @param orderNo 订单编号
     * @return 受影响的行数
     */
    Integer deleteOrder(@Param("orderNo") String orderNo);
    /**
     * 查询登录用户的全部订单
     * @param userId 用户编号
     * @return 所有订单
     */
    List getOrdersByUserId(@Param("userId") String userId);
}
  • lagou-edu-service
public interface OrderService {
    /**
     * 修改订单状态
     * @param orderNo 订单编号
     * @param status 订单状态 0已创建 10已支付 20已完成 30已取消 40已过期
     * @return 受影响的行数
     */
    Integer updateOrder( String orderNo,int status );
    /**
     * 删除订单
     * @param orderNo 订单编号
     * @return 受影响的行数
     */
    Integer deleteOrder(String orderNo);
    /**
     * 查询登录用户的全部订单
     * @param userId 用户编号
     * @return 所有订单
     */
    List getOrdersByUserId(String userId);
}
@Service //暴露服务
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    public Integer updateOrder(String orderNo, int status) {
        return orderDao.updateOrder(orderNo,status);
    }
    public Integer deleteOrder(String orderNo) {
        return orderDao.deleteOrder(orderNo);
    }
    public List getOrdersByUserId(String userId) {
        return orderDao.getOrdersByUserId(userId);
    }
}
  • lagou-edu-web
public interface OrderService {
    /**
     * 修改订单状态
     * @param orderNo 订单编号
     * @param status 订单状态 0已创建 10已支付 20已完成 30已取消 40已过期
     * @return 受影响的行数
     */
    Integer updateOrder( String orderNo,int status );
    /**
     * 删除订单
     * @param orderNo 订单编号
     * @return 受影响的行数
     */
    Integer deleteOrder(@Param("orderNo") String orderNo);
    /**
     * 查询登录用户的全部订单
     * @param userId 用户编号
     * @return 所有订单
     */
    List getOrdersByUserId(String userId);
}
@RestController
@RequestMapping("order")
public class OrderController {
    @Reference // 远程消费
    private OrderService orderService;
    @GetMapping("updateOrder/{orderno}/{status}")
    public Integer updateOrder(@PathVariable("orderno")String orderno , 
                               @PathVariable("status")Integer status) {
        Integer integer = orderService.updateOrder(orderno, status);
        return integer;
    }
    @GetMapping("deleteOrder/{orderno}")
    public Integer deleteOrder(@PathVariable("orderno")String orderno ) {
    Integer integer = orderService.deleteOrder(orderno);
        return integer;
    }
    @GetMapping("getOrdersByUserId/{userid}")
    public List getOrdersByUserId(@PathVariable("userid")String userid ) {
        List list = orderService.getOrdersByUserId(userid);
        return list;
    }
}

2.4 留言模块

2.4.1 保存留言

image-20220112205016922

  • lagou-edu-entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseComment implements Serializable {
    private static final long serialVersionUID = 922554392538715061L;
  • lagou-edu-dao
<?xml version="1.0" encoding="UTF-8"?>


    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    
   
       insert into`course_comment`(`course_id`,`section_id`,`lesson_id`,ùser_id`,
                                   ùser_name`,`parent_id`,ìs_top`,`comment`,`like_count`,ìs_reply`,
                                   `type`,`status`,`create_time`,ùpdate_time`,ìs_del`,`last_operator`,
                                   ìs_notify`,`mark_belong`,`replied`) 
       values (#{courseId},#{sectionId},#{lessonId},#{userId},#{userName},#{parentId},
               0,#{comment},0,0,#{type},0,sysdate(),sysdate(),0,#{lastOperator},1,0,0)
   

@Service
public interface CourseCommentDao {
    /**
     * 保存留言
     * @param comment 留言内容对象
     * @return 受影响的行数
     */
    Integer saveComment(CourseComment comment);
}
  • lagou-edu-service
public interface CommentService {
    /**
     * 保存留言
     * @param comment 留言内容对象
     * @return 受影响的行数
     */
    Integer saveComment(CourseComment comment);
}
@Service // 暴露服务
public class CommentServiceImpl implements CommentService {
    @Autowired
    private CourseCommentDao courseCommentDao;
    
    public Integer saveComment(CourseComment comment) {
        return courseCommentDao.saveComment(comment);
    }
}
  • lagou-edu-web
public interface CommentService {
    /**
     * 保存留言
     * @param comment 留言内容对象
     * @return 受影响的行数
     */
    Integer saveComment(CourseComment comment);
}
@RestController
@RequestMapping("course")
public class CommentController {
    @Reference // 远程消费
    private CommentService commentService;
    @GetMapping("comment/saveCourseComment")
    public Object saveCourseComment(){
        CourseComment comment = new CourseComment();
        comment.setCourseId(7); // 课程编号
        comment.setSectionId(8); // 章节编号
        comment.setLessonId(10);// 小节编号
        comment.setUserId(100030011); // 用户编号
        comment.setUserName("Angier"); // 用户昵称
        comment.setParentId(0); //没有父id
        comment.setComment("old tie, 666!");// 留言内容
        comment.setType(0); // 0用户留言
        comment.setLastOperator(100030011); //最后操作的用户编号
        Integer i = commentService.saveComment(comment);
        System.out.println(i);
        return null;
    }
}

2.4.2 留言列表

某门课程的全部留言

image-20220112205342773

  • lagou-edu-entity(同上)
  • lagou-edu-dao

@Service
public interface CourseCommentDao {
    /**
     * 某个课程的全部留言(分页)
     * @param courseid 课程编号
     * @param offset 数据偏移
     * @param pageSize 每页条目数
     * @return 留言集合
     */
    List getCommentsByCourseId(@Param("courseid")Integer courseid, 
                                              @Param("offset")Integer offset, 
                                              @Param("pageSize")Integer pageSize);
}
  • lagou-edu-service
public interface CommentService {
    /**
     * 某个课程的全部留言(分页)
     * @param courseid 课程编号
     * @param offset 数据偏移
     * @param pageSize 每页条目数
     * @return 留言集合
     */
    List getCommentsByCourseId(@Param("courseid")Integer courseid, 
                                              @Param("offset")Integer offset,  
                                              @Param("pageSize")Integer pageSize);
}
@Service // 暴露服务
public class CommentServiceImpl implements CommentService {
    @Autowired
    private CourseCommentDao courseCommentDao;
    public List getCommentsByCourseId(Integer courseid, Integer offset, Integer pageSize) {
        return courseCommentDao.getCommentsByCourseId(courseid, offset, pageSize);
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring/spring-*.xml" })
public class TestComment {
    @Autowired
    private CommentService commentService;
    @Test
    public void getCommentsByCourseId(){
        int pageSize = 20;
        int pageIndex = 3; //页码(第几页)
        List list = commentService.getCommentsByCourseId(1, (pageIndex-1)*pageSize,pageSize);
        for(int i = 0;i
  • lagou-edu-web
public interface CommentService {
    /**
     * 某个课程的全部留言(分页)
     * @param courseid 课程编号
     * @param offset 数据偏移
     * @param pageSize 每页条目数
     * @return 留言集合
     */
    List getCommentsByCourseId(@Param("courseid")Integer courseid, 
                                              @Param("offset")Integer offset,  
                                              @Param("pageSize")Integer pageSize);
}
@RestController
@RequestMapping("course")
public class CommentController {
    @Reference // 远程消费
    private CommentService commentService;
   
 @GetMapping("comment/getCourseCommentList/{courseid}/{pageIndex}/{pageSize}")
    public List getCommentsByCourseId(@PathVariable("courseid") Integer courseid, 
                                                     @PathVariable("pageIndex") Integer pageIndex, 
                                                     @PathVariable("pageSize") Integer pageSize){
        List list = commentService.getCommentsByCourseId(courseid, pageIndex, pageSize);
        return list;
    }
}

2.4.3 留言 点赞/取消赞

image-20220112205716018

  • lagou-edu-entity(无)
  • lagou-edu-dao




    insert  into `course_comment_favorite_record`(user_id,`comment_id`,`is_del`,`create_time`,`update_time`) 	 values(#{uid},#{cid},0,sysdate(),sysdate())



    update course_comment_favorite_record set is_del = #{status} where comment_id = #{cid} 
    and user_id = #{uid}



    update course_comment set like_count = like_count + #{x} where id = #{comment_id}

@Service
public interface CourseCommentDao {
    /**
     * 查看某个用户的某条留言是否点过赞
     * @param comment_id 留言编号
     * @param userid 用户编号
     * @return 0:没点过赞,1:点过赞
     */
    Integer existsFavorite(@Param("cid")Integer comment_id,@Param("uid")Integer userid);
 /**
     * 保存点赞信息
     * @param comment_id 留言编号
     * @param userid 用户编号
     * @return 0:保存失败,1:保存成功
     */
    Integer saveCommentFavorite(@Param("cid")Integer comment_id,@Param("uid")Integer userid);
    /**
     * 更新点赞信息的状态(将is_del=0,表示已赞)
     * @param status 状态,0:已赞,1:取消赞
     * @param comment_id 留言编号
     * @param userid 用户编号
     * @return 0:保存失败,1:保存成功
     */
    Integer updateFavoriteStatus( @Param("status")Integer status, @Param("cid")Integercomment_id,
                                  @Param("uid")Integer userid);
    /**
     * 更新点赞的数量
     * @param x +1的话,赞的数量增加,-1的话,赞的数量减少
     * @param comment_id 某条留言的编号
     * @return 0:保存失败,1:保存成功
     */
    Integer updateLikeCount(@Param("x")Integer x ,@Param("comment_id")Integer comment_id);
}
  • lagou-edu-service
public interface CommentService {
    /**
     * 点赞
     * @param comment_id 留言编号
     * @param userid 用户编号
     * @return 0:保存失败,1:保存成功
     */
    Integer saveFavorite(Integer comment_id,Integer userid);
    /**
     * 取消赞
     * @param comment_id 留言编号
     * @param userid 用户编号
     * @return 0:保存失败,1:保存成功
     */
    Integer cancelFavorite(Integer comment_id,Integer userid);
}
@Service // 暴露服务
public class CommentServiceImpl implements CommentService {
    @Autowired
    private CourseCommentDao courseCommentDao;
    /**
     *点赞:
     * 先查看当前用户对这条留言是否点过赞,
     * 如果点过:修改is_del状态即可,取消赞
     * 如果没点过:保存一条点赞的信息
     *
     * 最终,更新赞的数量
      */
    public Integer saveFavorite(Integer comment_id, Integer userid) {
        Integer i = courseCommentDao.existsFavorite(comment_id,userid);
        int i1 = 0;
        int i2 = 0;
        if(i == 0){ //没点过赞
            i1 = courseCommentDao.saveCommentFavorite(comment_id,userid);
        }else{
            i1 = courseCommentDao.updateFavoriteStatus(0,comment_id,userid);
        }
        i2 = courseCommentDao.updateLikeCount(1,comment_id);
        if(i1==0 || i2==0){
            throw  new RuntimeException("点赞失败!");
        }
        return comment_id;
    }
    /**
     * 删除点赞的信息(is_del = 1)
     * 更新留言赞的数量-1
     * @param comment_id 留言编号
     * @param userid 用户编号
     * @return 0:失败,1:成功
     */
    public Integer cancelFavorite(Integer comment_id, Integer userid) {
        Integer i1 = courseCommentDao.updateFavoriteStatus(1,comment_id, userid);
        Integer i2 = courseCommentDao.updateLikeCount(-1,comment_id);
        if(i1==0 || i2==0){
            throw  new RuntimeException("取消赞失败!");
        }
        return i2;
    }
}
  • lagou-edu-web
public interface CommentService {
    /**
     * 点赞
     * @param comment_id 留言编号
     * @param userid 用户编号
     * @return 0:保存失败,1:保存成功
     */
    Integer saveFavorite(Integer comment_id,Integer userid);
    /**
     * 取消赞
     * @param comment_id 留言编号
     * @param userid 用户编号
     * @return 0:保存失败,1:保存成功
     */
    Integer cancelFavorite(Integer comment_id,Integer userid);
}
@RestController
@RequestMapping("course")
public class CommentController {
    @Reference // 远程消费
    private CommentService commentService;
    // 点赞
 @GetMapping("comment/saveFavorite/{commentid}/{userid}")
    public Integer saveFavorite(@PathVariable("commentid") Integer commentid,
                                @PathVariable("userid") Integer userid){
        Integer integer = commentService.saveFavorite(commentid, userid);
        return integer;
    }
    // 取消赞
   @GetMapping("comment/cancelFavorite/{commentid}/{userid}")
    public Integer cancelFavorite(@PathVariable("commentid") Integer commentid,
                                  @PathVariable("userid") Integer userid){
        Integer integer = commentService.cancelFavorite(commentid, userid);
        return integer;
    }
}