程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)

Spring Boot -- Spring Boot之@Async异步调用、Mybatis、事务管理等

这一节将在上一节的基础上,继续深入学习Spring Boot相关知识,其中主要包括@Async异步调用,@Value自定义参数、Mybatis、事务管理等。

本节所使用的代码是在上一节项目代码中,继续追加的,因此需要先学习上一节内容。

一、使用@Async实现异步调用

要在springboot中使用异步调用方法,只要在被调用的方法上面加上@Async就可以了;

1.1.准备工作

准备一个Spring Boot项目,在App类上加上@EnableAsync注解开启异步:

复制代码
package com.zy.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

/**
 * 启动代码
 *
 * @since 2020-2-2
 * @author zy
 */

@SpringBootApplication
@EnableAsync
public class App {
    public static void main(String[] args){
        //整个程序入口 启动Spring Boot项目
        SpringApplication.run(App.class,args);
    }
}
复制代码

这个注解如果不加,@Async注解失效。

1.2、controller

在包com.zy.example.controller下,创建文件HelloController.java:

复制代码
package com.zy.example.controller;

import com.zy.example.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Instant;

/**
 * 用于演示@Async异步调用
 *
 * @author zy
 * @since 2020-2-4
 */
@RestController
@RequestMapping("/hello")
public class HelloController {

    @Autowired
    private HelloService helloService;/**
     * 同步方法
     * @return
     */
    @RequestMapping("/sync")
    public String getSyncHello(){

        long n = Instant.now().toEpochMilli();
        //异步
        String s = helloService.syncSayHello();

        long f = Instant.now().toEpochMilli();
        return s + " 时间: " + (f-n);
    }

    /**
     * 异步方法
     * @return
     */
    @RequestMapping("/async")
    public String getAsyncHello(){
        long n = Instant.now().toEpochMilli();
        //异步
        String s = helloService.asyncSayHello();

        long f = Instant.now().toEpochMilli();
        return s + "时间:" + (f-n);
    }

}
复制代码

1.3、Service

新建包com.zy.example.service,并在包下创建HelloService.java文件:

复制代码
package com.zy.example.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 用于演示@Async异步调用
 *
 * @author zy
 * @since 2020-2-4
 */
@Service
@Slf4j
public class HelloService {
    @Autowired
    private SleepService sleepService;

    /**
     * 同步方法
     * @return
     */
    public String syncSayHello() {
        try {
            sleepService.syncSleep();
            return "hello world,这是同步方法";
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            return "error";
        }
    }

    /**
     * 异步方法
     * @return
     */
    public String asyncSayHello() {
        try {
            log.info("主线程 " + Thread.currentThread().getName());
            sleepService.asyncSleep();
            return "hello world,这是异步方法";
        } catch (InterruptedException e) {
            log.error(e.getMessage(),e);
            return "error";
        }
    }
}
复制代码

这里为了模拟应用场景,将耗时的方法放在另一个service里面,就叫SleepService,两个方法都是休眠3秒,aysncSleep方法上面有一个@Async注解。

复制代码
package com.zy.example.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * 用于演示@Async异步调用
 *
 * @author zy
 * @since 2020-2-4
 */
@Service
@Slf4j
public class SleepService {
    /**
     * 同步方法
     * @throws InterruptedException
     */
    public void syncSleep() throws InterruptedException {
        log.info("线程名: " +Thread.currentThread().getName());
        log.info("开始同步休眠3秒");
        Thread.sleep(3000);
        log.info("同步休眠结束");
    }

    /**
     * 异步方法
     * @throws InterruptedException
     */
    @Async
    public void asyncSleep() throws InterruptedException {
        log.info("次线程 "+Thread.currentThread().getName());
        log.info("开始异步休眠3秒");
        Thread.sleep(3000);
        log.info("异步休眠休眠结束");
    }
}
复制代码

1.4、测试

同步:访问 http://localhost:8080/hello/sync需要3秒的时间才能收到响应;

异步:访问 http://localhost:8080/hello/async,可见主线程和次线程打印出来的线程名不一样,也就是Spring Boot帮我们开启了一个线程去处理。

注意事项

  • 必须要加@EnableAsync注解;
  • 不能在同一类下调用@Async注解的方法,比如A类下有a和b方法,b方法有@Async注解,不能直接这样a调用b,要把b放到其他类中;
  • @Async也可以打在类上,这样类下面的所有方法都是异步的(被其他类调用的时候);

