> 文档中心 > JavaEE——Spring Boot整合框架

JavaEE——Spring Boot整合框架

目录

  • 数据访问
    • 准备数据库
    • 整合Mybatis
      • 第一步:创建项目
      • 第二步:在 pom.xml 中添加相关 jar 依赖
      • 第三步:配置数据源
      • 第四步:编写Model类
      • 第四步:编写Controller
      • 第五步:编写Service接口和实现类
      • 第六步:编写Mapper接口
      • 第七步:编写Mapper映射
      • 第八步:配置Mapper映射文件编译目录
      • 第九步:配置Mapper映射文件存储位置
      • 第十步:启动测试
    • 优化Mapper接口开发
      • 第一步:注释掉@Mapper注解
      • 第二步:打开@MapperScan注解
    • 整合数据源
      • 测试默认数据源
      • 切换成其他数据源
      • 数据源的基本配置
      • 数据源的其他信息
        • 测试连接池默认参数
        • 连接池其他参数设置
    • 整合事务支持
      • 第一步:在Mapper接口中定义添加商品方法
      • 第二步:定义Mapper映射
      • 第三步:在Service接口中定义添加商品方法
      • 第四步:在Service实现类中实现添加商品方法
      • 第五步:编写控制器类
      • 第六步:在启动类上开启事务
      • 第七步:启动测试事务
        • 测试业务方法正常执行
        • 测试方法抛出RuntimeException
        • 测试方法抛出Exception

数据访问

准备数据库

CREATE DATABASE eshop;USE eshop;#创建用户表CREATE TABLE userinfo (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,userName VARCHAR(20) NOT NULL , #用户名称userPass VARCHAR(48) NOT NULL, #用户密码birthday DATE DEFAULT NULL , #生日gender CHAR(1) DEFAULT NULL , #性别address VARCHAR(256) DEFAULT NULL #地址);#商品表CREATE TABLE goods (id INT AUTO_INCREMENT PRIMARY KEY,goodsname VARCHAR(32), #商品名称price FLOAT(10,1), #商品定价memo TEXT , #商品描述pic VARCHAR(200) , #商品图片createtime DATETIME #生产日期);#订单CREATE TABLE orders (id INT AUTO_INCREMENT PRIMARY KEY,#订单号userid INT , #下单用户idcreatetime DATETIME NOT NULL, #创建订单时间memo VARCHAR(100) #备注);#外键:订单表userid引用userinfo的idALTER TABLE orders ADD CONSTRAINT fk_orders_userinfo_id FOREIGN KEY (userid)REFERENCES userinfo (id);#订单明细表CREATE TABLE orderdetail (id INT AUTO_INCREMENT PRIMARY KEY,orderid INT NOT NULL , #订单idgoodsid INT NOT NULL , #商品iditemsnum INT DEFAULT NULL #商品购买数量);#外键:orderdetail的ordersid引用表orders表的idALTER TABLE orderdetail ADD CONSTRAINT fk_orderdetail_orders_id FOREIGN KEY(orderid)REFERENCES orders (id);#外键:orderdetail的goodsid引用表goods表的idALTER TABLE orderdetail ADD CONSTRAINT fk_orderdetail_goods_id FOREIGN KEY(goodsid)REFERENCES goods (id);#初始化用户数据INSERT INTO userinfo(userName,userPass,birthday,gender,address)VALUES('admin','admin','1980-10-10','男','陕西西安');INSERT INTO userinfo(userName,userPass,birthday,gender,address)VALUES('林冲','lichong','1982-11-10','男','河南开封');INSERT INTO userinfo(userName,userPass,birthday,gender,address)VALUES('扈三娘','husanniang','1981-03-10','女','山东聊城');INSERT INTO userinfo(userName,userPass,birthday,gender,address)VALUES('孙二娘','sunerniang','1979-03-10','女','山东曾头市');#初始化商品数据INSERT INTO goods(goodsname,price,memo,pic,createtime)VALUES('平谷大桃','33.6','产自河北','pinggudatao.jpg','2017-12-12 12:12:12');INSERT INTO goods(goodsname,price,memo,pic,createtime)VALUES('油桃','17.6','产自河北','youtao.jpg','2017-12-13 12:12:12');INSERT INTO goods(goodsname,price,memo,pic,createtime)VALUES('水蜜桃','39.6','产自河北','shuimitao.jpg','2017-12-14 12:12:12');INSERT INTO goods(goodsname,price,memo,pic,createtime)VALUES('蟠桃','33.6','产自河北','pantao.jpg','2017-12-11 12:12:12');INSERT INTO goods(goodsname,price,memo,pic,createtime)VALUES('毛桃','31.6','产自河北','maotao.jpg','2017-10-12 12:12:12');INSERT INTO goods(goodsname,price,memo,pic,createtime)VALUES('樱桃','43.6','产自河北','yingtao.jpg','2017-11-22 12:12:12');#初始化一条订单INSERT INTO orders(userid,createtime,memo)VALUES(2,'2017-09-21 16:26:51','要新鲜的');#初始化订单明细INSERT INTO orderdetail(orderid,goodsid,itemsnum)VALUES(1,1,3);INSERT INTO orderdetail(orderid,goodsid,itemsnum)VALUES(1,2,2);#初始化一条订单INSERT INTO orders(userid,createtime,memo)VALUES(2,'2017-09-22 16:26:50','和上次的一样');#初始化订单明细INSERT INTO orderdetail(orderid,goodsid,itemsnum)VALUES(2,1,3);INSERT INTO orderdetail(orderid,goodsid,itemsnum)VALUES(2,2,2);

