构建spring boot web项目:五、集成redis

目录

一、docker安装redis

1.1拉去镜像

1.2创建文件目录

1.3 编辑配置文件

1.4 启动容器

二、spring boot整合redis

2.1创建redis模块

2.2 引入依赖

2.3 创建配置类 以及工具类

三、管理应用模块(management)集成redis

一、docker安装redis

1.1拉去镜像

docker pull redis:6.2.1

1.2创建文件目录

mkdir -p /home/redis/conf
mkdir -p /home/redis/data

1.3 编辑配置文件

vi /home/redis/conf/redis.conf
requirepass 123456
# 默认redis不是以后台进程的方式启动,如果需要在后台运行,需要将这个值设置成yes
# 默认no,改为yes意为以守护进程方式启动,可后台运行,除非kill进程,改为yes会使配置文件方式启动redis失败
# 以后台方式启动的时候,redis会写入默认的进程文件/var/run/redis.pid
daemonize no
 
# 默认yes,开启保护模式,限制为本地访问
protected-mode no
 
# redis启动的进程路径
pidfile /var/run/redis.pid
 
# 启动进程端口号,默认6379,可以改
port 6379
 
tcp-backlog 511
 
# 配置redis监听到的ip地址,可以是一个也可以多个
#bind 127.0.0.110.254.3.42
 
# redis的sock路径
unixsocket /tmp/redis.sock
unixsocketperm 755
 
# 超时时间
timeout 0
 
#指定TCP连接是否为长连接,"侦探"信号有server端维护。默认为0.表示禁用
tcp-keepalive 0
 
# 日志级别,log 等级分为4 级,debug,verbose,notice, 和warning。生产环境下一般开启notice
loglevel notice
 
# 日志文件地址
logfile /data/redis.log
 
# 设置数据库的个数,可以使用SELECT 命令来切换数据库。默认使用的数据库是0号库。默认16个库
databases 16
 
# RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的所有数据进行快照并存储在硬盘上。进行快照的条件可以由用户在配置文件中自定义,由两个参数构成:时间和改动的键的个数。当在指定的时间内被更改的键的个数大于指定的数值时就会进行快照。RDB是Redis默认采用的持久化方式,在配置文件中已经预置了3个条件:
save 900 1    # 900秒内有至少1个键被更改则进行快照
save 300 10   # 300秒内有至少10个键被更改则进行快照
save 60 10000  # 60秒内有至少10000个键被更改则进行快照
 
# 持久化数据存储目录
dir /data
 
# 当持久化出现错误时,是否依然继续进行工作,是否终止所有的客户端write请求。默认设置"yes"表示终止,一旦snapshot数据保存故障,那么此server为只读服务。如果为"no",那么此次snapshot将失败,但下一次snapshot不会受到影响,不过如果出现故障,数据只能恢复到"最近一个成功点"
stop-writes-on-bgsave-error no
 
# 在进行数据镜像备份时,是否启用rdb文件压缩手段,默认为yes。压缩可能需要额外的cpu开支,不过这能够有效的减小rdb文件的大,有利于存储/备份/传输/数据恢复
rdbcompression yes
 
# checksum文件检测,读取写入的时候rdb文件checksum,会损失一些性能
rdbchecksum yes
 
#镜像备份文件的文件名,默认为dump.rdb
dbfilename dump.rdb
 
#当主master服务器挂机或主从复制在进行时,是否依然可以允许客户访问可能过期的数据。在"yes"情况下,slave继续向客户端提供只读服务,有可能此时的数据已经过期;在"no"情况下,任何向此server发送的数据请求服务(包括客户端和此server的slave)都将被告知"error"
slave-serve-stale-data yes
 
# 如果是slave库,只允许只读,不允许修改
slave-read-only yes
 
# slave与master的连接,是否禁用TCPnodelay选项。"yes"表示禁用,那么socket通讯中数据将会以packet方式发送(packet大小受到socket buffer限制)。可以提高socket通讯的效率(tcp交互次数),但是小数据将会被buffer,不会被立即发送,对于接受者可能存在延迟。"no"表示开启tcp nodelay选项,任何数据都会被立即发送,及时性较好,但是效率较低,建议设为no,在高并发或者主从有大量操作的情况下,设置为yes
repl-disable-tcp-nodelay no
 
# 适用Sentinel模块(unstable,M-S集群管理和监控),需要额外的配置文件支持。slave的权重值,默认100.当master失效后,Sentinel将会从slave列表中找到权重值最低(>0)的slave,并提升为master。如果权重值为0,表示此slave为"观察者",不参与master选举
slave-priority 100
 
# 限制同时连接的客户数量。当连接数超过这个值时,redis 将不再接收其他连接请求,客户端尝试连接时将收到error 信息。默认为10000,要考虑系统文件描述符限制,不宜过大,浪费文件描述符,具体多少根据具体情况而定
maxclients 10000
 
# redis-cache所能使用的最大内存(bytes),默认为0,表示"无限制",最终由OS物理内存大小决定(如果物理内存不足,有可能会使用swap)。此值尽量不要超过机器的物理内存尺寸,从性能和实施的角度考虑,可以为物理内存3/4。此配置需要和"maxmemory-policy"配合使用,当redis中内存数据达到maxmemory时,触发"清除策略"。在"内存不足"时,任何write操作(比如set,lpush等)都会触发"清除策略"的执行。在实际环境中,建议redis的所有物理机器的硬件配置保持一致(内存一致),同时确保master/slave中"maxmemory""policy"配置一致。
maxmemory 0
 
