SSM框架整合
文章目录
前言
- 理解:
三层框架调用不变,属于纵向关系,使用相关的架构相当于添加横向配置。纵向只需要调用相关方法,配置会自动生效。
即对每一层添加相关的配置,controller层添加springmvc配置就可实现外部请求与controller的一些交互;dao层添加mybatis配置,在service层正常调用相关的方法,mybatis就会根据相关的配置执行对应的运行逻辑。 - 框架的配置:编写相关的配置类(使用不同注解需要开启相关注解支持),配置类要结合组件的注解使用,容器用来加载配置类。因为ssm整合是实现web应用程序,因此容器加载配置使用springmvc提供的接口。
- springmvc提供的接口:AbstractAnnotationConfigDispatcherServletInitializer,该接口替代web.xml方案,实现完全注解方式。在这里可以指定root、web容器对应的配置类,相当于使用配置类创建ioc容器,从而为bean添加实现添加配置信息的功能,专注于写代码实现,其他的全部交给spring去干!
- ssm整合:通过配置类/配置文件实现相关注解的功能,然后将配置信息加载到IoC容器中,Spring就起作用了。可以理解为是把mybatis、springmvc加到springioc核心容器中
一、SMM整合理解
1.1 什么是SMM框架
- 宏观:将学习的Spring SpringMVC Mybatis框架应用到项目中
- SpringMVC框架负责控制层
- Spring 框架负责整体和业务层的声明式事务管理
- MyBatis框架负责数据库访问层
- 宏观:Spring接管一切(将三层架构和框架核心API组件交给SpringIoC容器管理),代码更加简洁。
- SpringMVC管理表述层、SpringMVC相关组件
- Spring管理业务层、持久层、以及数据库相关(DataSource,MyBatis)的组件
- 使用IoC的方式管理一切所需组件
实施:每种方式编写配置文件/配置类,实现SpringIoC容器接管一切组件。
2.2 初步整合SMM框架流程
- 配置文件/配置类【推荐配置类】
三层架构每层对应一个配置类,分别指定两个容器加载web容器加载第一个,root容器加载其余两个。- WebJavaConfig:controller,springmvc相关
- ServiceJavaConfig:service,aop,tx相关
- MapperJavaConfig:mapper,datasource,mybatis相关
- 创建两个容器IoC容器
好处:分离各个层次的关注点(责任和功能);解耦,各个层次组件分离装配不同的IoC容器,各个模块可以独立维护/测试;灵活配置不同层次和组件的特定需求。
关系及调用:由于两个无关联IoC容器之间的组件无法注入,但是子IoC容器可以单向的注入父IoC容器的组件。- web容器:子容器,web相关组件(controller,springmvc核心组件)
- root容器:父容器,业务和持久层相关组件(service,aop,tx,dataSource,mybatis,mapper等)
- 初始化IoC方式和配置位置
对于web项目,选择web.xml和配置类方式进行ioc配置【推荐配置类】,这边就是学习springmvc框架时创建ioc容器那一步骤
配置web的spring配置的应用程序extends接口AbstractAnnotationConfigDispatcherServletInitializer,利用三个实现方法指定每种容器对应的配置类 - 编写三层架构,实现相关功能即可:纵向调用的同时,通过上面的配置会横向加载这些相关的配置实现配置的功能!
web项目,进行ioc配置,指定每种容器对应的配置类!
通过上面几步的配置,就可以整合SSM,不同的配置类配置不同的框架、bean组件/架构层、功能。
二、SMM框架整合实战
SSM框架:构建单体项目的技术栈需求,SpringMVC负责简化表述层(控制层)
2.1 整合依赖添加
- 准备数据库
- 准备项目
- 导入依赖
- 添加实体类
- 配置logback:位置resources/logback.xml,用于对数据操作的日志
整合SMM框架所需依赖:spring、springmvc、mybatis、整合需要
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu</groupId>
<artifactId>part04-ssm-integration</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties></properties>
<!--需要依赖清单分析:
spring
ioc/di
spring-context / 6.0.6
jakarta.annotation-api / 2.1.1 jsr250
aop
spring-aspects / 6.0.6
tx
spring-tx / 6.0.6
spring-jdbc / 6.0.6
springmvc
spring-webmvc 6.0.6
jakarta.jakartaee-web-api 9.1.0
jakarta.servlet.jsp.jstl-api / 3.0.0 jsp需要依赖
jackson-databind 2.15.0
hibernate-validator / hibernate-validator-annotation-processor 8.0.0.Final
mybatis
mybatis / 3.5.11
mysql / 8.0.25
pagehelper / 5.1.11
整合需要
加载spring容器 spring-web / 6.0.6
整合mybatis mybatis-spring x x mybatis整合包提供的FactoryBean组件快速整合(提供封装SqlSessionFactory和Mapper实
例化的逻辑)
会自动传递slf4j门面 logback-classic / 1.2.3
数据库连接池 druid / x
lombok lombok / 1.18.26
logback logback/ 1.2.3
-->
<dependencies>
<dependency></dependency>
</dependencies>
</project>
logback配置:导入相关依赖就可配置使用,位置resources/logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<!-- 指定日志输出的位置,ConsoleAppender表示输出到控制台 -->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 日志输出的格式 -->
<!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 设置全局日志级别。日志级别按顺序分别是:TRACE、DEBUG、INFO、WARN、ERROR -->
<!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
<root level="DEBUG">
<!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
<appender-ref ref="STDOUT" />
</root>
<!-- 根据特殊需求指定局部日志级别,可也是包名或全类名。 -->
<logger name="com.atguigu.mybatis" level="DEBUG" />
</configuration>
2.2 控制层配置类对SpringMVC整合并扫描控制层注解
Controller配置类:实现Springmvc组件声明标准化接口WebMvcConfigurer 提供了各种组件对应的方法;配置controller层
由于springmvc就是属于spring的因此无需做过多的操作,完全适配!
controller层配置类的实现:WebJavaConfig.java(命名随意)
@Configuration //表明配置类
@EnableWebMvc //mvc复合开关:添加经理、秘书、支持json
@ComponentScan("com.atguigu.controller") //扫描controller层
public class WebJavaConfig implements WebMvcConfigurer {
//开启默认处理器,支持静态资源处理
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
2.3 业务层配置类对AOP/Tx并扫业务层注解
Service配置类:主要配置service,注解aop和声明事务相关配置
Service层配置类的实现:ServiceJavaConfig.java(命名随意)
@EnableTransactionManagement //开启事务注解支持
@EnableAspectJAutoProxy //开启aspect aop注解支持
@Configuration //代表配置类
@ComponentScan("com.atguigu.service") //进行业务组件扫描
public class ServiceJavaConfig {
@Bean
//指定具体的事务管理器
public DataSourceTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
2.4 持久层配置对Mybatis整合并扫持久层注解
1、mybatis实现过程:针对持久层和数据库,step1:mybatis有配置文件(有一大堆标签可以实现相关的功能、数据源、mappers扫描);step2:在使用的时候还需要通过sqlSessionFactory获取去sqlSession等等,才能调用相关的mapper接口方法。
2、回顾Mybatis核心api使用:即step2使用mybatis的过程
- SqlSessionFactoryBuilder:创建了 SqlSessionFactory后,就不需要了。 因此最佳作用域是方法作用域(也就是局部方法变量)
- SqlSessionFactory:是“生产”SqlSession的“工厂”。在应用的运行期间一直存在,无需丢弃/重新创建。最佳作用域是应用作用域。
- SqlSession:Java程序和数据库之间的会话。每个线程都有自己的实例,线程不安全。最佳的作用域是请求/方法作用域。
- Mapper映射器实例:一些绑定映射语句的接口。其实例最大作用域与sqlSession相同,但最合适作用域是方法作用域。
由于业务类service需要注入mapper接口,所以mapper应该交给ioc容器管理。
//1.读取外部配置文件
InputStream ips = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建sqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(ips);
//3.创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.获取mapper代理对象
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
//5.数据库方法调用
int rows = empMapper.deleteEmpById(1);
System.out.println("rows = " + rows);
//6.提交和回滚
sqlSession.commit();
sqlSession.close();
3、整合思路:将SqlSessionFactory实例、Mapper实例存储到IoC容器
- 自己实现sqlSessionFactory加入ioc容器:用注解@Bean
- mybatis提供了FactoryBean组件SqlSessionFactoryBean:其提供封装SqlSessionFactory和Mapper实例化的逻辑。作用指定连接池对象和外部配置文件。
4、整合方式
回顾mybatis配置文件:配置数据库连接信息、mapper.xml、mapper扫描包、别名、settings、插件等信息。
- 法一:保留mybatis配置文件mybatis-config.xml:一共有三种配置即mybatis得xml配置+数据库配置类+mybatis配置类
- mybatis-config.xml配置文件:别名、settings、插件等信息
- 持久层配置类:持久层Mapper配置(mapper扫描包)、数据库配置、Mybatis配置信息(指定连接池对象和外部配置文件)。
这里不需要mybatis核心api实现mybatis了,因为SqlSessionFactory和Mapper实例化的逻辑已经封装在SqlSessionFactoryBean中了,因此只需要指定连接池对象和外部配置文件即可实现他们的实例化。
- 法二:完全配置类,去掉mybatis配置文件mybatis-config.xml:mybatis得xml文件中得配置(settings、插件、别名等)全部在声明SqlSessionFactoryBean得代码中指定。一共有两种配置即mybatis配置类+数据库配置类
优势:全部配置类,避免了XML文件解析效率低问题!
法一保留mybatis配置文件——实现mybatis配置文件功能:别名、settings、插件等信息
<?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>
<!-- 开启驼峰式映射-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 开启logback日志输出-->
<setting name="logImpl" value="SLF4J"/>
<!--开启resultMap自动映射 -->
<setting name="autoMappingBehavior" value="FULL"/>
</settings>
<typeAliases>
<!-- 给实体类起别名 -->
<package name="com.atguigu.pojo"/>
</typeAliases>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--helperDialect:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。
name="helperDialect"时value的可选值oracle, mysql, mariadb, sqlite, hsqldb, postgresql, db2, sqlserver,
informix, h2, sqlserver2012[特别注意], derby(完整内容看 PageAutoDialect)
-->
<property name="helperDialect" value="mysql"/>
</plugin>
</plugins>
</configuration>
法一保留mybatis配置文件——实现mybatis和持久层配置类功能:持久层Mapper配置、数据库配置、Mybatis配置信息
由于SqlSessionFactoryBean封装了封装SqlSessionFactory和Mapper实例化的逻辑,因此只需指定连接池对象和外部配置文件即可。
- 问题:数据库配置和其他写在一个配置类中,出现@Value注解读取不到值为null?
- 原因:Spring配置类中的方法sqlSessionFactoryBean和mapperScannerConfigurer是基于MyBatis框架的配置。它们用于配置MyBatis相关的Bean,例如数据源、事务管理器、Mapper扫描等。当配置类被加载时,Spring容器会首先处理Bean的定义和初始化,其中包括这两个的初始化。在这个过程中,如果@Value注解所在的Bean还没有被完全初始化,可能会导致注入的属性值为null。
- 解决方法:分成两个配置类独立配置,互不影响,数据库提取一个配置类,mybatis提取一个配置类即可解决!
拆分配置1:数据库配置类——配置连接池对象
法二完全配置类,去掉mybatis配置文件——实现数据库配置类:数据库配置
两种方法通用!!
@Configuration
@PropertySource("classpath:jdbc.properties")
public class DataSourceJavaConfig{
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driver}")
private String driver;
//数据库连接池配置
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUsername(user);
dataSource.setPassword(password);
dataSource.setUrl(url);
dataSource.setDriverClassName(driver);
return dataSource;
}
法一拆分配置2:mybatis配置类——指定连接池对象和外部配置文件即可
@Configuration
public class MapperJavaConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){//需要注入连接池对象
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();//实例化SqlSessionFactory工厂
sqlSessionFactoryBean.setDataSource(dataSource);//设置连接池
Resource resource = new ClassPathResource("mybatis-config.xml");
sqlSessionFactoryBean.setConfigLocation(resource);//设置mybatis配置文件
return sqlSessionFactoryBean;//返回工厂Bean
}
//配置Mapper实例扫描工厂,配置 <mapper <package 对应接口和mapperxml文件所在的包
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//设置mapper接口和xml文件所在的共同包
mapperScannerConfigurer.setBasePackage("com.atguigu.mapper");
return mapperScannerConfigurer;
}
}
法二完全配置类,去掉mybatis配置文件——实现mybatis配置类:即实现功能替代mybatis的xml文件的java配置(别名、settings、插件等信息)+mybatis配置类功能(持久层Mapper配置、Mybatis配置信息)
/**
* projectName: com.atguigu.config
*
* description: 持久层配置和Druid和Mybatis配置 使用一个配置文件
*/
@Configuration
public class MapperJavaConfigNew {
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
//实例化SqlSessionFactory工厂
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource); //设置连接池
/** TODO: 能替代mybatis的xml文件的java配置(别名、settings、插件等信息)
*/
//settings [包裹到一个configuration对象,切记别倒错包]
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
configuration.setLogImpl(Slf4jImpl.class);
configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
sqlSessionFactoryBean.setConfiguration(configuration);
//typeAliases
sqlSessionFactoryBean.setTypeAliasesPackage("com.atguigu.pojo");
//分页插件配置
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect","mysql");
pageInterceptor.setProperties(properties);
sqlSessionFactoryBean.addPlugins(pageInterceptor);
return sqlSessionFactoryBean;
}
//配置Mapper实例扫描工厂,配置 <mapper <package 对应接口和mapperxml文件所在的包
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//设置mapper接口和xml文件所在的共同包
mapperScannerConfigurer.setBasePackage("com.atguigu.mapper");
return mapperScannerConfigurer;
}
}
2.5 IoC容器初始化配置类
对于web项目,选择web.xml和配置类方式进行ioc配置【推荐配置类】,这边就是学习springmvc框架时创建ioc容器那一步骤
配置web的spring配置的应用程序extends接口AbstractAnnotationConfigDispatcherServletInitializer,利用三个实现方法指定每种容器对应的配置类
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
//指定root容器对应的配置类
//root容器的配置类
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { ServiceJavaConfig.class,MapperJavaConfig.class };
}
//指定web容器对应的配置类 webioc容器的配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebJavaConfig.class };
}
//指定dispatcherServlet处理路径,通常为 /
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
2.6 整合测试
编写相关的配置类及IoC容器,接下来创建三层架构并实现相关功能,纵向调用三层架构,横向加载其配置信息,实现目标功能!
三层架构的实现方式使用接口规范。
1、controller:根据需求接口编写相关handler方法
2、service:可以添加一些AOP、Tx
3、mapper
- mapper接口 包:com.atguigu.mapper
- mapper XML 文件位置: resources/mappers
三、前后端分离项目开发
前后端分离
前端用node后端用tomcat,前后端依赖管理工具:npm、maven
安装node自动下载npm
前后端分离项目中,会定义统一的接口说明:请求url、请求方式(json、param等等)、响应的json
这种开发都是针对接口开发。
注解是接口,xml定义配置他的具体实现。