微观:将学习的Spring SpringMVC Mybatis框架应用到项目中!
- SpringMVC框架负责控制层
- Spring 框架负责整体和业务层的声明式事务管理
- MyBatis框架负责数据库访问层
宏观:Spring接管一切(将框架核心组件交给Spring进行IoC管理),代码更加简洁。
- SpringMVC管理表述层、SpringMVC相关组件
- Spring管理业务层、持久层、以及数据库相关(DataSource,MyBatis)的组件
- 使用IoC的方式管理一切所需组件
实施:通过编写配置文件,实现SpringIoC容器接管一切组件。
①SSM整合需要几个IOC容器?
两个容器
web容器:装SpringMVC,Controller相关的web组件
root容器:装业务层和持久层相关的组件
好处:
1. 分离关注点
2. 解耦合
3. 灵活配置
②每个IOC容器对应那些类型组件?
|容器名 |
盛放组件| |
|web容器 |
web相关组件(controller,springmvc核心组件) | |
|root容器 |
业务和持久层相关组件(service,aop,tx,dataSource,mybatis,mapper等)| |
③容器之间的关系
结论:web容器是root容器的子容器,父子容器关系。
- 父容器:root容器,盛放service、mapper、mybatis等相关组件
- 子容器:web容器,盛放controller、web相关组件
子容器可以引用父容器的组件,父容器调不了子容器
④具体多少配置类以及对应容器关系
每一层(controller;service,mapper(dao层))写一个对应配置类
1WebJavaConfig(controlller层):web相关,springmvc相关组件;
2ServiceJavaConfig(service层):业务层的扫描,aop,tx相关组件;
3MapperJavaConfig(mapper层):连接池,mybatis相关组件
初始化类
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
/**
* 控制层的配置类(controller,springmvc)
* 1 controller
* 2 全局异常处理器
* 重新写一个异常处理类
* 3 handlerMapping handlerAdapter
* 4 json转化器
* 使用注解@EnableWebMvc可以自动配置3与4
*
* 5 静态资源处理
* 重写configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)方法
* 在方法内通过configurer调用enable()方法
* 6 jsp 视图解析器前后缀
* 重写configureViewResolvers(ViewResolverRegistry registry)方法
* 在方法内通过 registry调用jsp()方法,传入前缀和后缀
* 7 拦截器...
* 重写addInterceptors(InterceptorRegistry registry)方法
* 在方法内registry调用addInterceptor()方法传入拦截器类,
* 默认是拦截所有请求的,
* 如果想要指定拦截,可以连续调用addPathPatterns()传入handler的地址(可以模糊*)
* 如果想要排除那个,可以连续调用excludePathPatterns()方法传入要排除的handler的地址
* 注意:该配置类可以实现WebMvcConfigurer接口,有springmvc的组件有对应的方法提供。
*/
@Configuration
@ComponentScan({"com.atguigu.controller","com.atguigu.exceptionhandler"})
@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(拦截器类).addPathPatterns().excludePathPatterns();
}
}
/**
* 业务层配置类:service,aop,tx
* 1 service
* 2 开启aop注解的支持(@EnableAspectJAutoProxy) aspect:@Before @After @AfterReturning @AfterThrowing @Around @Aspect @Order
* 3 tx开启事务声明管理(@EnableTransactionManagement):
* 1对应的事务管理器实现 [最大接口TransactionManager 实现类:DataSourceTransactionManager Hibernate.. Jpa..]
* 创建一个方法,该方法返回DataSourceTransactionManager对象
* 注意:DataSourceTransactionManager对象需要连接池,所以在方法的形参中要有一个(DataSource dataSource)会自动引用
* 对象调用setDataSource()传入连接池对象
* 2开启事务注解支持 @Transactional
*/
@Configuration
@EnableAspectJAutoProxy
@EnableTransactionManagement
public class ServiceJavaConfig {
@Bean
public TransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);//需要连接池
return dataSourceTransactionManager;
}
}
主要配置mapper代理对象,连接池和mybatis核心组件配置
- 总结
- 将SqlSessionFactory实例存储到IoC容器
- 将Mapper实例存储到IoC容器
SqlSessionFactoryBean类:
package org.mybatis.spring
public class SqlSessionFactoryBean
implements FactoryBean
, InitializingBean, ApplicationListener { //封装了实例化流程
public SqlSessionFactory getObject() throws Exception {
if (this.sqlSessionFactory == null) {
//实例化对象逻辑
afterPropertiesSet();
}
//返回对象逻辑
return this.sqlSessionFactory;
}
}
mybatis整合思路总结:
- 需要将SqlSessionFactory和Mapper实例加入到IoC容器
- 使用mybatis整合包提供的FactoryBean快速整合
/**
* 连接池的配置类
*/
@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.diver")
private String driver;
@Bean
public DataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUsername(user);
druidDataSource.setPassword(password);
druidDataSource.setUrl(url);
druidDataSource.setDriverClassName(driver);
return druidDataSource;
}
}
持久层配置类方式一(不推荐)
/**
* 持久层配置类:连接池,sqlSessionFactory,Mapper代理对象
* 方式1:保留外部配置文件mybatis-config.xml
* 出现的问题:如果将dataSource和mybatis的组件配置到一起,会触发@value注解不生效的问题
* 原因:mybatis的组件优先加载,@value还没有读取!
* 解决:分开配置,写到不同的类即可
*/
@Configuration
public class MapperJavaConfig {
/**
* sqlSession加入ioc容器
* mybatis会提供一个 sqlSessionFactoryBean,在此工厂类的getObject方法中会完成sqlSession对象的实例化
* 方式1 外部指定mybatis-config.xml【在此文件中,不用配置连接池,mapper指定,其他照旧】
*
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//指定配置文件等信息
//指定数据库连接对象
sqlSessionFactoryBean.setDataSource(dataSource);
//指定外部的mybatis配置文件
ClassPathResource resource = new ClassPathResource("mybatis-config.xml");
sqlSessionFactoryBean.setConfigLocation(resource);
return sqlSessionFactoryBean;
}
/**
* mapper代理对象加入ioc
* mybatis也会提供一个工厂类
*
*/
public MapperScannerConfigurer mapperScannerConfigurer(){
//mapper代理对象的factoryBean-》指定一个包-》mapper接口 -》sqlSession-》getMapper
MapperScannerConfigurer mapperScannerConfigurer=new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.atguigu.mapper");//mapper接口和mapperxml所在的共同包
return mapperScannerConfigurer;
}
}
持久层配置类方式二(推荐)
/**
* 持久层配置类:连接池,sqlSessionFactory,Mapper代理对象
* 方式2:不保留外部配置文件mybatis-config.xml 全部mybatis属性都在代码中设置!
*/
@Configuration
public class MapperJavaConfigNew {
/**
* sqlSession加入ioc容器
* mybatis会提供一个 sqlSessionFactoryBean,在此工厂类的getObject方法中会完成sqlSession对象的实例化
*
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//指定配置文件等信息
//指定数据库连接对象
sqlSessionFactoryBean.setDataSource(dataSource);
**************************************************************
//指定mybatis配置文件的功能,使用代码的形式
org.apache.ibatis.session.Configuration configuration
= new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
configuration.setLogImpl(Slf4jImpl.class);
configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
//org.apache.ibatis.session.Configuration 存储setting的配置文件
sqlSessionFactoryBean.setConfiguration(configuration);
//别名设置
sqlSessionFactoryBean.setTypeAliasesPackage("com.atguigu.pojo");
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect","mysql");
pageInterceptor.setProperties(properties);
sqlSessionFactoryBean.addPlugins();
sqlSessionFactoryBean.addPlugins(pageInterceptor);
*************************************************************************
return sqlSessionFactoryBean;
}
/**
* mapper代理对象加入ioc
* mybatis也会提供一个工厂类
*/
public MapperScannerConfigurer mapperScannerConfigurer(){
//mapper代理对象的factoryBean-》指定一个包-》mapper接口 -》sqlSession-》getMapper
MapperScannerConfigurer mapperScannerConfigurer=new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.atguigu.mapper");//mapper接口和mapperxml所在的共同包
return mapperScannerConfigurer;
}
}
配置类初始化
/**
* ioc的初始化类(设置那个是父ioc)
*/
public class SpringIocInit extends AbstractAnnotationConfigDispatcherServletInitializer {
//rootioc容器的配置类
@Override
protected Class>[] getRootConfigClasses() {
return new Class[]{DataSourceJavaConfig.class, MapperJavaConfigNew.class, ServiceJavaConfig.class};
}
//webioc容器的配置类
@Override
protected Class>[] getServletConfigClasses() {
return new Class[]{WebMvcJavaConfig.class};
}
//dispatcherServlet的拦截路径
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
前后端联调:
确保前后端接口能够正常对接,数据能够正确传输的过程
前后端联调的主要内容和目的:
①接口对接
前后端共同确认接口文档,约定数据格式(JSON/XML),确定接口调用方式和参数
②数据传输
③功能验证
④问题排查
跨域问题:
补充:浏览器遵循同源策略,要求是同源的资源才可以互相访问
同源策略:比较访问方和被访问方的域名(协议,ip,端口)三者相同就是同源,可以访问;不同就是非同源拒绝访问
前端的域名:http://127.0.0.1:5173
后端的域名:http://localhost:8080/ssm
二者是非同源的,那么如何才能让二者同源呢?
在后端修改
在后端的controller层的类上加上跨域访问的注解:
@CrossOrigin//允许其他源访问我们的controller 浏览器将不在拦截