1 添加依赖
- 在项目下的pom.xml里面设置打包方式为pom
<packaging>pom</packaging>
- 在项目下的pom.xml里面加入需要的依赖
<!-- ssm整合需要的所有的依赖 --> <properties> <spring.version>6.0.6</spring.version> <jakarta.annotation-api.version>2.1.1</jakarta.annotation-api.version> <jakarta.jakartaee-web-api.version>9.1.0</jakarta.jakartaee-web-api.v ersion> <jackson-databind.version>2.15.0</jackson-databind.version> <hibernate-validator.version>8.0.0.Final</hibernate-validator.version> <mybatis.version>3.5.11</mybatis.version> <mysql.version>8.0.25</mysql.version> <pagehelper.version>5.1.11</pagehelper.version> <druid.version>1.2.8</druid.version> <mybatis-spring.version>3.0.2</mybatis-spring.version> <jakarta.servlet.jsp.jstl-api.version>3.0.0</jakarta.servlet.jsp.jstl-api.version> <logback.version>1.2.3</logback.version> <lombok.version>1.18.26</lombok.version> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </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 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 --> <dependencies> <!--spring pom.xml依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>jakarta.annotation</groupId> <artifactId>jakarta.annotation-api</artifactId> <version>${jakarta.annotation-api.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</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-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- 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 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-web-api</artifactId> <version>${jakarta.jakartaee-web-api.version}</version> <scope>provided</scope> </dependency> <!-- jsp需要依赖! jstl--> <dependency> <groupId>jakarta.servlet.jsp.jstl</groupId> <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> <version>${jakarta.servlet.jsp.jstl-api.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson-databind.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>${hibernate-validator.version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator-annotation-processor --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator-annotation-processor</artifactId> <version>${hibernate-validator.version}</version> </dependency> <!-- mybatis mybatis / 3.5.11 mysql / 8.0.25 pagehelper / 5.1.11 --> <!-- mybatis依赖 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <!-- MySQL驱动 mybatis底层依赖jdbc驱动实现,本次不需要导入连接池,mybatis自带! --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pagehelper.version}</version> </dependency> <!-- 整合第三方特殊依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis-spring.version}</version> </dependency> <!-- 日志 , 会自动传递slf4j门面--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> </dependencies>
- 配置日志
<?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.example.mybatis" level="DEBUG" /> </configuration>
- 新建module,module下面的pom.xml文件里设置打包方式为war
<packaging>war</packaging>
- 设置webapp:在左上角project structure-> module中,选中相应的模块,点击左上角的加号,增加“web”模块
- 将
Web Module Deployment Descriptor
添加为……\src\main\webapp\WEB-INF\web.xml - 将
Web Resource Directory
设置为……\src\main\webapp
- 将
2 控制层配置类
控制层的配置类,需要配置controller,SpringMVC
在src文件的自己的包(如com.example)下建包config,新建WebJavaConfig.java
-
声明@Configuration注解,代表配置类
-
实现implements接口WebMvcConfigurer
-
实现功能与对应方式
实现功能 方式 controller @ComponentScan({“com.example.controller”}) 全局异常处理器 @ComponentScan({“com.example.exceptionhandler”}) handlerMapping,handlerAdapter @EnableWebMvc 静态资源处理 configurer.enable() 视图解析器前后缀 registry.jsp(“/WEB-INF/views/”,“jsp”) json转换器 registry.addInterceptor(new XXInterceptor()).addPathPatterns(“”).excludePathPatterns(“”) 拦截器 @EnableWebMvc -
实现代码
@Configuration @EnableWebMvc @ComponentScan({"com.example.controller","com.example.exceptionhandler"}) 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 XXInterceptor()).addPathPatterns("").excludePathPatterns(""); } }
3 业务层配置类
业务层配置类:需要配置service,aop,tx
在src文件下的包(如com.example)-> config,新建ServiceJavaConfig.java
-
声明@Configuration注解,代表配置类
-
实现功能与对应方式
实现功能 方式 service @ComponentScan(“com.example.service”) aop代理 @EnableAspectJAutoProxy tx事务管理 @EnableTransactionManagement 指定具体的事务管理器 transactionManager(DataSource dataSource) -
注意:其中TransactionManager(DataSource dataSource)需要注入连接池(配置mybatis的配置类后IOC可以自动注入)
-
实现代码
@EnableTransactionManagement @EnableAspectJAutoProxy @Configuration @ComponentScan("com.example.service") public class ServiceJavaConfig { @Bean public DataSourceTransactionManager transactionManager(DataSource dataSource){ DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSource); return transactionManager; } }
4 持久层配置类
配置mapper代理对象,连接池和mybatis核心组件配置
mybatis之前自己调用官方api使用的核心方法有:
//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();
注意:
- 其中事务的提交也可以使用
sqlSessionFactory.openSession(true)
来自动提交 - 并不是所有的类对象都需要存储到IOC容器中,只需要:
- 将SqlSessionFactory实例存储到IoC容器
- 将Mapper实例存储到IoC容器
4.1 方式1
保留mybatis的外部配置文件(xml), 但是数据库连接信息交给Druid连接池配置,不使用mybatis-config.xml中自带的配置
- 数据库连接配置文件 Resources->jdbc.properties
jdbc.user=root jdbc.password=root jdbc.url=jdbc:mysql:///mybatis-example jdbc.driver=com.mysql.cj.jdbc.Driver
- mybatis核心配置文件 mybatis-config.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> <!-- 开启驼峰式映射--> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 开启logback日志输出--> <setting name="logImpl" value="SLF4J"/> <!--开启resultMap自动映射 --> <setting name="autoMappingBehavior" value="FULL"/> </settings> <typeAliases> <!-- 给实体类起别名 --> <package name="com.example.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> </configuration>
4.1.1 合起来配置(会出现问题)
- 配置类文件 MapperJavaConfig.java
实现功能 | 方式 |
---|---|
数据库配置文件 | @PropertySource(“classpath:jdbc.properties”),@Value(“${jdbc.user}”) |
数据库连接池配置 | DataSource dataSource() |
数据库工厂 | SqlSessionFactoryBean sqlSessionFactoryBean |
mapper的类与xml配置 | MapperScannerConfigurer mapperScannerConfigurer |
- 但是这种方式(如下)会产生问题:初始化顺序(SqlSessionFactoryBean和MapperScannerConfigurer会早于Value注解生效)可能会导致属性注入@Value读取为null,因此需要拆分配置类
出现问题: 当配置类被加载时,Spring容器会首先处理Bean的定义和初始化,其中包括sqlSessionFactoryBean和mapperScannerConfigurer的初始化。在这个过程中,如果@Value注解所在的Bean还没有被完全初始化,可能会导致注入的属性值为null
解决方法: 分开配置时,会把所有对象全都生成之后缓存起来,再统一进行互相引用。因此可以进行分开配置
@Configuration
@PropertySource("classpath:jdbc.properties")
public class MapperJavaConfig {
@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;
}
/**
* 配置SqlSessionFactoryBean,指定连接池对象和外部配置文件即可
* @param dataSource 需要注入连接池对象
* @return 工厂Bean
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
//实例化SqlSessionFactory工厂
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//设置连接池
sqlSessionFactoryBean.setDataSource(dataSource);
//设置配置文件
//包裹外部配置文件地址对象
Resource resource = new ClassPathResource("mybatis-config.xml");
sqlSessionFactoryBean.setConfigLocation(resource);
return sqlSessionFactoryBean;
}
/**
* 配置Mapper实例扫描工厂,配置 <mapper <package 对应接口和mapperxml文件所在的包
* @return
*/
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//设置mapper接口和xml文件所在的共同包
mapperScannerConfigurer.setBasePackage("com.example.mapper");
return mapperScannerConfigurer;
}
}
4.1.2 分开配置
-
将MapperJavaConfig.java拆分为数据库配置类DataSourceJavaConfig.java和
mybatis配置类MapperJavaConfig.java- 数据库配置类DataSourceJavaConfig.java
@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配置类MapperJavaConfig.java
@Configuration public class MapperJavaConfig { /** * 配置SqlSessionFactoryBean,指定连接池对象和外部配置文件即可 * @param dataSource 需要注入连接池对象 * @return 工厂Bean */ @Bean public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){ //实例化SqlSessionFactory工厂 SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); //设置连接池 sqlSessionFactoryBean.setDataSource(dataSource); //设置配置文件 //包裹外部配置文件地址对象 Resource resource = new ClassPathResource("mybatis-config.xml"); sqlSessionFactoryBean.setConfigLocation(resource); return sqlSessionFactoryBean; } /** * 配置Mapper实例扫描工厂,配置 <mapper <package 对应接口和mapperxml文件所在的包 * @return */ @Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); //设置mapper接口和xml文件所在的共同包 mapperScannerConfigurer.setBasePackage("com.example.mapper"); return mapperScannerConfigurer; } }
4.2 方式2
不使用mybatis-config.xml配置文件,全部使用配置类。可以避免xml文件解析效率低的问题
- 数据库连接池配置类如上节DataSourceJavaConfig.java
@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; } }
- 创建文件config->MapperJavaConfig.java(与上节不同)
@Configuration public class MapperJavaConfigNew { /** * 配置SqlSessionFactoryBean,指定连接池对象和外部配置文件即可 * @param dataSource 需要注入连接池对象 * @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.example.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.example.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.example.mapper"); return mapperScannerConfigurer; } }
5 配置类的初始化
- Spring的初始化类:将上述所有配置类进行初始化
- config->SpringIoCInit.java
- 继承AbstractAnnotationConfigDispatcherServletInitializer,需要实现三个方法
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { //指定root容器对应的配置类 @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[] {MapperJavaConfig.class, ServiceJavaConfig.class, DataSourceJavaConfig.class }; } //指定web容器对应的配置类 @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] { WebJavaConfig.class }; } //指定dispatcherServlet处理路径,通常为 / @Override protected String[] getServletMappings() { return new String[] { "/" }; } }
6 实际测试
下一节:【SSM】4. SSM项目的配置测试demo用一个简单的小demo来测试整个配置,附上所有的代码