整合Mybatis

新建模块,名称:springboot004

第一步:创建项目

在这里插入图片描述
在这里插入图片描述

第二步:在 pom.xml 中添加相关 jar 依赖

<!--MyBatis 整合 SpringBoot 的起步依赖--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.0.0</version></dependency><!--MySQL 的驱动依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>

提示:MySQL 的驱动依赖的版本由父工程管理

第三步:配置数据源

SpringBoot2.6.0版本默认使用Hikari数据源

#配置数据库的连接信息spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/eshop?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTCspring.datasource.username=rootspring.datasource.password=

第四步:编写Model类

在com.ltw.model包中创建实体类

//使用lombokpublic class Goods {private Integer id;private String goodsname;private Double price;private String memo;private String pic;private Date createtime;}

第四步:编写Controller

在com.ltw.controller包中创建控制器
请求/goods/list
响应JSON

@Controller@RequestMapping("/goods")public class GoodsController {@Autowiredprivate IGoodsService goodsService;@RequestMapping("/list")public @ResponseBody Object list(){List<Goods> list = goodsService.selectList();return list;}public IGoodsService getGoodsService() {return goodsService;}public void setGoodsService(IGoodsService goodsService) {this.goodsService = goodsService;}}

第五步:编写Service接口和实现类

在com.ltw.service包中创建业务接口
Service接口

public interface IGoodsService {List<Goods> selectList();}

在com.ltw.service.impl包中创建业务实现
Service实现

@Servicepublic class GoodsService implements IGoodsService {@Autowiredprivate IGoodsMapper goodsMapper;@Overridepublic List<Goods> selectList() {return goodsMapper.selectList();}public IGoodsMapper getGoodsMapper() {return goodsMapper;}public void setGoodsMapper(IGoodsMapper goodsMapper) {this.goodsMapper = goodsMapper;}}

在这里插入图片描述

第六步:编写Mapper接口

在com.ltw.mapper包中创建Mapper接口

@Mapperpublic interface IGoodsMapper {List<Goods> selectList();}

@Mapper注解创建了Mapper对象,并交给spring容器管理

第七步:编写Mapper映射