# 内存过期策略,内存不足"时,数据清除策略,默认为"volatile-lru"。
# volatile-lru  ->对"过期集合"中的数据采取LRU(近期最少使用)算法.如果对key使用"expire"指令指定了过期时间,那么此key将会被添加到"过期集合"中。将已经过期/LRU的数据优先移除.如果"过期集合"中全部移除仍不能满足内存需求,将OOM.
# allkeys-lru ->对所有的数据,采用LRU算法
# volatile-random ->对"过期集合"中的数据采取"随即选取"算法,并移除选中的K-V,直到"内存足够"为止. 如果如果"过期集合"中全部移除全部移除仍不能满足,将OOM
# allkeys-random ->对所有的数据,采取"随机选取"算法,并移除选中的K-V,直到"内存足够"为止
# volatile-ttl ->对"过期集合"中的数据采取TTL算法(最小存活时间),移除即将过期的数据.
# noeviction ->不做任何干扰操作,直接返回OOM异常
# 另外,如果数据的过期不会对"应用系统"带来异常,且系统中write操作比较密集,建议采取"allkeys-lru"
maxmemory-policy volatile-lru
 
# 默认值5,上面LRU和最小TTL策略并非严谨的策略,而是大约估算的方式,因此可以选择取样值以便检查
maxmemory-samples 5
 
# 默认情况下,redis 会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁。所以redis 提供了另外一种更加高效的数据库备份及灾难恢复方式。开启append only 模式之后,redis 会把所接收到的每一次写操作请求都追加到appendonly.aof 文件中,当redis 重新启动时,会从该文件恢复出之前的状态。但是这样会造成appendonly.aof 文件过大,所以redis 还支持了BGREWRITEAOF 指令,对appendonly.aof 进行重新整理。如果不经常进行数据迁移操作,推荐生产环境下的做法为关闭镜像,开启appendonly.aof,同时可以选择在访问较少的时间每天对appendonly.aof 进行重写一次。
# 另外,对master机器,主要负责写,建议使用AOF,对于slave,主要负责读,挑选出1-2台开启AOF,其余的建议关闭
appendonly yes
 
# aof文件名字,默认为appendonly.aof
appendfilename "appendonly.aof"
 
# 设置对appendonly.aof 文件进行同步的频率。always表示每次有写操作都进行同步,everysec 表示对写操作进行累积,每秒同步一次。no不主动fsync,由OS自己来完成。这个需要根据实际业务场景进行配置
appendfsync everysec
 
# 在aof rewrite期间,是否对aof新记录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。默认为no,表示"不暂缓",新的aof记录仍然会被立即同步
no-appendfsync-on-rewrite no
 
# 当Aof log增长超过指定比例时,重写logfile,设置为0表示不自动重写Aof 日志,重写是为了使aof体积保持最小,而确保保存最完整的数据。
auto-aof-rewrite-percentage 100
# 触发aof rewrite的最小文件尺寸
auto-aof-rewrite-min-size 64mb
 
# lua脚本执行的最大时间,单位毫秒
lua-time-limit 5000
 
# 慢日志记录,单位微妙,10000就是10毫秒值,如果操作时间超过此值,将会把command信息"记录"起来.(内存,非文件)。其中"操作时间"不包括网络IO开支,只包括请求达到server后进行"内存实施"的时间."0"表示记录全部操作
slowlog-log-slower-than 10000
 
# "慢操作日志"保留的最大条数,"记录"将会被队列化,如果超过了此长度,旧记录将会被移除。可以通过"SLOWLOG<subcommand> args"查看慢记录的信息(SLOWLOG get 10,SLOWLOG reset)
slowlog-max-len 128
notify-keyspace-events ""
 
# hash类型的数据结构在编码上可以使用ziplist和hashtable。ziplist的特点就是文件存储(以及内存存储)所需的空间较小,在内容较小时,性能和hashtable几乎一样.因此redis对hash类型默认采取ziplist。如果hash中条目的条目个数或者value长度达到阀值,将会被重构为hashtable。
# 这个参数指的是ziplist中允许存储的最大条目个数,,默认为512,建议为128
hash-max-ziplist-entries 512
# ziplist中允许条目value值最大字节数,默认为64,建议为1024
hash-max-ziplist-value 64
 
# 同上
list-max-ziplist-entries 512
list-max-ziplist-value 64
 
# intset中允许保存的最大条目个数,如果达到阀值,intset将会被重构为hashtable
set-max-intset-entries 512
 
# zset为有序集合,有2中编码类型:ziplist,skiplist。因为"排序"将会消耗额外的性能,当zset中数据较多时,将会被重构为skiplist。
zset-max-ziplist-entries 128
# zset中允许条目value值最大字节数,默认为64,建议为1024
zset-max-ziplist-value 64
 
# 是否开启顶层数据结构的rehash功能,如果内存允许,请开启。rehash能够很大程度上提高K-V存取的效率
activerehashing yes
 
# 客户端buffer控制。在客户端与server进行的交互中,每个连接都会与一个buffer关联,此buffer用来队列化等待被client接受的响应信息。如果client不能及时的消费响应信息,那么buffer将会被不断积压而给server带来内存压力.如果buffer中积压的数据达到阀值,将会导致连接被关闭,buffer被移除。
 
# buffer控制类型包括:normal -> 普通连接;slave->与slave之间的连接;pubsub ->pub/sub类型连接,此类型的连接,往往会产生此种问题;因为pub端会密集的发布消息,但是sub端可能消费不足.指令格式:client-output-buffer-limit <class> <hard><soft><seconds>",其中hard表示buffer最大值,一旦达到阀值将立即关闭连接;soft表示"容忍值",它和seconds配合,如果buffer值超过soft且持续时间达到了seconds,也将立即关闭连接,如果超过了soft但是在seconds之后,buffer数据小于了soft,连接将会被保留.其中hard和soft都设置为0,则表示禁用buffer控制.通常hard值大于soft.
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
 
