spring boot:配置shardingsphere(sharding jdbc)使用druid数据源(druid 1.1.23 / sharding-jdbc 4.1.1 / mybatis / spring boot 2.3.3)

一,为什么要使用druid数据源?

1,druid的优点

Druid是阿里巴巴开发的号称为监控而生的数据库连接池

它的优点包括:

可以监控数据库访问性能

SQL执行日志

SQL防火墙 

但spring boot和shardingjdbc默认使用的数据库连接池是 HikariCP

如果要在shardingsphere中使用druid,需要在项目中整合后才能生效

 

2,druid的官方代码站:

https://github.com/alibaba/druid/

 

说明:刘宏缔的架构森林是一个专注架构的博客,

网站:https://blog.imgtouch.com
本文: https://blog.imgtouch.com/index.php/2023/05/24/springboot-pei-zhi-shardingsphereshardingjdbc-shi-yong-druid-shu-ju-yuan/

         对应的源码可以访问这里获取: https://github.com/liuhongdi/

说明:作者:刘宏缔 邮箱: 371125307@qq.com

 

二,演示项目的相关信息

1,项目地址:

https://github.com/liuhongdi/shardingdruid

 

2, 功能说明:

    为shardingsphere配置druid数据源,

    监控功能需要可用

 

3,项目结构:如图:

 

4,用到的数据表:如图: 

 

 

三,配置文件说明

1,pom.xml

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        <!--exclude log-->
            <exclusions>
              <exclusion>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-starter-logging</artifactId>
              </exclusion>
            </exclusions>
        </dependency>
     <!--druid begin-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.23</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>3.4.2</version>
        </dependency>
        <!--sharding jdbc begin-->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.1</version>
        </dependency>
        <!--sharding jdbc   end-->
        <!--mybatis begin-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <!--mybatis end-->
        <!--pagehelper begin-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.13</version>
        </dependency>
        <!--pagehelper end-->
        <!--mysql begin-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--mysql end-->
        <!--thymeleaf begin-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--thymeleaf end-->

说明:1,为shardingsphere使用druid数据源时,不要使用: druid-spring-boot-starter这个包,

         因为它在会启动时自动从配置文件生成datasource,

         所以在这里使用druid这个包

         2,因为druid使用了log4j2,我们对spring-boot-starter-logging做了exclusion

 

2,配置application.properties:

#error
server.error.include-stacktrace=always

#thymeleaf
spring.thymeleaf.cache=false
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.mode=HTML
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

#shardingsphere
spring.shardingsphere.datasource.names=saleorder01,saleorder02
spring.shardingsphere.datasource.saleorder01.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.saleorder01.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.saleorder01.url=jdbc:mysql://127.0.0.1:3306/saleorder01?characterEncoding=utf-8
spring.shardingsphere.datasource.saleorder01.username=root
spring.shardingsphere.datasource.saleorder01.password=lhddemo
spring.shardingsphere.datasource.saleorder01.initial-size=5
spring.shardingsphere.datasource.saleorder01.min-idle=5
spring.shardingsphere.datasource.saleorder01.maxActive=20
spring.shardingsphere.datasource.saleorder01.maxWait=60000
spring.shardingsphere.datasource.saleorder01.timeBetweenEvictionRunsMillis=60000
spring.shardingsphere.datasource.saleorder01.minEvictableIdleTimeMillis=300000
spring.shardingsphere.datasource.saleorder01.validationQuery=SELECT 1 
spring.shardingsphere.datasource.saleorder01.testWhileIdle=true
spring.shardingsphere.datasource.saleorder01.testOnBorrow=false
spring.shardingsphere.datasource.saleorder01.testOnReturn=false
spring.shardingsphere.datasource.saleorder01.poolPreparedStatements=true
spring.shardingsphere.datasource.saleorder01.maxPoolPreparedStatementPerConnectionSize=20
spring.shardingsphere.datasource.saleorder01.filters=stat,wall,log4j2
spring.shardingsphere.datasource.saleorder01.connectionProperties=druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000

