Distributed architecture project - backend

Phase 8 module 1

Build lagoon education PC station with distributed architecture

1. Project architecture

1.1 project introduction

Pull hook education PC station is a website for students to watch technical videos

After registering and logging in with their mobile phone number, students can choose courses suitable for themselves and watch course videos; There are free courses and vip exclusive courses

1.2 page prototype display

visit: http://edufront.lagou.com/

User name: 15510792995 password: 111111

1.3 technical selection

1.3.1 front end technology selection

Vue.js: a set of progressive JavaScript frameworks for building user interfaces

Element UI Library: element UI is a Vue.js based background component library produced by the front end, which is convenient for programmers to quickly layout and build pages

Node.js: simply put, node.js is the JavaScript running environment running on the server side

axios: the encapsulation of ajax is simply that ajax technology realizes the refresh of local data, and axios realizes the encapsulation of ajax

1.3.2 back end technology selection

Web layer: receive requests and jump views with spring MVC

Service layer: IOC, AOP, and transaction management with spring

dao layer: database interaction with mybatis

EasyCode plug-in: a plug-in for IDEA to quickly generate entity classes

Zookeeper: service registration and service discovery

Dubbo: distributed framework, remote RPC call

Redis: in memory database, cache

Lombok: eliminate redundant get and set in entity classes

SpringSocial: SpringSocial (Spring social), which is simply understood as dealing with third-party applications, is used for wechat login

1.4 project development environment

development tool

Back end: IDEA 2019

Front end: VS code

Database client tool: SQLYog

development environment

​ JDK 11

​ Maven 3.6.3

​ MySQL 5.7

​ Zookeeper 3.6.0

​ Dubbo 2.5.7

​ Redis 5.0.4

2. Develop back-end service interface

We adopt the development mode of front end and back end separation. We first develop the back-end service interface, test it successfully, then develop the front-end vue interface, and finally conduct the front-end and back-end joint commissioning, and the project goes online

2.1 project structure and naming

Single architecture:

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (IMG tuqjnldm-1633605894193) (E: \ markdown \ hook notes \ single architecture)]

Distributed architecture:

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-m77J38fD-1633605894197)(E:\MarkDown \ hook notes \ distributed architecture)]

For the back-end project architecture, we adopt dubbo's producer and consumer theory to create two projects: service provider and service consumer, which are built through maven aggregation project. The modules are divided as follows:

Service provision

Lagou edu parent: pom aggregates parent projects and unifies dependency settings

Lagou edu entity: jar project, encapsulating entity classes

Lagou edu Dao: jar project, which encapsulates the part dealing with the database

Lagou edu service: a web project that exposes the interface and implementation of a service

Service consumption

Lagou edu web: web Engineering, which receives requests from front-end engineering, remotely invokes services and consumes

2.1.2 URL naming

Query: http://localhost:8002/course/getList - start with get

preservation: http://localhost:8002/course/saveXx - start with save

to update: http://localhost:8002/course/updateXx - start with update

2.1.3 interface response format
/**
Data transmission object
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ResponseDTO<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    private int state; // Operation status
    private String message; // State description
    private T content; // Response content
}
2.1.4 pom.xml
<properties>
    <spring.version>5.0.6.RELEASE</spring.version>
</properties>
<dependencies>
    <!-- Spring -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
        <scope>test</scope>
    </dependency>
    
    <!-- Mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.2.8</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.2</version>
    </dependency>
    
    <!-- Connection pool -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.0.9</version>
    </dependency>
    
    <!-- database -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.32</version>
    </dependency>
    
    <!--dubbo -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.5.7</version>
    </dependency>
    
    <!--zookeeper -->
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.4.6</version>
    </dependency>
    
    <!--zookeeper client -->
    <dependency>
        <groupId>com.github.sgroschupf</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.1</version>
    </dependency>
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.11.0.GA</version>
    </dependency>
    
    <!-- fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
    </dependency>
    
    <!-- junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    
    <!--spring operation redis Tool class for-->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>2.3.2.RELEASE</version>
    </dependency>
    
    <!--redis client-->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.1.0</version>
    </dependency>
    
    <!--json Parsing tool-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.8</version>
    </dependency>
</dependencies>
2.1.5 initializing the database

Database design document V1.0.pdf

edu.sql

2.2 user module

There is no arbitrary technical content in the preparation of entity classes, and it also wastes time. The legendary "old cow lives"

Using a plug-in, you can quickly generate entity, dao, service, mapper and other files

There are many solutions to generate "old cow live" Code: the more common one in enterprises is "reverse engineering of mybatis (self-study)"

2.2.1 user login / registration
Function nameUser registration / login
Function descriptionThe user enters the mobile phone number and password, clicks login, and calls the back-end interface to start login
If the phone number is not registered, it will be automatically registered and logged in
Functional interface/user/login
remarksnothing
lagou-edu-entity

lombok pepper, using annotations to replace the original redundant get and set, null construction and all parameter construction

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>
@Data //Both get and set are generated
@AllArgsConstructor //Construction method of generating full parameters
@NoArgsConstructor //Generate empty construction method
@ToString // Generate toString method
public class User implements Serializable {
    private static final long serialVersionUID = -89788707895046947L;
    /**
	* User id
	*/
    private Integer id;
}
lagou-edu-dao

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- Background log output: for developers-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
</configuration>

spring-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       	http://www.springframework.org/schema/beans
       	http://www.springframework.org/schema/beans/spring-beans.xsd
       	http://www.springframework.org/schema/tx
       	http://www.springframework.org/schema/tx/spring-tx.xsd
       	http://www.springframework.org/schema/context
      	http://www.springframework.org/schema/context/spring-context.xsd">

    <!--1.Scan package-->
    <context:component-scan base-package="mapper"/>
    <!--2.Data connection pool-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="jdbc:mysql://192.168.44.128:3306/edu?
                                    serverTimezone=GMT"/>
        <property name="username" value="root"/>
        <property name="password" value="123123"/>
        <property name="maxActive" value="10"/>
        <property name="minIdle" value="5"/>
    </bean>
    <!--3.sqlsessionFactory-->
    <bean id="sqlSessionFactory"
          class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis/mybatisconfig.xml"/>
    </bean>
    <!--4.Transaction manager-->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--5.Open transaction-->
    <tx:annotation-driven/>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="mapper"/>
    </bean>
</beans>