在com.ltw.mapper包中创建Mapper映射配置文件

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.ltw.mapper.IGoodsMapper"><resultMap id="goodsMap" type="com.ltw.model.Goods"><id column="id" property="id" /><result column="goodsname" property="goodsname" /><result column="price" property="price"/><result column="memo" property="memo"/><result column="pic" property="pic"/><result column="createtime" property="createtime"/></resultMap><select id="selectList" resultMap="goodsMap">select * from goods</select></mapper>

第八步:配置Mapper映射文件编译目录

<resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource></resources>

第九步:配置Mapper映射文件存储位置

#配置mapper映射文件存储位置mybatis.mapper-locations=classpath:**/mapper/*.xml

**表示classpath目录及其所有的子目录

至此整合Mybatis完毕,完整的项目结构如下
在这里插入图片描述

第十步:启动测试

在这里插入图片描述

优化Mapper接口开发

@Mapper注解标注在Mapper接口上,实现了Mapper接口对象的创建
使用@MapperScan注解扫描包,可省去在每个Mapper接口上标注@Mapper

第一步:注释掉@Mapper注解

//@Mapperpublic interface IGoodsMapper {List<Goods> selectList();}

第二步:打开@MapperScan注解

@SpringBootApplication@MapperScan(basePackages = "com.kaifamiao.mapper")public class Springboot005Application {public static void main(String[] args) {SpringApplication.run(Springboot005Application.class, args);}}

整合数据源

SpringBoot 2.6.0默认使用HikariDataSource,我们可以通过测试类确认SpringBoot使用的数据源。

测试默认数据源

在测试类中将Spring容器中的数据源对象注入给测试类的属性,输出类名。

@SpringBootTestclass Springboot005ApplicationTests {@AutowiredDataSource dataSource;@Testvoid contextLoads() {System.out.println(dataSource.getClass());}}

运行测试类,观察控制器输出结果如下:
JavaEE——Spring Boot整合框架
证明默认使用的是Hikari数据源。
Springboot默认支持4种数据源类型,分别是:

  1. org.apache.tomcat.jdbc.pool.DataSource
  2. com.zaxxer.hikari.HikariDataSource
  3. org.apache.commons.dbcp.BasicDataSource
  4. org.apache.commons.dbcp2.BasicDataSource

对于这4种数据源,当 classpath 下有相应的类存在时,Springboot 会通过自动配置为其生成DataSourceBean,DataSourceBean默认只会生成一个,四种数据源类型的生效先后顺序如下:Tomcat–> Hikari --> Dbcp --> Dbcp2 。

切换成其他数据源

如果想更换成其他数据源,需要两个步骤,例如更换成Druid数据源。
第一步:导入数据源jar包

<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version></dependency>

第二步:在application.properties中配置数据源

#数据源基本配置spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/eshop?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTCspring.datasource.username=rootspring.datasource.password=#切换成Druid数据源spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

测试数据源切换是否成功
重新运行测试类

@SpringBootTestclass Springboot005ApplicationTests {@AutowiredDataSource dataSource;@Testvoid contextLoads() {System.out.println(dataSource.getClass());}}

运行测试类,观察控制器输出结果如下:
class com.alibaba.druid.pool.DruidDataSource
证明数据源已经切换成Druid。

数据源的基本配置

数据源的基本配置包括了
spring.datasource.driver-class-name
spring.datasource.url
spring.datasource.username
spring.datasource.password
以上四个数据源基本配置对于每一种数据源都是通用的。

数据源的其他信息

虽然数据源基本配置对于每一种数据源都是通用的,但是不同数据源连接池参数配置不是通用的。

测试连接池默认参数

现在数据源已经切换到Druid,Druid负责管理连接池,而连接池参数的设置是否合理在极大程度上影响程序运行的性能。那么此时Druid连接池参数是怎么设置的呢?
在调试模式下运行下面的测试,在控制台中观察默认情况下Druid的连接池参数默认设置。

@SpringBootTestclass Springboot005ApplicationTests {@AutowiredDataSource dataSource;@Testvoid contextLoads() throws SQLException {System.out.println(dataSource.getClass());}}