二、@Value自定义参数

@Value在Spring中,功能非常强大,可以注入一个配置项,可以引用容器中的Bean(调用其方法),也可以做一些简单的运算。下面通过@Value引用一个配置项。在配置文件application.properties中配置如下内容:

name=www.zy.example.com

修改HelloController.java文件,添加如下代码:

 

    //初始化的时候加载
    @Value("${name}")
    private String name;

    @RequestMapping("/getName")
    public String getName(){
        return name;
    }

此时访问http://localhost:8080/hello/getName,将会返回配置文件中name属性的值。

此外@configurationproperties也具有类似的作用,具体可以查看博客springboot @value和@configurationproperties注解的区别

三、多环境配置

软件开发中经常有开发环境、测试环境、预发布环境、生产环境,而且一般这些环境配置会各不相同,手动改配置麻烦且容易出错,如何管理不同环境的配置参数呢?Spring Boot + maven可以解决不同环境独立配置不同参数的问题。

不同环境的配置yml(或者properties,yml比properties配置文件更加节约、简约)文件名不一样:

  • application-dev.yml(开发环境);
  • application-test.yml(测试环境);
  • application-uat.yml(预发布);
  • application-pro.yml(生产环境);

eg:

application-dev.yml配置示例:

复制代码
info:
  build:
    name: ${project.artifactId}
    groupId: ${project.groupId}
    artifactId: ${project.artifactId}
    version: ${project.version}

server:
  port: 8081

endpoints:
  enabled: true
  sensitive: false

data:
  test:
    envName: dev
    envconfig: 127.0.0.1:8081
复制代码

注意属性名: 属性值,在:后有一个空格;

application.properties文件追加:

spring.profiles.active=dev

如果要切换不同环境,只需要修改spring.profiles.active即可。

如果想读取开发环境中的配置信息,可以通过如下方式:

复制代码
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Component
@ConfigurationProperties(prefix = "data.test")
@Service
public class DataConfig {
    private String envName;
    private String envconfig;
}
复制代码

验证环境参数: 

复制代码
@Api("home controller")
@RestController
public class HomeController {
    @Autowired
    private DataConfig dataConfig;

    @RequestMapping("/env")
    @ApiOperation("env")
    public Object testEnv() {
        return dataConfig;
    }
}
复制代码

四、Mybatis

4.1、创建数据表

这里测试采用的是mysql数据库,首先创建example数据库:

复制代码
--创建数据库
DROP DATABASE IF EXISTS  GLODWIND;

CREATE DATABASE IF NOT EXISTS  example;

--选择数据库
USE  example;
复制代码

创建student数据表、并插入数据:

复制代码
--创建表
CREATE TABLE student(
             ID INT PRIMARY KEY AUTO_INCREMENT ,
             NAME VARCHAR(20),
             AGE SMALLINT,
             SEX BIT,
             CLASS  VARCHAR(50),
             ADDRESS  VARCHAR(100)) default charset=utf8;

--插入
insert into student(name,age,sex,class,address) values('郑洋','24',1,'计算机(1)班','江苏省无锡市滨湖区');

--查询
select * from student;
复制代码

4.2、pom文件导入依赖

复制代码
<!--  mybatis  -->
<dependency>
   <groupId>org.mybatis.spring.boot</groupId>
   <artifactId>mybatis-spring-boot-starter</artifactId>
   <version>2.1.1</version>
</dependency>

<!--  mysql依赖  -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
复制代码

4.3、配置mybatis

修改appliction.properties,追加sql配置信息:

复制代码
#mybati sql配置
#MySQL的JDBC URL编写方式:jdbc:mysql://主机名称:连接端口/数据库的名称  默认使用zy.example数据库
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/example?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456aa
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
复制代码

4.4、代码

在包com.zy.example.entity下新建StudentEntity.java文件

复制代码
package com.zy.example.entity;

import lombok.Data;

/**
 * student实体类
 *
 * @author zy
 * @since  2020-2-4
 */
@Data
public class StudentEntity {
    /**
     * id 主键、自增
     */
    private Integer id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 性别
     */
    private Boolean sex;

    /**
     * 班级
     */
    private String className;