userDao.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="mapper.UserDao">
    <resultMap type="com.lagou.entity.User" id="UserMap">
        <result property="id" column="id" jdbcType="INTEGER"/>
        <result property="name" column="name" jdbcType="VARCHAR"/>
        <result property="portrait" column="portrait" jdbcType="VARCHAR"/>
        <result property="phone" column="phone" jdbcType="VARCHAR"/>
        <result property="password" column="password" jdbcType="VARCHAR"/>
        <result property="regIp" column="reg_ip" jdbcType="VARCHAR"/>
        <result property="accountNonExpired" column="account_non_expired"
                jdbcType="OTHER"/>
        <result property="credentialsNonExpired"
                column="credentials_non_expired" jdbcType="OTHER"/>
        <result property="accountNonLocked" column="account_non_locked"
                jdbcType="OTHER"/>
        <result property="status" column="status" jdbcType="VARCHAR"/>
        <result property="isDel" column="is_del" jdbcType="OTHER"/>
        <result property="createTime" column="create_time"
                jdbcType="TIMESTAMP"/>
        <result property="updateTime" column="update_time"
                jdbcType="TIMESTAMP"/>
    </resultMap>
    
    <!--User login-->
    <select id="login" resultMap="UserMap">
        select * from user where phone = #{phone} and password = #{password}
    </select>
    
    <!--Check whether the mobile phone number has been registered-->
    <select id="checkPhone" resultType="integer">
        select count(*) from user where phone = #{phone}
    </select>
    
    <!--register-->
    <insert id="register">
        insert  into `user` (`name`,phone,password,create_time,update_time) values (#{phone},#{phone},#{password},sysdate(),sysdate())
    </insert>
    
</mapper>

userDao

@Service
public interface UserDao {
    /**
	* @param phone cell-phone number
	* @param password password
	* @return User object
	*/
    User login(@Param("phone") String phone, @Param("password") String password);
    
    /**
     * Check whether the mobile phone number has been registered
     * @param phone cell-phone number
     * @return 0: Unregistered, 1: registered
     */
    Integer checkPhone(String phone);
    
    /**
     * register
     * @param phone cell-phone number
     * @param password password
     * @return Number of rows affected
     */
    Integer register(@Param("phone") String phone, @Param("password") String password);
}

Test class

// Test class
@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("110", "123");
        System.out.println("user = " + user);
    }
    
    @Test
    public void checkPhone(){
        Integer i = userDao.checkPhone("1101");
        System.out.println("i = " + i); //0: not registered, 1: registered
    }
}
lagou-edu-service

spring-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="
       	http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!--1.Service provider in zookeeper Alias in-->
    <dubbo:application name="lagou-edu-service"/>
    <!--2.Address of the registry-->
    <dubbo:registry address="zookeeper://192.168.44.129:2181"/>
    <!--3.Scan classes (what classes under the package are used as service provider classes)-->
    <dubbo:annotation package="com.lagou"/>

    <dubbo:provider timeout="60000"/>

    <bean id="redisTemplate"
          class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="connectionFactory"></property>
    </bean>
    <bean id="connectionFactory"
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="192.168.44.129"></property>
        <property name="port" value="6379"/>
    </bean>
</beans>

UserService/USerServiceImpl

/**
 * User table service interface
 *
 * @author makejava
 * @since 2021-10-03 16:12:28
 */
public interface UserService {

    /**
     * User login
     * @param phone cell-phone number
     * @param password password
     * @return User object
     */
    User login(String phone, String password);
    
    /**
     * Check whether the mobile phone number has been registered
     * @param phone cell-phone number
     * @return 0: Unregistered, 1: registered
     */
    Integer checkPhone(String phone);
    
    /**
     * register
     * @param phone cell-phone number
     * @param password password
     * @return Number of rows affected
     */
    Integer register(String phone, String password);
}
/**
 * User table service implementation class
 *
 * @author makejava
 * @since 2021-10-03 16:12:28
 */
@Service    // Exposure service: let consumers find me
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public User login(String phone, String password) {
        return userDao.login(phone,password);
    }
    
    @Override
    public Integer checkPhone(String phone) {
        return userDao.checkPhone(phone);
    }
    
    @Override
    public Integer register(String phone, String password) {
        return userDao.register(phone,password);
    }
}

Test class

