拉勾教育后台管理系统(SSM)
拉勾教育后台管理系统(SSM)
1.项目架构
1.1 项目介绍
拉勾教育后台管理系统为拉勾教育相关业务人员开发的一个专业管理平台,在这个后台管理平台上业务人员可以方便地完成课程信息管理、广告效果监测以及用户行为分析等功能
1.2 技术选型
1.2.1 前端技术选型
| 前端技术选型 | 说明 |
|---|---|
| Vue.js | 是一套用于构建用户界面的渐进式JavaScript框架 |
| Element UI 库 | element-ui 是饿了么前端出品的基于 Vue.js的 后台组件库, 方便程序员进行页面快速布局和构建 |
| node.js | 运行在服务端的 JavaScript 运行环境 . |
| axios | 对ajax的封装, 简单来说就是ajax技术实现了局部数据的刷新, |
1.2.2 后端技术选型
| 后端技术 | 说明 |
|---|---|
| Web层 | 借助springmvc接收请求,进行视图跳转 |
| Service层 | 借助spring进行IOC、AOP、及事务管理 |
| dao层 | 借助mybatis进行数据库交互 |
1.3 项目开发环境
-
开发工具:
- 后端: IDEA 2019
- 前端: VS code
- 数据库客户端工具: SQLYog
-
开发环境
- JDK 11
- Maven 3.6.3
- MySQL 5.7
2.Maven聚合工程
2.1 maven的依赖传递
2.1.1 什么是依赖传递
- 在Maven框架中,默认支持逆向继承项目的依赖关系。假设有三个构建任务依次为A、B和C。如果构建顺序为先启动A后启动B再启动C,则基于Maven的逆向继承机制可知构建顺序与实际执行顺序一致。

2.1.2 依赖冲突
因为存在依赖传递现象,在项目中选择了 spring-webmvc 作为框架时,默认会基于 spring-beans-5.1.5 进行配置;而对于 aop 节点,则基于 springbeans-5.1.6 进行配置。然而,在实际开发中发现spring-beans-5.1.5 已被成功引入到工程中,而我们则希望加入 spring-beans-5.1.6 进入项目结构。这不可避免地导致了两种版本的依存关系出现了冲突

2.1.3 如何解决依赖冲突
借助maven所提供的依赖调解机制实现系统功能的协调与管理
- 排除依赖
- 锁定版本(常用)
2.1.4 依赖调节原则——第一声明者优先原则
依据坐标导入时的顺序来决定使用的那个传递进来的依赖项。

结论:从图表中可以看出,在线学习系统中各功能模块之间实现了良好的信息交互与数据共享机制设计。其中,在课程管理模块与在线测试模块之间建立的动态通信通道最为关键,并且该机制能够有效保障系统运行的稳定性与可靠性
2.1.5 依赖调节原则——路径近者优先原则

- Spring-MVC 5.1.5 版本中的依赖项会被后续版本中自动引入的 beans 所覆盖。
- 总结:在Spring-MVC框架中存在一种现象即直接引用的依赖项数量多于通过传递引用的方式获取到的依赖项数量。
2.1.6 排除依赖
- 可以使用exclusions标签将传递过来的依赖排除出去。

- 将Spring-MVC传递的5.1.5版本的beans依赖排除,后续使用Spring-aop 5.1.6版本。
2.1.7 版本锁定
通过直接锁定机制实现对所需依赖项的精确版本号获取,在不考虑依赖项声明顺序及路径的前提下完成版本锁定操作,并将其配置到工程中作为标准引用。这种方法常被采用于企业级项目开发中
版本锁定的使用方式:
-
第一步:在 dependencyManagement 标签中锁定依赖的版本号
-
第二步:在 dependencies 标签中配置需要导入的 Maven 坐标
-
dependencyManagement标签中锁定依赖的版本。
<!--配合properties标签 -->
<properties>
<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>
</dependencies>
</dependencyManagement>
- 在dependencies标签中声明需要导入的maven坐标
<dependencies>
<!--mybatis坐标-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
</dependencies>
2.2.maven聚合工程(分模块)
2.2.1 分模块构建maven工程分析
常见的大型项目拆分方法通常采用以下两种方式:一种是基于业务功能划分并独立开发的方式;另一种则是根据系统的层次划分来实现功能分离的方法。前者的具体实现时会创建独立的Maven工程;而后者则会将系统划分为如数据库操作层(DB)、业务处理层(Business)、用户界面显示层(UI)等不同的层次,并为每个层次分别构建相应的Maven工程。
无论采用何种拆分方式, 一般会提供一个父工程, 并整合一些公共的代码和配置到该父工程中进行集中管理