    /**
     * 地址
     */
    private String address;

}
复制代码

新建包com.zy.example.mapper,并在包下新建StudentMapper.java文件:

复制代码
package com.zy.example.mapper;

import com.zy.example.entity.StudentEntity;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * student Mapper类
 *
 * @author zy
 * @since 2020-2-4
 */
@Service
public interface  StudentMapper {
    //查询语句
    @Select("SELECT id,name,age,sex,`class` as className,address FROM STUDENT WHERE ID = #{id}")
    StudentEntity getStudentById(@Param("id") Integer id);

    //新增语句
    @Insert("INSERT INTO STUDENT(name,age,sex) VALUES(#{name}, #{age},#{sex})")
    int insertStudent(@Param("name") String name, @Param("age") Integer age, @Param("sex") Boolean sex);
}
复制代码

在包com.zy.example.service下新建StudentService.java文件:

复制代码
package com.zy.example.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zy.example.mapper.StudentMapper;
import com.zy.example.entity.StudentEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;

/**
 * student业务逻辑
 *
 * @author zy
 * @since 2020-2-4
 */
@Slf4j
@Service
public class StudentService {

    @Autowired
    private StudentMapper studentMapper;

    /**
     * 新增学生
     * @param name:姓名
     * @param age:年龄
     * @param sex:性别
     * @return 返回受影响的行数
     */public int insertStudent(String name,Integer age,Boolean sex){
        int ret = studentMapper.insertStudent(name,age,sex);
        int i = 1/age;
        log.info("#####新增学生###########",ret);
        return ret;
    }


    /**
     * 根据id获取学生信息
     * @param id 学生id
     * @return 返回学生信息
     */
    public StudentEntity getStudentById(Integer id){
        log.info("#####获取学生信息###########",id);
        return studentMapper.getStudentById(id);
    }

}
复制代码

在包com.zy.example.controller下新建StudentController.java文件:

复制代码
package com.zy.example.controller;

import com.github.pagehelper.PageInfo;
import com.zy.example.entity.StudentEntity;
import com.zy.example.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * student控制器  测试mybatis
 *
 * @author zy
 * @since 2020-2-4
 */
@RestController
public class StudentController {

    @Autowired
    private StudentService studentService;

    /**
     * 新增学生 这里没有对参数进行校验  127.0.0.1:8081/insertStudent?name=李艳&age=25&sex=1
     * @param name 姓名
     * @param age 年龄
     * @param sex 性别
     * @return 返回受影响的行数
     */
    @RequestMapping("/insertStudent")
    public int insertStudent(@RequestParam String name,@RequestParam Integer age,@RequestParam Boolean sex){
        return studentService.insertStudent(name,age,sex);
    }

    /**
     * 根据id获取学生信息 127.0.0.1:8081/getStudent?id=1
     * @param id 学生id
     * @return 返回学生信息
     */
    @RequestMapping("/getStudent")
    public StudentEntity getStudentById(@RequestParam Integer id){
        return studentService.getStudentById(id);
    }

}
复制代码

修改App.java文件,加入mapper扫包范围:

复制代码
package com.zy.example;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

/**
 * 启动代码
 * mybatis启动方式有两种:
 * 1、在mapper层添加@Mapper注解
 * 2、在启动类上加@MapperScan指定扫包范围
 *
 * @since 2020-2-2
 * @author zy
 */
@SpringBootApplication
@MapperScan(basePackages = {"com.zy.example.mapper"})
@EnableAsync
public class App {
    public static void main(String[] args){
        //整个程序入口 启动Spring Boot项目
        SpringApplication.run(App.class,args);
    }
}
复制代码

启动程序,访问http://127.0.0.1:8081/getStudent?id=1,输出结果如下:

4.5、mybatis整合分页插件

(1)、pageHelper

PageHelper 是一款好用的开源免费的 Mybatis 第三方物理分页插件,它具有以下特点:

  • 物理分页;
  • 支持常见的 12 种数据库,Oracle,MySql,MariaDB,SQLite,DB2,PostgreSQL,SqlServer 等;
  • 支持多种分页方式;
  • 支持常见的 RowBounds(PageRowBounds),PageHelper.startPage 方法调用,Mapper 接口参数调用;

(2)、新增依赖