// Test class
@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);
    }
    
    @Test
    public void checkPhone(){
        Integer i = userService.checkPhone("110");
        System.out.println("i = " + i); //0: not registered, 1: registered
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="
         	http://xmlns.jcp.org/xml/ns/javaee
         	http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring/spring-*.xml</param-value>
    </context-param>
</web-app>

tomcat plug-in

<packaging>war</packaging>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <configuration>
                <port>8001</port>
                <path>/</path>
            </configuration>
            <executions>
                <execution>
                    <!-- After packaging,Running services -->
                    <phase>package</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
lagou-edu-web

spring-consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
       	http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!--json converter-->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="supportedMediaTypes" value="application/json"/>
                <property name="features">
                    <array>
                        <value>WriteMapNullValue</value>
                        <value>WriteDateUseDateFormat</value>
                    </array>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <!--1.Service provider in zookeeper Alias in-->
    <dubbo:application name="lagou-edu-web"/>
    <!--2.Address of the registry-->
    <dubbo:registry address="zookeeper://192.168.44.129:2181"/>
    <!--3.Scan class (what kind of class under the package is used as the consumer class)-->
    <dubbo:annotation package="com.lagou"/>
</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">
    <!-- solve post Garbled code -->
    <filter>
        <filter-name>charset</filter-name>
        <filterclass>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>charset</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <!--Cross domain configuration-->
    <filter>
        <filter-name>corsFitler</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>corsFitler</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servletclass>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring-consumer.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

tomcat plug-in

<packaging>war</packaging>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <configuration>
                <port>8002</port>
                <path>/</path>
            </configuration>
            <executions>
                <execution>
                    <!-- After packaging,Running services -->
                    <phase>package</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

UserService-interface

/**
 * @auther wei
 * @date 2021/10/3 17:46
 * @description
 */
public interface UserService {

    /**
     * User login
     * @param phone cell-phone number
     * @param password password
     * @return User object
     */
    User login(String phone, String password);

    /**
     * Check whether the mobile phone number has been registered
     * @param phone cell-phone number
     * @return 0: Unregistered, 1: registered
     */
    Integer checkPhone(String phone);

    /**
     * register
     * @param phone cell-phone number
     * @param password password
     * @return Number of rows affected
     */
    Integer register(String phone, String password);
}

UserController

/**
 * @auther wei
 * @date 2021/10/3 17:47
 * @description
 */
@RestController
@RequestMapping("user")
public class UserController {

    @Reference  // Remote injection (consumption)
    private UserService userService;

    @GetMapping("login")
    public UserDTO login(String phone, String password){
        UserDTO dto = new UserDTO();
        User user = null;
        System.out.println("phone = " + phone);
        System.out.println("password = " + password);

        // Check whether the mobile phone number is registered
        Integer i = userService.checkPhone(phone);
        if (i == 0){
            // Unregistered, automatically register and log in
            userService.register(phone,password);
            dto.setMessage("The mobile phone number has not been registered. The system has automatically registered for you. Please remember the password!");
            user = userService.login(phone, password);
        }else {
            user = userService.login(phone, password);
            if (user == null){
                dto.setState(300);  // 300 indicates failure
                dto.setMessage("The account and password do not match. Login failed!");
            }else {
                dto.setState(200);  // 200 indicates success
                dto.setMessage("Login succeeded!");
            }
        }
        dto.setContent(user);
        return dto;
    }

}
2.2.2 wechat quick login
Function nameUser registration / login
Function descriptionUse wechat to scan and log in to the system
Functional interface/user/wxLogin
lagou-edu-entity
lagou-edu-dao
lagou-edu-service
lagou-edu-web

2.3 course module

2.2.1 all courses

Course: Java from little white to great God (course) -- > starting point teacher: dragnet senior lecturer

Chapter I: course_section

01 what is java (course_less)

02 introduction and installation of JDK

Chapter II: Application

01 what is a data type

02 what are variables

course 1: 1 teacher

course 1: N course_section

course_section 1: N course_lesson

course_lesson1: N course_media

Function nameCourse selection
Function description1. The user is not logged in. Get all courses on the shelves in the following order:
Configure the priority display of activity information labels, and then display them according to the sequence of course display serial number;
The same serial number is displayed in reverse order according to the creation time, and the courses are not purchased.
Functional interface/course/getAllCourse
lagou-edu-entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Course implements Serializable {
    private Teacher teacher; // One course corresponds to one instructor
    private List<CourseSection> courseSections; //A course corresponds to multiple chapters
    private ActivityCourse activityCourse;// Do an activity in one class
    // ellipsis
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseSection implements Serializable {
    private List<CourseLesson> courseLessons; // A chapter corresponds to multiple sections
    // ellipsis
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseLesson implements Serializable {
    private CourseMedia courseMedia; // A lesson corresponds to a video
    // ellipsis
}
/**
 * Lesson video table (CourseMedia) entity class
 *
 * @author wei
 * @since 2021-10-04 10:29:15
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseMedia implements Serializable {
    private static final long serialVersionUID = 374655570418259374L;
    // ellipsis
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Teacher implements Serializable {
    private static final long serialVersionUID = -41718476002951108L;
    // ellipsis
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class ActivityCourse implements Serializable {
    private static final long serialVersionUID = 646866458347820977L;
}
lagou-edu-dao

CourseDao.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="mapper.CourseDao">

    <resultMap type="com.lagou.entity.Course" id="CourseMap">
        <result property="id" column="c_id" jdbcType="VARCHAR"/>
        <result property="courseName" column="course_name" jdbcType="VARCHAR"/>
        <result property="brief" column="brief" jdbcType="VARCHAR"/>
        <result property="price" column="price" jdbcType="VARCHAR"/>
        <result property="priceTag" column="price_tag" jdbcType="VARCHAR"/>
        <result property="discounts" column="discounts" jdbcType="VARCHAR"/>
        <result property="discountsTag" column="discounts_tag" jdbcType="VARCHAR"/>
        <result property="courseDescriptionMarkDown" column="course_description_mark_down" jdbcType="VARCHAR"/>
        <result property="courseDescription" column="course_description" jdbcType="VARCHAR"/>
        <result property="courseImgUrl" column="course_img_url" jdbcType="VARCHAR"/>
        <result property="isNew" column="is_new" jdbcType="INTEGER"/>
        <result property="isNewDes" column="is_new_des" jdbcType="VARCHAR"/>
        <result property="lastOperatorId" column="last_operator_id" jdbcType="INTEGER"/>
        <result property="autoOnlineTime" column="auto_online_time" jdbcType="TIMESTAMP"/>
        <result property="createTime" column="c_create_time" jdbcType="TIMESTAMP"/>
        <result property="updateTime" column="c_update_time" jdbcType="TIMESTAMP"/>
        <result property="isDel" column="c_is_del" jdbcType="INTEGER"/>
        <result property="totalDuration" column="total_duration" jdbcType="INTEGER"/>
        <result property="courseListImg" column="course_list_img" jdbcType="VARCHAR"/>
        <result property="status" column="c_status" jdbcType="INTEGER"/>
        <result property="sortNum" column="sort_num" jdbcType="INTEGER"/>
        <result property="previewFirstField" column="preview_first_field" jdbcType="VARCHAR"/>
        <result property="previewSecondField" column="preview_second_field" jdbcType="VARCHAR"/>
        <result property="sales" column="sales" jdbcType="INTEGER"/>

        <!--1:teacher-->
        <association property="teacher" javaType="com.lagou.entity.Teacher">
            <result property="id" column="t_id" jdbcType="VARCHAR"/>
            <result property="courseId" column="t_course_id" jdbcType="INTEGER"/>
            <result property="teacherName" column="teacher_name" jdbcType="VARCHAR"/>
            <result property="position" column="position" jdbcType="VARCHAR"/>
            <result property="description" column="t_description" jdbcType="VARCHAR"/>
            <result property="createTime" column="t_create_time" jdbcType="TIMESTAMP"/>
            <result property="updateTime" column="t_update_time" jdbcType="TIMESTAMP"/>
            <result property="isDel" column="t_is_del" jdbcType="INTEGER"/>
        </association>

        <!--1:activity curriculum -->
        <association property="activityCourse" javaType="com.lagou.entity.ActivityCourse">
            <result property="id" column="ac_id" jdbcType="INTEGER"/>
            <result property="courseId" column="ac_course_id" jdbcType="INTEGER"/>
            <result property="beginTime" column="begin_time" jdbcType="TIMESTAMP"/>
            <result property="endTime" column="end_time" jdbcType="TIMESTAMP"/>
            <result property="amount" column="amount" jdbcType="VARCHAR"/>
            <result property="stock" column="stock" jdbcType="INTEGER"/>
            <result property="status" column="ac_status" jdbcType="INTEGER"/>
            <result property="isDel" column="ac_is_del" jdbcType="INTEGER"/>
            <result property="remark" column="remark" jdbcType="VARCHAR"/>
            <result property="createTime" column="ac_create_time" jdbcType="TIMESTAMP"/>
            <result property="createUser" column="create_user" jdbcType="VARCHAR"/>
            <result property="updateTime" column="ac_update_time" jdbcType="TIMESTAMP"/>
            <result property="updateUser" column="update_user" jdbcType="VARCHAR"/>
        </association>

        <!--N:chapter-->
        <collection property="courseSections" ofType="com.lagou.entity.CourseSection">
            <result property="id" column="cs_id" jdbcType="VARCHAR"/>
            <result property="courseId" column="cs_course_id" jdbcType="INTEGER"/>
            <result property="sectionName" column="section_name" jdbcType="VARCHAR"/>
            <result property="description" column="cs_description" jdbcType="VARCHAR"/>
            <result property="createTime" column="cs_create_time" jdbcType="TIMESTAMP"/>
            <result property="updateTime" column="cs_update_time" jdbcType="TIMESTAMP"/>
            <result property="isDe" column="is_de" jdbcType="INTEGER"/>
            <result property="orderNum" column="cs_order_num" jdbcType="INTEGER"/>
            <result property="status" column="cs_status" jdbcType="INTEGER"/>

            <!--N:Summary-->
            <collection property="courseLessons" ofType="com.lagou.entity.CourseLesson">
                <result property="id" column="cl_id" jdbcType="VARCHAR"/>
                <result property="courseId" column="cl_course_id" jdbcType="INTEGER"/>
                <result property="sectionId" column="cl_section_id" jdbcType="INTEGER"/>
                <result property="theme" column="theme" jdbcType="VARCHAR"/>
                <result property="duration" column="cl_duration" jdbcType="INTEGER"/>
                <result property="isFree" column="is_free" jdbcType="INTEGER"/>
                <result property="createTime" column="cl_create_time" jdbcType="TIMESTAMP"/>
                <result property="updateTime" column="cl_update_time" jdbcType="TIMESTAMP"/>
                <result property="isDel" column="cl_is_del" jdbcType="INTEGER"/>
                <result property="orderNum" column="cl_order_num" jdbcType="INTEGER"/>
                <result property="status" column="cl_status" jdbcType="INTEGER"/>

                <!--1:Section video-->
                <association property="courseMedia" javaType="com.lagou.entity.CourseMedia">
                    <result property="id" column="cm_id" jdbcType="INTEGER"/>
                    <result property="courseId" column="cm_course_id" jdbcType="INTEGER"/>
                    <result property="sectionId" column="cm_section_id" jdbcType="INTEGER"/>
                    <result property="lessonId" column="lesson_id" jdbcType="INTEGER"/>
                    <result property="coverImageUrl" column="cover_image_url" jdbcType="VARCHAR"/>
                    <result property="duration" column="cm_duration" jdbcType="VARCHAR"/>
                    <result property="fileEdk" column="file_edk" jdbcType="VARCHAR"/>
                    <result property="fileSize" column="file_size" jdbcType="VARCHAR"/>
                    <result property="fileName" column="file_name" jdbcType="VARCHAR"/>
                    <result property="fileDk" column="file_dk" jdbcType="VARCHAR"/>
                    <result property="createTime" column="cm_create_time" jdbcType="TIMESTAMP"/>
                    <result property="updateTime" column="cm_update_time" jdbcType="TIMESTAMP"/>
                    <result property="isDel" column="cm_is_del" jdbcType="INTEGER"/>
                    <result property="durationNum" column="duration_num" jdbcType="INTEGER"/>
                    <result property="fileId" column="file_id" jdbcType="VARCHAR"/>
                </association>
            </collection>
        </collection>
    </resultMap>

    <!--Query all courses-->
    <select id="getAllCourse" resultMap="CourseMap">
        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,`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
        order by amount desc ,c_id , ac_create_time desc
    </select>

</mapper>

CourseDao/ TestCourse

/**
 * @auther wei
 * @date 2021/10/4 11:20
 * @description
 */
@Service
public interface CourseDao {

    /**
     * Query all course information
     * @return
     */
    List<Course> getAllCourse();
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring/spring-dao.xml" })
public class TestCourse {

    @Autowired
    private CourseDao courseDao;

    @Test
    public void getAllCourse(){
        List<Course> list = courseDao.getAllCourse();
        for (Course course : list){
//            if (course.getId().toString().equals("8")){
                String flag = course.getActivityCourse() != null ? "[Hot activity]":"";
                System.out.println("Course:"+ flag + course.getId() + "--->" + course.getCourseName());

                for (CourseSection cs : course.getCourseSections()) {
                    System.out.println("\t\t Section:" + cs.getId() + "--->" + cs.getSectionName());
                    for (CourseLesson cl : cs.getCourseLessons()) {
                        if (cl.getCourseMedia() != null) {
                            System.out.println("\t\t\t class hour:" + cl.getId() + "--->" + cl.getTheme() + ",Video:" + cl.getCourseMedia().getFileId() + ",Duration:[" + cl.getCourseMedia().getDuration() + "]");
                        }else {
                            System.out.println("\t\t\t class hour:" + cl.getId() + "--->" + cl.getTheme() + ",Video: [to be uploaded], duration: [00]:00]");
                        }
                    }
                }
//            }
        }
    }
}
lagou-edu-service

CourseService/CourseServiceImpl

public interface CourseService {

    /**
     * Query all course information
     * @return
     */
    List<Course> getAllCourse();
}
@Service
public class CourseServiceImpl implements CourseService {
    
    @Autowired
    private CourseDao courseDao; 
    
    @Override
    public List<Course> getAllCourse() {
        return courseDao.getAllCourse();
    }
}
lagou-edu-web

CourseService

public interface CourseService {

    /**
     * Query all course information
     * @return
     */
    List<Course> getAllCourse();
}

CourseController

/**
 * @auther wei
 * @date 2021/10/4 15:46
 * @description
 */
@RestController
@RequestMapping("course")
public class CourseController {

    @Reference
    private CourseService courseService;

    @GetMapping("getAllCourse")
    public List<Course> getAllCourse(){
        List<Course> list = courseService.getAllCourse();
        return list;
    }
}
2.2.2 purchased courses
Function namePurchased
Function description1. If the user is not logged in, it is empty.
2. The user logs in and invokes the service to obtain the purchased courses through the user ID
Functional interface/course/getCourseByUserId/{userid}
Agou edu entity (ibid.)
lagou-edu-dao
<!--By user id Query purchased courses-->
<select id="getCourseByUserId" resultMap="CourseMap">
    <include refid="courseInfo"/>
    where c.id in (select course_id from user_course_order where status = 20 and is_del = 0 and user_id = #{userid})
    order by amount desc ,c_id , ac_create_time desc
</select>
@Service
public interface CourseDao {

    /**
     * Query all courses purchased by a user
     * @param userId
     * @return
     */
    List<Course> getCourseByUserId(String userId);
}
lagou-edu-service

CourseService/CourseServiceImpl

public interface CourseService {

    /**
     * Query all courses purchased by a user
     * @param userId User number
     * @return
     */
    List<Course> getCourseByUserId(String userId);
}
@Service
public class CourseServiceImpl implements CourseService {

    @Autowired
    private CourseDao courseDao;

    @Override
    public List<Course> getCourseByUserId(String userId) {
        return courseDao.getCourseByUserId(userId);
    }
}
lagou-edu-web

CourseService

@Service
public interface CourseDao {

    /**
     * Query all courses purchased by a user
     * @param userId User number
     * @return
     */
    List<Course> getCourseByUserId(String userId);
}

CourseController

@RestController
@RequestMapping("course")
public class CourseController {

    @Reference
    private CourseService courseService;

    @GetMapping("getCourseByUserId/{userid}")
    public List<Course> getCourseByUserId(@PathVariable("userid") String userid){
        List<Course> list = courseService.getCourseByUserId(userid);
        return list;
    }
}
2.2.3 course details
Function nameCourse Details
Function description1. If the user is not logged in,
The "buy now" button is displayed in the details of the course obtained through the course ID.
Click the buy enough button to display the login. At the same time, the course directory, course information and teacher information will be displayed.
Note that the course information is the information in the course_description field.
2. After the user logs in, we get the course information through the course Id,
The order service will be called through the user ID and course ID to obtain the order to judge whether the user purchases,
If it is enough to buy, it displays "learn now", otherwise it displays "enough to buy now",
At the same time, the course catalogue, course information and teacher information will be displayed.
Note that the course information is the information in the course_description field.
Functional interface/course/getCourseById/{courseid}
Lagou edu entity (ibid.)
lagou-edu-dao
<!--According to the course ID Get course details-->
<select id="getCourseById" resultMap="CourseMap">
    <include refid="courseInfo"/>
    where c.id = #{courseid}
</select>

CourseDao

@Service
public interface CourseDao {

    /**
     * Query the details of a course
     * @param courseid Course number
     * @return
     */
    Course getCourseById(@Param("courseid") Integer courseid);
}

TestCourse

@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 ? "[Hot activity]":"";
        System.out.println("Course:"+ flag + course.getId() + "--->" + course.getCourseName());

        for (CourseSection cs : course.getCourseSections()) {
            System.out.println("\t\t Section:" + cs.getId() + "--->" + cs.getSectionName());
            for (CourseLesson cl : cs.getCourseLessons()) {
                if (cl.getCourseMedia() != null) {
                    System.out.println("\t\t\t class hour:" + cl.getId() + "--->" + cl.getTheme() + ",Video:" + cl.getCourseMedia().getFileId() + ",Duration:[" + cl.getCourseMedia().getDuration() + "]");
                }else {
                    System.out.println("\t\t\t class hour:" + cl.getId() + "--->" + cl.getTheme() + ",Video: [to be uploaded], duration: [00]:00]");
                }
            }
        }
    }
}
lagou-edu-service

CourseService/CourseServiceImpl

public interface CourseService {

    /**
     * Query the details of a course
     * @param courseid Course number
     * @return
     */
    Course getCourseById(Integer courseid);
}
@Service
public class CourseServiceImpl implements CourseService {

    @Autowired
    private CourseDao courseDao;

    @Override
    public Course getCourseById(Integer courseid) {
        return courseDao.getCourseById(courseid);
    }
}
lagou-edu-web

CourseService

public interface CourseService {
    
    /**
     * Query the details of a course
     * @param courseid Course number
     * @return
     */
    Course getCourseById(Integer courseid);
}

CourseController

@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 course broadcasting
Function nameCourse play
Function descriptionThe front end calls the interface through the class ID
1 get the fileId of the course, and then call the interface through the fileId
2. Get the playAuth for video playback. The front end will call Ali's player through playAuth, and Ali will call back our interface
3. We will use Alibaba's callback to determine whether it is a legitimate user and whether the user purchases the course, so as to prevent our playback link from being played even after it is stolen, and ensure the security of the copyright of our course.
Functional interface1. Get media information through class ID / front/course/media/getByLessonId
2. Get alikey / front / course / media / alikey
3. Get Ali play key (callback for ALI) / front/course/media/alikey

2.4 order module

2.4.1 purchase / order generation
Function nameplace an order
Function descriptionThe user selects the course, clicks buy now, calls the back-end interface, and starts to create the commodity order.
Necessary data need to be verified: whether the user logs in,
The request of the interface, whether the course exists and whether the course is on the shelf,
Whether the user has successfully purchased the course before,
If the verification fails, the corresponding copy will be prompted.
Check whether the user has valid unsuccessful orders,
If yes, the corresponding order number will be returned directly,
If no new course order is created, the new order number is returned.
Functional interface/order/saveOrder/{userid}/{courseid}/{acid}/{stype}
lagou-edu-dao
<?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="mapper.OrderDao">

    <!--Generate order-->
    <insert id="saveOrder">
        insert  into `user_course_order`
        (`order_no`,`user_id`,`course_id`,`activity_course_id`,`source_type`,`status`,`create_time`,`update_time`,`is_del`)
        values
        (#{orderNo},#{user_id},#{course_id},#{activity_course_id},#{source_type},0,sysdate(),sysdate(),0)
    </insert>

</mapper>

OrderDao

@Service
public interface OrderDao {

    /**
     * Generate order
     * @param orderNo Order No
     * @param user_id User number
     * @param course_id Course number
     * @param activity_course_id Activity course number
     * @param source_type Order source type
     */
    void saveOrder(@Param("orderNo") String orderNo,@Param("user_id") String user_id,@Param("course_id") String course_id,@Param("activity_course_id") String activity_course_id,@Param("source_type") String source_type);
}
lagou-edu-service

OrderService/OrderServiceImpl

public interface OrderService {

    /**
     * Generate order
     * @param orderNo Order No
     * @param user_id User number
     * @param course_id Course number
     * @param activity_course_id Activity course number
     * @param source_type Order 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;
    
    @Override
    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);
    }
}

TestOrder

@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 means there are no activities in this course
        String source_type = "1";
        orderService.saveOrder(orderNo,user_id,course_id,activity_course_id,source_type);
    }

}
lagou-edu-web

OrderService

public interface OrderService {

    /**
     * Generate order
     * @param orderNo Order No
     * @param user_id User number
     * @param course_id Course number
     * @param activity_course_id Activity course number
     * @param source_type Order source type
     */
    void saveOrder(String orderNo, String user_id, String course_id, String activity_course_id, String source_type);
}

OrderController

@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.4.2 order operation
Function nameplace an order
Function description1. Modify order status.
2. Delete order.
3. Query all orders of logged in users.
Functional interface/order/updateOrder/{orderNo}/{status}

/order/deleteOrder/{orderNo}

/order/getOrdersByUserId/{userid}
lagou-edu-dao
<?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="mapper.OrderDao">

    <resultMap type="com.lagou.entity.UserCourseOrder" id="orderMap">
        <result property="id" column="id" jdbcType="INTEGER"/>
        <result property="orderNo" column="order_no" jdbcType="VARCHAR"/>
        <result property="userId" column="user_id" jdbcType="VARCHAR"/>
        <result property="courseId" column="course_id" jdbcType="VARCHAR"/>
        <result property="activityCourseId" column="activity_course_id" jdbcType="INTEGER"/>
        <result property="sourceType" column="source_type" jdbcType="VARCHAR"/>
        <result property="status" column="status" jdbcType="VARCHAR"/>
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
        <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
        <result property="isDel" column="is_del" jdbcType="VARCHAR"/>
    </resultMap>
    
    <!--Modify order status-->
    <update id="updateOrder">
        update user_course_order set status = #{status} where order_no = #{orderNo} and is_del = 0
    </update>

    <!--Delete order-->
    <update id="deleteOrder">
        update user_course_order set is_del = 1 where order_no = #{orderNo}
    </update>
    
    <!--Query all orders of login users-->
    <select id="getOrdersByUserId" resultMap="orderMap">
        select * from user_course_order where is_del = 0 and user_id = #{userId}
    </select>

</mapper>

OrderDao

@Service
public interface OrderDao {

    /**
     * Update order status
     * @param orderNo Order No
     * @param status Order status 0 created 10 unpaid 20 paid 30 cancelled 40 expired
     * @return Number of rows affected
     */
    Integer updateOrder(@Param("orderNo") String orderNo, @Param("status") int status);

    /**
     * Delete order
     * @param orderNo Order No
     * @return Number of rows affected
     */
    Integer deleteOrder(@Param("orderNo") String orderNo);

    /**
     * Query all orders of login users
     * @param userId User number
     * @return All orders
     */
    List<UserCourseOrder> getOrdersByUserId(@Param("userId") String userId);
}

lagou-edu-service

OrderService/OrderServiceImpl

public interface OrderService {

    /**
     * Update order status
     * @param orderNo Order No
     * @param status Order status 0 created 10 unpaid 20 paid 30 cancelled 40 expired
     * @return Number of rows affected
     */
    Integer updateOrder(String orderNo, int status);

    /**
     * Delete order
     * @param orderNo Order No
     * @return Number of rows affected
     */
    Integer deleteOrder(String orderNo);

    /**
     * Query all orders of login users
     * @param userId User number
     * @return All orders
     */
    List<UserCourseOrder> getOrdersByUserId(String userId);
}
@Service // Exposure services
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;

    @Override
    public Integer updateOrder(String orderNo, int status) {
        return orderDao.updateOrder(orderNo,status);
    }

    @Override
    public Integer deleteOrder(String orderNo) {
        return orderDao.deleteOrder(orderNo);
    }

    @Override
    public List<UserCourseOrder> getOrdersByUserId(String userId) {
        return orderDao.getOrdersByUserId(userId);
    }
}
lagou-edu-web

OrderService

public interface OrderService {

    /**
     * Update order status
     * @param orderNo Order No
     * @param status Order status 0 created 10 unpaid 20 paid 30 cancelled 40 expired
     * @return Number of rows affected
     */
    Integer updateOrder(String orderNo, int status);

    /**
     * Delete order
     * @param orderNo Order No
     * @return Number of rows affected
     */
    Integer deleteOrder(String orderNo);

    /**
     * Query all orders of login users
     * @param userId User number
     * @return All orders
     */
    List<UserCourseOrder> getOrdersByUserId(String userId);
}

OrderController

@RestController
@RequestMapping("order")
public class OrderController {

    @Reference
    private OrderService orderService;

    @GetMapping("updateOrder/{orderNo}/{status}")
    public Integer saveOrder(@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<UserCourseOrder> getOrdersByUserId(@PathVariable("userid") String userId){
        List<UserCourseOrder> list = orderService.getOrdersByUserId(userId);
        return list;
    }

}

2.5 message module

2.5.1 save message
Function nameSave course message
Function description1. Neither course Id nor comment content can be empty
2. When saving the message, you need to save the user's ID
So as to judge whether the message is written by a user when viewing the message.
Functional interface/course/comment/saveCourseComment
lagou-edu-entity

CourseComment

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseComment implements Serializable {
    private static final long serialVersionUID = -16176381063806716L;
}
lagou-edu-dao

CourseCommentDao

<?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="mapper.CourseCommentDao">

    <resultMap type="com.lagou.entity.CourseComment" id="commentMap">
        <result property="id" column="id" jdbcType="VARCHAR"/>
        <result property="courseId" column="course_id" jdbcType="INTEGER"/>
        <result property="sectionId" column="section_id" jdbcType="INTEGER"/>
        <result property="lessonId" column="lesson_id" jdbcType="INTEGER"/>
        <result property="userId" column="user_id" jdbcType="INTEGER"/>
        <result property="userName" column="user_name" jdbcType="VARCHAR"/>
        <result property="parentId" column="parent_id" jdbcType="INTEGER"/>
        <result property="isTop" column="is_top" jdbcType="INTEGER"/>
        <result property="comment" column="comment" jdbcType="VARCHAR"/>
        <result property="likeCount" column="like_count" jdbcType="INTEGER"/>
        <result property="isReply" column="is_reply" jdbcType="INTEGER"/>
        <result property="type" column="type" jdbcType="INTEGER"/>
        <result property="status" column="status" jdbcType="INTEGER"/>
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
        <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
        <result property="isDel" column="is_del" jdbcType="INTEGER"/>
        <result property="lastOperator" column="last_operator" jdbcType="INTEGER"/>
        <result property="isNotify" column="is_notify" jdbcType="INTEGER"/>
        <result property="markBelong" column="mark_belong" jdbcType="INTEGER"/>
        <result property="replied" column="replied" jdbcType="INTEGER"/>
    </resultMap>

    <!--Save message-->
    <insert id="saveComment">
        insert  into `course_comment`(`course_id`,`section_id`,`lesson_id`,`user_id`,`user_name`,`parent_id`,`is_top`,`comment`,`like_count`,`is_reply`,`type`,`status`,`create_time`,`update_time`,`is_del`,`last_operator`,`is_notify`,`mark_belong`,`replied`) values
        (#{courseId},#{sectionId},#{lessonId},#{userId},#{userName},#{parentId},0,#{comment},0,0,#{type},0,sysdate(),sysdate(),0,#{lastOperator},1,0,0)
    </insert>

</mapper>
@Service
public interface CourseCommentDao {

    /**
     * Save message
     * @param comment Message content object
     * @return Number of rows affected
     */
    Integer saveComment(CourseComment comment);
}
lagou-edu-service

CommentService/ CommentServiceImpl

public interface CommentService {

    /**
     * Save message
     * @param comment Message content object
     * @return Number of rows affected
     */
    Integer saveComment(CourseComment comment);
}
@Service    // Exposure services
public class CommentServiceImpl implements CommentService {
    
    @Autowired
    private CourseCommentDao courseCommentDao;
    
    @Override
    public Integer saveComment(CourseComment comment) {
        return courseCommentDao.saveComment(comment);
    }
}

TestComment

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring/spring-*.xml" })
public class TestComment {

    @Autowired
    private CommentService commentService;

    @Test
    public void save(){
        CourseComment comment = new CourseComment();
        comment.setCourseId(7); // Course number
        comment.setSectionId(8);    // Chapter number
        comment.setLessonId(10);     // Section number
        comment.setUserId(100030011);   // User number
        comment.setUserName("Tom");  // User nickname
        comment.setParentId(0); // No parent id
        comment.setComment("very good!");  // Message content
        comment.setType(0); // 0 user message
        comment.setLastOperator(100030011); // User number of the last operation
        Integer i = commentService.saveComment(comment);
        System.out.println(i);
    }
}
lagou-edu-web

CommentService

public interface CommentService {

    /**
     * Save message
     * @param comment Message content object
     * @return Number of rows affected
     */
    Integer saveComment(CourseComment comment);
}

CommentController

@RestController
@RequestMapping("course")
public class CommentController {

    @Reference // Remote consumption
    private CommentService commentService;

    @GetMapping("comment/saveCourseComment")
    public Object saveCourseComment(){
        CourseComment comment = new CourseComment();
        comment.setCourseId(7); // Course number
        comment.setSectionId(8);    // Chapter number
        comment.setLessonId(10);     // Section number
        comment.setUserId(100030011);   // User number
        comment.setUserName("Tom");  // User nickname
        comment.setParentId(0); // No parent id
        comment.setComment("old tie 666!");  // Message content
        comment.setType(0); // 0 user message
        comment.setLastOperator(100030011); // User number of the last operation
        Integer i = commentService.saveComment(comment);
        System.out.println(i);
        return null;
    }
}
2.5.2 message list

All messages for a course

Function nameGet course messages
Function description1. Get message information by pagination through course ID, page number and user ID
The default number of entries per page is 20.
When the user Id is not empty, the front end identifies the message that the user likes.
2. The important contents returned in the message include:
Comment content, whether I like it, user nickname, whether I like it or not, identification and number of likes.
3. Messages are displayed in reverse order according to the number of likes and creation time.
Functional interface/course/comment/getCourseCommentList/{courseid}/{pageIndex}/{pageSize}
Lagou edu entity (ibid.)
lagou-edu-dao

CourseCommentDao

<!--Query message list-->
<select id="getCommentByCourseId" resultMap="commentMap">
    select * from course_comment
    where is_del = 0
    and course_id = #{courseId}
    order by is_top desc , like_count desc , create_time desc
    limit #{offset},#{pageSize}
</select>
@Service
public interface CourseCommentDao {

    /**
     * All messages of a course (pagination)
     * @param courseId Course number
     * @param offset Data offset
     * @param pageSize Entries per page
     * @return Message collection
     */
    List<CourseComment> getCommentByCourseId(@Param("courseId") Integer courseId,@Param("offset") Integer offset,@Param("pageSize") Integer pageSize);
}
lagou-edu-service

CommentService/ CommentServiceImpl

public interface CommentService {

    /**
     * All messages of a course (pagination)
     * @param courseId Course number
     * @param offset Data offset
     * @param pageSize Entries per page
     * @return Message collection
     */
    List<CourseComment> getCommentByCourseId(Integer courseId,Integer offset, Integer pageSize);
}
@Service    // Exposure services
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CourseCommentDao courseCommentDao;

    @Override
    public List<CourseComment> getCommentByCourseId(Integer courseId, Integer offset, Integer pageSize) {
        return courseCommentDao.getCommentByCourseId(courseId,offset,pageSize);
    }
}

TestComment

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring/spring-*.xml" })
public class TestComment {

    @Autowired
    private CommentService commentService;

    @Test
    public void getCommentByCourseId(){
        int pageSize = 20;
        int pageIndex = 3;  // Page number

        List<CourseComment> list = commentService.getCommentByCourseId(1, (pageIndex-1)*pageSize, 20);
        for (int i = 0; i < list.size(); i++) {
            CourseComment comment = list.get(i);
            System.out.println((i+1)+ ",Building[" + comment.getUserName() + "]Say:" + comment.getComment());
        }
    }
}
lagou-edu-web

CommentService

public interface CommentService {

    /**
     * All messages of a course (pagination)
     * @param courseId Course number
     * @param offset Data offset
     * @param pageSize Entries per page
     * @return Message collection
     */
    List<CourseComment> getCommentByCourseId(Integer courseId, Integer offset, Integer pageSize);
}

CommentController

@RestController
@RequestMapping("course")
public class CommentController {

    @Reference // Remote consumption
    private CommentService commentService;

    @GetMapping("comment/getCourseCommentList/{courseId}/{pageIndex}/{pageSize}")
    public List<CourseComment> getCommentByCourseId(@PathVariable("courseId") Integer courseId,@PathVariable("pageIndex") Integer pageIndex,@PathVariable("pageSize") Integer pageSize){
        List<CourseComment> list = commentService.getCommentByCourseId(courseId, pageIndex, pageSize);
        return list;
    }
    
}
2.5.3 comment like / cancel like
Function namegive the thumbs-up
Function descriptiongive the thumbs-up
1. First check whether there is likes in the message according to the user ID and message ID
If it exists, update the deletion status, otherwise save the likes information.
2. After saving the likes, you need to update the number of likes in the corresponding message.

Cancel like
1. Get the user's likes information through the user ID and message ID
2. Then delete the record logically, and update the number of likes of the corresponding record
Functional interface/course/comment/saveFavorite/{commentid}/{userid} / / like

/course/comment/cancelFavorite/{commentid}/{userid} / / cancel like

Lagou edu entity (none)

lagou-edu-dao

CourseCommentDao

<!--Check whether a user likes a message-->
<select id="existsFavorite" resultType="Integer">
    select count(*) from course_comment_favorite_record where comment_id = #{cid} and user_id = #{uid}
</select>

<!--No likes. Save the likes information-->
<insert id="saveCommentFavorite">
    insert  into `course_comment_favorite_record`(`user_id`,`comment_id`,`is_del`,`create_time`,`update_time`) values
    (#{uid},#{cid},0,sysdate(),sysdate());
</insert>

<!--Modify the like status. 0 means like and 1 means cancel like-->
<update id="updateFavoriteStatus">
    update course_comment_favorite_record set is_del = #{status} where comment_id = #{cid} and user_id = #{uid}
</update>

<!--After you click like, the number of likes+1,Number of likes after canceling likes-1-->
<update id="updateLikeCount">
    update course_comment set like_count = like_count+#{x} where id = #{commentId}
</update>
@Service
public interface CourseCommentDao {

    /**
     * Check whether a user likes a message
     * @param commentId Message number
     * @param userId User number
     * @return 0: I didn't like it. 1: I liked it
     */
    Integer existsFavorite(@Param("cid") Integer commentId, @Param("uid") Integer userId);

    /**
     * Save likes
     * @param commentId Message number
     * @param userId User number
     * @return 0: Saving failed, 1: saving succeeded
     */
    Integer saveCommentFavorite(@Param("cid") Integer commentId, @Param("uid") Integer userId);

    /**
     * Update the status of like information (if is_del=0, it means like)
     * @param status Status, 0: like, 1: cancel like
     * @param commentId Message number
     * @param userId User number
     * @return 0: Saving failed, 1: saving succeeded
     */
    Integer updateFavoriteStatus(@Param("status") Integer status, @Param("cid") Integer commentId, @Param("uid") Integer userId);

    /**
     * Update the number of likes
     * @param x +1 The number of likes increased and the number of likes decreased for - 1
     * @param commentId Number of a message
     * @return 0: Saving failed, 1: saving succeeded
     */
    Integer updateLikeCount(@Param("x") Integer x, @Param("commentId") Integer commentId);
}
lagou-edu-service

CommentService/ CommentServiceImpl

public interface CommentService {

    /**
     * give the thumbs-up
     * @param commentId Message number
     * @param userId User number
     * @return 0: Saving failed, 1: saving succeeded
     */
    Integer saveFavorite(Integer commentId, Integer userId);

    /**
     * Cancel like information
     * @param commentId Message number
     * @param userId User number
     * @return 0: Saving failed, 1: saving succeeded
     */
    Integer cancelFavorite(Integer commentId, Integer userId);
}
@Service    // Exposure services
public class CommentServiceImpl implements CommentService {

    @Autowired
    private CourseCommentDao courseCommentDao;

    /**
     * give the thumbs-up:
     * First check whether the current user likes this message,
     * If the point is too large: modify is_del status, cancel like
     * If you don't click: save a like message
     *
     * Final: number of updated likes
     * @param commentId Message number
     * @param userId User number
     * @return Message No. commentId
     */
    @Override
    public Integer saveFavorite(Integer commentId, Integer userId) {
        Integer i = courseCommentDao.existsFavorite(commentId, userId);
        int i1 = 0;
        int i2 = 0;
        if (i == 0){
            // I didn't like it
            i1 = courseCommentDao.saveCommentFavorite(commentId,userId);
        } else {
            // give the thumbs-up
            i1 = courseCommentDao.updateFavoriteStatus(0,commentId,userId);
        }
        i2 = courseCommentDao.updateLikeCount(1,commentId);

        if (i1 == 0 || i2 == 0){
            throw new RuntimeException("Like failed!");
        }

        return commentId;
    }

    /**
     * Delete likes (is_del = 1)
     * Update the number of comment likes - 1
     * @param commentId Message number
     * @param userId User number
     * @return 0: Failed, 1: successful
     */
    @Override
    public Integer cancelFavorite(Integer commentId, Integer userId) {
        // Delete likes
        Integer i1 = courseCommentDao.updateFavoriteStatus(1, commentId, userId);
        Integer i2 = courseCommentDao.updateLikeCount(-1,commentId);

        if (i1 == 0 || i2 == 0){
            throw new RuntimeException("Failed to cancel like!");
        }
        return i2;
    }
}

TestCommnet

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring/spring-*.xml" })
public class TestComment {

    @Autowired
    private CommentService commentService;

    @Test
    public void saveFavorite(){
        Integer i = commentService.saveFavorite(1, 110);
        System.out.println("i = " + i);
    }

    @Test
    public void cancelFavorite(){
        Integer i = commentService.cancelFavorite(1,110);
        System.out.println("i = " + i);
    }
}
lagou-edu-web

CommentService

public interface CommentService {

    /**
     * give the thumbs-up
     * @param commentId Message number
     * @param userId User number
     * @return 0: Saving failed, 1: saving succeeded
     */
    Integer saveFavorite(Integer commentId, Integer userId);

    /**
     * Cancel like
     * @param commentId Message number
     * @param userId User number
     * @return 0: Saving failed, 1: saving succeeded
     */
    Integer cancelFavorite(Integer commentId, Integer userId);
}

CommentController

@RestController
@RequestMapping("course")
public class CommentController {

    @Reference // Remote consumption
    private CommentService commentService;

    @GetMapping("comment/saveFavorite/{commentid}/{userid}")
    public Integer saveFavorite(@PathVariable("commentid") Integer commentId,@PathVariable("userid") Integer userId){
        Integer i = commentService.saveFavorite(commentId, userId);
        return i;
    }

    @GetMapping("comment/cancelFavorite/{commentid}/{userid}")
    public Integer cancelFavorite(@PathVariable("commentid") Integer commentId,@PathVariable("userid") Integer userId){
        Integer i = commentService.cancelFavorite(commentId, userId);
        return i;
    }
}

Tags: Java Distribution

Posted on Thu, 07 Oct 2021 20:25:03 -0400 by steadyguy