拉勾教育后台管理系统(SSM)(课程管理模块开发)【学习笔记】

文章目录

1、项目架构

1.1、项目介绍

      拉勾教育后台管理系统,是提供给拉勾教育的相关业务人员使用的一个后台管理系统, 业务人员可以在这个后台管理系统中,对课程信息、广告信息、用户信息、 权限信息等数据进行维护
      在 web阶段,我们已经完成了拉勾教育后台管理系统中课程模块, 接下来将对拉勾教育后台管理系统进行升级改造,基于SSM框架来完成课程信息模块,广告信息模块,用户信息模块,权限信息模块

1.2、技术选型

1.2.1、前端技术选型

前端技术说明
Vue.js是一套用于构建用户界面的渐进式JavaScript框架
Element UI库element-ui 是饿了么前端出品的基于 Vue.js的 后台组件库,方便程序员进行页面快速布局和构建
node.js简单的说 Node.js 就是运行在服务端的 JavaScript 运行环境
axios对ajax的封装, 简单来说就是ajax技术实现了局部数据的刷新,axios实现了对ajax的封装,

1.2.2、后端技术选型

后端技术说明
Web层借助springmvc接收请求,进行视图跳转
Service层借助spring进行IOC、AOP、及事务管理
dao层借助mybatis进行数据库交互

1.3、项目开发环境

  • 开发工具
    • 后端: IDEA 2022.3
    • 前端: VS code
    • 数据库客户端工具: Navicat Premium
  • 开发环境
    • JDK 11
    • Maven 3.8.6
    • MySQL 5.7

2、Maven进阶使用(Maven聚合工程)

2.1、maven的依赖传递

2.1.1、什么是依赖传递

      在maven中,依赖是可以传递的,假设存在三个项目,分别是项目A,项目B以及项目C。假设C依赖B,B依赖A,那么我们可以根据maven项目依赖的特征不难推出项目C也依赖A。

在这里插入图片描述
在这里插入图片描述
      通过上面的图可以看到,我们的web项目直接依赖了spring-webmvc,而spring-webmvc依赖了sping-aop、spring-beans等。最终的结果就是在我们的web项目中间接依赖了spring-aop、spring-beans等。

  • 依赖冲突

      由于依赖传递现象的存在, spring-webmvc 依赖 spirng-beans-5.1.5,spring-aop 依赖 spring-beans-5.1.6,但是发现 spirng-beans-5.1.5 加入到了工程中,而我们希望 spring-beans-5.1.6 加入工程。这就造成了依赖冲突

在这里插入图片描述

2.1.2、如何解决依赖冲突

  • 使用maven提供的依赖调解原则
    • 第一声明者优先原则
    • 路径近者优先原则
  • 排除依赖
  • 锁定版本

2.1.3、依赖调节原则——第一声明者优先原则

      在 pom 文件中定义依赖,以先声明的依赖为准。其实就是根据坐标导入的顺序来确定最终使用哪个传递过来的依赖
在这里插入图片描述
最终:这里使用的依赖是spring-beans:5.1.6,为什么不用spring-webmvc中的5.1.5呢,原因就在于spring-beans位置在前spring-webmvc在后,所以5.1.6版本优先

2.1.4、依赖调节原则——路径近者优先原则

在这里插入图片描述
最终:使用的依赖是spring-beans是5.1.6版本的,因为这个是直接依赖的,spring-webmvc中的spring-beans是间接依赖的

2.1.5、排除依赖

可以使用exclusions标签将传递过来的依赖排除出去

在这里插入图片描述

2.1.6、版本锁定

      采用直接锁定版本的方法确定依赖jar包的版本,版本锁定后则不考虑依赖的声明顺序或依赖的路径,以锁定的版本为准添加到工程中,此方法在企业开发中经常使用。

版本锁定的使用方式:
第一步:在dependencyManagement标签中锁定依赖的版本
第二步:在dependencies标签中声明需要导入的maven坐标

  1. 在dependencyManagement标签中锁定依赖的版本
    在这里插入图片描述
  2. 在dependencies标签中声明需要导入的maven坐标
    在这里插入图片描述

也就是你不用在搞版本了,你导入的依赖都是安装dependencyManagement设置的版本处理的

2.1.7、properties标签的使用

<properties>
	<maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>5.1.5.RELEASE</spring.version>
    <springmvc.version>5.1.5.RELEASE</springmvc.version>
    <mybatis.version>3.5.1</mybatis.version>
</properties>
<!--锁定jar版本-->
<dependencyManagement>
    <dependencies>
    <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <!-- springMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springmvc.version}</version>
        </dependency>
        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</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-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</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-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

通过设置不同的框架的版本号,做到改一处就可以修改整个依赖的版本号,上面的代码只是约束了版本号,但是没有真正的导入依赖,导入依赖还得denpendecys那种方式去导入,不用加version了

2.2、maven聚合工程(分模块)

      在现实生活中,汽车厂家进行汽车生产时,由于整个生产过程非常复杂和繁琐,工作量非常大,所以厂家都会将整个汽车的部件分开生产,最终再将生产好的部件进行组装,形成一台完整的车。
在这里插入图片描述

2.2.1、分模块构建maven工程分析

      在企业项目开发中,由于项目规模大,业务复杂,参与的人员比较多,一般会通过合理的模块拆分将一个大型的项目拆分为N多个小模块,分别进行开发。而且拆分出的模块可以非常容易的被其他模块复用

常见的拆分方式有两种:
      第一种:按照业务模块进行拆分,每个模块拆分成一个maven工程,例如将一个项目分为用户模块,订单模块,购物车模块等,每个模块对应就是一个maven工程
      第二种:按照层进行拆分,例如持久层、业务层、表现层等,每个层对应就是一个maven工程

不管上面那种拆分方式,通常都会提供一个父工程,将一些公共的代码和配置提取到父工程中进行统一管理和配置。
在这里插入图片描述