<!-- springboot 整合 pagehelper -->
<dependency>
       <groupId>com.github.pagehelper</groupId>
       <artifactId>pagehelper-spring-boot-starter</artifactId>
        <version>1.2.5</version>
</dependency>

(3)、新增配置信息

在application.properties文件中追加如下配置:

logging.level.com.example.demo.dao=DEBUG
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
pagehelper.page-size-zero=true

(4)、代码

修改StudentMapper.java,添加查询全部学生信息的方法:

复制代码
package com.zy.example.mapper;

import com.zy.example.entity.StudentEntity;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * student Mapper类
 *
 * @author zy
 * @since 2020-2-4
 */
@Service
public interface  StudentMapper {
    //查询语句
    @Select("SELECT id,name,age,sex,`class` as className,address FROM STUDENT WHERE ID = #{id}")
    StudentEntity getStudentById(@Param("id") Integer id);

    //查询全部
    @Select("SELECT id,name,age,sex,`class` as className,address FROM STUDENT")
    List<StudentEntity> getStudentList();

    //新增语句
    @Insert("INSERT INTO STUDENT(name,age,sex) VALUES(#{name}, #{age},#{sex})")
    int insertStudent(@Param("name") String name, @Param("age") Integer age, @Param("sex") Boolean sex);
}
复制代码

修改StudentService.java:

复制代码
package com.zy.example.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zy.example.mapper.StudentMapper;
import com.zy.example.entity.StudentEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;

/**
 * student业务逻辑
 *
 * @author zy
 * @since 2020-2-4
 */
@Slf4j
@Service
public class StudentService {

    @Autowired
    private StudentMapper studentMapper;

    /**
     * 新增学生
     * @param name:姓名
     * @param age:年龄
     * @param sex:性别
     * @return 返回受影响的行数
     */public int insertStudent(String name,Integer age,Boolean sex){
        int ret = studentMapper.insertStudent(name,age,sex);
        int i = 1/age;
        log.info("#####新增学生###########",ret);
        return ret;
    }


    /**
     * 根据id获取学生信息
     * @param id 学生id
     * @return 返回学生信息
     */
    public StudentEntity getStudentById(Integer id){
        log.info("#####获取学生信息###########",id);
        return studentMapper.getStudentById(id);
    }


    /**
     * 分页查询 获取学生信息
     * @param page 当前页
     * @param pageSize 每页记录数目
     * @return 返回学生信息
     */
    public  PageInfo<StudentEntity>  getStudentList(int page,int pageSize){
        //mysql查询 limit
        //pageHelper 帮我们生成分页语句     底层实现原理:利用AOP、改写sql语句
        PageHelper.startPage(page,pageSize);
        List<StudentEntity> listStudent = studentMapper.getStudentList();
        //返回给客户端展示
        PageInfo<StudentEntity> pageInfoStudent = new PageInfo<StudentEntity>(listStudent);
        return pageInfoStudent;
    }
}
复制代码

修改StudentController.java:

复制代码
package com.zy.example.controller;

import com.github.pagehelper.PageInfo;
import com.zy.example.entity.StudentEntity;
import com.zy.example.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * student控制器  测试mybatis
 *
 * @author zy
 * @since 2020-2-4
 */
@RestController
public class StudentController {

    @Autowired
    private StudentService studentService;

    /**
     * 新增学生 这里没有对参数进行校验  127.0.0.1:8081/insertStudent?name=李艳&age=25&sex=1
     * @param name 姓名
     * @param age 年龄
     * @param sex 性别
     * @return 返回受影响的行数
     */
    @RequestMapping("/insertStudent")
    public int insertStudent(@RequestParam String name,@RequestParam Integer age,@RequestParam Boolean sex){
        return studentService.insertStudent(name,age,sex);
    }

    /**
     * 根据id获取学生信息 127.0.0.1:8081/getStudent?id=1
     * @param id 学生id
     * @return 返回学生信息
     */
    @RequestMapping("/getStudent")
    public StudentEntity getStudentById(@RequestParam Integer id){
        return studentService.getStudentById(id);
    }

    /**
     * 分页查询 获取学生信息  127.0.0.1:8081/student?page=1&pageSize=2
     * @param page 当前页
     * @param pageSize 每页记录数目
     * @return 返回学生信息
     */

    @RequestMapping("/student")
    public PageInfo<StudentEntity> getStudentList(@RequestParam  int page,@RequestParam  int pageSize){
        return studentService.getStudentList(page,pageSize);
    }
}
复制代码