# Redis server执行后台任务的频率,默认为10,此值越大表示redis对"间歇性task"的执行次数越频繁(次数/秒)。"间歇性task"包括"过期集合"检测、关闭"空闲超时"的连接等,此值必须大于0且小于500。此值过小就意味着更多的cpu周期消耗,后台task被轮询的次数更频繁。此值过大意味着"内存敏感"性较差。建议采用默认值。
hz 10
 
# 当一个child在重写AOF文件的时候,如果aof-rewrite-incremental-fsync值为yes生效,那么这个文件会以每次32M数据的来被同步,这大量新增提交到磁盘是有用的,并且能避免高峰延迟。
aof-rewrite-incremental-fsync yes

1.4 启动容器


docker run --restart=always -p 6379:6379 --name redis --privileged=true -v /home/redis/conf/redis.conf:/etc/redis/redis.conf -v /home/redis/data:/data -d redis:6.2.1 redis-server /etc/redis/redis.conf

查看

docker ps

二、spring boot整合redis

2.1创建redis模块

2.2 引入依赖

pom.xml(initMode)

        <!--redisson客户端版本-->
        <redisson.verison>3.14.1</redisson.verison>

            <dependency>
                <groupId>org.redisson</groupId>
                <artifactId>redisson-spring-boot-starter</artifactId>
                <version>${redisson.verison}</version>
            </dependency>

            <dependency>
                <groupId>com.lyj.initMode</groupId>
                <artifactId>initMode-function-redis</artifactId>
                <version>${project.version}</version>
            </dependency>

 pom.xml(function)

<module>redis</module>

 pom.xml(redis)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.lyj.initMode</groupId>
        <artifactId>initMode-function</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>initMode-function-redis</artifactId>

    <description>redis功能模块</description>

    <dependencies>
        <!--引入redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--Redis的客户端-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

</project>

2.3 创建配置类 以及工具类

RedisConfig.java(redis)
package com.lyj.function.redis.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * redis配置
 */
@Configuration
@EnableCaching //启用缓存配置
@Slf4j
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 创建RedisTemplate实例
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(factory);
        //如果直接使用Jackson2JsonRedisSerializer 获取存储的对象则会变为LinkedHashMap,添加ObjectMapper可解决
        //Jackson2JsonRedisSerializer序列化时 存数据都采用JSON字符串方式,然后取数据时也不直接将结果强转,而是使用JSON反序列化 将JSON字符串反序列化为java对象或集合或者配置ObjectMapper使其支持对象序列化到Redis
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        //解决json 转换LocalDateTime类型时失败问题 同时需要在属性上面增加 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        //两个缺一不可
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        om.registerModule(javaTimeModule);
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 设置键的序列化器为StringRedisSerializer
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        // 设置值的序列化器为Jackson2JsonRedisSerializer,Jackson2JsonRedisSerializer是GenericJackson2JsonRedisSerializer
        // GenericJackson2JsonRedisSerializer可以序列化任何类型,但是这可能会导致一些性能问题,因为它需要类型信息来正确地反序列化对象。而Jackson2JsonRedisSerializer只需要序列化JSON对象,通常会有更好的性能。
        // GenericJackson2JsonRedisSerializer可以序列化任何类型,但是这可能会导致一些性能问题,因为它需要类型信息来正确地反序列化对象。而Jackson2JsonRedisSerializer只需要序列化JSON对象,通常会有更好的性能。
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    /**
     * 特殊的RedisTemplate 继承自RedisTemplate
     * @param factory
     * @return
     */
    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(factory);
        return template;
    }

    /**
     * 初始化RedisCacheManager缓存
     * @Cacheable(value = "someCache", key = "#id")
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisCacheManager defaultManage(RedisConnectionFactory connectionFactory) { //可配置多个
        RedisCacheConfiguration config = instanceConfig(); //设置过期时间为1天(这是缓存超时时间非 redis超时时间)
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
    }

    //配置序列化,解决乱码问题 过期时间1天
    private RedisCacheConfiguration instanceConfig() {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        //解决json 转换LocalDateTime类型时失败问题 同时需要在属性上面增加 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        //两个缺一不可
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        om.registerModule(javaTimeModule);
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        return RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(jackson2JsonRedisSerializer)).entryTtl(Duration.ofDays(1));
    }

    @Bean
    public Boolean chekRedissonClient(RedissonClient redissonClient) {
        if (redissonClient != null) {
            log.info("Redis 连接成功!.");
        }
      return  true;
    }
}
RedisSequenceFactory.java(redis)
package com.lyj.function.redis.util;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @Description 唯一编号生产
 */
@Component
public class RedisSequenceFactory {
        @Resource
        private RedisTemplate redisTemplate;

        public RedisSequenceFactory() {
        }

        public void set(String key, long value) {
            RedisAtomicLong counter = new RedisAtomicLong(key, this.redisTemplate.getConnectionFactory());
            counter.set(value);
        }

    /**
     * 增加increment
     * @param key
     * @param increment
     * @return
     */
        public long generate(String key, long increment) {
            RedisAtomicLong counter = new RedisAtomicLong(key, this.redisTemplate.getConnectionFactory());
            return counter.addAndGet(increment);
        }

        public long queryValue(String key) {
            Object value = this.redisTemplate.opsForValue().get(key);
            if (value == null) {
                return 0L;
            }
            return Long.valueOf(value.toString());
        }

        public Boolean del(String key) {
            return redisTemplate.delete(key);
        }