在这里插入图片描述
发现连接池初始化大小默认为0。如何设置连接池运行参数呢。
下面介绍如何配置德鲁伊数据源的连接池参数配置。

连接池其他参数设置

第一步:配置连接池参数
首先将德鲁伊连接池配置参数输入到application.properties配置文件中

#数据源连接池的参数配置spring.datasource.initialSize: 5spring.datasource.minIdle: 5spring.datasource.maxActive: 20spring.datasource.maxWait: 60000

第二步:自定义Druid数据源对象,交给spring容器管理
使用Java-based方式定义Druid数据源的bean对象,交给spring容器管理

package com.ltw.config;import com.alibaba.druid.pool.DruidDataSource;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.sql.DataSource;//@Configuration注解定义Bean的来源类@Configurationpublic class DruidConfig {//@Bean将对象交给spring容器管理@Bean//@ConfigurationProperties注解将application.properties配置文件中前缀为spring.datasource的属性注入给DruidDataSource的bean对象@ConfigurationProperties(prefix = "spring.datasource")public DataSource druid(){return new DruidDataSource();}}

解释:
@ConfigurationProperties注解用于读取application.properties中的配置信息
参数prefix = "spring.datasource"表示读取以"spring.datasource"开头的配置信息,并按照"spring.datasource"后面的名称与Druid连接池参数名称相同注入属性值。
第三步:测试连接池其他参数设置
在调试模式下运行下面的测试,在控制台中观察默认情况下Druid的连接池参数默认设置。

@SpringBootTestclass Springboot005ApplicationTests {@AutowiredDataSource dataSource;@Testvoid contextLoads() throws SQLException {System.out.println(dataSource.getClass());}}

在这里插入图片描述
发现连接池初始化大小默认为5。application.perperties中连接池参数设置已经生效。

整合事务支持

Spring Boot 使用事务非常简单,底层依然采用的是 Spring 本身提供的事务管理

在入口类中使用注解 @EnableTransactionManagement 开启事务支持
在访问数据库的 Service 方法上添加注解 @Transactional 即可

事务执行的三种情况:
当方法内部抛出RuntimeException时事务回滚
当方法内部抛出Exception时事务提交
当方法内部没有抛出异常时事务提交

提示:事务是在业务层实现的

以添加订单为例,测试事务
一个订单中购买两件商品
向orders表中添加订单
向orderdetail表中添加订单中购买的商品

第一步:在Mapper接口中定义添加商品方法

public interface IOrdersMapper {int insert(Orders record);}
public interface IOrderdetailMapper {int insert(Orderdetail record);}

第二步:定义Mapper映射