运行程序,访问http://127.0.0.1:8081/student?page=1&pageSize=2,输出如下:

五、Spring事务管理

按是否通过编程分为声明式事务和编程式事务:

  • 声明式事务:通过XML配置或者注解实现;
  • 编程式事务:通过编程代码在业务逻辑时需要时自行实现,粒度更小;

Spring Boot默认集成事物,只要在方法上加上@Transactional即可。

5.1、@Transactional使用

我们给类StudentService的insertStudent()方法加上@Transactional注解,并修改代码如下:

复制代码
    /**
     * 新增学生
     * @param name:姓名
     * @param age:年龄
     * @param sex:性别
     * @return:返回受影响的行数
     */
    @Transactional
    public int insertStudent(String name,Integer age,Boolean sex){
        int ret = studentMapper.insertStudent(name,age,sex);
        int i = 1/age;
        log.info("#####新增学生###########",ret);
        return ret;
    }
复制代码

当我们运行程序,访问http://127.0.0.1:8081/insertStudent?name=李艳&age=25&sex=1,此时会将数据成功插入数据库。而当我们访问http://127.0.0.1:8081/insertStudent?name=李艳&age=0&sex=1,此时事务将会执行失败,执行回归操作,数据不会插入数据库。

 

使用Spring事务注意事项:不要try,为什么不要try,因为需要将异常抛出给外层;

六、Spring Boot整合多数据源

什么是多数据源,说白了就是一个项目使用到多个数据库。

在一个项目中多数据源如何划分:分包名(业务)或者注解方式。

采用分包的方式划分如:

  • com.zy.example.datasource1---- datasource1
  • com.zy.example.datasource2 ---- datasource2

为了演示分包方式,我们将会新建一个项目spring-boot-multidatasource。

6.1、创建数据库、数据表

复制代码
--创建数据库1
DROP DATABASE IF EXISTS  DATABASE1;

CREATE DATABASE IF NOT EXISTS  DATABASE1;

--选择数据库
USE  DATABASE1;

--创建表
CREATE TABLE student1(
             ID INT PRIMARY KEY AUTO_INCREMENT ,
             NAME VARCHAR(20),
             AGE SMALLINT,
             SEX BIT,
             CLASS  VARCHAR(50),
             ADDRESS  VARCHAR(100)) default charset=utf8;


--创建数据库2
DROP DATABASE IF EXISTS  DATABASE2;

CREATE DATABASE IF NOT EXISTS  DATABASE2;

--选择数据库
USE  DATABASE2;

--创建表
CREATE TABLE student2(
             ID INT PRIMARY KEY AUTO_INCREMENT ,
             NAME VARCHAR(20),
             AGE SMALLINT,
             SEX BIT,
             CLASS  VARCHAR(50),
             ADDRESS  VARCHAR(100)) default charset=utf8;
复制代码

6.2、配置mybatis

新建appliction.properties,追加多数据源sql配置信息:

复制代码
###datasource1
spring.datasource.datasource1.jdbc-url = jdbc:mysql://localhost:3306/database1
spring.datasource.datasource1.username = root
spring.datasource.datasource1.password = 123456aa
spring.datasource.datasource1.driver-class-name = com.mysql.jdbc.Driver

###datasource2
spring.datasource.datasource2.jdbc-url = jdbc:mysql://localhost:3306/database2
spring.datasource.datasource2.username = root
spring.datasource.datasource2.password = 123456aa
spring.datasource.datasource2.driver-class-name = com.mysql.jdbc.Driver
复制代码

6.3、pom文件追加依赖

复制代码
<?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">

    <groupId>com.zy.example</groupId>
    <artifactId>spring-boot-multidatasource</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>

    <!--  spring-boot-starter-parent  整合第三方常用框架依赖信息(各种引来信息)-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
    </parent>

    <!--  spring-boot-starter-web 是Spring Boot整合Spring MVC Web  -->
    <!--  相当于把第三方常用Maven依赖信息,在parent项目中封装好了,使用Spring Boot提供依赖信息关联整合的Jar包 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--  为什么不需要版本号,在parent里面已经封装好了版本号 -->
        </dependency>

        <!--   日志管理   -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <!-- 排除自带的logback依赖 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j</artifactId>
            <version>1.3.8.RELEASE</version>
        </dependency>

        <!--  lombok使用     -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
            <scope>provided</scope>
        </dependency>

        <!--  mybatis  -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

        <!--  mysql依赖  -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

    </dependencies>

