Sharding-JDBC只分表不分库

Sharding-JDBC只分表不分库

1.pom

复制代码
<!-- Sharding-JDBC 依赖 -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>2.2</version>
        </dependency>

2.yml

1.这里的分片算法是HASH_MOD,

2.这里总共配置了四个数据库的表,collection_library_0、collection_library_1、collection_library_2、collection_library_3 。配置里ds0.collection_library_$->{0...3}这个意思就是从collection_library_0开始总共到3

3.数据库只要创建这四个0123表即可,不需要创建collection_library表,但是pojo实体类里面配置的时候用collection_library,即@Table(name="collection_library"),不需要加0123

4.你配置了shardingsphere的数据源,如果你的数据库有其他的表,但是其他表不需要分表,这个shardingsphere的数据源也可以用,不需要再配置一边数据源

复制代码
server:
  port: 8774
spring:
  application:
    name: zzzz
  shardingsphere:
    datasource:
      names: ds0
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/xhstable?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
        username: root
        password: root
    rules:
      sharding:
        tables:
          collection_library:
            actual-data-nodes: ds0.collection_library_$->{0..3}
            table-strategy:
              standard:
                sharding-column: id
                sharding-algorithm-name: collection-library-hash-mod
        sharding-algorithms:
          collection-library-hash-mod:
            type: HASH_MOD
            props:
              sharding-count: 4
        key-generators:
          snowflake:
            type: SNOWFLAKE
            props:
              worker-id: 123
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: Asia/Shanghai
  servlet:
    multipart:
      max-file-size: 20MB
      max-request-size: 20MB
  # ==================== 新增:Redis配置 ====================
  redis:
    host: localhost          # Redis服务器地址,生产环境请修改
    port: 6379               # Redis端口
    password: root               # Redis密码,如果没有留空
    database: 0              # 数据库索引
    timeout: 3000ms          # 连接超时时间
    lettuce:
      pool:
        max-active: 8        # 最大连接数
        max-idle: 8          # 最大空闲连接
        min-idle: 0          # 最小空闲连接
        max-wait: -1ms       # 最大等待时间
  quartz:
    job-store-type: jdbc # Job 存储器类型。默认为 memory,表示内存,jdbc 表示使用数据库
    scheduler-name: scheduler
    wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false,建议设置为 true
    overwrite-existing-jobs: true # 是否覆盖已有 Job 的配置
    jdbc:
      initialize-schema: never # 数据库初始化方式,默认为 never,表示不初始化(前面已经手动初始化了)
    properties: # 添加 Quartz Scheduler 附加属性
      org:
        quartz:
          scheduler:
            instanceName: scheduler
            instanceId: AUTO
          # 数据源配置
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            tablePrefix: QRTZ_
            isClustered: false
            clusterCheckinInterval: 10000
            useProperties: false
            dataSource: quartzDs
          # 线程池配置
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8763/eureka
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true

3.数据库

数据库设计时,只需要id的类型是bigint,然后再数据库里面id不能设置为自增,主要是因为要用yml配置的雪花算法生成的id,所有的字段一模一样

1.collection_library_0

