欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Springboot整合ShardingJdbc實現(xiàn)分庫分表方式

 更新時間:2025年06月10日 08:41:08   作者:y&m  
這篇文章主要介紹了Springboot整合ShardingJdbc實現(xiàn)分庫分表方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

創(chuàng)建庫表

1、創(chuàng)建兩個數(shù)據(jù)庫

CREATE SCHEMA `shard_db_0` DEFAULT CHARACTER SET utf8 ;
CREATE SCHEMA `shard_db_1` DEFAULT CHARACTER SET utf8 ;

2、在每個數(shù)據(jù)庫各創(chuàng)建三個分表

CREATE TABLE `tb_order_0` (
  `order_id` bigint(20) NOT NULL,
  `buyer_id` bigint(20) not null comment '買家ID',
  `seller_id` bigint(20) not null comment '賣家ID',
  `order_name` varchar(64) not NULL COMMENT '商品名稱',
  `price` decimal(10,2) DEFAULT NULL COMMENT '商品價格',
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `tb_order_1` (
  `order_id` bigint(20) NOT NULL,
  `buyer_id` bigint(20) not null comment '買家ID',
  `seller_id` bigint(20) not null comment '賣家ID',
  `order_name` varchar(64) not NULL COMMENT '商品名稱',
  `price` decimal(10,2) DEFAULT NULL COMMENT '商品價格',
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `tb_order_2` (
  `order_id` bigint(20) NOT NULL,
  `buyer_id` bigint(20) not null comment '買家ID',
  `seller_id` bigint(20) not null comment '賣家ID',
  `order_name` varchar(64) not NULL COMMENT '商品名稱',
  `price` decimal(10,2) DEFAULT NULL COMMENT '商品價格',
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

創(chuàng)建工程

1、引入maven依賴

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>sharding-sphere-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sharding-sphere-demo</name>
    <description>sharding-sphere-demo</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>

        <!-- MyBatis-Plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>3.5.7</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/shardingsphere-jdbc-core-spring-boot-starter -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.2.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.1</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2、創(chuàng)建po

@Builder
@Data
@TableName("tb_buyer")
public class TbBuyer {

    @TableId
    private Long buyerId;
    private String buyerName;
    private Boolean sex;
    private Integer age;

}
@Builder
@Data
@TableName("tb_order")
public class TbOrder {

    @TableId
    private Long orderId;
    private Long buyerId;
    private Long sellerId;
    private String orderName;
    private BigDecimal price;

}
@Builder
@Data
@TableName("tb_seller")
public class TbSeller {

    @TableId
    private Long sellerId;
    private String sellerName;
    private Boolean sex;
    private Integer age;

}

3、創(chuàng)建mapper

package com.example.shardingsphere.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.shardingsphere.po.TbBuyer;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface TbBuyerMapper extends BaseMapper<TbBuyer> {
    // 可以在這里定義自定義方法
}
package com.example.shardingsphere.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.shardingsphere.po.TbOrder;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface TbOrderMapper extends BaseMapper<TbOrder> {
    // 可以在這里定義自定義方法
}
package com.example.shardingsphere.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.shardingsphere.po.TbSeller;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface TbSellerMapper extends BaseMapper<TbSeller> {
    // 可以在這里定義自定義方法
}

4、創(chuàng)建controller控制器

package com.example.shardingsphere.web;

import com.example.shardingsphere.mapper.TbBuyerMapper;
import com.example.shardingsphere.mapper.TbOrderMapper;
import com.example.shardingsphere.mapper.TbSellerMapper;
import com.example.shardingsphere.po.TbOrder;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class OrderController {

    @Resource
    private TbBuyerMapper tbBuyerMapper ;
    @Resource
    private TbSellerMapper tbSellerMapper ;
    @Resource
    private TbOrderMapper tbOrderMapper ;

    /**
     * 查詢訂單詳情
     */
    @GetMapping("/order/info/{orderId}")
    public Map<String,Object> orderInfo (@PathVariable Long orderId){
        Map<String,Object> orderMap = new HashMap<>() ;
        TbOrder order = tbOrderMapper.selectById(orderId) ;
        if (order != null){
            orderMap.put("order",order) ;
            orderMap.put("buyer",tbBuyerMapper.selectById(order.getBuyerId())) ;
            orderMap.put("seller",tbSellerMapper.selectById(order.getSellerId())) ;
        }
        return orderMap ;
    }
}

5、用到的工具類(雪花算法生成關聯(lián)表主鍵ID,測試用,無特殊意義)

package com.example.shardingsphere.provider;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * 雪花算法
 *
 */
@Slf4j
@Component
public class SnowFlakeProvider implements ApplicationRunner {

    private long workerId;
    private Snowflake snowFlake;
    private long datacenterId;

    /**
     * 初始化方法,用于在類實例化后進行必要的設置。
     * 本方法主要用于確定WorkerId,這是一個在分布式系統(tǒng)中唯一標識當前節(jié)點的ID。
     * 它通過獲取本地主機名或IP并轉(zhuǎn)換為long值來實現(xiàn)。
     * 如果無法獲取本地主機名或IP,或者轉(zhuǎn)換過程中發(fā)生異常,將不設置workerId,可能導致后續(xù)ID生成失敗。
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        //初始化workId
        initWorkId();

        initDataCenterId();

        //初始化SnowflakeID生成器
        createSnowFlake(workerId, datacenterId);
    }

    /**
     * 根據(jù)IP Address 生成workId
     *
     * @return
     */
    private void initWorkId() {
        try {
            String hostAddress = Inet4Address.getLocalHost().getHostAddress();
            log.info("hostAddress========={}", hostAddress);
            int[] ints = StringUtils.toCodePoints(hostAddress);
            int sums = 0;
            for (int b : ints) {
                sums += b;
            }
            workerId= (long) (sums % 32);
        } catch (UnknownHostException e) {
            log.error("根據(jù)IP獲取workId失敗。", e);
            // 如果獲取失敗,則使用隨機數(shù)備用
            workerId = RandomUtil.randomLong(0, 31);
        }
    }
    /**
     * 根據(jù)HostName 生成dataCenterId
     * @return
     */
    private void initDataCenterId() {
        String hostName = getHostName();
        log.info("hostName========={}", hostName);
        int[] ints = StringUtils.toCodePoints(hostName);
        int sums = 0;
        for (int i : ints) {
            sums += i;
        }
        datacenterId = (long) (sums % 32);
    }

    /**
     * 獲取 hostName
     *   SystemUtils.getHostName() 在mac系統(tǒng)為空處理
     * @return
     */
    public static String getHostName() {
        //獲取當前操作系統(tǒng)名稱,例如:windows xp,linux 等
        String osName = System.getProperty("os.name");
        String hostName = null;
        if(!StringUtils.startsWithIgnoreCase(osName,"mac")){
            hostName = SystemUtils.getHostName();
        }else{
            try {
                hostName = InetAddress.getLocalHost().getHostName().toUpperCase();
            } catch (UnknownHostException e) {
                hostName = "N/A";
                log.error("獲取 hostName錯誤:", e);
            }
        }
        return hostName;
    }

    /**
     * 初始化SnowflakeID生成器。
     * 使用指定的workerId和datacenterId創(chuàng)建SnowflakeID生成器實例。如果創(chuàng)建失敗,將拋出異常。
     *
     * @param workerId 工作節(jié)點ID,用于標識當前節(jié)點。
     * @param datacenterId 數(shù)據(jù)中心ID,用于標識數(shù)據(jù)中心。
     * @throws IllegalArgumentException 如果Snowflake實例創(chuàng)建失敗,則拋出此異常。
     * @throws RuntimeException 如果Snowflake實例創(chuàng)建過程中發(fā)生其他異常,則拋出此異常。
     */
    private Snowflake createSnowFlake(long workerId, long datacenterId) {
        try {
            this.snowFlake = IdUtil.createSnowflake(workerId, datacenterId);
            // 參數(shù)合法性檢查
            if (null == snowFlake) {
                throw new IllegalArgumentException("Failed to create Snowflake instance. Check workerId and datacenterId.");
            }
            return snowFlake;
        } catch (Exception e) {
            log.error("創(chuàng)建Snowflake實例失敗,異常:{}", e.getMessage());
            throw new RuntimeException("Initialization failed for Snowflake ID generator.", e);
        }
    }

    /**
     * 獲取一個唯一的雪花ID。使用Snowflake算法生成ID,該算法由Twitter開源。
     * 具體來說,這個方法調(diào)用了Snowflake實例的nextId方法來獲取一個唯一的長整型ID。
     * 使用synchronized關鍵字確保了這個方法在多線程環(huán)境下的線程安全,
     * 保證了ID的生成不會因為并發(fā)而產(chǎn)生重復或錯亂。
     *
     * @return 生成的唯一長整型ID。
     */
    public synchronized long snowflakeId() {
        // 調(diào)用Snowflake實例的nextId方法獲取唯一ID
        return this.snowFlake.nextId();
    }

    /**
     * 生成基于Snowflake算法的唯一ID。
     * <p>
     * 使用Snowflake算法生成唯一的分布式ID。該算法由Twitter提出,通過組合時間戳、工作機器ID和序列號來生成全局唯一的ID。
     * 具體結(jié)構(gòu)如下:
     * - 1位符號位,用于區(qū)分正負,由于ID只能是正數(shù),所以這個位始終為0。
     * - 41位時間戳,精確到毫秒,可以使用約69年。
     * - 10位工作機器ID,可以部署在1024個節(jié)點,包括5位數(shù)據(jù)中心ID和5位工作機器ID。
     * - 12位序列號,用于同一毫秒內(nèi)生成的ID去重,每個節(jié)點每毫秒可以生成4096個ID。
     * <p>
     * 參數(shù):
     * workerId - 工作機器ID,用于標識不同的工作機器或進程。
     * datacenterId - 數(shù)據(jù)中心ID,用于標識不同的數(shù)據(jù)中心。
     * <p>
     * 返回:
     * 一個長整型的唯一ID,根據(jù)Snowflake算法生成。
     */
    public synchronized long snowflakeId(long workerId, long datacenterId) {
        return createSnowFlake(workerId, datacenterId).nextId();
    }

}

6、測試用例

package com.example.shardingsphere;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.shardingsphere.mapper.TbOrderMapper;
import com.example.shardingsphere.po.TbOrder;
import com.example.shardingsphere.provider.SnowFlakeProvider;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class ShardTest extends ShardingSphereDemoApplicationTests{

    @Autowired
    private SnowFlakeProvider snowFlakeProvider;

    @Autowired
    private TbOrderMapper tbOrderMapper ;

    /**
     * 寫入100條數(shù)據(jù)
     */
    @Test
    public void testOrderInsert (){
        List<TbOrder> list = new ArrayList<>();
        for (int i=1 ; i<= 10 ; i++){
            TbOrder order = TbOrder.builder()
//                    .orderId(snowFlakeProvider.snowflakeId())
                    .buyerId(snowFlakeProvider.snowflakeId())
                    .sellerId(snowFlakeProvider.snowflakeId())
                    .orderName("訂單"+ RandomUtil.randomInt(6))
                    .price(RandomUtil.randomBigDecimal().setScale(2, BigDecimal.ROUND_HALF_UP))
                    .build();
            list.add(order);
        }
        tbOrderMapper.insert(list);
    }

    @Test
    public void testOrderQuery (){
        TbOrder order = tbOrderMapper.selectById(5) ;
        Assert.assertNotNull(order);
        log.info("查詢結(jié)果:"+ JSONUtil.toJsonStr(order));
    }

    @Test
    public void testOrderUpdate (){
        TbOrder order = tbOrderMapper.selectById(3) ;
        Assert.assertNotNull(order);
        order.setBuyerId(1l);
        order.setSellerId(3l);
        int count = tbOrderMapper.updateById(order) ;
        log.info("更新記錄數(shù):"+count);
    }

    @Test
    public void testOrderPage (){
        //分頁參數(shù)
        Page<TbOrder> rowPage = new Page<>(1, 2);
        //queryWrapper組裝查詢where條件
        LambdaQueryWrapper<TbOrder> queryWrapper = new LambdaQueryWrapper<>();
        Page<TbOrder> page = tbOrderMapper.selectPage(rowPage, queryWrapper);
        log.info("分頁查詢結(jié)果:"+ JSONUtil.toJsonStr(page));
    }

}

7、yml配置

server:
  port: 8095

spring:
  application:
    name: dynamic-datasource-spring-boot-starter
  shardingsphere:
    mode:
      type: Standalone
      repository:
        type: JDBC
    database:
      name: db0
    # 數(shù)據(jù)源配置
    datasource:
      # 數(shù)據(jù)源名稱,多數(shù)據(jù)源以逗號分隔
      names: db0,db1
      db0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://xx:3306/shard_db_0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
        username: xx
        password: xx
      db1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://xx:3306/shard_db_1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
        username: xx
        password: xx
    # 分片規(guī)則配置
    rules:
      sharding:
        # 分片算法配置
        sharding-algorithms:
          database-inline:
            # 分片算法類型
            type: INLINE
            props:
              # 分片算法的行表達式(算法自行定義,此處為方便演示效果)
              algorithm-expression: db${order_id % 2}
          table-inline:
            # 分片算法類型
            type: INLINE
            props:
              # 分片算法的行表達式
              algorithm-expression: tb_order_${order_id % 3}
        tables:
          # 邏輯表名稱
          tb_order:
            # 行表達式標識符可以使用 ${...} 或 $->{...},但前者與 Spring 本身的屬性文件占位符沖突,因此在 Spring 環(huán)境中使用行表達式標識符建議使用 $->{...}
            actual-data-nodes: db${0..1}.tb_order_${0..2}
            # 分庫策略
            database-strategy:
              standard:
                # 分片列名稱
                sharding-column: order_id
                # 分片算法名稱
                sharding-algorithm-name: database-inline
            # 分表策略
            table-strategy:
              standard:
                # 分片列名稱
                sharding-column: order_id
                # 分片算法名稱
                sharding-algorithm-name: table-inline
    # 屬性配置
    props:
      # 展示修改以后的sql語句
      sql-show: true

mybatis-plus:
  type-aliases-package: com.example.dynamic.po
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations:
    - classpath:/mapper/*.xml

至此,一個支持分庫分表的工程搭建完成。

關于搭建過程中遇到的問題(shardingsphere-jdbc-core-spring-boot-starter 5.2.1)

1、Caused by: java.lang.NoSuchMethodError: org.yaml.snakeyaml.representer.Representer: method 'void <init>()' not found

解答:該問題是由于版本問題導致的,是個兼容性問題。

shardingsphere-jdbc-core-spring-boot-starter 5.2.1中使用snakeyaml版本1.33 spring-boot-starter-web使用snakeyaml版本2.2 2.2中刪除了Representer和SafeRepresenter的無參構(gòu)造器,因此導致了該異常。

可通過降低boot版本號從而降低其中snakeyaml版本號解決,但由于snakeyaml 1.x版本有安全問題,而shardingsphere-jdbc-core-spring-boot-starter已是當前最高版本,因此可通過重新jar中bean新增無參構(gòu)造器去覆蓋jar bean去解決。

com.main.java下新增目錄org.yaml.snakeyaml.representer

目錄下新建bean

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.yaml.snakeyaml.representer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.introspector.PropertyUtils;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;

public class Representer extends SafeRepresenter {
    protected Map<Class<? extends Object>, TypeDescription> typeDefinitions = Collections.emptyMap();

    public Representer() {
        this.representers.put(null, new RepresentJavaBean());
    }

    public Representer(DumperOptions options) {
        super(options);
        this.representers.put(null, new RepresentJavaBean());
    }

    public TypeDescription addTypeDescription(TypeDescription td) {
        if (Collections.EMPTY_MAP == this.typeDefinitions) {
            this.typeDefinitions = new HashMap();
        }

        if (td.getTag() != null) {
            this.addClassTag(td.getType(), td.getTag());
        }

        td.setPropertyUtils(this.getPropertyUtils());
        return (TypeDescription)this.typeDefinitions.put(td.getType(), td);
    }

    public void setPropertyUtils(PropertyUtils propertyUtils) {
        super.setPropertyUtils(propertyUtils);
        Collection<TypeDescription> tds = this.typeDefinitions.values();
        Iterator var3 = tds.iterator();

        while(var3.hasNext()) {
            TypeDescription typeDescription = (TypeDescription)var3.next();
            typeDescription.setPropertyUtils(propertyUtils);
        }

    }

    protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
        List<NodeTuple> value = new ArrayList(properties.size());
        Tag customTag = (Tag)this.classTags.get(javaBean.getClass());
        Tag tag = customTag != null ? customTag : new Tag(javaBean.getClass());
        MappingNode node = new MappingNode(tag, value, FlowStyle.AUTO);
        this.representedObjects.put(javaBean, node);
        DumperOptions.FlowStyle bestStyle = FlowStyle.FLOW;
        Iterator var8 = properties.iterator();

        while(true) {
            NodeTuple tuple;
            do {
                if (!var8.hasNext()) {
                    if (this.defaultFlowStyle != FlowStyle.AUTO) {
                        node.setFlowStyle(this.defaultFlowStyle);
                    } else {
                        node.setFlowStyle(bestStyle);
                    }

                    return node;
                }

                Property property = (Property)var8.next();
                Object memberValue = property.get(javaBean);
                Tag customPropertyTag = memberValue == null ? null : (Tag)this.classTags.get(memberValue.getClass());
                tuple = this.representJavaBeanProperty(javaBean, property, memberValue, customPropertyTag);
            } while(tuple == null);

            if (!((ScalarNode)tuple.getKeyNode()).isPlain()) {
                bestStyle = FlowStyle.BLOCK;
            }

            Node nodeValue = tuple.getValueNode();
            if (!(nodeValue instanceof ScalarNode) || !((ScalarNode)nodeValue).isPlain()) {
                bestStyle = FlowStyle.BLOCK;
            }

            value.add(tuple);
        }
    }

    protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
        ScalarNode nodeKey = (ScalarNode)this.representData(property.getName());
        boolean hasAlias = this.representedObjects.containsKey(propertyValue);
        Node nodeValue = this.representData(propertyValue);
        if (propertyValue != null && !hasAlias) {
            NodeId nodeId = nodeValue.getNodeId();
            if (customTag == null) {
                if (nodeId == NodeId.scalar) {
                    if (property.getType() != Enum.class && propertyValue instanceof Enum) {
                        nodeValue.setTag(Tag.STR);
                    }
                } else {
                    if (nodeId == NodeId.mapping && property.getType() == propertyValue.getClass() && !(propertyValue instanceof Map) && !nodeValue.getTag().equals(Tag.SET)) {
                        nodeValue.setTag(Tag.MAP);
                    }

                    this.checkGlobalTag(property, nodeValue, propertyValue);
                }
            }
        }

        return new NodeTuple(nodeKey, nodeValue);
    }

    protected void checkGlobalTag(Property property, Node node, Object object) {
        if (!object.getClass().isArray() || !object.getClass().getComponentType().isPrimitive()) {
            Class<?>[] arguments = property.getActualTypeArguments();
            if (arguments != null) {
                Class t;
                Iterator iter;
                Iterator var9;
                if (node.getNodeId() == NodeId.sequence) {
                    t = arguments[0];
                    SequenceNode snode = (SequenceNode)node;
                    Iterable<Object> memberList = Collections.emptyList();
                    if (object.getClass().isArray()) {
                        memberList = Arrays.asList((Object[])object);
                    } else if (object instanceof Iterable) {
                        memberList = (Iterable)object;
                    }

                    iter = ((Iterable)memberList).iterator();
                    if (iter.hasNext()) {
                        var9 = snode.getValue().iterator();

                        while(var9.hasNext()) {
                            Node childNode = (Node)var9.next();
                            Object member = iter.next();
                            if (member != null && t.equals(member.getClass()) && childNode.getNodeId() == NodeId.mapping) {
                                childNode.setTag(Tag.MAP);
                            }
                        }
                    }
                } else if (object instanceof Set) {
                    t = arguments[0];
                    MappingNode mnode = (MappingNode)node;
                    Iterator<NodeTuple> ite = mnode.getValue().iterator();
                    Set<?> set = (Set)object;
                    var9 = set.iterator();

                    while(var9.hasNext()) {
                        Object member = var9.next();
                        NodeTuple tuple = (NodeTuple)ite.next();
                        Node keyNode = tuple.getKeyNode();
                        if (t.equals(member.getClass()) && keyNode.getNodeId() == NodeId.mapping) {
                            keyNode.setTag(Tag.MAP);
                        }
                    }
                } else if (object instanceof Map) {
                    t = arguments[0];
                    Class<?> valueType = arguments[1];
                    MappingNode mnode = (MappingNode)node;
                    iter = mnode.getValue().iterator();

                    while(iter.hasNext()) {
                        NodeTuple tuple = (NodeTuple)iter.next();
                        this.resetTag(t, tuple.getKeyNode());
                        this.resetTag(valueType, tuple.getValueNode());
                    }
                }
            }

        }
    }

    private void resetTag(Class<? extends Object> type, Node node) {
        Tag tag = node.getTag();
        if (tag.matches(type)) {
            if (Enum.class.isAssignableFrom(type)) {
                node.setTag(Tag.STR);
            } else {
                node.setTag(Tag.MAP);
            }
        }

    }

    protected Set<Property> getProperties(Class<? extends Object> type) {
        return this.typeDefinitions.containsKey(type) ? ((TypeDescription)this.typeDefinitions.get(type)).getProperties() : this.getPropertyUtils().getProperties(type);
    }

    protected class RepresentJavaBean implements Represent {
        protected RepresentJavaBean() {
        }

        public Node representData(Object data) {
            return Representer.this.representJavaBean(Representer.this.getProperties(data.getClass()), data);
        }
    }
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.yaml.snakeyaml.representer;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import java.util.regex.Pattern;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.DumperOptions.NonPrintableStyle;
import org.yaml.snakeyaml.DumperOptions.ScalarStyle;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.reader.StreamReader;

class SafeRepresenter extends BaseRepresenter {
    protected Map<Class<? extends Object>, Tag> classTags;
    protected TimeZone timeZone = null;
    protected DumperOptions.NonPrintableStyle nonPrintableStyle;
    private static final Pattern MULTILINE_PATTERN = Pattern.compile("\n|\u0085|\u2028|\u2029");

    public SafeRepresenter() {
        this(new DumperOptions());
    }

    public SafeRepresenter(DumperOptions options) {
        if (options == null) {
            throw new NullPointerException("DumperOptions must be provided.");
        } else {
            this.nullRepresenter = new RepresentNull();
            this.representers.put(String.class, new RepresentString());
            this.representers.put(Boolean.class, new RepresentBoolean());
            this.representers.put(Character.class, new RepresentString());
            this.representers.put(UUID.class, new RepresentUuid());
            this.representers.put(byte[].class, new RepresentByteArray());
            Represent primitiveArray = new RepresentPrimitiveArray();
            this.representers.put(short[].class, primitiveArray);
            this.representers.put(int[].class, primitiveArray);
            this.representers.put(long[].class, primitiveArray);
            this.representers.put(float[].class, primitiveArray);
            this.representers.put(double[].class, primitiveArray);
            this.representers.put(char[].class, primitiveArray);
            this.representers.put(boolean[].class, primitiveArray);
            this.multiRepresenters.put(Number.class, new RepresentNumber());
            this.multiRepresenters.put(List.class, new RepresentList());
            this.multiRepresenters.put(Map.class, new RepresentMap());
            this.multiRepresenters.put(Set.class, new RepresentSet());
            this.multiRepresenters.put(Iterator.class, new RepresentIterator());
            this.multiRepresenters.put((new Object[0]).getClass(), new RepresentArray());
            this.multiRepresenters.put(Date.class, new RepresentDate());
            this.multiRepresenters.put(Enum.class, new RepresentEnum());
            this.multiRepresenters.put(Calendar.class, new RepresentDate());
            this.classTags = new HashMap();
            this.nonPrintableStyle = options.getNonPrintableStyle();
            this.setDefaultScalarStyle(options.getDefaultScalarStyle());
            this.setDefaultFlowStyle(options.getDefaultFlowStyle());
        }
    }

    protected Tag getTag(Class<?> clazz, Tag defaultTag) {
        return this.classTags.containsKey(clazz) ? (Tag)this.classTags.get(clazz) : defaultTag;
    }

    public Tag addClassTag(Class<? extends Object> clazz, Tag tag) {
        if (tag == null) {
            throw new NullPointerException("Tag must be provided.");
        } else {
            return (Tag)this.classTags.put(clazz, tag);
        }
    }

    public TimeZone getTimeZone() {
        return this.timeZone;
    }

    public void setTimeZone(TimeZone timeZone) {
        this.timeZone = timeZone;
    }

    protected class RepresentUuid implements Represent {
        protected RepresentUuid() {
        }

        public Node representData(Object data) {
            return SafeRepresenter.this.representScalar(SafeRepresenter.this.getTag(data.getClass(), new Tag(UUID.class)), data.toString());
        }
    }

    protected class RepresentByteArray implements Represent {
        protected RepresentByteArray() {
        }

        public Node representData(Object data) {
            char[] binary = Base64Coder.encode((byte[])data);
            return SafeRepresenter.this.representScalar(Tag.BINARY, String.valueOf(binary), ScalarStyle.LITERAL);
        }
    }

    protected class RepresentEnum implements Represent {
        protected RepresentEnum() {
        }

        public Node representData(Object data) {
            Tag tag = new Tag(data.getClass());
            return SafeRepresenter.this.representScalar(SafeRepresenter.this.getTag(data.getClass(), tag), ((Enum)data).name());
        }
    }

    protected class RepresentDate implements Represent {
        protected RepresentDate() {
        }

        public Node representData(Object data) {
            Calendar calendar;
            if (data instanceof Calendar) {
                calendar = (Calendar)data;
            } else {
                calendar = Calendar.getInstance(SafeRepresenter.this.getTimeZone() == null ? TimeZone.getTimeZone("UTC") : SafeRepresenter.this.timeZone);
                calendar.setTime((Date)data);
            }

            int years = calendar.get(1);
            int months = calendar.get(2) + 1;
            int days = calendar.get(5);
            int hour24 = calendar.get(11);
            int minutes = calendar.get(12);
            int seconds = calendar.get(13);
            int millis = calendar.get(14);
            StringBuilder buffer = new StringBuilder(String.valueOf(years));

            while(buffer.length() < 4) {
                buffer.insert(0, "0");
            }

            buffer.append("-");
            if (months < 10) {
                buffer.append("0");
            }

            buffer.append(months);
            buffer.append("-");
            if (days < 10) {
                buffer.append("0");
            }

            buffer.append(days);
            buffer.append("T");
            if (hour24 < 10) {
                buffer.append("0");
            }

            buffer.append(hour24);
            buffer.append(":");
            if (minutes < 10) {
                buffer.append("0");
            }

            buffer.append(minutes);
            buffer.append(":");
            if (seconds < 10) {
                buffer.append("0");
            }

            buffer.append(seconds);
            if (millis > 0) {
                if (millis < 10) {
                    buffer.append(".00");
                } else if (millis < 100) {
                    buffer.append(".0");
                } else {
                    buffer.append(".");
                }

                buffer.append(millis);
            }

            int gmtOffset = calendar.getTimeZone().getOffset(calendar.getTime().getTime());
            if (gmtOffset == 0) {
                buffer.append('Z');
            } else {
                if (gmtOffset < 0) {
                    buffer.append('-');
                    gmtOffset *= -1;
                } else {
                    buffer.append('+');
                }

                int minutesOffset = gmtOffset / '\uea60';
                int hoursOffset = minutesOffset / 60;
                int partOfHour = minutesOffset % 60;
                if (hoursOffset < 10) {
                    buffer.append('0');
                }

                buffer.append(hoursOffset);
                buffer.append(':');
                if (partOfHour < 10) {
                    buffer.append('0');
                }

                buffer.append(partOfHour);
            }

            return SafeRepresenter.this.representScalar(SafeRepresenter.this.getTag(data.getClass(), Tag.TIMESTAMP), buffer.toString(), ScalarStyle.PLAIN);
        }
    }

    protected class RepresentSet implements Represent {
        protected RepresentSet() {
        }

        public Node representData(Object data) {
            Map<Object, Object> value = new LinkedHashMap();
            Set<Object> set = (Set)data;
            Iterator var4 = set.iterator();

            while(var4.hasNext()) {
                Object key = var4.next();
                value.put(key, (Object)null);
            }

            return SafeRepresenter.this.representMapping(SafeRepresenter.this.getTag(data.getClass(), Tag.SET), value, FlowStyle.AUTO);
        }
    }

    protected class RepresentMap implements Represent {
        protected RepresentMap() {
        }

        public Node representData(Object data) {
            return SafeRepresenter.this.representMapping(SafeRepresenter.this.getTag(data.getClass(), Tag.MAP), (Map)data, FlowStyle.AUTO);
        }
    }

    protected class RepresentPrimitiveArray implements Represent {
        protected RepresentPrimitiveArray() {
        }

        public Node representData(Object data) {
            Class<?> type = data.getClass().getComponentType();
            if (Byte.TYPE == type) {
                return SafeRepresenter.this.representSequence(Tag.SEQ, this.asByteList(data), FlowStyle.AUTO);
            } else if (Short.TYPE == type) {
                return SafeRepresenter.this.representSequence(Tag.SEQ, this.asShortList(data), FlowStyle.AUTO);
            } else if (Integer.TYPE == type) {
                return SafeRepresenter.this.representSequence(Tag.SEQ, this.asIntList(data), FlowStyle.AUTO);
            } else if (Long.TYPE == type) {
                return SafeRepresenter.this.representSequence(Tag.SEQ, this.asLongList(data), FlowStyle.AUTO);
            } else if (Float.TYPE == type) {
                return SafeRepresenter.this.representSequence(Tag.SEQ, this.asFloatList(data), FlowStyle.AUTO);
            } else if (Double.TYPE == type) {
                return SafeRepresenter.this.representSequence(Tag.SEQ, this.asDoubleList(data), FlowStyle.AUTO);
            } else if (Character.TYPE == type) {
                return SafeRepresenter.this.representSequence(Tag.SEQ, this.asCharList(data), FlowStyle.AUTO);
            } else if (Boolean.TYPE == type) {
                return SafeRepresenter.this.representSequence(Tag.SEQ, this.asBooleanList(data), FlowStyle.AUTO);
            } else {
                throw new YAMLException("Unexpected primitive '" + type.getCanonicalName() + "'");
            }
        }

        private List<Byte> asByteList(Object in) {
            byte[] array = (byte[])in;
            List<Byte> list = new ArrayList(array.length);

            for(int i = 0; i < array.length; ++i) {
                list.add(array[i]);
            }

            return list;
        }

        private List<Short> asShortList(Object in) {
            short[] array = (short[])in;
            List<Short> list = new ArrayList(array.length);

            for(int i = 0; i < array.length; ++i) {
                list.add(array[i]);
            }

            return list;
        }

        private List<Integer> asIntList(Object in) {
            int[] array = (int[])in;
            List<Integer> list = new ArrayList(array.length);

            for(int i = 0; i < array.length; ++i) {
                list.add(array[i]);
            }

            return list;
        }

        private List<Long> asLongList(Object in) {
            long[] array = (long[])in;
            List<Long> list = new ArrayList(array.length);

            for(int i = 0; i < array.length; ++i) {
                list.add(array[i]);
            }

            return list;
        }

        private List<Float> asFloatList(Object in) {
            float[] array = (float[])in;
            List<Float> list = new ArrayList(array.length);

            for(int i = 0; i < array.length; ++i) {
                list.add(array[i]);
            }

            return list;
        }

        private List<Double> asDoubleList(Object in) {
            double[] array = (double[])in;
            List<Double> list = new ArrayList(array.length);

            for(int i = 0; i < array.length; ++i) {
                list.add(array[i]);
            }

            return list;
        }

        private List<Character> asCharList(Object in) {
            char[] array = (char[])in;
            List<Character> list = new ArrayList(array.length);

            for(int i = 0; i < array.length; ++i) {
                list.add(array[i]);
            }

            return list;
        }

        private List<Boolean> asBooleanList(Object in) {
            boolean[] array = (boolean[])in;
            List<Boolean> list = new ArrayList(array.length);

            for(int i = 0; i < array.length; ++i) {
                list.add(array[i]);
            }

            return list;
        }
    }

    protected class RepresentArray implements Represent {
        protected RepresentArray() {
        }

        public Node representData(Object data) {
            Object[] array = (Object[])data;
            List<Object> list = Arrays.asList(array);
            return SafeRepresenter.this.representSequence(Tag.SEQ, list, FlowStyle.AUTO);
        }
    }

    private static class IteratorWrapper implements Iterable<Object> {
        private final Iterator<Object> iter;

        public IteratorWrapper(Iterator<Object> iter) {
            this.iter = iter;
        }

        public Iterator<Object> iterator() {
            return this.iter;
        }
    }

    protected class RepresentIterator implements Represent {
        protected RepresentIterator() {
        }

        public Node representData(Object data) {
            Iterator<Object> iter = (Iterator)data;
            return SafeRepresenter.this.representSequence(SafeRepresenter.this.getTag(data.getClass(), Tag.SEQ), new IteratorWrapper(iter), FlowStyle.AUTO);
        }
    }

    protected class RepresentList implements Represent {
        protected RepresentList() {
        }

        public Node representData(Object data) {
            return SafeRepresenter.this.representSequence(SafeRepresenter.this.getTag(data.getClass(), Tag.SEQ), (List)data, FlowStyle.AUTO);
        }
    }

    protected class RepresentNumber implements Represent {
        protected RepresentNumber() {
        }

        public Node representData(Object data) {
            Tag tag;
            String value;
            if (!(data instanceof Byte) && !(data instanceof Short) && !(data instanceof Integer) && !(data instanceof Long) && !(data instanceof BigInteger)) {
                Number number = (Number)data;
                tag = Tag.FLOAT;
                if (number.equals(Double.NaN)) {
                    value = ".NaN";
                } else if (number.equals(Double.POSITIVE_INFINITY)) {
                    value = ".inf";
                } else if (number.equals(Double.NEGATIVE_INFINITY)) {
                    value = "-.inf";
                } else {
                    value = number.toString();
                }
            } else {
                tag = Tag.INT;
                value = data.toString();
            }

            return SafeRepresenter.this.representScalar(SafeRepresenter.this.getTag(data.getClass(), tag), value);
        }
    }

    protected class RepresentBoolean implements Represent {
        protected RepresentBoolean() {
        }

        public Node representData(Object data) {
            String value;
            if (Boolean.TRUE.equals(data)) {
                value = "true";
            } else {
                value = "false";
            }

            return SafeRepresenter.this.representScalar(Tag.BOOL, value);
        }
    }

    protected class RepresentString implements Represent {
        protected RepresentString() {
        }

        public Node representData(Object data) {
            Tag tag = Tag.STR;
            DumperOptions.ScalarStyle style = SafeRepresenter.this.defaultScalarStyle;
            String value = data.toString();
            if (SafeRepresenter.this.nonPrintableStyle == NonPrintableStyle.BINARY && !StreamReader.isPrintable(value)) {
                tag = Tag.BINARY;
                byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
                String checkValue = new String(bytes, StandardCharsets.UTF_8);
                if (!checkValue.equals(value)) {
                    throw new YAMLException("invalid string value has occurred");
                }

                char[] binary = Base64Coder.encode(bytes);
                value = String.valueOf(binary);
                style = ScalarStyle.LITERAL;
            }

            if (SafeRepresenter.this.defaultScalarStyle == ScalarStyle.PLAIN && SafeRepresenter.MULTILINE_PATTERN.matcher(value).find()) {
                style = ScalarStyle.LITERAL;
            }

            return SafeRepresenter.this.representScalar(tag, value, style);
        }
    }

    protected class RepresentNull implements Represent {
        protected RepresentNull() {
        }

        public Node representData(Object data) {
            return SafeRepresenter.this.representScalar(Tag.NULL, "null");
        }
    }
}

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • JavaWeb實現(xiàn)Session跨頁面?zhèn)鬟f數(shù)據(jù)

    JavaWeb實現(xiàn)Session跨頁面?zhèn)鬟f數(shù)據(jù)

    本文主要介紹了 JavaWeb實現(xiàn)Session跨頁面?zhèn)鬟f數(shù)據(jù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • SpringBoot整合TKMyBatis實現(xiàn)單表增刪改查操作

    SpringBoot整合TKMyBatis實現(xiàn)單表增刪改查操作

    據(jù)說tk.mybatis能夠讓我不寫sql代碼就可以所有單表操作問題,作為熱愛偷懶的我,怎么能放過這種機會。talk is cheap, show me the code。趕緊搞個例子爽一把先
    2023-01-01
  • 全鏈路監(jiān)控平臺Pinpoint?SkyWalking?Zipkin選型對比

    全鏈路監(jiān)控平臺Pinpoint?SkyWalking?Zipkin選型對比

    這篇文章主要為大家介紹了全鏈路監(jiān)控平臺Pinpoint?SkyWalking?Zipkin實現(xiàn)的選型對比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-03-03
  • ShardingSphere-Proxy5搭建使用過程分析

    ShardingSphere-Proxy5搭建使用過程分析

    ShardingSphere-Proxy是跨語言的數(shù)據(jù)庫代理服務端,主要用來處理:分表、分庫、讀寫分離 等,這篇文章主要介紹了ShardingSphere-Proxy5搭建使用過程,需要的朋友可以參考下
    2022-10-10
  • IDEA中GitLab的使用詳解

    IDEA中GitLab的使用詳解

    這篇文章主要介紹了IDEA中GitLab的使用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-07-07
  • Java調(diào)用groovy實現(xiàn)原理代碼實例

    Java調(diào)用groovy實現(xiàn)原理代碼實例

    這篇文章主要介紹了Java調(diào)用groovy實現(xiàn)原理代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-12-12
  • 線程阻塞喚醒工具 LockSupport使用詳解

    線程阻塞喚醒工具 LockSupport使用詳解

    這篇文章主要為大家介紹了線程阻塞喚醒工具LockSupport使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • 在idea中設置項目編碼格式為UTF-8的操作方法

    在idea中設置項目編碼格式為UTF-8的操作方法

    idea中的默認編碼為GBK,在開發(fā)過程中一般將編碼格式改為UTF-8,所以本文給大家介紹了在idea中設置項目編碼為UTF-8的操作方法,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2023-12-12
  • mybatis QueryWrapper的條件構(gòu)造之a(chǎn)pply、last、select解析

    mybatis QueryWrapper的條件構(gòu)造之a(chǎn)pply、last、select解析

    這篇文章主要介紹了mybatis QueryWrapper的條件構(gòu)造之a(chǎn)pply、last、select,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java檢查字符串是否一致的四種方法

    Java檢查字符串是否一致的四種方法

    字符串比較是常見的操作,包括比較相等、比較大小、比較前綴和后綴串等,在 Java 中,比較字符串的常用方法有四個:equals(),equalsIgnoreCase(),compareTo()和compareToIgnoreCase(),下面詳細介紹這四個方法的使用
    2024-04-04

最新評論