</project>
复制代码

6.4、代码

新建包com.zy.example.entity,新建StudentEntity.java文件:

复制代码
package com.zy.example.entity;

import lombok.Data;

/**
 * student实体类
 * 
 * @author zy
 * @since  2020-2-4
 */
@Data
public class StudentEntity {
    /**
     * id 主键、自增
     */
    private Integer id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 性别
     */
    private Boolean sex;

    /**
     * 班级
     */
    private String className;

    /**
     * 地址
     */
    private String address;

}
View Code
复制代码

新建包com.zy.example.mapper.datasource1.,并新建StudentMapper01.java文件:

复制代码
package com.zy.example.mapper.datasource1;

import com.zy.example.entity.StudentEntity;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Service;

/**
 * student Mapper类
 * 
 * @author zy
 * @since  2020-2-4
 */
@Service
public interface StudentMapper01 {
    //查询语句
    @Select("SELECT id,name,age,sex,`class` as className,address FROM STUDENT1 WHERE ID = #{id}")
    StudentEntity getStudentById(@Param("id") Integer id);

    //新增语句
    @Insert("INSERT INTO STUDENT1(name,age,sex) VALUES(#{name}, #{age},#{sex})")
    int insertStudent(@Param("name") String name, @Param("age") Integer age,@Param("sex") Boolean sex);
}
复制代码

新建包com.zy.example.mapper.datasource2.,并新建StudentMapper02.java文件:

复制代码
package com.zy.example.mapper.datasource2;

import com.zy.example.entity.StudentEntity;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Service;

/**
 * student Mapper类
 * 
 * @author zy
 * @since 2020-2-4
 */
@Service
public interface StudentMapper02 {
    //查询语句
    @Select("SELECT id,name,age,sex,`class` as className,address FROM STUDENT2 WHERE ID = #{id}")
    StudentEntity getStudentById(@Param("id") Integer id);

    //新增语句
    @Insert("INSERT INTO STUDENT2(name,age,sex) VALUES(#{name}, #{age},#{sex})")
    int insertStudent(@Param("name") String name, @Param("age") Integer age, @Param("sex") Boolean sex);
}
复制代码

新建包com.zy.example.service.datasource1,并新建StudentService01.java文件:

复制代码
package com.zy.example.service.datasource1;

import com.zy.example.mapper.datasource1.StudentMapper01;
import com.zy.example.entity.StudentEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * student业务逻辑
 * 
 * @author zy
 * @since 2020-2-4
 */
@Service
@Slf4j
public class StudentService01 {
    @Autowired
    private StudentMapper01 studentMapper01;

    /**
     * 新增学生
     * @param name 姓名
     * @param age 年龄
     * @param sex 性别
     * @return 返回受影响的行数
     */
    public int insertStudent(String name,Integer age,Boolean sex){
        int ret = studentMapper01.insertStudent(name,age,sex);
        log.info("#####新增学生###########",ret);
        return ret;
    }


    /**
     * 根据id获取学生信息
     * @param id 学生id
     * @return 返回学生信息
     */
    public StudentEntity  getStudentById(Integer id){
        log.info("#####获取学生信息###########",id);
        return studentMapper01.getStudentById(id);
    }
}
复制代码

新建包com.zy.example.service.datasource2,并新建StudentService02.java文件:

复制代码
package com.zy.example.service.datasource2;

import com.zy.example.mapper.datasource2.StudentMapper02;
import com.zy.example.entity.StudentEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * student业务逻辑
 *
 * @author zy
 * @since 2020-2-4
 */
@Service
@Slf4j
public class StudentService02 {
    @Autowired
    private StudentMapper02 studentMapper02;

    /**
     * 新增学生
     * @param name 姓名
     * @param age 年龄
     * @param sex 性别
     * @return 返回受影响的行数
     */
    public int insertStudent(String name,Integer age,Boolean sex){
        int ret = studentMapper02.insertStudent(name,age,sex);
        log.info("#####新增学生###########",ret);
        return ret;
    }