2.2.2maven工程的继承
基于Maven的工程之间也可以实现代码继承。当子项目继承自父项目时,则可以复用父项目中引入的依赖项。代码继承的主要目的是为了减少冗余代码量。

父工程:
<groupId>com.lagou</groupId>
<artifactId>lagou_edu_home_parent</artifactId>
<packaging>pom</packaging><!--打包方式为pom-->
<version>1.0-SNAPSHOT</version>
子工程:
<parent><!--通过parent标签继承-->
<artifactId>lagou_edu_home_parent</artifactId>
<groupId>com.lagou</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
2.2.3maven工程的聚合
- 在父工程的pom.xml文件中使用/将子工程聚合在一起,进行统一操作(打包)。

2.2.4 maven聚合工程_搭建拉勾教育后台管理系统
该父项目被定义为基础架构模块,并由所有后续子项目遵循该父结构
lagou_edu_home_parent工程将其子工程都进行了聚合
子工程之间存在依赖关系:
在SSM中,默认会引入一个名为‘utils’的库。
其中‘DAO’类通常会继承自‘Domain’类。
服务层对象则主要负责业务逻辑实现。
而Web层则主要负责前端界面展示。
依赖配置:
<!-- ssm-web依赖ssm-service-->
<dependencies>
<dependency>
<groupId>com.lagou</groupId>
<artifactId>ssm-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!-- ssm-service依赖ssm-dao-->
<artifactId>ssm-service</artifactId>
<dependencies>
<dependency>
<groupId>com.lagou</groupId>
<artifactId>ssm-dao</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
3. 配置文件一览
3.1 ssm-dao层配置文件
3.1.1 sqlConfig.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>
<settings>
<!-- 是否开启自动驼峰命名规则(camel case)映射,即从数据库列名 A_COLUMN 到属性名 aColumn 的类似映射
a_name aName-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
applicationContext.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">
<!--Spring整合Mybatis-->
<!--1.数据源配置-->
<!--引入jdbc.properties-->
<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>
<!--2.sqlSessionFactory-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--指定别名-->
<property name="typeAliasesPackage" value="com.lagou.domain"/>
<!--加载mybatis核心配置文件-->
<property name="configLocation" value="classpath:sqlMapConfig.xml"/>
<!--分页插件-->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<value>helperDialect=mysql</value>
</property>
</bean>
</array>
</property>
</bean>
<!--3.mapper映射扫描-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.lagou.dao"/>
</bean>
</beans>
3.2 ssm-service层配置文件
- 相关约束头已省略
- applicationContext-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans ……>
<!--开启IOC注解扫描-->
<context:component-scan base-package="com.lagou.service"/>
<!--引入applicationContext-dao.xml。 最终我们只加载一个配置文件即可-->
<import resource="classpath:applicationContext-dao.xml"/>
</beans>
3.3 ssm-web层配置文件
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans ……>
<!--引入applicationContext-service.xml-->
<import resource="classpath:applicationContext-service.xml"/>
</beans>
springmvc.xml
<beans >
<!--1.注解扫描,只扫描controller-->
<context:component-scan base-package="com.lagou.controller"/>
<!--2. mvc注解增强-->
<mvc:annotation-driven/>
<!--3.视图解析器(暂时不用配置)-->
<!--4.放行静态资源-->
<mvc:default-servlet-handler/>
<!--5.配置文件解析器-->
<!-- 此处id为固定写法,不能随便取名-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1048576"></property>
</bean>
</beans>
web.xml
<?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:springmvc.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.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>
<!--跨域过滤器-->
<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>
```