        public Boolean hashKey(String key) {
            return redisTemplate.hasKey(key);
        }
}
RedisUtil.java(redis)
package com.lyj.function.redis.util;


import com.lyj.common.base.util.BizExceptionUtil;
import com.lyj.common.base.util.DateUtil;
import com.lyj.common.base.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * redis工具类
 */
@Slf4j
@Component
public class RedisUtil {

    private StringRedisTemplate redisTemplate;
    private static RedisUtil staticRedisUtil;

    public static final String KEY_USER_CODE = "userCode";
    public static final String KEY_PROCESS = "process";
    public static final String SETTLEMENT_KEY_PROCESS1 = "createSettlementOrder1";
    public static final String SETTLEMENT_KEY_PROCESS2 = "createSettlementOrder2";
    public static final String DATE_FORMAT = "yyyyMMdd";

    public RedisUtil(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @PostConstruct //用于标记一个方法,该方法将在bean的依赖注入完成之后被调用。该方法没有参数,返回值类型可以是void或任意其他类型。
    private void init() {
        staticRedisUtil = this;
        staticRedisUtil.redisTemplate = this.redisTemplate;
    }

    /**
     * 指定缓存失效时间
     *
     * @param key         键
     * @param timeSeconds 时间(秒)
     * @return true-成功;false-失败
     */
    public static Boolean expire(String key, long timeSeconds) {
        try {
            if (timeSeconds > 0) {
                staticRedisUtil.redisTemplate.expire(key, timeSeconds, TimeUnit.SECONDS);
            }
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("RedisUtil|expire|error|key={},time={}", key, timeSeconds, e);
            return Boolean.FALSE;
        }
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public static Long getExpire(String key) {
        return staticRedisUtil.redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return true-存在;false-不存在
     */
    public static Boolean hasKey(String key) {
        try {
            return staticRedisUtil.redisTemplate.hasKey(key);
        } catch (Exception e) {
            log.error("RedisUtil|hasKey|error|key={}", key, e);
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个值 或多个
     */
    public static Boolean delete(String... key) {
        try {
            List<String> list = new ArrayList<>(Arrays.asList(key));
            if (!list.isEmpty()) {
                staticRedisUtil.redisTemplate.delete(list);
            }
        } catch (Exception e) {
            log.error("RedisUtil|delete|error|key={}", key, e);
            return false;
        }
        return true;
    }

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public static String get(String key) {
        try {
            return staticRedisUtil.redisTemplate.opsForValue().get(key);
        } catch (Exception e) {
            log.error("Redis|getString|failed,key={}", key, e);
        }
        return null;
    }

    /**
     * 获取指定类型缓存
     *
     * @param key   键
     * @param clazz 反序列化类型
     * @return 缓存值
     */
    public static <T> T get(String key, Class<T> clazz) {
        try {
            String json = staticRedisUtil.redisTemplate.opsForValue().get(key);
            return JsonUtil.deserialize(json, clazz);
        } catch (Exception e) {
            log.error("Redis|getGeneric|failed,key={}", key, e);
        }
        return null;
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public static boolean set(String key, Object value) {
        try {
            String json = JsonUtil.serialize(value);
            staticRedisUtil.redisTemplate.opsForValue().set(key, json);
            return true;
        } catch (Exception e) {
            log.error("RedisUtil|set|error|key={},value={}", key, value, e);
            return false;
        }
    }

    /**
     * 普通缓存放入并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public static boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                String json = JsonUtil.serialize(value);
                staticRedisUtil.redisTemplate.opsForValue().set(key, json, time, TimeUnit.SECONDS);
                return true;
            } else {
                return set(key, value);
            }
        } catch (Exception e) {
            log.error("RedisUtil|set|error|key={},value={},time={}", key, value, time, e);
            return false;
        }
    }

    /**
     * 递增
     *
     * @param key   键
     * @param delta 要增加几(大于0)
     * @return 增加时间数
     */
    public static Long incr(String key, long delta) {
        if (delta < 0) {
            BizExceptionUtil.bizException("递增因子必须大于0");
        }
        return staticRedisUtil.redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     *
     * @param key   键
     * @param delta 要减少几(小于0)
     * @return 减少时间数
     */
    public static Long decr(String key, long delta) {
        if (delta < 0) {
            BizExceptionUtil.bizException("递增因子必须大于0");
        }
        return staticRedisUtil.redisTemplate.opsForValue().increment(key, -delta);
    }

    public static String generateSecId(Integer length) {
        RedisAtomicLong counter = new RedisAtomicLong("redisGenerateSecId", staticRedisUtil.redisTemplate.getConnectionFactory());
        long num = counter.incrementAndGet();
        //Atomically adds the given value to the current value.
        counter.expireAt(DateUtil.getAfterOneMin());
        return DateUtil.nowDateSec() + String.format("%0" + length + "d", num);
    }

    public static String generate(String redisCounter) {
        RedisAtomicLong counter = new RedisAtomicLong(redisCounter, staticRedisUtil.redisTemplate.getConnectionFactory());
        long num = counter.incrementAndGet();
        //Atomically adds the given value to the current value.
        if (num == 1L) {
            // 第一次获取,设置一天后失效
            counter.expire(1, TimeUnit.DAYS);
        }
        return String.format("%04d", num);
    }

}
JsonUtil.java(base)
package com.lyj.common.base.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

/**
 * json工具类
 */
public class JsonUtil {

    private JsonUtil() {
        super();
    }

    /*
    * 对象转json字符串 忽略null
     */
    public static String serialize(Object source) {
        if (source instanceof String) {
            return (String) source;
        }
        return JSON.toJSONString(source);
    }
    /*
     * 对象转json字符串 忽略null
     */
    public static String serializeNoNnull(Object source) {
        if (source instanceof String) {
            return (String) source;
        }
        return JSON.toJSONString(source, SerializerFeature.WriteMapNullValue);
    }
    /*
     * json字符串转对象
     */
    public static <T> T deserialize(String source, Class<T> clazz) {
        return JSON.parseObject(source, clazz);
    }
}
DateUtil.java
package com.lyj.common.base.util;

import cn.hutool.core.util.StrUtil;
import com.lyj.common.base.constant.CommonConstant;
import com.lyj.common.base.constant.ErrorMessageConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.stereotype.Component;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

/**
 * 日期工具类
 */
@Component
@Slf4j
public class DateUtil {

    public static final String PATTERN_YEAR = "yyyy";

    public static final String PATTERN_YEAR_MONTH = "yyyyMM";

    public static final String PATTERN_YEAR_MONTH_ISO = "yyyy-MM";

    public static final String PATTERN_YEAR_MONTH_DAY = "yyyyMMdd";

    public static final String PATTERN_YEAR_MONTH_DAY_ISO = "yyyy-MM-dd";

    public static final String PATTERN_YEAR_MONTH_DAY_TIME_ISO = "yyyy-MM-dd HH:mm:ss";

    public static final String PATTERN_YEAR_MONTH_DAY_HH_MM_SS = "yyyyMMddHHmmss";

    public static final String PATTERN_TIME = "HH:mm";

    /**
     * 获取当前时间戳
     *
     * @return 当前时间戳
     */
    public static Timestamp nowTimestamp() {
        return new Timestamp(System.currentTimeMillis());
    }

    /**
     * 获取当前时间
     *
     * @return 当前时间
     */
    public static Date nowDate() {
        return new Date(System.currentTimeMillis());
    }

    /**
     * 获取当前毫秒时间
     *
     * @return 当前毫秒时间
     */
    public static long nowTimeInMillis() {
        return System.currentTimeMillis();
    }


    /**
     * 返回入参的当天最早时间
     *
     * @param param 必填
     * @return Date
     */
    public static Date earliestTime(Date param) {

        Calendar instance = Calendar.getInstance();
        instance.setTime(param);

        instance.set(Calendar.HOUR_OF_DAY, 0);
        instance.set(Calendar.MINUTE, 0);
        instance.set(Calendar.SECOND, 0);

        return instance.getTime();
    }

    /**
     * 返回入参的当天最晚时间
     *
     * @param param 必填
     * @return Date
     */
    public static Date latestTime(Date param) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(param);

        instance.set(Calendar.HOUR_OF_DAY, 23);
        instance.set(Calendar.MINUTE, 59);
        instance.set(Calendar.SECOND, 59);

        return instance.getTime();
    }

    /**
     * 对时间进行加减计算
     *
     * @param date      计算时间
     * @param timeField 时间属性默认 Calendar.DAY_OF_YEAR
     * @param number    计算数量
     * @return Date
     */
    public static Date computeDate(Date date, Integer timeField, Integer number) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(date);

        instance.add(timeField, number);

        return instance.getTime();
    }


    /**
     * 判断给定年份是否不符合yyyy格式
     *
     * @param year 给定年份
     * @return true表示非法,反之合法
     */
    public static boolean illegalYear(Integer year) {
        if (Objects.isNull(year)) {
            return true;
        }
        try {
            Year.parse(String.valueOf(year), DateTimeFormatter.ofPattern(PATTERN_YEAR));
            return false;
        } catch (Exception e) {
            return true;
        }
    }

    /**
     * 判断给定月份是否非法
     *
     * @param month 月份
     * @return true表示给定月份非法,false表示合法
     */
    public static boolean illegalMonth(Integer month) {
        return Objects.isNull(month) || month < Month.JANUARY.getValue() || month > Month.DECEMBER.getValue();
    }

    /**
     * 判断给定日历天是否非法
     *
     * @param year  年份
     * @param month 月份
     * @param day   日历天
     * @return true
     */
    public static boolean illegalDay(Integer year, Integer month, Integer day) {
        if (Objects.isNull(year) || Objects.isNull(month) || Objects.isNull(day)) {
            return true;
        }
        try {
            int maxDay = YearMonth.of(year, month).lengthOfMonth();
            return day < CommonConstant.NUMBER_INT_ONE || day > maxDay;
        } catch (Exception e) {
            return true;
        }
    }

    /**
     * 判断给定日期是否是周末
     *
     * @param localDate 日期
     * @return true表示是周末,反之则不是
     */
    public static boolean weekends(LocalDate localDate) {
        if (Objects.isNull(localDate)) {
            return false;
        }
        return DayOfWeek.SATURDAY == localDate.getDayOfWeek() || DayOfWeek.SUNDAY == localDate.getDayOfWeek();
    }

    public static boolean weekends(Timestamp timestamp) {
        if (Objects.isNull(timestamp)) {
            return false;
        }
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp.getTime()), ZoneId.systemDefault());
        return DayOfWeek.SATURDAY == localDateTime.getDayOfWeek() || DayOfWeek.SUNDAY == localDateTime.getDayOfWeek();
    }

    public static boolean weekends(Integer year, Integer month, Integer day) {
        if (illegalDay(year, month, day)) {
            return false;
        }
        LocalDate localDate = of(year, month, day);
        if (Objects.isNull(localDate)) {
            return false;
        }
        return DayOfWeek.SATURDAY == localDate.getDayOfWeek() || DayOfWeek.SUNDAY == localDate.getDayOfWeek();
    }

    /**
     * 获取给定日期对应的考核账期
     */
    public static String appraisalMonth(LocalDate date) {
        try {
            return date.format(DateTimeFormatter.ofPattern(PATTERN_YEAR_MONTH_ISO));
        } catch (Exception e) {
            BizExceptionUtil.bizException("月份格式错误");
        }
        return "";
    }


    /**
     * 是否处于生命周期内
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static Boolean inLifeCycle(LocalDate startTime, LocalDate endTime) {
        LocalDate now = LocalDate.now();
        return (startTime.isBefore(now) || startTime.equals(now)) && (endTime.isAfter(now) || endTime.equals(now));
    }

    /**
     * 按照给定格式格式化日期
     */
    public static LocalDate parseDate(String date, String pattern) {
        try {
            return LocalDate.parse(date, DateTimeFormatter.ofPattern(pattern));
        } catch (Exception e) {
            BizExceptionUtil.bizException("月份格式错误");
        }
        return LocalDate.now();
    }

    /**
     * 格式化时间
     *
     * @param timeStamp 时间戳,毫秒
     * @param pattern   格式
     * @return String
     */
    public static String formatDate(Long timeStamp, String pattern) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timeStamp), ZoneId.systemDefault())
                .format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 格式化时间
     *
     * @param timeStamp 时间戳,毫秒
     * @param pattern   格式
     * @return String
     */
    public static String formatDate(Timestamp timeStamp, String pattern) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timeStamp.getTime()), ZoneId.systemDefault())
                .format(DateTimeFormatter.ofPattern(pattern));
    }

    public static String formatDate(LocalDate date, String pattern) {
        return date.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static String formatDate(LocalDateTime date, String pattern) {
        return date.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static void main(String[] args) {
        System.out.println(formatDate(LocalDateTime.now(), "HH:mm"));
    }

    /**
     * 格式化时间
     *
     * @param time    时间字符串
     * @param pattern 时间格式
     * @return 时间
     */
    public static LocalTime formatTime(String time, String pattern) {
        try {
            return LocalTime.parse(time, DateTimeFormatter.ofPattern(pattern));
        } catch (Exception e) {
            BizExceptionUtil.bizException(ErrorMessageConstant.BIZ_ILLEGAL_TIME);
        }
        return null;
    }

    public static long toEpochMills(LocalDate date, String time, String pattern) {
        LocalTime localTime = formatTime(time, pattern);
        if (Objects.isNull(localTime)) {
            BizExceptionUtil.bizException(ErrorMessageConstant.BIZ_ILLEGAL_TIME);
        }
        return toEpochMills(date.atTime(localTime));
    }

    /**
     * 转换为毫秒时间戳
     *
     * @param source 给定时间
     * @return 毫秒时间戳
     */
    public static long toEpochMills(LocalDateTime source) {
        return source.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 日期字符串转换为毫秒时间戳(时间部分为给定天的起始时间)
     *
     * @param date    日期字符串,不含时间
     * @param pattern 日期格式,不含时间
     * @return 毫秒时间戳
     */
    public static long toEpochMills(String date, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        LocalDateTime dateTime = LocalDate.parse(date, formatter).atStartOfDay();
        return toEpochMills(dateTime);
    }


    /**
     * 获取某个月一共有多少天
     *
     * @param date
     * @return
     */
    public static int getDaysOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取当天最后一秒的毫秒数
     *
     * @param localDate
     * @return
     */
    public static Timestamp lastSecond(LocalDate localDate) {
        Timestamp lastDayTimeStamp = new Timestamp(localDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli());
        String lastSecond = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Timestamp timestamp = new Timestamp(lastDayTimeStamp.getTime());
        try {
            //一天的毫秒-1
            int dayMis = 1000 * 60 * 60 * 24;
            //当天的毫秒
            long curMillisecond = lastDayTimeStamp.getTime();
            //当天最后一秒
            long resultMis = curMillisecond + (dayMis - 1);
            //得到当天最后一秒
            Date resultDate = new Date(resultMis);
            lastSecond = sdf.format(resultDate);
            timestamp = new Timestamp(sdf.parse(lastSecond).getTime());
            return timestamp;
        } catch (Exception e) {
            BizExceptionUtil.bizException(ErrorMessageConstant.BIZ_ILLEGAL_YEAR_MONTH_DAY);
        }
        return timestamp;
    }


    /**
     * 这里默认所有参数均为正整数
     */
    public static LocalDate of(Integer year, Integer month, Integer day) {
        try {
            return LocalDate.of(year, month, day);
        } catch (Exception e) {
            BizExceptionUtil.bizException(ErrorMessageConstant.BIZ_ILLEGAL_YEAR_MONTH_DAY);
        }
        return LocalDate.now();
    }

    /**
     * 返回Timestamp
     * @param source
     * @return
     */
    public static Timestamp from(LocalDateTime source) {
        long epochMilli = source.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        return new Timestamp(epochMilli);
    }

    /**
     * 返回Timestamp
     * @param mills
     * @return
     */
    public static Timestamp from(Long mills) {
        return new Timestamp(mills);
    }

    /**
     * 比较两个日期是否是同一天
     * @param one
     * @param another
     * @return
     */
    public static boolean theSameDay(LocalDateTime one, LocalDateTime another) {
        return one.getYear() == another.getYear()
                && one.getMonthValue() == another.getMonthValue()
                && one.getDayOfMonth() == another.getDayOfMonth();
    }

    /**
     * 日期字符串指定格式返回LocalDateTime实例
     * @param s
     * @param pattern
     * @return LocalDateTime
     */
    public static LocalDateTime parse(String s, String pattern) {
        return LocalDateTime.parse(s, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 当前时间减一天
     */
    public static LocalDateTime yesterday() {
        LocalDateTime now = LocalDateTime.now();
        return now.minusDays(1);
    }

    //判断时间是否在本月之内
    public static boolean isInThisMonth(LocalDate localDate) {
        LocalDate now = LocalDate.now();
        return localDate.isAfter(now.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth())) &&
                localDate.isBefore(now.plusMonths(1).with(TemporalAdjusters.firstDayOfMonth()));
    }


    /**
     * 获取后一分钟
     */
    public static Date getAfterOneMin() {
        Calendar calendar = Calendar.getInstance();
        int minute = calendar.get(Calendar.MINUTE);
        calendar.set(Calendar.MINUTE, minute + 1);
        return calendar.getTime();
    }
    /**
     * 返回yyyyMMddHHmmss格式的当前时间
     */
    public static String nowDateSec() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(PATTERN_YEAR_MONTH_DAY_HH_MM_SS);
        return simpleDateFormat.format(new Date());
    }


    /**
     * 从一个文本字符串(如 yyyy-MM-dd)获取一个 LocalDate。
     */
    public static LocalDate getLocalDate(String date) {
        if (StrUtil.isEmpty(date)) {
            return null;
        }
        try {
            return LocalDate.parse(date, DateTimeFormatter.ofPattern(PATTERN_YEAR_MONTH_DAY_ISO));
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 从一个文本字符串(如 yyyy-MM-dd HH:mm:ss)获取一个 LocalDateTime的实例。
     */
    public static LocalDateTime getLocalDateTime(String date) {
        if (StrUtil.isEmpty(date)) {
            return null;
        }
        try {
            return LocalDateTime.parse(date, DateTimeFormatter.ofPattern(PATTERN_YEAR_MONTH_DAY_TIME_ISO));
        } catch (Exception e) {
            return null;
        }
    }
    /**
     * 格式化时间YYYMMDD
     */
    public static String getCurrentDateYYYMMDD() {
        return formatDate(new Date(), PATTERN_YEAR_MONTH_DAY);
    }

    /**
     * 获取当前时间yyyyMMddHHmmss
     */
    public static String getLocalDateTime() {
        return formatDate(LocalDateTime.now(), PATTERN_YEAR_MONTH_DAY_HH_MM_SS);
    }

    public static String formatDate(Date date, String pattern) {
        return DateFormatUtils.format(date, pattern);
    }

    /**
     * 获取年份对应的第一天日期
     *
     * @param year 年
     * @return 年月日
     */
    public static String getYearStartDate(Integer year) {
        if (year == null) {
            return null;
        }
        return year + "-01-01";
    }

    /**
     * 获取年份对应的最后一天日期
     *
     * @param year 年
     * @return 年月日
     */
    public static String getYearEndDate(Integer year) {
        if (year == null) {
            return null;
        }
        return year + "-12-31";
    }
}
ErrorMessageConstant.java
package com.lyj.common.base.constant;

/**
 * 错误信息常量池
 */
public class ErrorMessageConstant {

    // BizException相关
    public static final String BIZ_ILLEGAL_YEAR = "年份格式非法";
    public static final String BIZ_ILLEGAL_MONTH = "月份格式非法";
    public static final String BIZ_ILLEGAL_DAY = "日历天格式非法";
    public static final String BIZ_ILLEGAL_TIME = "时间格式非法";
    public static final String BIZ_ILLEGAL_YEAR_MONTH_DAY = "年月日格式非法";
    public static final String BIZ_ILLEGAL_DATE = "日期格式非法";
}
CommonConstant.java
package com.lyj.common.base.constant;

/**
 * 常量池
 */
public class CommonConstant {

    public static final int HTTP_STATUS_MOVED_TEMPORARILY = 302;

    private CommonConstant() {
    }

    ///
    // 数字区
    ///
    /**
     * 整形数字0
     */
    public static final int NUMBER_INT_ZERO = 0;
    /**
     * 整形数字1
     */
    public static final int NUMBER_INT_ONE = 1;

    /**
     * 整形数字2
     */
    public static final int NUMBER_INT_TWO = 2;
    /**
     * 整形数字3
     */
    public static final int NUMBER_INT_THREE = 3;
    /**
     * 整形数字4
     */
    public static final int NUMBER_INT_FOUR = 4;
    /**
     * 整形数字3
     */
    public static final int NUMBER_INT_FIVE = 5;
    /**
     * 整形数字6
     */
    public static final int NUMBER_INT_SIX = 6;
    /**
     * 整形数字7
     */
    public static final int NUMBER_INT_SEVEN = 7;
    /**
     * 整形数字8
     */
    public static final int NUMBER_INT_EIGHT = 8;
    /**
     * 整形数字10
     */
    public static final int NUMBER_INT_TEN = 10;

    /**
     * 整形数字13
     */
    public static final int NUMBER_INT_THIRTEEN = 13;

    /**
     * 整形数字15
     */
    public static final int NUMBER_INT_FIFTEEN = 15;

    /**
     * 整形数字20
     */
    public static final int NUMBER_INT_TWENTY = 20;
    /**
     * 整形数字35
     */
    public static final int NUMBER_INT_THIRTY_FIVE = 35;
    /**
     * 整形数字50
     */
    public static final int NUMBER_INT_FIFTY = 50;
    /**
     * 整形数字85
     */
    public static final int NUMBER_INT_EIGHTY_FIVE = 85;
    /**
     * 整形数字95
     */
    public static final int NUMBER_INT_NINETY_FIVE = 95;
    /**
     * 整形数字100
     */
    public static final int NUMBER_INT_ONE_HUNDRED = 100;
    /**
     * 整形数字200
     */
    public static final int NUMBER_INT_TWO_HUNDRED = 200;
    /**
     * 整形数字1000
     */
    public static final int NUMBER_INT_ONE_THOUSAND = 1000;
    /**
     * 整形数字2000
     */
    public static final int NUMBER_INT_TWO_THOUSAND = 2000;
    /**
     * 长整型数字0
     */
    public static final long NUMBER_LONG_ZERO = 0L;
    /**
     * 长整形数字1
     */
    public static final long NUMBER_LONG_ONE = 1L;
    /**
     * 长整形数字10
     */
    public static final long NUMBER_LONG_TEN = 10L;
    /**
     * 长整形数字100
     */
    public static final long NUMBER_LONG_ONE_HUNDRED = 100L;
    /**
     * 长整形数字1000
     */
    public static final long NUMBER_LONG_ONE_THOUSAND = 1000L;
    /**
     * 长整形数字3600
     */
    public static final long NUMBER_LONG_3600 = 3600L;

    /**
     * 双精度浮点数-1
     */
    public static final double NUMBER_DOUBLE_NEGATIVE_ONE = -1d;

    /**
     * 双精度浮点数-0.5
     */
    public static final double NUMBER_DOUBLE_NEGATIVE_POINT_FIVE = -0.5d;

    /**
     * 双精度浮点数0
     */
    public static final double NUMBER_DOUBLE_ZERO = 0d;
    /**
     * 双精度浮点数0.5
     */
    public static final double NUMBER_DOUBLE_POINT_FIVE = 0.5d;
    /**
     * 双精度浮点数1
     */
    public static final double NUMBER_DOUBLE_ONE = 1d;
    /**
     * 双精度浮点数1.5
     */
    public static final double NUMBER_DOUBLE_ONE_POINT_FIVE = 1.5d;
    /**
     * 双精度浮点数2
     */
    public static final double NUMBER_DOUBLE_TWO = 2d;
    /**
     * 双精度浮点数2.5
     */
    public static final double NUMBER_DOUBLE_TWO_POINT_FIVE = 2.5d;
    /**
     * 双精度浮点数3
     */
    public static final double NUMBER_DOUBLE_THREE = 3d;
    /**
     * 双精度浮点数0
     */
    public static final double NUMBER_DOUBLE_FOUR = 4d;
    /**
     * 双精度浮点数5
     */
    public static final double NUMBER_DOUBLE_FIVE = 5d;
    /**
     * 双精度浮点数6
     */
    public static final double NUMBER_DOUBLE_SIX = 6d;
    /**
     * 双精度浮点数0
     */
    public static final double NUMBER_DOUBLE_EIGHT = 8d;
    /**
     * 双精度浮点数3600
     */
    public static final double NUMBER_DOUBLE_THIRTY_SIX_HUNDREDS = 3600d;

    /**
     * 一年有几个月份
     */
    public static final int MONTHS_IN_YEAR = 12;
    /**
     * HashMap默认初始化大小
     */
    public static final int DEFAULT_HASH_MAP_SIZE = 16; ///
    // 字符/字符串区
    ///
    /**
     * 微信token缓存key
     */
    public static final String WECHAT_ACCESS_TOKEN_KEY = "WECHAT_ACCESS_TOKEN";
    /**
     * 生产环境
     */
    public static final String ENVIRONMENT_PROD = "production";
    /**
     * 路径分隔符
     */
    public static final String PATH_SEPARATOR = "/";
    /**
     * 中文未知
     */
    public static final String UNKNOWN_ZH = "未知";
    /**
     * 英文未知
     */
    public static final String UNKNOWN_EN = "unknown";
    /**
     * 逗号
     */
    public static final String COMMA = ",";
    /**
     * 点
     */
    public static final String DOT = ".";
    /**
     * 冒号
     */
    public static final String COLON = ":";
    /**
     * 连字符
     */
    public static final String HYPHEN = "-";
    /**
     * 顿号
     */
    public static final String CAESURA = "、";
    /**
     * 新
     */
    public static final String NEW = "new";
    /**
     * 过滤未删除数据sql
     */
    public static final String DELETE_FLAG_CLAUSE = "delete_flag = 0";

    public static final String CUSTOMER_CONST = "缺省";




}

三、管理应用模块(management)集成redis

pom.xml(management)


        <dependency>
            <groupId>com.lyj.initMode</groupId>
            <artifactId>initMode-function-redis</artifactId>
        </dependency>

application.yml

spring:  
  redis:              #redis
    host: 192.168.163.158
    port: 6379
    password: 123456
    database: 0
    jedis:
      pool:
        max-active: 8 # 最大连接数
        max-wait: 1ms # 最大阻塞时间
        max-idle: 4
        min-idle: 0

 测试方法

package com.lyj.service.management.api;

import com.lyj.common.base.common.R;
import com.lyj.common.base.util.BizExceptionUtil;
import com.lyj.common.base.util.JsonUtil;
import com.lyj.common.domain.sysUser.entity.SysUser;
import com.lyj.function.redis.util.RedisUtil;
import com.lyj.service.management.service.sysUser.SysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.NotEmpty;

@RestController
@AllArgsConstructor //生成该类下全部属性的构造方法 代替@Autowired 属于lombok
@RequestMapping("/api/test/")
@Validated  //有该@NotEmpty才生效
@Api(tags = "测试API")
public class testApi {

    private SysUserService service;

    @GetMapping("/info")
    @ApiOperation("测试info")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true)
    })
    public R<SysUser> info(@NotEmpty(message = "id不能为空") @RequestParam("id") String id) {
        SysUser sysUser = service.getById(1);
        RedisUtil.set("uesr",sysUser);
        String userJson = RedisUtil.get("uesr");
        return R.ok(JsonUtil.deserialize(userJson,SysUser.class));
    }
}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值