spring.shardingsphere.datasource.saleorder02.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.saleorder02.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.saleorder02.url=jdbc:mysql://127.0.0.1:3306/saleorder02?characterEncoding=utf-8
spring.shardingsphere.datasource.saleorder02.username=root
spring.shardingsphere.datasource.saleorder02.password=lhddemo
spring.shardingsphere.datasource.saleorder02.filters=stat,wall,log4j2
spring.shardingsphere.datasource.saleorder02.connectionProperties=druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000

spring.shardingsphere.sharding.default-data-source-name=saleorder01
spring.shardingsphere.sharding.default-database-strategy.standard.sharding-column=orderId
spring.shardingsphere.sharding.default-database-strategy.standard.precise-algorithm-class-name=com.shardingdruid.demo.algorithm.DatabasePreciseShardingAlgorithm

spring.shardingsphere.sharding.binding-tables=t_order
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=saleorder0$->{1..1}.t_order_$->{1..2},saleorder0$->{2..2}.t_order_$->{3..4}
spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.sharding-column=orderId
spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.precise-algorithm-class-name=com.shardingdruid.demo.algorithm.OrderTablePreciseShardingAlgorithm

spring.shardingsphere.props.sql.show=true

#mybatis
mybatis.mapper-locations=classpath:/mapper/*Mapper.xml
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

说明:使用druid数据源时,原有的shardingsphere配置中,jdbc-url要修改为url,

        否则druid会报错

 

3,数据库和数据表:

 我们创建两个库:saleorder01,saleorder02

然后在各个库内各创建两个数据表:

saleorder01库包括t_order_1,t_order_2

saleorder02库包括t_order_3,t_order_4

建表的sql:

CREATE TABLE `t_order_4` (
 `orderId` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
 `goodsName` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT 'name',
 PRIMARY KEY (`orderId`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='order4'

 

四,java代码说明

1,DatabasePreciseShardingAlgorithm.java

public class DatabasePreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        Long curValue = shardingValue.getValue();
        String curBase = "";
        if (curValue > 0 && curValue<=200) {
            curBase = "saleorder01";
        } else {
            curBase = "saleorder02";
        }
        return curBase;
    }
}

分库的算法

 

2,OrderTablePreciseShardingAlgorithm.java

public class OrderTablePreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        Long curValue = shardingValue.getValue();
        String curTable = "";
        if (curValue > 0 && curValue<=100) {
            curTable = "t_order_1";
        } else if (curValue > 100 && curValue<=200) {
            curTable = "t_order_2";
        } else if (curValue > 200 && curValue<=300) {
            curTable = "t_order_3";
        } else {
            curTable = "t_order_4";
        }
        return curTable;
    }
}

分表的算法

 

3,DruidConfig.java

@Configuration
public class DruidConfig {
    /**
     * Druid监控
     */
    @Bean
    public ServletRegistrationBean statViewServlet(){
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        Map<String,String> initParams = new HashMap<>();//这是配置的druid监控的登录密码
        initParams.put("loginUsername","root");
        initParams.put("loginPassword","root");
        //默认就是允许所有访问
        initParams.put("allow","127.0.0.1,192.168.3.4");
        //黑名单IP
        initParams.put("deny","192.168.15.21");
        bean.setInitParameters(initParams);
        return bean;
    }

    /**
     * web监控的filter
     */
    @Bean
    public FilterRegistrationBean webStatFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());
        Map<String,String> initParams = new HashMap<>();
        initParams.put("exclusions","/static/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");//过滤掉需要监控的文件
        bean.setInitParameters(initParams);
        bean.setUrlPatterns(Arrays.asList("/*"));
        return  bean;
    }
}

说明:因为没有使用druid-spring-boot-starter,在代码中配置监控view

 

