SSM整合的介绍
微观:将Spring SpringMVC Mybatis框架应用到项目中
- SpringMVC框架负责控制层
- Spring 框架负责整体和业务层的声明式事务管理
- MyBatis框架负责数据库访问层
宏观:Spring接管一切(将框架核心组件交给Spring进行IoC管理),代码更加简洁。
- SpringMVC管理表述层、SpringMVC相关组件
- Spring管理业务层、持久层、以及数据库相关(DataSource,MyBatis)的组件
- 使用IoC的方式管理一切所需组件
实施:通过编写配置文件,实现SpringIoC容器接管一切组件。
关于整合时的ioc容器
两个ioc容器
常见的操作是创建两个ioc容器,web容器和root容器,让组件分类管理
两个ioc容器的优点:
- 分离关注点:通过初始化两个容器,可以将各个层次的关注点进行分离。这种分离使得各个层次的组件能够更好地聚焦于各自的责任和功能。
- 解耦合:各个层次组件分离装配不同的IoC容器,这样可以进行解耦。这种解耦合使得各个模块可以独立操作和测试,提高了代码的可维护性和可测试性。
- 灵活配置:通过使用两个容器,可以为每个容器提供各自的配置,以满足不同层次和组件的特定需求。每个配置文件也更加清晰和灵活。
它们各自负责不同的层次和功能,并通过合适的集成方式协同工作
关于两个ioc容器盛放的组件
容器名 | 盛放组件 |
---|---|
web容器 | web相关组件(controller,springmvc核心组件) |
root容器 | 业务和持久层相关组件(service,aop,tx,dataSource,mybatis,mapper等) |
容器之间对应关系
- 两个无关联的ioc容器之间的组件无法注入
- 子ioc容器可以单向注入父ioc容器的组件
web容器和root容器之间的关系:web容器是root容器的子容器
关于配置类
建议有三个配置类:
配置名 | 对应内容 | 对应容器 |
---|---|---|
WebJavaConfig | controller,springmvc相关 | web容器 |
ServiceJavaConfig | service,aop,tx相关 | root容器 |
MapperJavaConfig | mapper,datasource,mybatis相关 | root容器 |
在Init类中。重写的getRootConfigClasses中,指定root容器对应的配置类。在重写的getServletConfigClasses方法中指定web容器对应的配置类
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[] { "/" };
}
}
整合配置
依赖整合和添加
需要的依赖清单:
需要依赖清单分析:
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
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
数据库连接池 druid / x
lombok lombok / 1.18.26
logback logback/ 1.2.3
日志输出配置:(在resource目录下)
<?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>
springmvc层的配置
配置类WebMvcJavaConfig:
/**
*要加入其中的组件
* 1.controller
* 2.全局异常处理器
* 3.handlerMapping handlerAdapter
* 4.静态资源处理
* 5.jsp视图解析器前后缀
* 6.json转化器
* 7.拦截器
*/
@Configuration
@ComponentScan({"com.ergou.controller","com.ergou.error"})
@EnableWebMvc
public class WebMvcJavaConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views","jsp");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(new xxx()).addPathPatterns();
}
}
service和aop以及tx的配置
ServiceJavaConfig配置类:
/**
* 业务层配置类:service,aop,tx
* 1.service
* 2.开启aop注解的支持
* 3.tx声明式事务管理:对应事务管理器的实现,开启事务注解支持
* 4.声明包扫描注解
* 5.配置事务管理器
*/
@Configuration
@ComponentScan("com.ergou.service")
@EnableAspectJAutoProxy
@EnableTransactionManagement
public class ServiceJavaConfig {
@Bean
public TransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
}
Mybatis整合配置方式
mybatis整合思路:
- 需要将SqlSessionFactory和Mapper实例加入到IoC容器
- sqlSessionFactory的ioc配置交给SqlSessionFactoryBean来创建
- Mapper的配置交给MapperScannerConfigurer进行mapper的包扫描
- 使用mybatis整合包提供的FactoryBean快速整合
配置方式一(保留mybatis-config.xml)
依然保留mybatis的外部配置文件,将数据库连接信息交给Druid连接池配置
DataSource的配置不要和mybatis的配置放在一个文件中,否则DaraSource的@Value注解会晚于mybatis的配置生效,会显示DataSource的配置信息为空,应该将DataSource的配置放在另一个文件中进行
MapperJavaConfig:
@Configuration
@PropertySource("classpath:jdbc.properties")
public class MapperJavaConfig {
//sqlSessionFactory加入ioc容器,使用SqlSessionFactoryBean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//指定配置文件等信息
//指定数据库连接池对象
sqlSessionFactoryBean.setDataSource(dataSource);
//指定外部的mybatis配置文件
//Resource用的org.springframework.core.io包下的
Resource resource = new ClassPathResource("mybatis-config.xml");
sqlSessionFactoryBean.setConfigLocation(resource);
return sqlSessionFactoryBean;
}
//mapper代理对象加入到ioc
public MapperScannerConfigurer mapperScannerConfigurer(){
//指定包,会将包下的mapper的代理对象加入到ioc容器中
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.ergou.mapper");//指定mapper接口和mapper.xml所在的共同的包名
return mapperScannerConfigurer;
}
}
DataSourceJavaConfig:
@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;
}
}
配置方式二(完全类配置)
不保留mybatis的外部配置文件(xml), 所有配置信息(settings、插件、别名等)全部在声明SqlSessionFactoryBean的代码中指定!数据库信息依然使用DruidDataSource实例替代
DataSourceJavaConfig的配置类上同。
MapperJavaConfig:
@Configuration
@Import(DataSourceJavaConfig.class)
public class MapperJavaConfig {
/**
*配置SqlSessionFactoryBean,指定连接池对象和外部配置文件即可
* @paramdataSource需要注入连接池对象
* @return工厂Bean
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
//实例化SqlSessionFactory工厂
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//设置连接池
sqlSessionFactoryBean.setDataSource(dataSource);
//TODO:替代xml文件的java配置
/*
<settings>
<!--开启驼峰式映射-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启logback日志输出-->
<setting name="logImpl" value="SLF4J"/>
<!--开启resultMap自动映射 -->
<setting name="autoMappingBehavior" value="FULL"/>
</settings>
<typeAliases>
<!--给实体类起别名 -->
<package name="com.ergou.pojo"/>
</typeAliases>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--
helperDialect:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。
你可以配置helperDialect属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:
oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby
(完整内容看 PageAutoDialect) 特别注意:使用 SqlServer2012数据库时,
<https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md#%E5%A6%82%E4%BD%95%E9%85%8D%E7%BD%AE%E6%95%B0%E6%8D%AE%E5%BA%93%E6%96%B9%E8%A8%80>
-->
<property name="helperDialect" value="mysql"/>
</plugin>
</plugins>
*/
//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.ergou.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文件所在的包
* @return
*/
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//设置mapper接口和xml文件所在的共同包
mapperScannerConfigurer.setBasePackage("com.ergou.mapper");
return mapperScannerConfigurer;
}
}
配置类的初始化
初始化类:
public class SpringIoCInit extends AbstractAnnotationConfigDispatcherServletInitializer {
//rootIoc容器的指定
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{DataSourceJavaConfig.class, MapperJavaConfig.class, ServiceJavaConfig.class};
}
//webIoc容器的指定
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebMvcJavaConfig.class};
}
//dispatcherServlet的拦截路径
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}