2.2.2、maven工程的继承

      在Java语言中,类之间是可以继承的,通过继承,子类就可以引用父类中非private的属性和方法。同样,在maven工程之间也可以继承,子工程继承父工程后,就可以使用在父工程中引入的依赖。继承的目的是为了消除重复代码。
在这里插入图片描述

2.2.3、maven工程的聚合

      在maven工程的pom.xml文件中可以使用标签将其他maven工程聚合到一起,聚合的目的是为了进行统一操作
      例如拆分后的maven工程有多个,如果要进行打包,就需要针对每个工程分别执行打包命令,操作起来非常繁琐。这时就可以使用标签将这些工程统一聚合到maven父工中,需要打包的时候,只需要在此工程中执行一次打包命令,其下被聚合的工程就都会被打包了。
在这里插入图片描述

2.2.4、maven聚合工程_搭建拉勾教育后台管理系统

工程整体结构如下:

  1. lagou_edu_home_parent为父工程,其余工程为子工程,都继承父工程lagou_edu_home_parent
  2. lagou_edu_home_parent工程将其子工程都进行了聚合
  3. 子工程之间存在依赖关系:
    • ssm_domain依赖ssm_utils
    • ssm_dao依赖ssm_domain
    • ssm_service依赖ssm_dao
    • ssm_web依赖ssm_service

在这里插入图片描述
依赖关系建立原则:当前项目中要用到那个项目的资源,那么当前项目就依赖要用到资源的项目(直接依赖和间接依赖)

2.2.5、聚合工程创建

  1. 先创建一个maven工程lagou_edu_home_parent
  2. 然后删除掉src目录
  3. 然后创建子工程
    • 创建ssm_utils
    • 创建ssm_domain
    • 创建ssm_dao
    • 创建ssm_service
    • 创建ssm_web
      • 这里还要配置一下ssm_web中的pom中的打包方式为war,并且创建webapp和对应的webx.ml文件
  4. 然后开始配置子工程之间的依赖关系
    • ssm_domain的pom.xml中配置(ctrl+鼠标左键跳转过去就可以了)
    <dependencies>
        <dependency>
            <groupId>com.lzy</groupId>
            <artifactId>ssm_utils</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
    
    • ssm_dao的pom.xml配置
    <dependencies>
        <dependency>
            <groupId>com.lzy</groupId>
            <artifactId>ssm_domain</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
    
    • ssm_service的pom.xml配置
    <dependencies>
        <dependency>
            <groupId>com.lzy</groupId>
            <artifactId>ssm_dao</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
    
    • ssm_web的pom.xml配置
    <dependencies>
        <dependency>
            <groupId>com.lzy</groupId>
            <artifactId>ssm_service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
    
  5. 最后输入maven install
    在这里插入图片描述
  6. 最终的项目结构
    在这里插入图片描述

2.2.6、父工程进行依赖管理

<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>5.1.5.RELEASE</spring.version>
    <springmvc.version>5.1.5.RELEASE</springmvc.version>
    <mybatis.version>3.5.1</mybatis.version>
</properties>

<!--版本锁定-->
<dependencyManagement>
    <dependencies>
        <!--Mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <!--SpringMVC-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springmvc.version}</version>
        </dependency>
        <!--spring-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</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-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!--mybatis坐标-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.31</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.15</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>

    <!--spring坐标-->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.13</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
    </dependency>

    <!--mybatis整合spring坐标-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.1</version>
    </dependency>

    <!--springMVC坐标-->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>

    </dependency>

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.8</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.9.8</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.9.0</version>
    </dependency>
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>4.1.6</version>
    </dependency>

    <!--Beanutils-->
    <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.8.3</version>
    </dependency>
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>

    <!--解决跨域问题所需依赖-->
    <dependency>
        <groupId>com.thetransactioncompany</groupId>
        <artifactId>cors-filter</artifactId>
        <version>2.5</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

2.2.7、子工程ssm_dao构建

首先要创建一个实体类在ssm_domain中
在这里插入图片描述

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Account {
    private Integer id;
    private String name;
    private Double money;
}
  • 然后创建一个mapper接口和对应的mapper.xml文件
public interface AccountMapper {
    public List<Account> findAllTest();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzy.dao.AccountMapper">
    <select id="findAllTest" resultType="account">
        select * from account
    </select>
</mapper>
  • 创建applicationContext-dao.xml和jdbc.properties
<?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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--spring整合mybaits-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--domain别名-->
        <property name="typeAliasesPackage" value="com.lzy.domain"/>
        <!--开启自动驼峰命名规则-->
        <property name="configuration">
            <bean class="org.apache.ibatis.session.Configuration">
                <property name="mapUnderscoreToCamelCase" value="true"/>
            </bean>
        </property>
    </bean>

    <!--mapper映射扫描-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.lzy.dao"/>
    </bean>
</beans>
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db
jdbc.username=root
jdbc.password=xxxx

2.2.8、子工程ssm_serivce构建

  • 创建AccountServiceImpl和接口
public interface AccountService {
    public List<Account> findAllTest();
}
@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;

    @Override
    public List<Account> findAllTest() {
        return accountMapper.findAllTest();
    }
}
  • 创建applicationContext-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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置IOC相关操作:开启注解扫描-->
    <context:component-scan base-package="com.lzy.service"/>

    <!--引入dao层中的spring配置文件-->
    <import resource="classpath:applicationContext-dao.xml"/>
</beans>

2.2.9、子工程ssm_web构建

  • AccountController
@RestController
@RequestMapping("/test")
public class AccountController {
    @Autowired
    private AccountService accountService;

    @RequestMapping("/findAllTest")
    public List<Account> findAllTest(){
        return accountService.findAllTest();
    }
}
  • applicationContext-web.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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--引入application_service.xml-->
    <import resource="classpath:applicationContext-service.xml"/>
</beans>
  • spring-mvc.xml核心配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <!--组件扫描-->
    <context:component-scan base-package="com.lzy.controller"/>

    <!--mvc注解增强-->
    <mvc:annotation-driven/>

    <!--视图解析器-->
    
    <!--静态资源-->
    <mvc:default-servlet-handler/>