4,OrderController.java

@Controller
@RequestMapping("/order")
public class OrderController {
    @Resource
    private OrderService orderService;

    //添加订单,参数:订单id/订单商品名字
    @RequestMapping("/added")
    @ResponseBody
    public ServerResponseUtil added(@RequestParam(value="orderid",required = false,defaultValue = "0") Long orderId,
                        @RequestParam(value="goodsname",required = false,defaultValue = "") String goodsName){
        Order orderOne = new Order();
        orderOne.setOrderId(orderId);
        orderOne.setGoodsName(goodsName);
        boolean isAdd = orderService.addOneOrder(orderOne);
        System.out.println("isAdd:"+isAdd);
        if (isAdd == true) {
            return ServerResponseUtil.success("添加成功");
        } else {
            throw new ServiceException(ResponseCode.DATA_INS_FAIL.getMsg());
        }
    }
    
    //添加订单的form页面
    @RequestMapping("/add")
    public String add(){
        return "order/add";
    }

    //订单的列表,参数:第几页
    @GetMapping("/list")
    public String list(Model model,
                     @RequestParam(value="currentPage",required = false,defaultValue = "1") Integer currentPage){

        PageHelper.startPage(currentPage, Constant.ORDER_PAGE_SIZE);
        List<Order> order_list = orderService.getAllOrder();
        model.addAttribute("order_list",order_list);
        PageInfo<Order> pageInfo = new PageInfo<>(order_list);
        model.addAttribute("pageInfo", pageInfo);
        return "order/list";
    }
}

 

5,OrderServiceImpl.java

@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderMapper orderMapper;

    //列出所有订单
    @Override
    public List<Order> getAllOrder() {
        List<Order> order_list = orderMapper.selectAllOrder();
        return order_list;
    }

    //添加订单
    @Override
    public boolean addOneOrder(Order orderOne) {
        int num = orderMapper.insertOneOrder(orderOne);
        if (num == 1) {
            return true;
        } else {
            return false;
        }
    }
}

 

6,OrderMapper.java

@Repository
@Mapper
public interface OrderMapper {
    int insertOneOrder(Order orderOne);
    String selectNameById(String userId);
    List<Order> selectAllOrder();
}

 

7,Order.java

public class Order {

    //订单id
    private Long orderId;
    public Long getOrderId() {
        return this.orderId;
    }
    public void setOrderId(Long orderId) {
        this.orderId = orderId;
    }

    //商品名字
    private String goodsName;
    public String getGoodsName() {
        return this.goodsName;
    }
    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }
}

 

8,OrderMapper.xml

<?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.shardingdruid.demo.mapper.OrderMapper" >
    <resultMap id="BaseResultMap" type="com.shardingdruid.demo.pojo.Order" >
        <result column="orderId" property="orderId" jdbcType="BIGINT" />
        <result column="goodsName" property="goodsName" jdbcType="VARCHAR" />
    </resultMap>
    <sql id="Base_Column_List" >
        orderId, goodsName
    </sql>
    <insert id="insertOneOrder" parameterType="com.shardingdruid.demo.pojo.Order" >
        INSERT ignore INTO
        t_order
        (orderId,goodsName)
        VALUES
        (#{orderId},#{goodsName})
    </insert>
    <select id="selectAllOrder" resultType="com.shardingdruid.demo.pojo.Order">
        select * from t_order order by orderId desc
    </select>
</mapper>

 

9,其他代码,可以从github上参考

 

五,测试效果

1,查看订单列表,访问:

http://127.0.0.1:8080/order/list/

效果如图:

2,查看druid,访问:

http://127.0.0.1:8080/druid

登录后可以看到我们建立的连接:如图:

 

六,查看spring boot的版本:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.3.RELEASE)

 

posted @ 2020-08-20 19:08  刘宏缔的架构森林  阅读(14966)  评论(0编辑  收藏  举报