SSM的简易整合,基于RESTful风格
1、整合前言
本文是一个简单的SSM整合案例,基于RESTful风格,主要是简单记录一下学习笔记。
开发的相关环境:
- JDK:1.8
- Spring:5.2.7.RELEASE
- Mybatis:3.5.3
- MySQL数据库
- Druid连接池
数据库源文件:
-- ----------------------------
-- Table structure for t_emp
-- ----------------------------
DROP TABLE IF EXISTS `t_emp`;
CREATE TABLE `t_emp` (
`emp_id` int(11) NOT NULL AUTO_INCREMENT,
`emp_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`emp_salary` double(10, 2) NULL DEFAULT NULL,
`emp_address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`emp_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_emp
-- ----------------------------
INSERT INTO `t_emp` VALUES (1, '张三', 13000.00, '广东深圳南山区');
INSERT INTO `t_emp` VALUES (2, '李四', 6000.00, '山东菏泽曹县');
INSERT INTO `t_emp` VALUES (3, '赵六', 10000.00, '上海浦东区');
导入相关的依赖:
<!--定义版本信息-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<spring.version>5.2.7.RELEASE</spring.version>
<mybatis.version>3.5.3</mybatis.version>
<mybatis.spring.version>2.0.6</mybatis.spring.version>
<mybatis.generator.version>1.4.0</mybatis.generator.version>
<log4j.version>1.2.17</log4j.version>
<mysql.version>8.0.23</mysql.version>
<druid.version>1.2.4</druid.version>
</properties>
<dependencies>
<!--Spring相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</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-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<!--Mybatis相关依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis.spring.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>${mybatis.generator.version}</version>
</dependency>
<!--数据库相关依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--日志相关依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!--单元测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--处理json数据的依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.5</version>
</dependency>
</dependencies>
2、相关的配置文件
注:配置文件都放在maven项目的resources目录下。
连接数据库的文件(db.properties):
datasource.driver-class-name=com.mysql.cj.jdbc.Driver
datasource.url=jdbc:mysql://localhost:3306/ssm?useSSL=false&serverTimezone=UTC&characterEncoding=utf8&allowMultiQueries=true
datasource.username=root
datasource.password=root
Spring的核心xml配置文件(applicationContext.xml):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- ================一、连接数据库================ -->
<!--1、引入外部资源文件-->
<context:property-placeholder location="classpath:db.properties"/>
<!--2、配置数据源-->
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="driverClassName" value="${datasource.driver-class-name}"/>
<property name="url" value="${datasource.url}"/>
<property name="username" value="${datasource.username}"/>
<property name="password" value="${datasource.password}"/>
</bean>
<!-- ===================二、整合Mybatis==================== -->
<!-- 1.配置SqlSessionFactory -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<!-- 装配数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 配置Mybatis全局配置的两个方案只能二选一 -->
<!-- (1)、配置Mybatis全局配置方案一:还是在Mybatis自己的配置文件中配,在Spring中指定配置文件位置 -->
<!-- Mybatis全局配置文件的位置使用configLocation指定 <property name="configLocation" value=""/> -->
<!-- (2)、配置Mybatis全局配置方案二(推荐):在Spring配置文件配置 -->
<!-- 在Spring中执行Mybatis全局配置 -->
<property name="configuration">
<bean class="org.apache.ibatis.session.Configuration">
<property name="mapUnderscoreToCamelCase" value="true"/><!--驼峰原则-->
<property name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/><!--打印SQL-->
</bean>
</property>
<!-- 配置别名,使用包扫描-->
<property name="typeAliasesPackage" value="com.thr.entity"/>
<!-- 指定Mapper配置文件的位置XxxMapper.xml -->
<property name="mapperLocations" value="classpath:com/thr/mapper/*Mapper.xml"/>
</bean>
<!-- 2.对Mapper接口所在的包进行扫描 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" id="mapperScannerConfigurer">
<!-- 指定Mybatis中存放Mapper接口的包 -->
<property name="basePackage" value="com.thr.mapper"/>
<!-- 可选,如果不写,Spring启动时候。容器中自动会按照类型去把SqlSessionFactory对象注入进来 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<!-- ===================三、配置声明式事务==================== -->
<!-- 1.配置事务管理器的bean -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 2.开启基于注解的声明式事务 -->
<tx:annotation-driven/>
<!-- 3.配置自动扫描的包 -->
<context:component-scan base-package="com.thr.service"/>
</beans>
SpringMVC相关的xml配置文件(spring-mvc.xml):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.thr.controller"/>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 配置default-servlet-handler将没有映射的请求放行 -->
<mvc:default-servlet-handler/>
<!-- 开启SpringMVC的注解驱动功能(标配) -->
<mvc:annotation-driven/>
</beans>
日志的配置(log4j.properties):
# 全局日志配置 INFO DEBUG ERROR
log4j.rootLogger=INFO, stdout
# MyBatis 日志配置
log4j.logger.cn.kgc.kb09=TRACE
# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%ns
3、Mybatis逆向工程生成代码
逆向工程的配置文件(generatorConfig.xml):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--targetRuntime="MyBatis3Simple"表示生成简易版本,这里创建原始版本,参数为MyBatis3-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释,true:是;false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8&
useSSL=false&serverTimezone=GMT%2B8"
userId="root"
password="root">
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL和NUMERIC类型解析为Integer,为true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- javaBean的生成策略,targetProject:POJO类生成的位置,注意要加上项目名称,在这里搞了好久 -->
<javaModelGenerator targetPackage="com.thr.entity" targetProject="./ssm/src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="true"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- SQL映射文件的生成策略,targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.thr.mapper" targetProject="./ssm/src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- Mapper接口的生成策略,targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.thr.mapper" targetProject="./ssm/src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 配置表信息 -->
<!-- schema即为数据库名 tableName为对应的数据库表 domainObjectName是要生成的实体类 enableByExample是否生成example类 -->
<table schema="ssm" tableName="t_emp" domainObjectName="Employee"/>
</context>
</generatorConfiguration>
逆向工程生成相关代码的启动类:
/**
* 逆向工程核心生成代码
*/
public class GeneratorSql {
public static void main(String[] args) throws Exception {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
// 指定逆向工程配置文件
String file = GeneratorSql.class.getResource("/generatorConfig.xml").getFile();
File configFile = new File(file);
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
}
执行后会生成如下相关的代码。
4、业务层(Service)和控制层(Controller)
编写Service接口(EmployeeService):
public interface EmployeeService {
List<Employee> findAll();
Employee findById(Integer id);
void add(Employee employee);
void update(Employee employee);
void delete(Integer id);
}
编写Service接口的实现类(EmployeeServiceImpl):
@Service
@Transactional
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
@Override
public List<Employee> findAll() {
return employeeMapper.selectByExample(new EmployeeExample());
}
@Override
public Employee findById(Integer id) {
return employeeMapper.selectByPrimaryKey(id);
}
@Override
public void add(Employee employee) {
employeeMapper.insert(employee);
}
@Override
public void update(Employee employee) {
employeeMapper.updateByPrimaryKey(employee);
}
@Override
public void delete(Integer id) {
employeeMapper.deleteByPrimaryKey(id);
}
}
编写控制层Controller代码(EmployeeController):
@RestController
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
/**
* 查询所有员工信息
* @return
*/
@GetMapping("/emp")
public List<Employee> findAll(){
List<Employee> list = employeeService.findAll();
System.out.println(list);
return list;
}
/**
* 根据ID查询
* @param id
* @return
*/
@GetMapping("/emp/{id}")
public Employee findById(@PathVariable("id") Integer id){
return employeeService.findById(id);
}
/**
* 添加
* @param employee
*/
@PostMapping("/emp")
public void add(Employee employee){
employeeService.add(employee);
}
/**
* 修改,这里接收前端发来的JSON格式的数据
* @param employee
*/
@PutMapping("/emp")
public void update(@RequestBody Employee employee){
employeeService.update(employee);
}
/**
* 删除数据
* @param id
*/
@DeleteMapping("/emp/{id}")
public void delete(@PathVariable("id") Integer id){
employeeService.delete(id);
}
}
5、测试整合结果
[1]、查询所有数据(GET请求):http://localhost:8080/ssm/emp/
[2]、根据ID查询数据(GET请求):http://localhost:8080/ssm/emp/1
[3]、添加员工信息(POST请求):http://localhost:8080/ssm/emp
对PostMan的Body中的四个选项进行简单说明:
- form-data:等价于http请求中的multipart/form-data,可以上传文件或者键值对,最后都会转化为一条消息,一般用来做文件的上传。
- x-www-form-urlencoded:相当于http请求中的application/x-www-from-urlencoded,只能上传键值对,相当于将表单内的数据转换为Key-Value。
- raw:表示的参数可以是任意格式的,可以上传text、json、xml、html等。
- binary:相当于Content-Type:application/octet-stream,只可以上传二进制数据,通常用来上传文件,但是一次只能上传一个文件。
添加后的数据库变化:
[4]、修改数据(PUT请求):http://localhost:8080/ssm/emp
,这里发送的json格式的数据,因为PUT请求用key--value不好测试。
修改后的数据库变化:
[1]、删除数据(DELETE请求):http://localhost:8080/ssm/emp/4