</beans>
  • 前端控制器、中文乱码、spring监听器、跨域
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--配置前端控制器-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--中文乱码-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <!--配置spring监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext-web.xml</param-value>
    </context-param>

    <!--配置跨域过滤器-->
    <filter>
        <filter-name>CORSFilter</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CORSFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

最后配置tomcat然后访问/test/findAllTest,说明环境没什么大问题了

在这里插入图片描述

3、拉勾教育后台管理系统研发

3.1、课程管理模块功能分析

     在本次的项目中,首先先来完成拉勾教育后台管理系统的 课程管理模块, 课程管理模块包含了多条件查询、 图片上传、 新建&修改课程、课程状态管理、课程内容展示、回显章节对应的课程信息、新建&修改章节信息、修改章节状态、 新建&修改课时信息等接口的编写

  • 实现以下功能:
    • 多条件查询
    • 图片上传
    • 新建课程信息
    • 回显课程信息
    • 修改课程信息
    • 课程状态管理
    • 课程内容展示
    • 回显章节对应的课程信息
    • 新建&修改章节信息
    • 修改章节状态
    • 新建课时信息

3.2、课程管理模块表设计

创建数据库及表
在这里插入图片描述
在这里插入图片描述
课程表
在这里插入图片描述
章节表
在这里插入图片描述
课时表
在这里插入图片描述
课程媒体
在这里插入图片描述

3.3、课程管理模块接口实现

3.3.1、多条件课程列表查询

接口地址: http://localhost:8080/ssm-web/course/findCourseByCondition

请求方式: POST

接口描述: 分页获取课程列表数据&多条件查询

请求参数:

参数名称参数说明in是否必须数据类型schema
courseNamefalsestring
statusfalseinteger(int32)

请求示例:

{
	"courseName": "Vue.js 3.0 核心源码解析",
	"status": 1
}

响应参数:

参数名称参数说明类型schema
successboolean
stateinteger(int32)integer(int32)
messagestring
contentobject

响应示例:

{
	"success": true,
	"state": 0,
	"message": "响应成功",
	"content": {课程数据}
}
3.3.1.1、实体类创建

Course

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Course {
    private int id;
    //课程名称
    private String courseName;
    //课程一句话简介
    private String brief;
    //原价
    private double price;
    //原价标签
    private String priceTag;
    //优惠价
    private double discounts;
    //优惠价标签
    private String discountsTag;
    //课程内容markdown
    private String courseDescriptionMarkDown;
    //课程描述
    private String courseDescription;
    //课程分享图片url
    private String courseImgUrl;
    //是否新品
    private int isNew;
    //广告语
    private String isNewDes;
    //最后操作者
    private int lastOperatorId;
    //自动上架时间
    private Date autoOnlineTime;
    //创建时间
    private Date createTime;
    //更新时间
    private Date updateTime;
    //是否删除
    private int isDel;
    //总时长
    private int totalDuration;
    //课程列表展示图片
    private String courseListImg;
    //课程状态,0-草稿,1-上架
    private int status;
    //课程排序
    private int sortNum;
    //课程预览第一个字段
    private String previewFirstField;
    //课程预览第二个字段
    private String previewSecondField;
}

ResponseResult

@AllArgsConstructor
@NoArgsConstructor
@Data
public class ResponseResult {
    private Boolean success;
    private Integer state;
    private String message;
    private Object content;
}

CourseVo:View Object表现层对象:主要用于表现层来接收参数的