    /**
     * 根据id获取学生信息
     * @param id 学生id
     * @return 返回学生信息
     */
    public StudentEntity  getStudentById(Integer id){
        log.info("#####获取学生信息###########",id);
        return studentMapper02.getStudentById(id);
    }
}
复制代码

新建包com.zy.example.datasource,在包下新建Datasource1Config.java:

复制代码
package com.zy.example.datasource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;


/**
 * 读取数据源datasource1配置信息
 * {@link Configuration}用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器
 * {@link Configuration}等价于<Beans></Beans>
 * {@link Bean}等价于<Bean></Bean>
 * {@link ComponentScan}等价于<context:component-scan base-package="com.zy.example.datasource1"/>
 *
 * @author zy
 * @since  2020-2-5
 */
//表示这个类为一个配置类
@Configuration
//配置mybatis的接口类放的地方
@MapperScan(basePackages = "com.zy.example.mapper.datasource1", sqlSessionFactoryRef = "datasource1SqlSessionFactory")
public class Datasource1Config {

    /**
     * 功能描述:(配置datasource1数据库)
     * @return:@return DataSource
     */
    //创建一个bean对象,并注入到Spring容器中
    @Bean(name = "datasource1DataSource")
    // 读取application.properties中的配置参数映射成为一个对象
    @ConfigurationProperties(prefix = "spring.datasource.datasource1")
    //表示这个数据源是默认数据源
    @Primary
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }


    /**
     * 功能描述:(datasource1 sql会话工厂)
     * @param dataSource
     * @return
     * @throws Exception
     */
    @Bean(name = "datasource1SqlSessionFactory")
    //表示这个数据源是默认数据源
    @Primary
    //@Qualifier表示查找Spring容器中名字为datasource1DataSource的对象
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("datasource1DataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }


    /**
     * 功能描述:(datasource1 事物管理)
     * @param dataSource
     * @return
     */
    @Bean(name = "datasource1TransactionManager")
    //表示这个数据源是默认数据源
    @Primary
    public DataSourceTransactionManager testTransactionManager(@Qualifier("datasource1DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "datasource1SqlSessionTemplate")
    //表示这个数据源是默认数据源
    @Primary
    public SqlSessionTemplate testSqlSessionTemplate(
            @Qualifier("datasource1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}
复制代码

在包com.zy.example.datasource下,新建Datasource2Config.java:

复制代码
package com.zy.example.datasource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;


/**
 * 读取数据源datasource1配置信息
 * {@link Configuration}用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器
 * {@link Configuration}等价于<Beans></Beans>
 * {@link Bean}等价于<Bean></Bean>
 * {@link ComponentScan}等价于<context:component-scan base-package="com.zy.example.datasource2"/>
 *
 * @author zy
 * @since  2020-2-5
 */
//表示这个类为一个配置类
@Configuration
//配置mybatis的接口类放的地方
@MapperScan(basePackages = "com.zy.example.mapper.datasource2", sqlSessionFactoryRef = "datasource2SqlSessionFactory")
public class Datasource2Config {

    /**
     * 功能描述:(配置datasource2数据库)
     * @return:@return DataSource
     */
    //创建一个bean对象,并注入到Spring容器中
    @Bean(name = "datasource2DataSource")
    // 读取application.properties中的配置参数映射成为一个对象
    @ConfigurationProperties(prefix = "spring.datasource.datasource2")
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }


    /**
     * 功能描述:(datasource2 sql会话工厂)
     * @param dataSource
     * @return
     * @throws Exception
     */
    @Bean(name = "datasource2SqlSessionFactory")
    //@Qualifier表示查找Spring容器中名字为datasource2DataSource的对象
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("datasource2DataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }


    /**
     * 功能描述:(datasource2 事物管理)
     * @param dataSource
     * @return
     */
    @Bean(name = "datasource2TransactionManager")
    public DataSourceTransactionManager testTransactionManager(@Qualifier("datasource2DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "datasource2SqlSessionTemplate")
    public SqlSessionTemplate testSqlSessionTemplate(
            @Qualifier("datasource2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}
复制代码

新建包com.zy.example.controller,并新建MyBatisMultilDataSourceController.java文件:

复制代码
package com.zy.example.controller;

import com.zy.example.service.datasource1.StudentService01;
import com.zy.example.service.datasource2.StudentService02;
import com.zy.example.entity.StudentEntity;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 多数据源控制器
 * 
 * @author zy
 * @since  2020-2-5
 */
@RestController
public class MyBatisMultilDataSourceController {
    @Autowired
    private StudentService01 studentService01;

    /**
     * 新增学生 这里没有对参数进行校验  127.0.0.1:8080/insertStudent01?name=01&age=25&sex=1
     * @param name 姓名
     * @param age 年龄
     * @param sex 性别
     * @return 返回受影响的行数
     */
    @RequestMapping("/insertStudent01")
    public int insertStudent01(@RequestParam String name, @RequestParam Integer age, @RequestParam Boolean sex){
        return studentService01.insertStudent(name,age,sex);
    }

    /**
     * 根据id获取学生信息
     * @param id 学生id
     * @return 返回学生信息
     */
    @RequestMapping("/getStudent01")
    public StudentEntity getStudentById01(@RequestParam Integer id){
        return studentService01.getStudentById(id);
    }

    @Autowired
    private StudentService02 studentService02;

    /**
     * 新增学生 这里没有对参数进行校验  127.0.0.1:8080/insertStudent02?name=02&age=25&sex=1
     * @param name 姓名
     * @param age 年龄
     * @param sex 性别
     * @return 返回受影响的行数
     */
    @RequestMapping("/insertStudent02")
    public int insertStudent02(@RequestParam String name, @RequestParam Integer age, @RequestParam Boolean sex){
        return studentService02.insertStudent(name,age,sex);
    }

    /**
     * 根据id获取学生信息
     * @param id 学生id
     * @return 返回学生信息
     */
    @RequestMapping("/getStudent02")
    public StudentEntity getStudentById02(@RequestParam Integer id){
        return studentService02.getStudentById(id);
    }

}
复制代码

在包com.zy.example下新建程序入口文件App.java:

复制代码
package com.zy.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 启动代码
 * 
 * @author zy
 * @since  2020-2-2
 */

@SpringBootApplication
public class App {
    public static void main(String[] args){
        //整个程序入口 启动Spring Boot项目
        SpringApplication.run(App.class,args);
    }
}
复制代码

最终项目结构如下:

运行程序,访问http://127.0.0.1:8080/insertStudent01?name=01&age=25&sex=1,查看数据库database1表student1:

运行程序,访问http://127.0.0.1:8080/insertStudent02?name=02&age=25&sex=1,查看数据库database2表student2:

亲爱的读者和支持者们,自动博客加入了打赏功能,陆陆续续收到了各位老铁的打赏。在此,我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持,是我们前行的动力与源泉。

日期姓名金额
2023-09-06*源19
2023-09-11*朝科88
2023-09-21*号5
2023-09-16*真60
2023-10-26*通9.9
2023-11-04*慎0.66
2023-11-24*恩0.01
2023-12-30I*B1
2024-01-28*兴20
2024-02-01QYing20
2024-02-11*督6
2024-02-18一*x1
2024-02-20c*l18.88
2024-01-01*I5
2024-04-08*程150
2024-04-18*超20
2024-04-26.*V30
2024-05-08D*W5
2024-05-29*辉20
2024-05-30*雄10
2024-06-08*:10
2024-06-23小狮子666
2024-06-28*s6.66
2024-06-29*炼1
2024-06-30*!1
2024-07-08*方20
2024-07-18A*16.66
2024-07-31*北12
2024-08-13*基1
2024-08-23n*s2
2024-09-02*源50
2024-09-04*J2
2024-09-06*强8.8
2024-09-09*波1
2024-09-10*口1
2024-09-10*波1
2024-09-12*波10
2024-09-18*明1.68
2024-09-26B*h10
2024-09-3010
2024-10-02M*i1
2024-10-14*朋10
2024-10-22*海10
2024-10-23*南10
2024-10-26*节6.66
2024-10-27*o5
2024-10-28W*F6.66
2024-10-29R*n6.66
2024-11-02*球6
2024-11-021*鑫6.66
2024-11-25*沙5
2024-11-29C*n2.88
posted @   大奥特曼打小怪兽  阅读(4858)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
如果有任何技术小问题,欢迎大家交流沟通,共同进步

公告 & 打赏

>>

欢迎打赏支持我 ^_^

最新公告

程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)。

了解更多

点击右上角即可分享
微信分享提示