springBoot整合druid和mybatis

一.springboot自动配置数据源解析:

以前我们在操作数据库(sql、nosql)时,需要导入对饮给的依赖,然后再配置我们需要使用的数据源,这样我们就可以使用java的方式,访问数据库了,但是现在我们使用的springboot框架,最大的核心就是自动配置,所以我们的数据源也会自动装配,那么我们就来探析一下自动装配数据源的原理:

  • 我们都知道每一个自动配置都会有一个xxx AutoConfiguration的自动配置类,我们的数据源也有一个自动配置类:DataSourceAutoConfiguration

我们可以看到这个自动配置类里面会有一个这个内部类:

@Configuration(proxyBeanMethods = false)
	@Conditional(PooledDataSourceCondition.class)
	@ConditionalOnMissingBean({
    
     DataSource.class, XADataSource.class })
	@Import({
    
     DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
			DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,
			DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
	protected static class PooledDataSourceConfiguration {
    
    

	}

最主要的就是这个类上边自动导入了一些类:

@Import({
    
     DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
			DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,
			DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })

这些类都是属于DataSourceConfiguration这个类里面的,我们都知道springboot自动装配时,对应功能都会有一个xxxConfiguration的配置类,我们进去看一下

DataSourceConfiguration这个类里面放了很多的内部类:

@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource",
			matchIfMissing = true)
	static class Tomcat {
    
    

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.tomcat")
		org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties) {
    
    
			org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(properties,
					org.apache.tomcat.jdbc.pool.DataSource.class);
			DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(properties.determineUrl());
			String validationQuery = databaseDriver.getValidationQuery();
			if (validationQuery != null) {
    
    
				dataSource.setTestOnBorrow(true);
				dataSource.setValidationQuery(validationQuery);
			}
			return dataSource;
		}

	}

	/**
	 * Hikari DataSource configuration.
	 */
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(HikariDataSource.class)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
			matchIfMissing = true)
	static class Hikari {
    
    

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.hikari")
		HikariDataSource dataSource(DataSourceProperties properties) {
    
    
			HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
			if (StringUtils.hasText(properties.getName())) {
    
    
				dataSource.setPoolName(properties.getName());
			}
			return dataSource;
		}

	}

	/**
	 * DBCP DataSource configuration.
	 */
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(org.apache.commons.dbcp2.BasicDataSource.class)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp2.BasicDataSource",
			matchIfMissing = true)
	static class Dbcp2 {
    
    

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.dbcp2")
		org.apache.commons.dbcp2.BasicDataSource dataSource(DataSourceProperties properties) {
    
    
			return createDataSource(properties, org.apache.commons.dbcp2.BasicDataSource.class);
		}

	}

	/**
	 * Oracle UCP DataSource configuration.
	 */
	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass({
    
     PoolDataSourceImpl.class, OracleConnection.class })
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "oracle.ucp.jdbc.PoolDataSource",
			matchIfMissing = true)
	static class OracleUcp {
    
    

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.oracleucp")
		PoolDataSourceImpl dataSource(DataSourceProperties properties) throws SQLException {
    
    
			PoolDataSourceImpl dataSource = createDataSource(properties, PoolDataSourceImpl.class);
			dataSource.setValidateConnectionOnBorrow(true);
			if (StringUtils.hasText(properties.getName())) {
    
    
				dataSource.setConnectionPoolName(properties.getName());
			}
			return dataSource;
		}

	}
//=======================================
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
			matchIfMissing = true)
意思:会去配置文件中找spring.datasource.type属性的值,去和havingValue 中的值匹配,相同返回true,不相同返回false
matchIfMissing:缺少该property时是否可以加载。如果为true,没有该property也会正常加载;反之报错  

这其实就是springboot为我们自动配置的一些数据源,但是每个内部类上边会有ConditionalOnxxx的注解,其实也就是满足这个条件,这个类就执行,所以我们发现,springboot为我们自动配置了一个com.zaxxer.hikari.HikariDataSource的数据源(号称速度最快),不需要我们配置任何配置,他也可以生效。

@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(HikariDataSource.class)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
			matchIfMissing = true)

如果我们要使用别的数据源时,他也为我们提供了一个内部类:

@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type")
	static class Generic {
    
    

		@Bean
		DataSource dataSource(DataSourceProperties properties) {
    
    
			return properties.initializeDataSourceBuilder().build();
		}

	}

这个内部类的意思就是:当我们需要使用特殊的数据源时,就需要再配置文件中配置一个spring.datasource.type的属性,属性值也就是具体数据源饿全类名,这样他就可以按照我们的需求创建数据源了。

Spring Boot支持自定义数据源有一种机制:使用DataSourceBuilder创建数据源,利用反射创建对应type的数据源,并且绑定相关属性。这里使用的是建造者模式:properties.initializeDataSourceBuilder().build()

public DataSourceBuilder<?> initializeDataSourceBuilder() {
    
    
		return DataSourceBuilder.create(getClassLoader()).type(getType()).driverClassName(determineDriverClassName())
				.url(determineUrl()).username(determineUsername()).password(determinePassword());
	}

以上就是我们的自动装配数据源的分析(第一次理解,不对望理解)


二.springboot整合druid

  1. 导入依赖:
		<!--log4j:druid配备了log4j作为记录日志工具,不配置会报错(可以不在配置文件中配置)-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        还需要导入另外的两个依赖
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
  1. 配置文件:
spring:
  #数据库连接配置
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    #serverTimezone=UTC:配置时区
    #useUnicode=true&characterEncoding=utf-8&useSSL=true:防止乱码
    url: jdbc:mysql:///is?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    #设置数据源,默认使用springboot自带的数据源
    type: com.alibaba.druid.pool.DruidDataSource


    #druid的其他配置:可选择配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
   #   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  1. 编写配置类:
@Configuration
public class DruidConfig {
    
    


    //自己配置一个数据源,默认接收spring.datasource的配置,然后把他放入到工厂中
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DruidDataSource druidDataSource(){
    
    
        return new DruidDataSource();
    }

    //配置Druid的监控 可以使用:http://localhost:端口/下边配置的拦截路径,即可访问
    //1、配置一个管理后台的Servlet
    @Bean
    public ServletRegistrationBean statViewServlet(){
    
    
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        Map<String,String> initParams = new HashMap<>();

        initParams.put("loginUsername","admin");
        initParams.put("loginPassword","123456");
        initParams.put("allow","");//默认就是允许所有访问
        initParams.put("deny","192.168.15.21");

        bean.setInitParameters(initParams);
        return bean;
    }


    //2、配置一个web监控的filter
    @Bean
    public FilterRegistrationBean webStatFilter(){
    
    
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        Map<String,String> initParams = new HashMap<>();
        initParams.put("exclusions","*.js,*.css,/druid/*");

        bean.setInitParameters(initParams);

        bean.setUrlPatterns(Arrays.asList("/*"));

        return  bean;
    }


}
  1. 测试:
    在这里插入图片描述

  2. druid的监控中心
    在这里插入图片描述
    登陆用户名和密码就是在配置文件的:
    在这里插入图片描述

未知理解:如果要使用druid的其他配置(如:监控中心),那么我们就需要自己创建DataSource,并接收配置文件有关的内容,才可以生效。
大概的原因是springboot底层帮根据全类名映射出来的数据源只能绑定基础的四个属性,其他的配置不会生效(不知道对不对)
在这里插入图片描述

3.springboot整合mybatis

  1. 需要导入的依赖
		<!--mybatis,还需要导入其他的就不一一列举了-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        
  1. springboot整合mybatis需要使用的注解:
    @Mapper:标注在dao接口上,标注的接口一定要存在于ioc容器中
    @MapperScan(dao层包路径):标注在springboot主入口上
    作用:mybaits会有一个拦截器,自动拦截标注了@Mapper注解的类或者扫描的包下的所有的类,然后使用代理的方式,创建对应的实现类,我们就可以直接在需要使用的地方,使用@Autowarid注解注入了,像以前ssm框架中的作用。

  2. 编写dao层接口:
    注解方式:

@Repository
public interface UserDao {
    
    

    /*查询全部的用户 可以直接使用注解的方式编写sql*/
    @Select("select * from users")
    List<Users> findAll();

    /*根据id查询用户*/
    //@Select("select * from users where id = #{id}")
    Users findUsersByid(Integer id);

    /*当多个参数时,一定要加上注解@Param*/
    @Select("select * from users where username = #{username} and password = #{password}")
    Users findUsersByUsernameAndPassword(@Param("username") String username,
                                         @Param("password") String password);
 }

在需要使用的地方@AutoWarid注解注入即可使用。

@Controller
public class UsersController {
    
    

    @Autowired
    private UserDao userDao;
    @Autowired
    private DataSource dataSource;

    @RequestMapping("/AllUsers")
    public void AllUsers(){
    
    
        System.out.println(dataSource.getClass());
        List<Users> all = userDao.findAll();
        for (Users users : all) {
    
    
            System.out.println(users);
        }
    }
}

===================================================
配置文件方式:
编写接口(不需要再使用注解编写sql):

@Repository
public interface UserDao {
    
    

    /*查询全部的用户 可以直接使用注解的方式编写sql*/
    //@Select("select * from users")
    List<Users> findAll();

    /*根据id查询用户*/
    //@Select("select * from users where id = #{id}")
    Users findUsersByid(Integer id);

    /*当多个参数时,一定要加上注解@Param*/
    //@Select("select * from users where username = #{username} and password = #{password}")
    Users findUsersByUsernameAndPassword(@Param("username") String username,
                                         @Param("password") String password);
}

编写配置文件(同以前方式:)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ceh.dao.UserDao">

    <!--/*查询全部的用户 可以直接使用注解的方式编写sql*/
    /*@Select("select * from users")*/
    List<Users> findAll();-->
    <select id="findAll" resultType="Users">
        select * from users
    </select>

   <!-- /*根据id查询用户*/
    //@Select("select * from users where id = #{id}")
    Users findUsersByid(Integer id);-->
    <select id="findUsersByid" resultType="Users" parameterType="Integer">
        select * from users where id = #{id}
    </select>

    <!--/*当多个参数时,一定要加上注解@Param*/
    //@Select("select * from users where username = #{username} and password = #{password}")
    Users findUsersByUsernameAndPassword(@Param("username") String username,
    @Param("password") String password);-->
    <select id="findUsersByUsernameAndPassword" resultType="Users">
        select * from users where username = #{username} and password = #{password}
    </select>

xml中的namespace一定要和dao接口保持一致。

再application.yaml中编写配置:

    #整合mybatis
mybatis:
  #配置mapper文件位置目录,ssm中的扫描mapper文件包是一样的
  mapper-locations: classpath:mappers/*.xml
  #配置别名
  type-aliases-package: com.ceh.pojo

此时注意:
mapper-locations: classpath:mappers/*.xml的位置
目录结构:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43431123/article/details/112988191