<insert id="insert" parameterType="com.kaifamiao.model.Orders"><selectKey order="AFTER" keyProperty="id" resultType="java.lang.Integer">SELECT LAST_INSERT_ID()</selectKey>INSERT INTO orders(userid,createtime,memo)VALUES(#{userid},#{createtime},#{memo})</insert><insert id="insert" parameterType="com.kaifamiao.model.Orderdetail" >insert into orderdetail (id, orderid, goodsid, itemsnum)values (#{id}, #{orderid}, #{goodsid}, #{itemsnum)</insert>

第三步:在Service接口中定义添加商品方法

public interface IOrderService {public void insert(Orders orders, Orderdetail orderdetail[]) throwsException;}

注意:方法参数中包含了订单和订单中购买的商品

第四步:在Service实现类中实现添加商品方法

在insert方法上标注@Transactional注解,会在调用方法前开启事务,在方法调用结束后提交事务,在方法跑车RuntimeException时回滚事务。

/*** 插入订单和订单明细,多条SQL语句应该在事务环境下执行*/@Transactionalpublic void insert(Orders orders, Orderdetail[] orderdetail) throwsException {//orders插入到数据库,并获取出主键值ordersMapper.insert(orders);if(orderdetail!=null && orderdetail.length>0) {for (int i = 0; i < orderdetail.length; i++) {//订单的主键设置给订单明细的外键orderdetail[i].setOrderid(orders.getId());//orderdetail插入到数据库orderdetailMapper.insert(orderdetail[i]);}}}

第五步:编写控制器类

@RequestMapping("/insert")public @ResponseBody String addOrder() throws Exception {//创建订单,此时订单还没有编号Orders orders = new Orders();orders.setUserid(1);orders.setMemo("发票一起寄出");orders.setCreatetime(new Date());//创建订单中购买的商品明细1,该明细中还没有订单号Orderdetail orderdetail1 =new Orderdetail();orderdetail1.setGoodsid(1);orderdetail1.setItemsnum(3);//创建订单中购买的商品明细2,该明细中还没有订单号Orderdetail orderdetail2 =new Orderdetail();orderdetail2.setGoodsid(1);orderdetail2.setItemsnum(3);//将商品明细封装到数组中国Orderdetail orderdetails[] =new Orderdetail[]{orderdetail1,orderdetail2};orderService.insert(orders,orderdetails);return "已添加订单";}

第六步:在启动类上开启事务

@SpringBootApplication@MapperScan(basePackages = "com.kaifamiao.mapper")//开启事务支持(可选项,但业务方法上的@Transactional 必须添加)@EnableTransactionManagementpublic class Springboot005Application {public static void main(String[] args) {SpringApplication.run(Springboot005Application.class, args);}}

第七步:启动测试事务

测试业务方法正常执行

业务方法代码如下:程序正常运行,没有抛出异常,下单后提交事务,下单成功。

@Transactionalpublic void insert(Orders orders, Orderdetail[] orderdetail) throwsException {//orders插入到数据库,并获取出主键值ordersMapper.insert(orders);if(orderdetail!=null && orderdetail.length>0) {for (int i = 0; i < orderdetail.length; i++) {//订单的主键设置给订单明细的外键orderdetail[i].setOrderid(orders.getId());//orderdetail插入到数据库orderdetailMapper.insert(orderdetail[i]);}}}

运行后查看数据库
在这里插入图片描述
结果显示:订单添加正常

测试方法抛出RuntimeException

业务方法代码中抛出运行时异常,事务回滚,下单失败。

@Transactionalpublic void insert(Orders orders, Orderdetail[] orderdetail) throwsException {//orders插入到数据库,并获取出主键值ordersMapper.insert(orders);if(orderdetail!=null && orderdetail.length>0) {for (int i = 0; i < orderdetail.length; i++) {//订单的主键设置给订单明细的外键orderdetail[i].setOrderid(orders.getId());//orderdetail插入到数据库orderdetailMapper.insert(orderdetail[i]);throw new RuntimeException("事务中发生运行时异常");}}}

运行后抛出异常如下:
JavaEE——Spring Boot整合框架
由于抛出运行时异常,导致事务回滚,查看数据库,orders表和orderdetail表都没有新增记录,证明事务已经回滚。

测试方法抛出Exception

业务方法代码中抛出编译时异常,事务提交,但是下单失败,订单表中新增的记录与订单明细表中新增的记录不一致。

@Transactionalpublic void insert(Orders orders, Orderdetail[] orderdetail) throwsException {//orders插入到数据库,并获取出主键值ordersMapper.insert(orders);if(orderdetail!=null && orderdetail.length>0) {for (int i = 0; i < orderdetail.length; i++) {//订单的主键设置给订单明细的外键orderdetail[i].setOrderid(orders.getId());//orderdetail插入到数据库orderdetailMapper.insert(orderdetail[i]);throw new Exception("事务中发生编译时异常");}}}

运行后抛出异常如下:
JavaEE——Spring Boot整合框架
由于抛出编译时异常,事务仍然提交,查看数据库,orders表中新增一条订单记录,orderdetail表中新增一条订单明细记录,丢失了一条订单明细记录,证明抛出编译时异常事务仍然提交,导致事务控制失败。