SSM整合
1.整合原理
SMM框架指的是spring MVC,spring和mybatis框架的整合,是标准的MVC模式
各个框架的作用
- springMVC:表述层架构,处理浏览器发送给服务器的请求,将一些数据请求到浏览器。
- MyBatis:持久层框架,对数据库的操作(连接、访问、操作)。
- Spring:整合型架构,通过IOC管理对象,比如MyBatis中的SqlSession对象。
2.整合步骤
2.1创建新的项目
首先创建一个新的项目(项目名称命名为ssm)
这里选择Maven,之后点击创建,项目创建成功
2.2将项目转成为一个Maven工程
出现如下字样说明转换成功
同时打开项目目录出现webapp目录即为成功
2.3创建log4j和jdbc配置文件(resources包下)
jdbc.properties配置文件
在这里插入图片描述
log4j.properties配置文件(这段直接在网上找就好,我这里是找好的)
######
log4j.rootLogger = debug,stdout,D,E
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ./logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =./logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
2.4pom.xml文件中导入依赖
依赖有点多,已经分好了
在properties标签内我把版本号作为变量进行声明,方便maven依赖标签用${变量名}的形式动态获取版本号。这样做的好处是当版本号发生改变时,仅仅需要更新properties标签中的变量值就行了,不用煞费心思更新所有依赖的版本号,便于管理。
<?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>org.example</groupId>
<artifactId>ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<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.version>
<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>
<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>
<dependencies>
<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>
<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>
<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>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<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>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.8.0-beta4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.8.0-beta4</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</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>
</project>
2.5创建包以及配置类
整体包的创建就是这样
2.5.1数据源配置类DataSourceConfig
package com.csi.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
/**
* 数据源配置
*/
//@Configuration注解的作用:声明一个类为配置类,用于取代bean.xml配置文件注册bean对象。
@Configuration
//@PropertySource注解用来加载配置文件jdbc.properties,这里要声明路径
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfig {
//使用@Value注解注入属性值。
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
//使用@Bean注解告诉dataSource()方法,产生一个Bean对象,返回一个DataSource对象
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
2.5.2MyBatis的核心配置类MapperJavaConfig
package com.csi.config;
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.session.AutoMappingBehavior;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
public class MapperJavaConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
//实例化SqlSessionFactoryBean,SqlSessionFactoryBean是MyBatis中的一个类,用于创建SqlSessionFactory。
// SqlSessionFactory是用于创建SqlSession的工厂,而SqlSession是执行命令和获取映射的主要接口。
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
//'org.apache.ibatis.session.Configuration'是MyBatis的核心配置类,用于配置SQL映射语句、结果集映射、类型处理器等。创建这个类的实例,可以加载以下配置
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
//开启驼峰映射
//对应xml中的<setting name="mapUnderscoreToCamelCase" value="true"/>
configuration.setMapUnderscoreToCamelCase(true);
//开启logback日志输出
//<setting name="logImpl" value="SLF4J"/>
configuration.setLogImpl(Slf4jImpl.class);
//开启resultMap自动映射
//<setting name="autoMappingBehavior" value="FULL"/>
configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
//开启缓存
configuration.setCacheEnabled(true);
sqlSessionFactoryBean.setConfiguration(configuration);
/*
给实体类起别名
<typeAliases>
<package name="com.csi.pojo"/>
</typeAliases>
**/
sqlSessionFactoryBean.setTypeAliasesPackage("com.csi.domain");
/*
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
</plugin>
</plugins>
*/
/*
helperDialect:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。你可以配置helperDialect属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:
oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby
*/
PageInterceptor pageInterceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDiaLect", "mysql");
sqlSessionFactoryBean.setPlugins(pageInterceptor);
return sqlSessionFactoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
//MapperScannerConfigurer是一个用于在Spring启动时扫描指定包下的所有类
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//Spring启动时,它会扫描这个包(com.csi.mapper)下的所有类,并对其中的Mapper接口进行扫描和配置。
mapperScannerConfigurer.setBasePackage("com.csi.mapper");
return mapperScannerConfigurer;
}
}
2.5.3事务管理和AOP配置类ServiceJavaConfig
package com.csi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
//@EnableTransactionManagement:启用Spring的注解事务管理,Spring会自动管理事务的开启、提交和回滚。
@EnableTransactionManagement
//@ComponentScan("com.csi.service"):让Spring扫描"com.csi.service"这个包以及其子包,寻找并注册所有被@Component、@Service、@Repository、@Controller等注解的类,这些类在Spring中就是所谓的bean。
@ComponentScan("com.csi.service")
//@EnableAspectJAutoProxy:启动AspectJ的自动代理,用于实现面向切面的编程(AOP)。AOP是面向对象编程(OOP)的一种补充,它允许程序员在不改变业务逻辑代码的情况下,对业务逻辑进行增强,例如日志、事务管理等。
@EnableAspectJAutoProxy
public class ServiceJavaConfig {
//这个bean会被Spring用于管理数据库事务
@Bean
public TransactionManager transactionManager(DataSource dataSource){
TransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
return transactionManager;
}
}
2.5.4Spring MVC的配置类WebJavaConfig
package com.csi.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* WebMvcConfigurer接口用于通过实现类对Spring MVC框架进行定制。尽管这个类并没有实现任何方法,
* 但是它仍然必须被声明为实现这个接口,以启用Spring MVC的一些特定配置和功能。
*/
@Configuration
@ComponentScan("com.csi.controller")
//@EnableWebMvc注解将启用Spring MVC
@EnableWebMvc
public class WebJavaConfig implements WebMvcConfigurer {
}
2.5.5Spring MVC的初始化类WebMVCInit
package com.csi.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
* 此配置类是用来配置和初始化一个基于Spring MVC的Web应用程序的。
*/
public class WebMVCInit extends AbstractAnnotationConfigDispatcherServletInitializer {
/*
getRootConfigClasses()方法返回一个Class数组,表示的是这个应用程序的主配置类。
返回的是DataSourceConfig.class、MapperJavaConfig.class和ServiceJavaConfig.class三个类,
意味着Spring在启动时会加载这三个配置类。
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{DataSourceConfig.class, MapperJavaConfig.class, ServiceJavaConfig.class};
}
/*
getServletConfigClasses()方法返回一个Class数组,表示的是Web应用的Servlet配置类。
返回的是WebJavaConfig.class,Web应用会使用这个配置类来配置相关的Servlet。
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebJavaConfig.class};
}
/*
getServletMappings()方法返回一个字符串数组,表示的是Web应用中每个Servlet的URL映射。
返回的是"/",表示所有的请求都会被映射到这个Web应用。
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
配置类到这里就结束了,在项目中需要根据实际情况进行修改
2.6创建数据库(ssm)
2.6.1创建表
2.6.2添加数据
我在表中随机生成了1000条数据,便于测试
2.7创建实体类(Employee)
package com.csi.domain;
import lombok.Data;
/**
* 实体类
*/
//@Data注解省去代码中大量的get()、set()、toString()等方法。
@Data
public class Employee {
private int empId;
private String empName;
private double empSalary;
}
2.8创建数据访问层接口EmployeeMapper
package com.csi.mapper;
import com.csi.domain.Employee;
import java.util.List;
public interface EmployeeMapper {
//查询全部员工
List<Employee> employees();
}
2.9创建业务逻辑层接口EmployeeService及其实现类EmployeeServiceImpl
package com.csi.service;
import com.csi.domain.Employee;
import java.util.List;
public interface EmployeeService {
List<Employee> employees();
}
package com.csi.service.impl;
import com.csi.domain.Employee;
import com.csi.mapper.EmployeeMapper;
import com.csi.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
//@Service注解用于将EmployeeServiceImpl类标记为一个服务层的组件,并将其纳入Spring容器中进行管理。
@Service
//@Transactional是Spring框架的事务管理注解,用于声明EmployeeServiceImpl类的方法具有事务管理特性。
// 这意味着在方法执行过程中发生异常时,将自动回滚事务,保证数据的一致性。
@Transactional
public class EmployeeServiceImpl implements EmployeeService {
/*
@Autowired是Spring框架的自动装配注解,用于将EmployeeMapper类的实例自动注入到EmployeeServiceImpl类中。
*/
@Autowired
private EmployeeMapper employeeMapper;
/*
这是在employees()方法上的另一个@Transactional注解,用于声明该方法的事务属性。
Propagation.NOT_SUPPORTED表示该事务不支持嵌套事务,即不能在一个已经存在的事务内部再开启一个新的事务。
ReadOnly = true表示该事务只读,即对数据的操作不会改变数据库中的数据。
*/
@Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)
@Override
public List<Employee> employees() {
return employeeMapper.employees();
}
}
2.10创建EmployeeController
package com.csi.controller;
import com.csi.domain.Employee;
import com.csi.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
//@Controller:该标注用于标识一个SpringMVC控制器,用于处理HTTP请求。
//@Controller标注的类中定义的方法可以接收HTTP请求,并返回相应的视图或者数据。
@RestController
//@RequestMapping("/emp"):该注解为控制器类指定了一个URL前缀,即"/emp",表示该控制器处理的所有请求URL都需要以"/emp"开头。
@RequestMapping("/emp")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
//@GetMapping用于处理HTTP GET请求,它相当于@RequestMapping注解的快捷方式,用于映射GET请求到指定的处理方法上。
@GetMapping
public List<Employee> list(){
return employeeService.employees();
}
}
2.11创建EmployeeMapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--定义一个名为com.csi.mapper.EmployeeMapper的映射器-->
<mapper namespace="com.csi.mapper.EmployeeMapper">
<!-- 这里的id要与方法名相同,否则无法映射-->
<!-- resultType表示查询结果为Employee类型,将查询的结果映射到Employee实体类的属性-->
<select id="employees" resultType="employee">
SELECT emp_id empId,emp_name empName,emp_salary empSalary FROM t_emp
</select>
</mapper>
2.12配置Tomcat
Tomcat就已经配置好了,不过要确保Tomcat是10以上的版本,否则用不了,之后点击应用启动就可以了
3测试
输入设置好的路径localhost:8080/emp
里面会显示在之前在数据库生成的1000条数据,当然我们还可以做出一个分页的效果
在EmployeeController类做出修改
package com.csi.controller;
import com.csi.domain.Employee;
import com.csi.service.EmployeeService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
//@Controller:该标注用于标识一个SpringMVC控制器,用于处理HTTP请求。
//@Controller标注的类中定义的方法可以接收HTTP请求,并返回相应的视图或者数据。
@Controller
//@RequestMapping("/emp"):该注解为控制器类指定了一个URL前缀,即"/emp",表示该控制器处理的所有请求URL都需要以"/emp"开头。
@RequestMapping("/emp")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
//@GetMapping用于处理HTTP GET请求,它相当于@RequestMapping注解的快捷方式,用于映射GET请求到指定的处理方法上。
//pageNo用于设置页数,pageSize用于设置每页条数
@GetMapping
public List<Employee> list(@RequestParam(value = "pageNo",defaultValue = "1") int pageNo,
@RequestParam(value = "pageSize",defaultValue = "10")int pageSize){
PageHelper.startPage(pageNo,pageSize);
return employeeService.employees();
}
}
重新启动后结果如下:
默认只会显示第1页的10条数据
并且可以通过设置参数,查询第几页的数据
同时还可以修改每页的条数