@AllArgsConstructor
@NoArgsConstructor
@Data
public class CourseVo {
    private String courseName;
    private Integer status;
}
3.3.1.2、Dao层编写
public interface CourseMapper {
    public List<Course> findCourseByConditionin(CourseVo courseVo);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzy.dao.CourseMapper">
    <!--这里涉及到了逻辑删除,is_del != 1 -->
    <select id="findCourseByConditionin" parameterType="coursevo" resultType="course">
        select id, course_name, price, sort_num, status from course
        <where>
            <if test="courseName != null and courseName != ''">
                and course_name like concat('%', #{courseName}, '%')
            </if>
            <if test="status != null and status != ''">
                and status = #{status}
            </if>
            <if test="true">
                and is_del != 1
            </if>
        </where>
    </select>
</mapper> 
3.3.1.3、Servicec层
public interface CourseService {
    /*多条件列表查询*/
    public List<Course> findCourseByConditioin(CourseVo courseVo);
}
@Service
public class CourseServiceImpl implements CourseService {
    @Autowired
    private CourseMapper courseMapper;

    @Override
    public List<Course> findCourseByConditioin(CourseVo courseVo) {
        return courseMapper.findCourseByConditionin(courseVo);
    }
}
3.3.1.4、Web层编写
@RestController
@RequestMapping("/course")
public class CourseController {
    @Autowired
    private CourseService courseService;

    @RequestMapping("/findCourseByCondition")
    /*这里不加这个@RequestBody注解的话,就无法把前台传过来的数据进行封装*/
    public ResponseResult findCourseByCondition(@RequestBody CourseVo courseVo){
        System.out.println(courseVo);
        List<Course> courseByConditioin = courseService.findCourseByConditioin(courseVo);
        ResponseResult responseResult = new ResponseResult(true, 200, "成功", courseByConditioin);
        return responseResult;
    }
}
3.3.1.5、postman接口测试

在这里插入图片描述

3.3.2、课程图片上传

接口地址: http://localhost:8080/ssm-web/course/courseUpload

请求方式: POST

接口描述: 课程模块图片上传

请求参数:

file=1597112871741.JPG

响应参数:

参数名称参数说明类型schema
successboolean
stateinteger(int32)integer(int32)
messagestring
contentobject

响应示例:

{
    "success": true,
    "state": 200,
    "message": "响应成功",
    "content": {
        "fileName": "1597112871741.JPG",
        "filePath": "http://localhost:8080/upload/1597112871741.JPG"
    }
}
3.3.2.1、代码编写

spring-mvc.xml

<!--配置文件解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="1048576"/>
</bean>

web层

package com.lzy.service.impl;

import com.github.pagehelper.PageInfo;
import com.lzy.dao.CourseMapper;
import com.lzy.domain.Account;
import com.lzy.domain.Course;
import com.lzy.domain.CourseVo;
import com.lzy.domain.ResponseResult;
import com.lzy.service.CourseService;
import com.sun.org.apache.bcel.internal.generic.NEW;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class CourseServiceImpl implements CourseService {
    @Autowired
    private CourseMapper courseMapper;

    @Override
    public List<Course> findCourseByConditioin(CourseVo courseVo) {
        return courseMapper.findCourseByConditionin(courseVo);
    }

    @RequestMapping("/courseUpload")
    public ResponseResult fileUpload(MultipartFile file, HttpServletRequest request){
        try {
            /*判断文件是否为空*/
            if(file.isEmpty()){
                throw new RuntimeException();
            }

            /*获取项目部署路径*/
            // 这里是获得了到webapps/ssm/的路径
            String realPath = request.getServletContext().getRealPath("/");
            // 这里是获得了到webapps的路径
            String webappsPath = realPath.substring(0, realPath.indexOf("ssm"));

            /*获取原文件名*/
            String fileName = file.getOriginalFilename();

            /*新的文件名*/
            String newFileName = System.currentTimeMillis() + fileName.substring(fileName.lastIndexOf("."));

            /*存储文件*/
            String uploadPath = webappsPath + "upload\\";
            File filePath = new File(uploadPath, newFileName);

            /*如果目录不存在就创建目录*/
            if(!filePath.getParentFile().exists()){
                filePath.getParentFile().mkdirs();
                System.out.println("创建目录 = " + filePath);
            }
            file.transferTo(filePath);

            /*将文件名和文件路径返回*/
            Map<String, String> map = new HashMap<>();
            map.put("fileName", newFileName);
            map.put("filePath", "htt://localhost:8080/upload/" + newFileName);

            ResponseResult res = new ResponseResult(true, 200, "成功", map);
            return res;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}
3.3.2.2、postman测试

在这里插入图片描述

3.3.3、新建课程信息

接口地址: http://localhost:8080/ssm-web/course/saveOrUpdateCourse

请求方式: POST

接口描述: 新建课程或修改课程

请求参数:

字段说明类型是否必需备注
id课程idint添加操作不用携带, 修改操作必须携带ID
courseName课程名称String
brief课程简介String一句话介绍课程
teacherName讲师名称String
description讲师介绍String
position讲师职位String
previewFirstField课程概述1String第一段描述 例如: 课程共15讲
previewSecondField课程概述2String第二段描述 例如: 每周五更新
discounts售卖价格double课程的售卖价格
price商品原价double课程的原销售价
discountsTag活动标签String例如: 立即抢购
courseImgUrl课程图片urlString
courseListImg封面图urlString
sortNum课程排序int
course_description_mark_down课程描述String
sales销量int

请求示例

//新增
{
    "courseName":"大数据云计算",
    "brief":"海量大数据课程",
    "teacherName":"维尼",
    "description":"多年企业实战经验",
    "position":"高级讲师",
    "previewFirstField":"共10讲",
    "previewSecondField":"每周四更新",
    "discounts":66.6,
    "price":88,
    "discountsTag":"先到先得",
    "courseImgUrl":"http://localhost:8080/upload/1596520226925.jpg",
    "courseListImg":"http://localhost:8080/upload/1596520226925.jpg",
    "sortNum":1,
    "courseDescriptionMarkDown":"介绍当前流行大数据技术,数据技术原理,并介绍其思想,介绍大数据技术培训课程,概要介绍。",
    "sales":100
}

//修改
{
	"id":15,
    "courseName":"全栈工程师",
    "brief":"掌握多种技能,胜任前端与后端",
    "teacherName":"药水哥",
    "description":"多年企业实战经验",
    "position":"高级讲师",
    "previewFirstField":"共10讲",
    "previewSecondField":"每周四更新",
    "discounts":66.6,
    "price":88,
    "discountsTag":"先到先得",
    "courseImgUrl":"http://localhost:8080/upload/1596520226925.jpg",
    "courseListImg":"http://localhost:8080/upload/1596520226925.jpg",
    "sortNum":1,
    "courseDescriptionMarkDown":"介绍当前流行大数据技术,数据技术原理,并介绍其思想,介绍大数据技术培训课程,概要介绍。",
    "sales":100
}

响应参数:

参数名称参数说明类型schema
successboolean
stateinteger(int32)integer(int32)
messagestring
contentobject

响应示例

{
    "success": true,
    "state": 200,
    "message": "响应成功",
    "content": null
}

需求分析
      既要保存课程信息,又要保存教师的信息,并且教师的信息中存储着这门课的id值,所以这里要先保存课程信息,然后将自动生成的id作为course_id存储到教师信息中

在这里插入图片描述

3.3.3.1、dao层及其xml
 /*新增课程信息*/
public void saveCourse(Course course);

/*新增教师信息*/
public void saveTeacher(Teacher teacher);
<!--新增课程信息-->
<insert id="saveCourse" parameterType="course">
    INSERT INTO course(
        course_name,
        brief,
        preview_first_field,
        preview_second_field,
        course_img_url,
        course_list_img,
        sort_num,
        price,
        discounts,
        sales,
        discounts_tag,
        course_description_mark_down,
        create_time,
        update_time
    ) VALUES(#{courseName},#{brief},#{previewFirstField},#{previewSecondField},
    #{courseImgUrl},#{courseListImg},#{sortNum},#{price},#{discounts},#{sales},
    #{discountsTag},#{courseDescriptionMarkDown},#{createTime},#{updateTime});

    <selectKey resultType="int" order="AFTER" keyProperty="id">
        select LAST_INSERT_ID()
    </selectKey>
</insert>


<!--新增讲师信息-->
<insert id="saveTeacher" parameterType="teacher">
    INSERT INTO teacher(
        course_id,
        teacher_name,
        POSITION,
        description,
        create_time,
        update_time
    ) VALUES(#{courseId},#{teacherName},#{position},#{description},
             #{createTime},#{updateTime});
</insert>

新知识点:selectKey

3.3.3.2、service层
@Override
public void saveCourseOrTeacher(CourseVo courseVo) {
    try {
        // 封装课程信息
        Course course = new Course();
        ConvertUtils.register( new DateConverter(null), java.util.Date.class);
        BeanUtils.copyProperties(course, courseVo);
        System.out.println(course);
        // 补全信息
        Date date = new Date();
        course.setCreateTime(date);
        course.setUpdateTime(date);
        // 保存课程信息
        courseMapper.saveCourse(course);

        // 通过那个selectKey就可以获取新插入数据的id
        int id = course.getId();

        // 封装讲师信息
        Teacher teacher = new Teacher();
        BeanUtils.copyProperties(teacher, courseVo);

        // 补全信息
        teacher.setCourseId(id);
        teacher.setCreateTime(date);
        teacher.setUpdateTime(date);

        // 保存讲师信息
        courseMapper.saveTeacher(teacher);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
3.3.3.3、web层
// 保存更新课程信息
@RequestMapping("/saveOrUpdateCourse")
public ResponseResult saveOrUpdateCourse(@RequestBody CourseVo courseVo){
    courseService.saveCourseOrTeacher(courseVo);
    ResponseResult res = new ResponseResult(true, 200, "成功", null);
    return res;
}
3.3.3.4、postman测试

在这里插入图片描述

3.3.4、回显课程信息

  • 名称: findCourseById
  • 描述: 根据id查询课程信息
  • URL: http://localhost:8080/ssm-web/course/findCourseById
  • 请求方式: GET
  • 请求实例:http://localhost:8080/ssm-web/course/findCourseById?id=16
  • 请求参数
字段说明类型是否必需备注
id课程idint
  • 响应结果示例
{
    "success": true,
    "state": 200,
    "message": "响应成功",
    "content": 课程信息
}
3.3.4.1、dao层及其xml
/*回显课程信息*/
public CourseVo findCourseById(Integer id);
<select id="findCourseById" resultType="coursevo">
    SELECT
        course_name,
        brief,
        teacher_name,
        POSITION,
        description,
        preview_first_field,
        preview_second_field,
        course_img_url,
        course_list_img,
        sort_num,
        discounts,
        price,
        sales,
        discounts_tag,
        course_description_mark_down
    FROM course LEFT JOIN teacher ON course.id = teacher.course_id
    WHERE course.id = #{id}
</select>
3.3.4.2、service层
/*信息回显*/
public CourseVo findCourseById(Integer id);
@Override
public CourseVo findCourseById(Integer id) {
    return courseMapper.findCourseById(id);
}
3.3.4.3、web层
// 回显信息
@RequestMapping("/findCourseById")
public ResponseResult findCourseById(@RequestParam Integer id){
    CourseVo courseVo = courseService.findCourseById(id);
    ResponseResult res = new ResponseResult(true, 200, "成功", courseVo);
    return res;
}
3.3.4.4、postman测试

在这里插入图片描述

3.3.5、修改课程信息

3.3.5.1、dao层
/*修改课程信息*/
public void updateCourse(Course course);

/*修改讲师信息*/
public void updateTeacher(Teacher teacher);
<update id="updateCourse" parameterType="course">
  update course
    <trim prefix="set" suffixOverrides=",">
        <if test="courseName != null and courseName != ''">
            course_name = #{courseName},
        </if>
        <if test="brief != null and brief != ''">
            brief=#{brief},
        </if>
        <if test="previewFirstField != null and previewFirstField != ''">
            preview_first_field=#{previewFirstField},
        </if>
        <if test="previewSecondField != null and previewSecondField != ''">
            preview_second_field=#{previewSecondField},
        </if>
        <if test="courseImgUrl != null and courseImgUrl != ''">
            course_img_url=#{courseImgUrl},
        </if>
        <if test="courseListImg != null and courseListImg != ''">
            course_list_img=#{courseListImg},
        </if>
        <if test="sortNum != null and sortNum != ''">
            sort_num=#{sortNum},
        </if>
        <if test="price != null and price != ''">
            price=#{price},
        </if>
        <if test="discounts != null and discounts != ''">
            discounts=#{discounts},
        </if>
        <if test="sales != null and sales != '' or sales==0">
            sales=#{sales},
        </if>
        <if test="discountsTag != null and discountsTag != ''">
            discounts_tag=#{discountsTag},
        </if>
        <if test="courseDescriptionMarkDown != null and courseDescriptionMarkDown != ''">
            course_description_mark_down=#{courseDescriptionMarkDown},
        </if>
        <if test="updateTime != null">
            update_time=#{updateTime},
        </if>
    </trim>
    <where>
        <if test="id != null and id != ''">
            id = #{id}
        </if>
    </where>
</update>

<update id="updateTeacher" parameterType="teacher">
    update teacher
    <trim prefix="set" suffixOverrides=",">
        <if test="teacherName != null and teacherName != ''">
            teacher_name = #{teacherName},
        </if>
        <if test="position != null and position != ''">
            position = #{position},
        </if>
        <if test="description != null and description != ''">
            description = #{description},
        </if>
        <if test="updateTime != null">
            update_time=#{updateTime}
        </if>
    </trim>
    <where>
        <if test="courseId != null and courseId != ''">
            course_id = #{courseId}
        </if>
    </where>
</update>
3.3.5.2、service层
/*修改课程信息*/
public void updateCourseOrTeacher(CourseVo courseVo);
@Override
public void updateCourseOrTeacher(CourseVo courseVo) {
    try {
        // 封装课程数据
        Course course = new Course();
        ConvertUtils.register(new DateConverter(null), java.util.Date.class);
        BeanUtils.copyProperties(course, courseVo);

        // 补充信息
        Date date = new Date();
        course.setUpdateTime(date);

        // 更新课程
        courseMapper.updateCourse(course);

        // 封装讲师信息
        Teacher teacher = new Teacher();
        BeanUtils.copyProperties(teacher, courseVo);

        // 补充信息
        teacher.setCourseId(course.getId());
        teacher.setUpdateTime(date);

        //更新讲师信息
        courseMapper.updateTeacher(teacher);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
3.3.5.3、web层
// 保存或更新课程信息
@RequestMapping("/saveOrUpdateCourse")
public ResponseResult saveOrUpdateCourse(@RequestBody CourseVo courseVo){
    if (courseVo.getId() == null) {
        courseService.saveCourseOrTeacher(courseVo);
        ResponseResult res = new ResponseResult(true, 200, "成功", null);
        return res;
    }else{
        courseService.updateCourseOrTeacher(courseVo);
        ResponseResult res = new ResponseResult(true, 200, "成功", null);
        return res;
    }
}
3.3.5.4、postman测试

在这里插入图片描述

3.3.6、课程状态管理

接口地址: http://localhost:8080/ssm-web/course/updateCourseStatus

请求方式: GET

接口描述: 修改课程状态

请求参数:

参数名称参数说明in是否必须数据类型备注
id课程idtrueint
status课程状态trueint最新的状态值

请求示例:

http://localhost:8080/ssm-web/course/updateCourseStatus?status=1&id=15

响应参数:

参数名称参数说明类型schema
successboolean
stateinteger(int32)integer(int32)
messagestring
contentobject

响应示例:

{
    "success": true,
    "state": 200,
    "message": "响应成功",
    "content": {
        "status": 1
    }
}
3.3.6.1、dao层
/*课程状态管理*/
public void updateCourseStatus(Course course);
<update id="updateCourseStatus" parameterType="course">
    update course set status = #{status}, update_time=#{updateTime} where id = #{id}
</update>
3.3.6.2、service层
/*修改课程状态*/
public void updateCourseStatus(Integer id, Integer status);
/*修改课程信息*/
@Override
public void updateCourseStatus(Integer id, Integer status) {
    // 封装课程信息
    Course course = new Course();
    course.setStatus(status);
    course.setId(id);
    course.setUpdateTime(new Date());

    // 修改课程状态
    courseMapper.updateCourseStatus(course);
}
3.3.6.3、web层
// 修改课程状态
@RequestMapping("/updateCourseStatus")
public ResponseResult updateCourseStatus(@RequestParam Integer id, @RequestParam Integer status){
    courseService.updateCourseStatus(id, status);

    HashMap<Object, Object> map = new HashMap<>();
    map.put("status", status);
    ResponseResult res = new ResponseResult(true, 200, "成功", map);
    return res;
}
3.3.6.4、postman测试

在这里插入图片描述

3.3.7、课程内容展示

接口地址: http://localhost:8080/ssm-web/courseContent/findSectionAndLesson

请求方式: GET

接口描述: 根据课程ID查询章节与课时信息

请求参数:

参数名称参数说明in是否必须数据类型schema
courseId课程idtrueint
  • 请求示例
http://localhost:8080/ssm-web/courseContent/findSectionAndLesson?courseId=7
  • 响应结果示例
{
    "success": true,
    "state": 200,
    "message": "响应成功",
    "content": [
        {
            "id": 7,
            "courseId": 7,
            "sectionName": "开篇词 | 从小白到文案高手,手把手教你写出爆款文案",
            "description": "你好,我是兔妈!第一次见面,我用几句话简单介绍下自己",
            "createTime": null,
            "updateTime": null,
            "isDe": 0,
            "orderNum": 1,
            "status": 2,
            "lessonList": [
                {
                    "id": 9,
                    "courseId": 7,
                    "sectionId": 7,
                    "theme": "手把手教你写出爆款文案",
                    "duration": 0,
                    "isFree": 0,
                    "createTime": null,
                    "updateTime": null,
                    "isDel": 0,
                    "orderNum": 1,
                    "status": 2
                },
                {
                    "id": 8,
                    "courseId": 7,
                    "sectionId": 7,
                    "theme": "从小白到文案高手",
                    "duration": 0,
                    "isFree": 1,
                    "createTime": null,
                    "updateTime": null,
                    "isDel": 0,
                    "orderNum": 1,
                    "status": 2
                }
            ]
        },
        {
            "id": 8,
            "courseId": 7,
            "sectionName": "重点内容总结",
            "description": "重点内容总结",
            "createTime": null,
            "updateTime": null,
            "isDe": 0,
            "orderNum": 2,
            "status": 2,
            "lessonList": [
                {
                    "id": 11,
                    "courseId": 7,
                    "sectionId": 8,
                    "theme": "内容总结",
                    "duration": 0,
                    "isFree": 0,
                    "createTime": null,
                    "updateTime": null,
                    "isDel": 0,
                    "orderNum": 2,
                    "status": 2
                },
                {
                    "id": 10,
                    "courseId": 7,
                    "sectionId": 8,
                    "theme": "重点内容",
                    "duration": 0,
                    "isFree": 0,
                    "createTime": null,
                    "updateTime": null,
                    "isDel": 0,
                    "orderNum": 2,
                    "status": 2
                }
            ]
        }
    ]
}
3.3.7.1、实体类
package com.lzy.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;
import java.util.List;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class CourseSection {
    //id
    private Integer id;
    //课程id
    private int courseId;
    //章节名
    private String sectionName;
    //章节描述
    private String description;
    //创建时间
    private Date createTime;
    //更新时间
    private Date updateTime;
    //是否删除
    private int isDe;
    //排序
    private int orderNum;
    //状态
    private int status;

    // 课时集合
    private List<CourseLesson> lessonList;
}
package com.lzy.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class CourseLesson {
    private Integer id;
    private Integer courseId;
    private Integer sectionId;
    private String theme;
    private Integer duration;
    private Integer isFree;
    private Date createTime;
    private Date updateTime;
    private Integer isDel;
    private Integer orderNum;
    private Integer status;
}
3.3.7.2、dao层
public interface CourseContentMapper {
    /*查询课程下的章节与课时信息*/
    public List<CourseSection> findSectionAndLessonByCourseId(Integer courseId);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lzy.dao.CourseContentMapper">
    <!--根据课程id查询课程内容-->
    <select id="findSectionAndLessonByCourseId" resultMap="BaseResultMap">
        select
            cs.*,
            cl.id lessonid,
            cl.course_id,
            cl.section_id,
            cl.theme,
            cl.duration,
            cl.create_time,
            cl.update_time,
            cl.is_del,
            cl.order_num,
            cl.status,
            cl.is_free
            from course_section cs
                left join course_lesson cl
                    on cl.section_id = cs.id
            where cs.course_id = #{courseId}
            order by cs.order_num
    </select>

    <!--一对多配置,一个章节下有多个课时-->
    <resultMap id="BaseResultMap" type="CourseSection">
        <id property="id" column="id"/>
        <result property="courseId" column="course_id"/>
        <result property="sectionName" column="section_name"/>
        <result property="description" column="description"/>
        <result property="orderNum" column="order_num"/>
        <result property="status" column="status"/>
        <!--使用collection,配置一对多的关系-->
        <collection property="lessonList" resultMap="lessonListResultMap"/>
    </resultMap>

    <resultMap id="lessonListResultMap" type="CourseLesson">
        <id property="id" column="lessonid"/>
        <result property="courseId" column="course_id"/>
        <result property="sectionId" column="section_id"/>
        <result property="theme" column="theme"/>
        <result property="duration" column="duration"/>
        <result property="isFree" column="is_free"/>
        <result property="orderNum" column="order_num"/>
        <result property="status" column="status"/>
        <result property="isDel" column="is_del"/>
    </resultMap>
</mapper>
3.3.7.3、service层
public interface CourseContentService {
    /*展示课程内容*/
    public List<CourseSection> findSectionAndLessonByCourseId(Integer courseId);
}
import java.util.List;
@Service
@Transactional
public class CourseContentServiceImpl implements CourseContentService {

    @Autowired
    private CourseContentMapper courseContentMapper;
    @Override
    public List<CourseSection> findSectionAndLessonByCourseId(Integer courseId) {
        return courseContentMapper.findSectionAndLessonByCourseId(courseId);
    }
}
3.3.7.4、web层
@RestController
@RequestMapping("/courseContent")
public class CourseContentController {
    @Autowired
    private CourseContentService courseContentService;

    /*查询课程内容*/
    @RequestMapping("/findSectionAndLesson")
    public ResponseResult findSectionAndLessonByCourseId(@RequestParam Integer courseId){
        // 调用service
        List<CourseSection> sectionList = courseContentService.findSectionAndLessonByCourseId(courseId);

        // 封装返回数据
        ResponseResult res = new ResponseResult(true, 200, "成功", sectionList);
        return res;
    }
}
3.3.7.5、postman测试

在这里插入图片描述

3.3.8、回显章节对应的课程信息

  • 名称: findCourseById
  • 描述: 回显章节对应的课程信息
  • URL: http://localhost:8080/ssm-web/courseContent/findCourseByCourseId
  • 请求方式: GET
  • 请求参数
参数名称参数说明in是否必须数据类型schema
courseId课程idtrueint
  • 请求示例
http://localhost:8080/ssm-web/courseContent/findCourseByCourseId?courseId=15
  • 响应结果示例
{
    "success": true,
    "state": 200,
    "message": "响应成功",
    "content": {
        "id": 19,
        "courseName": "全栈工程师",
    }
}
3.3.8.1、dao层
/*回显章节对应的课程信息*/
public Course findCourseByCourseId(Integer courseId);
<select id="findCourseByCourseId" resultType="course">
    select id, course_name from course where id = #{courseId}
</select>
3.3.8.2、service层
/*回显信息*/
@Override
 public Course findCourseByCourseId(Integer courseId) {
     return courseContentMapper.findCourseByCourseId(courseId);
 }
/*回显信息*/
public Course findCourseByCourseId(Integer courseId);
3.3.8.3、web层
@RequestMapping("/findCourseByCourseId")
public ResponseResult findCourseByCourseId(@RequestParam Integer courseId){
    Course course = courseContentService.findCourseByCourseId(courseId);
    ResponseResult res = new ResponseResult(true, 200, "查询课程信息成功", course);
    return res;
}
3.3.8.4、postman测试

在这里插入图片描述

3.3.9、新建章节信息

  • 名称: saveOrUpdateSection
  • 描述: 保存和修改章节信息
  • URL: http://localhost:8080/ssm-web/courseContent/saveOrUpdateSection
  • 请求方式: POST
  • 请求参数
字段说明类型是否必需备注
id章节IDint添加操作不携带id, 修改操作必须携带ID
course_id课程IDint
section_name章节名称String
description章节描述String
order_num章节排序int
  • 请求参数示例
//新增
{
    "courseId":8,
    "sectionName":"Vue脚手架",
    "description":"快速搭建Vue项目",
    "orderNum":2
}

//修改
{
	"id":13,
    "sectionName":"Vue路由",
    "description":"单页面应用导航",
    "orderNum":0
}
  • 响应结果示例
{
    "success": true,
    "state": 200,
    "message": "响应成功",
    "content": null
}
3.3.9.1、dao层
/*保存章节*/
public void saveSection(CourseSection section);
3.3.9.2、service层
@Override
public void saveSection(CourseSection section) {
    /*补全信息*/
    Date date = new Date();
    section.setCreateTime(date);
    section.setUpdateTime(date);

    courseContentMapper.saveSection(section);
}
3.3.9.3、web层
@RequestMapping("/saveOrUpdateSection")
public ResponseResult saveOrUpdateSection(@RequestBody CourseSection section){
    courseContentService.saveSection(section);
    return new ResponseResult(true, 200, "新增章节成功", null);
}
3.3.9.4、postman测试

在这里插入图片描述

3.3.10、修改章节状态

  • 名称: updateSectionStatus
  • 描述: 修改章节状态
  • URL: http://localhost:8080/ssm-web/courseContent/updateSectionStatus
  • 请求方式: GET
  • 请求参数
字段说明类型是否必需备注
id章节IDint
status章节状态int状态,0:隐藏;1:待更新;2:已发布
  • 请求示例
http://localhost:8080/ssm-web/courseContent/updateSectionStatus?id=7&status=1
  • 响应结果示例
{
    "success": true,
    "state": 200,
    "message": "响应成功",
    "content": {
        "status": 1
    }
}
3.3.10.1、dao层
/*修改章节状态*/
public void updateSectionStatus(Course course);
3.3.10.2、service层
@Override
public void updateSectionStatus(Integer id, Integer status) {
    // 封装信息
    Course course = new Course();
    course.setId(id);
    course.setStatus(status);
    course.setUpdateTime(new Date());

    // 更新状态
    courseContentMapper.updateSectionStatus(course);
}
3.3.10.3、web层
@RequestMapping("/updateSectionStatus")
public ResponseResult updateSectionStatus(@RequestParam Integer id, @RequestParam Integer status){
    courseContentService.updateSectionStatus(id, status);
    HashMap<Object, Object> map = new HashMap<>();
    ResponseResult res = new ResponseResult(true, 200, "更新章节状态成功", map);
    return res;
}
3.3.10.4、postman测试

在这里插入图片描述

3.3.11、修改章节信息

3.3.11.1、dao层
/*修改章节信息*/
public void updateSection(CourseSection courseSection);
<update id="updateSection" parameterType="CourseSection">
 UPDATE course_section
    <trim prefix="SET" suffixOverrides=",">
        <if test="sectionName != null and sectionName != ''">
            section_name = #{sectionName},
        </if>
        <if test="description != null and description != ''">
            description = #{description},
        </if>
        <if test="orderNum != null and orderNum != '' or orderNum == 0">
            order_num = #{orderNum},
        </if>
        <if test="updateTime != null">
            update_time=#{updateTime}
        </if>
    </trim>
    <where>
        <if test="id != null and id != ''">
            id = #{id}
        </if>
    </where>
</update>
3.3.11.2、service层
// 修改章节
@Override
public void updateSection(CourseSection courseSection) {
    // 补全信息
    Date date = new Date();
    courseSection.setUpdateTime(date);

    courseContentMapper.updateSection(courseSection);
}
3.3.11.3、web层
@RequestMapping("/saveOrUpdateSection")
public ResponseResult saveOrUpdateSection(@RequestBody CourseSection section){
    if(section.getId() == null) {
        courseContentService.saveSection(section);
        return new ResponseResult(true, 200, "新增章节成功", null);
    }else{
        courseContentService.updateSection(section);
        return new ResponseResult(true, 200, "更新章节成功", null);
    }
}
3.3.11.4、postman测试

在这里插入图片描述

3.3.12、新建课时信息以及修改课时信息

  • 名称: saveLesson
  • 描述: 保存课时信息
  • URL: http://localhost:8080/ssm-web/courseContent/saveLesson
  • 请求方式: POST
  • 请求参数
字段说明类型是否必需备注
id课时IDint添加操作不携带id, 修改操作必须携带ID
courseId课程IDint
sectionId章节IDint
theme课时名称String
duration课时时长(分钟)int
isFree是否免费,0 免费,1 付费int
orderNum排序字段int
  • 请求示例
//新建
{
    "courseId":7,
    "sectionId":7,
    "theme":"文案高手养成",
    "duration":15,
    "isFree":0,
    "orderNu":2
}
3.3.12.1、dao层
/*保存课时信息*/
public void saveLesson(CourseLesson courseLesson);
<insert id="saveLesson" parameterType="CourseLesson">
  INSERT INTO course_lesson (
        id,course_id,
        section_id,
        theme,
        duration,
        is_free,
        order_num,
        create_time,
        update_time
    )VALUES(#{id},#{courseId},#{sectionId},#{theme},#{duration},#{isFree},
            #{orderNum},#{createTime},#{updateTime});
</insert>

<update id="updateLesson" parameterType="CourseLesson">
    update course_lesson
    <trim prefix="SET" suffixOverrides=",">
        <if test="theme != null and theme != ''">
            theme=#{theme},
        </if>
        <if test="duration != null and duration != ''">
            duration=#{duration},
        </if>
        <if test="isFree != null and isFree != ''">
            is_free=#{isFree},
        </if>
        <if test="orderNum != null and orderNum != '' or orderNum == 0">
            order_num=#{orderNum},
        </if>
        <if test="updateTime != null">
            update_time=#{updateTime},
        </if>
    </trim>
    <where>
        <if test="id != null and id != ''">
            id=#{id}
        </if>
    </where>
</update>
3.3.12.2、service层
@Override
public void saveLesson(CourseLesson courseLesson) {
    // 补全信息
    Date date = new Date();
    courseLesson.setCreateTime(date);
    courseLesson.setUpdateTime(date);

    courseContentMapper.saveLesson(courseLesson);
}

@Override
public void updateLesson(CourseLesson courseLesson) {
    // 补全信息
    Date date = new Date();
    courseLesson.setUpdateTime(date);

    courseContentMapper.updateLesson(courseLesson);
}
3.3.12.3、web层
@RequestMapping("/saveOrUpdateLesson")
public ResponseResult saveOrUpdateLesson(@RequestBody CourseLesson courseLesson){
    if(courseLesson.getId() == null){
        courseContentService.saveLesson(courseLesson);
        return new ResponseResult(true, 200, "保存信息成功", null);
    }else{
        courseContentService.updateLesson(courseLesson);
        return new ResponseResult(true, 200, "修改信息成功", null);
    }
}
3.3.12.4、postman测试

在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值