复制代码
CREATE TABLE `collection_library_0` (
  `id` bigint NOT NULL,
  `title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `cover_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `original_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `content_body` text COLLATE utf8mb4_unicode_ci,
  `topic_tags` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `image_url` text COLLATE utf8mb4_unicode_ci,
  `video_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `content_type` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `blogger_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `like_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `collect_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `comment_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `blogger_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `publish_time` datetime DEFAULT NULL,
  `add_to_imitation` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `collection_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

2.collection_library_1

复制代码
CREATE TABLE `collection_library_1` (
  `id` bigint NOT NULL,
  `title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `cover_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `original_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `content_body` text COLLATE utf8mb4_unicode_ci,
  `topic_tags` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `image_url` text COLLATE utf8mb4_unicode_ci,
  `video_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `content_type` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `blogger_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `like_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `collect_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `comment_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `blogger_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `publish_time` datetime DEFAULT NULL,
  `add_to_imitation` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `collection_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

3.collection_library_2

复制代码
CREATE TABLE `collection_library_2` (
  `id` bigint NOT NULL,
  `title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `cover_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `original_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `content_body` text COLLATE utf8mb4_unicode_ci,
  `topic_tags` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `image_url` text COLLATE utf8mb4_unicode_ci,
  `video_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `content_type` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `blogger_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `like_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `collect_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `comment_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `blogger_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `publish_time` datetime DEFAULT NULL,
  `add_to_imitation` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `collection_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

4.collection_library_3

复制代码
CREATE TABLE `collection_library_3` (
  `id` bigint NOT NULL,
  `title` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `cover_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `original_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `content_body` text COLLATE utf8mb4_unicode_ci,
  `topic_tags` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `image_url` text COLLATE utf8mb4_unicode_ci,
  `video_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `content_type` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `blogger_name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `like_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `collect_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `comment_count` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `blogger_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `publish_time` datetime DEFAULT NULL,
  `add_to_imitation` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `collection_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

4.实体类

主要是配置时用@Table(name="collection_library"),然后实体类的id是Long类型

复制代码
package com.microservices.user.pojo;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.lang.String;
import java.lang.Integer;
/****
 * @Author:shenkunlin
 * @Description:CollectionLibrary构建
 * @Date 2019/6/14 19:13
 *****/
@Table(name="collection_library")
public class CollectionLibrary implements Serializable{

	@Id
	@Column(name = "id")
	private Long id;//自增主键

	@Column(name = "title")
	private String title;//标题

	@Column(name = "cover_url")
	private String coverUrl;//封面链接

	@Column(name = "original_url")
	private String originalUrl;//原文链接

	@Column(name = "content_body")
	private String contentBody;//正文

	@Column(name = "topic_tags")
	private String topicTags;//话题标签

	@Column(name = "image_url")
	private String imageUrl;//图片链接

	@Column(name = "video_url")
	private String videoUrl;//视频链接

	@Column(name = "content_type")
	private String contentType;//类型(视频、图片)

	@Column(name = "blogger_name")
	private String bloggerName;//博主

	@Column(name = "like_count")
	private String likeCount;//点赞数

	@Column(name = "collect_count")
	private String collectCount;//收藏数

	@Column(name = "comment_count")
	private String commentCount;//评论数

	@Column(name = "blogger_url")
	private String bloggerUrl;//博主链接

	@Column(name = "publish_time")
	private Date publishTime;//发布时间

	@Column(name = "add_to_imitation")
	private String addToImitation;//加入仿写

	@Column(name = "collection_time")
	private Date collectionTime;//采集时间


	//get方法
	public Long getId() {
		return id;
	}

	//set方法
	public void setId(Long id) {
		this.id = id;
	}
	//get方法
	public String getTitle() {
		return title;
	}

	//set方法
	public void setTitle(String title) {
		this.title = title;
	}
	//get方法
	public String getCoverUrl() {
		return coverUrl;
	}

	//set方法
	public void setCoverUrl(String coverUrl) {
		this.coverUrl = coverUrl;
	}
	//get方法
	public String getOriginalUrl() {
		return originalUrl;
	}

	//set方法
	public void setOriginalUrl(String originalUrl) {
		this.originalUrl = originalUrl;
	}
	//get方法
	public String getContentBody() {
		return contentBody;
	}

	//set方法
	public void setContentBody(String contentBody) {
		this.contentBody = contentBody;
	}
	//get方法
	public String getTopicTags() {
		return topicTags;
	}

	//set方法
	public void setTopicTags(String topicTags) {
		this.topicTags = topicTags;
	}
	//get方法
	public String getImageUrl() {
		return imageUrl;
	}

	//set方法
	public void setImageUrl(String imageUrl) {
		this.imageUrl = imageUrl;
	}
	//get方法
	public String getVideoUrl() {
		return videoUrl;
	}

	//set方法
	public void setVideoUrl(String videoUrl) {
		this.videoUrl = videoUrl;
	}
	//get方法
	public String getContentType() {
		return contentType;
	}

	//set方法
	public void setContentType(String contentType) {
		this.contentType = contentType;
	}
	//get方法
	public String getBloggerName() {
		return bloggerName;
	}

	//set方法
	public void setBloggerName(String bloggerName) {
		this.bloggerName = bloggerName;
	}
	//get方法
	public String getLikeCount() {
		return likeCount;
	}

	//set方法
	public void setLikeCount(String likeCount) {
		this.likeCount = likeCount;
	}
	//get方法
	public String getCollectCount() {
		return collectCount;
	}

	//set方法
	public void setCollectCount(String collectCount) {
		this.collectCount = collectCount;
	}
	//get方法
	public String getCommentCount() {
		return commentCount;
	}

	//set方法
	public void setCommentCount(String commentCount) {
		this.commentCount = commentCount;
	}
	//get方法
	public String getBloggerUrl() {
		return bloggerUrl;
	}

	//set方法
	public void setBloggerUrl(String bloggerUrl) {
		this.bloggerUrl = bloggerUrl;
	}
	//get方法
	public Date getPublishTime() {
		return publishTime;
	}

	//set方法
	public void setPublishTime(Date publishTime) {
		this.publishTime = publishTime;
	}
	//get方法
	public String getAddToImitation() {
		return addToImitation;
	}

	//set方法
	public void setAddToImitation(String addToImitation) {
		this.addToImitation = addToImitation;
	}
	//get方法
	public Date getCollectionTime() {
		return collectionTime;
	}

	//set方法
	public void setCollectionTime(Date collectionTime) {
		this.collectionTime = collectionTime;
	}

}

5.Controller

不需要改

复制代码
package com.microservices.user.controller;
import com.microservices.user.pojo.CollectionLibrary;
import com.microservices.user.pojo.CopyLibrary;
import com.microservices.user.service.CollectionLibraryService;
import com.github.pagehelper.PageInfo;
import com.microservices.entity.Result;
import com.microservices.entity.StatusCode;

import com.microservices.user.service.CopyLibraryService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

/****
 * @Author:shenkunlin
 * @Description:
 * @Date 2019/6/14 0:18
 *****/

@RestController
@RequestMapping("/collectionLibrary")
@CrossOrigin
public class CollectionLibraryController {

    @Autowired
    private CollectionLibraryService collectionLibraryService;


    @Autowired
    private CopyLibraryService copyLibraryService;

    /***
     * CollectionLibrary分页条件搜索实现
     * @param collectionLibrary
     * @param page
     * @param size
     * @return
     */
    @PostMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@RequestBody(required = false)  CollectionLibrary collectionLibrary, @PathVariable  int page, @PathVariable  int size){
        //调用CollectionLibraryService实现分页条件查询CollectionLibrary
        PageInfo<CollectionLibrary> pageInfo = collectionLibraryService.findPage(collectionLibrary, page, size);
        return new Result(true,StatusCode.OK,"查询成功",pageInfo);
    }

    /***
     * CollectionLibrary分页搜索实现
     * @param page:当前页
     * @param size:每页显示多少条
     * @return
     */
    @GetMapping(value = "/search/{page}/{size}" )
    public Result<PageInfo> findPage(@PathVariable  int page, @PathVariable  int size){
        //调用CollectionLibraryService实现分页查询CollectionLibrary
        PageInfo<CollectionLibrary> pageInfo = collectionLibraryService.findPage(page, size);
        return new Result<PageInfo>(true,StatusCode.OK,"查询成功",pageInfo);
    }

    /***
     * 多条件搜索品牌数据
     * @param collectionLibrary
     * @return
     */
    @PostMapping(value = "/search" )
    public Result<List<CollectionLibrary>> findList(@RequestBody(required = false)  CollectionLibrary collectionLibrary){
        //调用CollectionLibraryService实现条件查询CollectionLibrary
        List<CollectionLibrary> list = collectionLibraryService.findList(collectionLibrary);
        return new Result<List<CollectionLibrary>>(true,StatusCode.OK,"查询成功",list);
    }

    /***
     * 根据ID删除品牌数据
     * @param id
     * @return
     */
    @DeleteMapping(value = "/{id}" )
    public Result delete(@PathVariable Long id){
        //调用CollectionLibraryService实现根据主键删除
        collectionLibraryService.delete(id);
        return new Result(true,StatusCode.OK,"删除成功");
    }

    /***
     * 修改CollectionLibrary数据
     * @param collectionLibrary
     * @param id
     * @return
     */
    @PutMapping(value="/{id}")
    public Result update(@RequestBody  CollectionLibrary collectionLibrary,@PathVariable Long id){
        //设置主键值
        collectionLibrary.setId(id);
        //调用CollectionLibraryService实现修改CollectionLibrary
        collectionLibraryService.update(collectionLibrary);
        return new Result(true,StatusCode.OK,"修改成功");
    }

    /***
     * 新增CollectionLibrary数据
     * @param collectionLibrary
     * @return
     */
    @PostMapping
    public Result add(@RequestBody   CollectionLibrary collectionLibrary){
        //调用CollectionLibraryService实现添加CollectionLibrary
        collectionLibraryService.add(collectionLibrary);
        return new Result(true,StatusCode.OK,"添加成功");
    }

    /***
     * 根据ID查询CollectionLibrary数据
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<CollectionLibrary> findById(@PathVariable Long id){
        //调用CollectionLibraryService实现根据主键查询CollectionLibrary
        CollectionLibrary collectionLibrary = collectionLibraryService.findById(id);
        return new Result<CollectionLibrary>(true,StatusCode.OK,"查询成功",collectionLibrary);
    }

    /***
     * 查询CollectionLibrary全部数据
     * @return
     */
    @GetMapping
    public Result<List<CollectionLibrary>> findAll(){
        //调用CollectionLibraryService实现查询所有CollectionLibrary
        List<CollectionLibrary> list = collectionLibraryService.findAll();
        return new Result<List<CollectionLibrary>>(true, StatusCode.OK,"查询成功",list) ;
    }

    /***
     * 加入仿写
     * @return
     */
    @PutMapping(value="/AddToImitation/{id}")
    public Result update(@PathVariable Long id){
        CollectionLibrary collectionLibrary = collectionLibraryService.findById(id);
        CopyLibrary copyLibrary = new CopyLibrary();
        BeanUtils.copyProperties(collectionLibrary, copyLibrary);
        copyLibrary.setId(null);
        copyLibrary.setAddToImitation("未加入");
        copyLibraryService.add(copyLibrary);
        collectionLibrary.setAddToImitation("已加入");
        collectionLibraryService.update(collectionLibrary);
        return new Result(true,StatusCode.OK,"添加仿写成功");
    }
}

6.Service

不需要改

复制代码
package com.microservices.user.service;

import com.github.pagehelper.PageInfo;
import com.microservices.user.pojo.CollectionLibrary;

import java.util.List;

/****
 * @Author:shenkunlin
 * @Description:CollectionLibrary业务层接口
 * @Date 2019/6/14 0:16
 *****/
public interface CollectionLibraryService {

    /***
     * CollectionLibrary多条件分页查询
     * @param collectionLibrary
     * @param page
     * @param size
     * @return
     */
    PageInfo<CollectionLibrary> findPage(CollectionLibrary collectionLibrary, int page, int size);

    /***
     * CollectionLibrary分页查询
     * @param page
     * @param size
     * @return
     */
    PageInfo<CollectionLibrary> findPage(int page, int size);

    /***
     * CollectionLibrary多条件搜索方法
     * @param collectionLibrary
     * @return
     */
    List<CollectionLibrary> findList(CollectionLibrary collectionLibrary);

    /***
     * 删除CollectionLibrary
     * @param id
     */
    void delete(Long id);

    /***
     * 修改CollectionLibrary数据
     * @param collectionLibrary
     */
    void update(CollectionLibrary collectionLibrary);

    /***
     * 新增CollectionLibrary
     * @param collectionLibrary
     */
    void add(CollectionLibrary collectionLibrary);

    /**
     * 根据ID查询CollectionLibrary
     * @param id
     * @return
     */
     CollectionLibrary findById(Long id);

    /***
     * 查询所有CollectionLibrary
     * @return
     */
    List<CollectionLibrary> findAll();
}

7.Impl

1.这里的新增需要改一下

因为你在数据库里面设置了id不能自增,所以这里id会为空,所以你得设置一个id,我们使用的时雪花算法

复制代码
    private static final IdWorker ID_WORKER = new IdWorker();

@Override
    public void add(CollectionLibrary collectionLibrary){
        // ShardingSphere 的分片键是 id;若 id 为空会导致路由失败
        if (collectionLibrary.getId() == null) {
            collectionLibrary.setId(ID_WORKER.nextId());
        }
        collectionLibraryMapper.insert(collectionLibrary);
    }

2.IdWorker工具

复制代码
package com.microservices.entity;

import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;

/**
 * <p>名称:IdWorker.java</p>
 * <p>描述:分布式自增长ID</p>
 * <pre>
 *     Twitter的 Snowflake JAVA实现方案
 * </pre>
 * 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用---分割开部分的作用:
 * 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
 * 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,
 * 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),
 * 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
 * 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),
 * 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。
 * <p>
 * 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))
 *
 * @author Polim
 */
public class IdWorker {
    // 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
    private final static long twepoch = 1288834974657L;
    // 机器标识位数
    private final static long workerIdBits = 5L;
    // 数据中心标识位数
    private final static long datacenterIdBits = 5L;
    // 机器ID最大值
    private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
    // 数据中心ID最大值
    private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    // 毫秒内自增位
    private final static long sequenceBits = 12L;
    // 机器ID偏左移12位
    private final static long workerIdShift = sequenceBits;
    // 数据中心ID左移17位
    private final static long datacenterIdShift = sequenceBits + workerIdBits;
    // 时间毫秒左移22位
    private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

    private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
    /* 上次生产id时间戳 */
    private static long lastTimestamp = -1L;
    // 0,并发控制
    private long sequence = 0L;

    private final long workerId;
    // 数据标识id部分
    private final long datacenterId;

    public IdWorker(){
        this.datacenterId = getDatacenterId(maxDatacenterId);
        this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
    }
    /**
     * @param workerId
     *            工作机器ID
     * @param datacenterId
     *            序列号
     */
    public IdWorker(long workerId, long datacenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }
    /**
     * 获取下一个ID
     *
     * @return
     */
    public synchronized long nextId() {
        long timestamp = timeGen();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        if (lastTimestamp == timestamp) {
            // 当前毫秒内,则+1
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                // 当前毫秒内计数满了,则等待下一秒
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        // ID偏移组合生成最终的ID,并返回ID
        long nextId = ((timestamp - twepoch) << timestampLeftShift)
                | (datacenterId << datacenterIdShift)
                | (workerId << workerIdShift) | sequence;

        return nextId;
    }

    private long tilNextMillis(final long lastTimestamp) {
        long timestamp = this.timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = this.timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }

    /**
     * <p>
     * 获取 maxWorkerId
     * </p>
     */
    protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
        StringBuffer mpid = new StringBuffer();
        mpid.append(datacenterId);
        String name = ManagementFactory.getRuntimeMXBean().getName();
        if (!name.isEmpty()) {
            /*
             * GET jvmPid
             */
            mpid.append(name.split("@")[0]);
        }
        /*
         * MAC + PID 的 hashcode 获取16个低位
         */
        return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
    }

    /**
     * <p>
     * 数据标识id部分
     * </p>
     */
    protected static long getDatacenterId(long maxDatacenterId) {
        long id = 0L;
        try {
            InetAddress ip = InetAddress.getLocalHost();
            NetworkInterface network = NetworkInterface.getByInetAddress(ip);
            if (network == null) {
                id = 1L;
            } else {
                byte[] mac = network.getHardwareAddress();
                id = ((0x000000FF & (long) mac[mac.length - 1])
                        | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
                id = id % (maxDatacenterId + 1);
            }
        } catch (Exception e) {
            System.out.println(" getDatacenterId: " + e.getMessage());
        }
        return id;
    }

    public static void main(String[] args) {
        com.microservices.entity.IdWorker idWorker = new com.microservices.entity.IdWorker(0,0);
		
        for (int i = 0; i <10000; i++) {
            long nextId=idWorker.nextId();
			System.out.println(nextId);
        }
    }
}

3.全部代码

复制代码
package com.microservices.user.service.impl;
import com.microservices.user.dao.CollectionLibraryMapper;
import com.microservices.user.pojo.CollectionLibrary;
import com.microservices.user.service.CollectionLibraryService;
import com.microservices.entity.IdWorker;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;
import java.util.List;
import java.util.regex.Pattern;

/****
 * @Author:shenkunlin
 * @Description:CollectionLibrary业务层接口实现类
 * @Date 2019/6/14 0:16
 *****/
@Service
public class CollectionLibraryServiceImpl implements CollectionLibraryService {

    @Autowired
    private CollectionLibraryMapper collectionLibraryMapper;


    /**
     * CollectionLibrary条件+分页查询
     * @param collectionLibrary 查询条件
     * @param page 页码
     * @param size 页大小
     * @return 分页结果
     */
    @Override
    public PageInfo<CollectionLibrary> findPage(CollectionLibrary collectionLibrary, int page, int size){
        //分页
        PageHelper.startPage(page,size);
        //搜索条件构建
        Example example = createExample(collectionLibrary);
        //执行搜索
        return new PageInfo<CollectionLibrary>(collectionLibraryMapper.selectByExample(example));
    }

    /**
     * CollectionLibrary分页查询
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageInfo<CollectionLibrary> findPage(int page, int size){
        //静态分页
        PageHelper.startPage(page,size);
        //分页查询
        return new PageInfo<CollectionLibrary>(collectionLibraryMapper.selectAll());
    }

    /**
     * CollectionLibrary条件查询
     * @param collectionLibrary
     * @return
     */
    @Override
    public List<CollectionLibrary> findList(CollectionLibrary collectionLibrary){
        //构建查询条件
        Example example = createExample(collectionLibrary);
        //根据构建的条件查询数据
        return collectionLibraryMapper.selectByExample(example);
    }


    /**
     * CollectionLibrary构建查询对象
     * @param collectionLibrary
     * @return
     */
    public Example createExample(CollectionLibrary collectionLibrary){
        Example example=new Example(CollectionLibrary.class);
        Example.Criteria criteria = example.createCriteria();
        if(collectionLibrary!=null){
            // 自增主键
            if(!StringUtils.isEmpty(collectionLibrary.getId())){
                criteria.andEqualTo("id",collectionLibrary.getId());
            }
            // 标题
            if(!StringUtils.isEmpty(collectionLibrary.getTitle())){
                criteria.andLike("title","%"+collectionLibrary.getTitle()+"%");
            }
            // 封面链接
            if(!StringUtils.isEmpty(collectionLibrary.getCoverUrl())){
                criteria.andEqualTo("coverUrl",collectionLibrary.getCoverUrl());
            }
            // 原文链接
            if(!StringUtils.isEmpty(collectionLibrary.getOriginalUrl())){
                criteria.andEqualTo("originalUrl",collectionLibrary.getOriginalUrl());
            }
            // 正文
            if(!StringUtils.isEmpty(collectionLibrary.getContentBody())){
                criteria.andEqualTo("contentBody",collectionLibrary.getContentBody());
            }
            // 话题标签
            if(!StringUtils.isEmpty(collectionLibrary.getTopicTags())){
                criteria.andEqualTo("topicTags",collectionLibrary.getTopicTags());
            }
            // 图片链接
            if(!StringUtils.isEmpty(collectionLibrary.getImageUrl())){
                criteria.andEqualTo("imageUrl",collectionLibrary.getImageUrl());
            }
            // 视频链接
            if(!StringUtils.isEmpty(collectionLibrary.getVideoUrl())){
                criteria.andEqualTo("videoUrl",collectionLibrary.getVideoUrl());
            }
            // 类型(视频、图片)
            if(!StringUtils.isEmpty(collectionLibrary.getContentType())){
                criteria.andEqualTo("contentType",collectionLibrary.getContentType());
            }
            // 博主
            if(!StringUtils.isEmpty(collectionLibrary.getBloggerName())){
                criteria.andEqualTo("bloggerName",collectionLibrary.getBloggerName());
            }
            // 点赞数
            if(!StringUtils.isEmpty(collectionLibrary.getLikeCount())){
                criteria.andEqualTo("likeCount",collectionLibrary.getLikeCount());
            }
            // 收藏数
            if(!StringUtils.isEmpty(collectionLibrary.getCollectCount())){
                criteria.andEqualTo("collectCount",collectionLibrary.getCollectCount());
            }
            // 评论数
            if(!StringUtils.isEmpty(collectionLibrary.getCommentCount())){
                criteria.andEqualTo("commentCount",collectionLibrary.getCommentCount());
            }
            // 博主链接
            if(!StringUtils.isEmpty(collectionLibrary.getBloggerUrl())){
                criteria.andEqualTo("bloggerUrl",collectionLibrary.getBloggerUrl());
            }
            // 发布时间
            if(!StringUtils.isEmpty(collectionLibrary.getPublishTime())){
                criteria.andEqualTo("publishTime",collectionLibrary.getPublishTime());
            }
            // 加入仿写
            if(!StringUtils.isEmpty(collectionLibrary.getAddToImitation())){
                criteria.andEqualTo("addToImitation",collectionLibrary.getAddToImitation());
            }
            // 采集时间
            if(!StringUtils.isEmpty(collectionLibrary.getCollectionTime())){
                criteria.andEqualTo("collectionTime",collectionLibrary.getCollectionTime());
            }
        }
        return example;
    }

    /**
     * 删除
     * @param id
     */
    @Override
    public void delete(Long id){
        collectionLibraryMapper.deleteByPrimaryKey(id);
    }

    /**
     * 修改CollectionLibrary
     * @param collectionLibrary
     */
    @Override
    public void update(CollectionLibrary collectionLibrary){
        collectionLibraryMapper.updateByPrimaryKey(collectionLibrary);
    }

    /**
     * 增加CollectionLibrary
     * @param collectionLibrary
     */
    @Override
    public void add(CollectionLibrary collectionLibrary){
        // ShardingSphere 的分片键是 id;若 id 为空会导致路由失败
        if (collectionLibrary.getId() == null) {
            collectionLibrary.setId(ID_WORKER.nextId());
        }
        collectionLibraryMapper.insert(collectionLibrary);
    }

    /**
     * 根据ID查询CollectionLibrary
     * @param id
     * @return
     */
    @Override
    public CollectionLibrary findById(Long id){
        return  collectionLibraryMapper.selectByPrimaryKey(id);
    }

    /**
     * 查询CollectionLibrary全部数据
     * @return
     */
    @Override
    public List<CollectionLibrary> findAll() {
        return collectionLibraryMapper.selectAll();
    }

    // 正则:匹配数字(包括整数、小数)
    private static final Pattern NUMERIC_PATTERN = Pattern.compile("^\\d+(\\.\\d+)?$");

    /**
     * 预处理数值字段,将空值/无效值转为"0"
     */
    private void preprocessNumericFields(CollectionLibrary collectionLibrary) {
        // 1. 点赞数
        collectionLibrary.setLikeCount(convertToValidNumeric(collectionLibrary.getLikeCount()));
        // 2. 收藏数
        collectionLibrary.setCollectCount(convertToValidNumeric(collectionLibrary.getCollectCount()));
        // 3. 评论数
        collectionLibrary.setCommentCount(convertToValidNumeric(collectionLibrary.getCommentCount()));
    }

    /**
     * 将字符串转换为有效的数值字符串,空值/无效值返回"0"
     */
    private String convertToValidNumeric(String value) {
        // 空值处理
        if (value == null || value.trim().isEmpty() || "''".equals(value) || "\"\"".equals(value)) {
            return "0";
        }

        String trimmedValue = value.trim();

        // 处理带单位的数值(如 1.2万、5k)
        if (trimmedValue.contains("万") || trimmedValue.contains("W")) {
            try {
                String numPart = trimmedValue.replaceAll("[^0-9.]", "");
                double num = Double.parseDouble(numPart) * 10000;
                return String.valueOf((long) num);
            } catch (Exception e) {
                return "0";
            }
        }
        if (trimmedValue.contains("千") || trimmedValue.contains("K") || trimmedValue.contains("k")) {
            try {
                String numPart = trimmedValue.replaceAll("[^0-9.]", "");
                double num = Double.parseDouble(numPart) * 1000;
                return String.valueOf((long) num);
            } catch (Exception e) {
                return "0";
            }
        }

        // 验证是否为有效数字
        if (NUMERIC_PATTERN.matcher(trimmedValue).matches()) {
            return trimmedValue;
        }

        // 提取数字部分
        try {
            String numPart = trimmedValue.replaceAll("[^0-9.]", "");
            if (numPart.isEmpty()) {
                return "0";
            }
            return numPart;
        } catch (Exception e) {
            return "0";
        }
    }

    private static final IdWorker ID_WORKER = new IdWorker();
}

8.拦截器JacksonConfig

主要是因为id太长了,前端传给后端的时候会丢失数据,所以这个要做一个处理,在根据id查询,根据id删除时都会用到这个id

创建config包

复制代码
package com.microservices.user.config;

import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonConfig {

//    这个是解决id超长的问题,id是雪花算法生成的,id的长度太长,从后端传过来的时候就会丢失数据
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> {
            // 把 Long 类型全局序列化为 String
            builder.serializerByType(Long.class, ToStringSerializer.instance);
            builder.serializerByType(Long.TYPE, ToStringSerializer.instance);
        };
    }
}
相关推荐
yaaakaaang2 小时前
十三、责任链模式
java·责任链模式
爱吃烤鸡翅的酸菜鱼2 小时前
【Java】封装位运算通用工具类——用一个整数字段替代几十个布尔列,极致节省存储空间
java·开发语言·设计模式·工具类·位运算·合成复用原则
菜菜小狗的学习笔记2 小时前
八股(三)Java并发
java·开发语言
云烟成雨TD2 小时前
Spring AI Alibaba 1.x 系列【10】ReactAgent 工具加载和执行流程
java·人工智能·spring
lee_curry2 小时前
JUC第一章 java中基础概念和CompletableFuture
java·多线程·并发·juc
迷藏4942 小时前
**超融合架构下的Go语言实践:从零搭建高性能容器化微服务集群**在现代云原生时代,*
java·python·云原生·架构·golang
それども2 小时前
Spring Bean @Autowired自注入空指针问题
java·开发语言·spring
如来神掌十八式2 小时前
Java所有的锁:从基础到进阶
java·
硅基诗人2 小时前
Java后端高并发核心瓶颈突破(JVM+并发+分布式底层实战)
java·jvm·分布式