• Linux服务器使用Redis作为数据缓存,并用log4j2进行日志记录


    前言

    个人网站使用Vue作为前端,SpringBoot作为后端,MySQL作为数据库,但前端每次请求都会从MySQL数据库中读取数据,而MySQL数据库的数据是存储于服务器磁盘中,所以响应速度有一定影响。之前了解过一点Redis数据库,该数据库数据存储于内存中(也可以持久化于磁盘中),数据读取速度就会比存储于磁盘中的MySQL快很多,故想把Redis数据库应用于该网站项目中。

    一、安装Redis

    Linux系统安装Redis比较简单,可以直接通过命令行安装,安装过程比较简单,在此就不赘述,下列出一些常用命令

    # 更新apt
    sudo apt update
    # 安装Redis
    sudo apt-get install redis-server
    # 设置密码(在配置文件redis.conf中,位置在 /etc/redis/redis.conf)
    requirepass ******
    
    # 启动Redis服务
    service redis-server start
    # 停止Redis服务
    service redis-server stop
    # 重启Redis服务
    service redis-server restart
    
    # 启动Redis客户端
    redis-cli
    # 测试Redis是否连接
    127.0.0.1:6379> ping
    

    注意:需要修改Redis配置文件中的保护模式“protected-mode"为修改为no,否则会出现无法连接的情况

    # 修改保护模式为no
    # protected-mode yes
    protected-mode no
    
    # 若不修改可能无法连接Redis,出现以下错误
    org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 127.0.0.1:6379
            at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.translateException(LettuceConnectionFactory.java:1689)
            at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1597)
    ······
    ······
    ······
    Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to 127.0.0.1:6379
            at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78)
            at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56)
    ······
    ······
    ······
    Caused by: java.lang.IllegalStateException: RedisHandshakeHandler not registered
            at io.lettuce.core.AbstractRedisClient.lambda$initializeChannelAsync0$6(AbstractRedisClient.java:431)
            at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590)
    ······
    ······
    ······
    

    二、SpringBoot项目集成Redis

    1、pom.xml添加依赖

    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-redisartifactId>
    dependency>
    

    2、Redis数据库连接配置 application.yml

    # Redis
    redis:
    # 服务器地址
    host: 127.0.0.1
    # 服务器端口号
    port: 6379
    # 使用的数据库索引
    database: 0
    # 连接超时时间
    timeout: 10000
    # 设置密码
    password: ******
    lettuce:
      # 连接池
      pool:
        # 最大阻塞等待时间,负数表示没有限制
        max-wait: -1
        # 连接池中最大空闲
        max-idle: 5
        # 连接池中最小空闲
        min-idle: 0
        # 连接池最大连接数
        max-active: 20
    

    3、Redis配置类RedisConfig

    package cn.huskysir.Config;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.cache.annotation.CachingConfigurerSupport;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.*;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    @Configuration
    @EnableCaching //开启注解
    public class RedisConfig extends CachingConfigurerSupport {
    
        /**
         * retemplate相关配置
         */
        @Bean
        public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
    
            RedisTemplate template = new RedisTemplate<>();
            // 配置连接工厂
            template.setConnectionFactory(factory);
    
            //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
            Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
    
            ObjectMapper om = new ObjectMapper();
            // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jacksonSeial.setObjectMapper(om);
    
            // 值采用json序列化
            template.setValueSerializer(jacksonSeial);
            //使用StringRedisSerializer来序列化和反序列化redis的key值
            template.setKeySerializer(new StringRedisSerializer());
    
            // 设置hash key 和value序列化模式
            template.setHashKeySerializer(new StringRedisSerializer());
            template.setHashValueSerializer(jacksonSeial);
            template.afterPropertiesSet();
    
            return template;
        }
    
        /**
         * 对hash类型的数据操作
         */
        @Bean
        public HashOperations hashOperations(RedisTemplate redisTemplate) {
            return redisTemplate.opsForHash();
        }
    
        /**
         * 对redis字符串类型数据操作
         */
        @Bean
        public ValueOperations valueOperations(RedisTemplate redisTemplate) {
            return redisTemplate.opsForValue();
        }
    
        /**
         * 对链表类型的数据操作
         */
        @Bean
        public ListOperations listOperations(RedisTemplate redisTemplate) {
            return redisTemplate.opsForList();
        }
    
        /**
         * 对无序集合类型的数据操作
         */
        @Bean
        public SetOperations setOperations(RedisTemplate redisTemplate) {
            return redisTemplate.opsForSet();
        }
    
        /**
         * 对有序集合类型的数据操作
         */
        @Bean
        public ZSetOperations zSetOperations(RedisTemplate redisTemplate) {
            return redisTemplate.opsForZSet();
        }
    }
    

    4、Redis工具类RedisUtil

    package cn.huskysir.Utils;
    
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Component;
    import org.springframework.util.CollectionUtils;
    
    import javax.annotation.Resource;
    import java.util.Collection;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    
    @Component
    public class RedisUtil {
    
        @Resource
        private RedisTemplate redisTemplate;
    
        public RedisUtil(RedisTemplate redisTemplate) {
            this.redisTemplate = redisTemplate;
        }
    
        /**
         * 指定缓存失效时间
         *
         * @param key  键
         * @param time 时间(秒)
         * @return
         */
        public boolean expire(String key, long time) {
            try {
                if (time > 0) {
                    redisTemplate.expire(key, time, TimeUnit.SECONDS);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 根据key 获取过期时间
         *
         * @param key 键 不能为null
         * @return 时间(秒) 返回0代表为永久有效
         */
        public long getExpire(String key) {
            return redisTemplate.getExpire(key, TimeUnit.SECONDS);
        }
    
        /**
         * 判断key是否存在
         *
         * @param key 键
         * @return true 存在 false不存在
         */
        public boolean hasKey(String key) {
            try {
                return redisTemplate.hasKey(key);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 删除缓存
         *
         * @param key 可以传一个值 或多个
         */
        @SuppressWarnings("unchecked")
        public void del(String... key) {
            if (key != null && key.length > 0) {
                if (key.length == 1) {
                    redisTemplate.delete(key[0]);
                } else {
                    redisTemplate.delete((Collection) CollectionUtils.arrayToList(key));
                }
            }
        }
    
        //============================String=============================
    
        /**
         * 普通缓存获取
         *
         * @param key 键
         * @return 值
         */
        public Object get(String key) {
            return key == null ? null : redisTemplate.opsForValue().get(key);
        }
    
        /**
         * 普通缓存放入
         *
         * @param key   键
         * @param value 值
         * @return true成功 false失败
         */
        public boolean set(String key, Object value) {
            try {
                redisTemplate.opsForValue().set(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 普通缓存放入并设置时间
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
         * @return true成功 false 失败
         */
        public boolean set(String key, Object value, long time) {
            try {
                if (time > 0) {
                    redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
                } else {
                    set(key, value);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 递增
         *
         * @param key   键
         * @param delta 要增加几(大于0)
         * @return
         */
        public long incr(String key, long delta) {
            if (delta < 0) {
                throw new RuntimeException("递增因子必须大于0");
            }
            return redisTemplate.opsForValue().increment(key, delta);
        }
    
        /**
         * 递减
         *
         * @param key   键
         * @param delta 要减少几(小于0)
         * @return
         */
        public long decr(String key, long delta) {
            if (delta < 0) {
                throw new RuntimeException("递减因子必须大于0");
            }
            return redisTemplate.opsForValue().increment(key, -delta);
        }
    
        //================================Map=================================
    
        /**
         * HashGet
         *
         * @param key  键 不能为null
         * @param item 项 不能为null
         * @return 值
         */
        public Object hget(String key, String item) {
            return redisTemplate.opsForHash().get(key, item);
        }
    
        /**
         * 获取hashKey对应的所有键值
         *
         * @param key 键
         * @return 对应的多个键值
         */
        public Map hmget(String key) {
            return redisTemplate.opsForHash().entries(key);
        }
    
        /**
         * HashSet
         *
         * @param key 键
         * @param map 对应多个键值
         * @return true 成功 false 失败
         */
        public boolean hmset(String key, Map map) {
            try {
                redisTemplate.opsForHash().putAll(key, map);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * HashSet 并设置时间
         *
         * @param key  键
         * @param map  对应多个键值
         * @param time 时间(秒)
         * @return true成功 false失败
         */
        public boolean hmset(String key, Map map, long time) {
            try {
                redisTemplate.opsForHash().putAll(key, map);
                if (time > 0) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 向一张hash表中放入数据,如果不存在将创建
         *
         * @param key   键
         * @param item  项
         * @param value 值
         * @return true 成功 false失败
         */
        public boolean hset(String key, String item, Object value) {
            try {
                redisTemplate.opsForHash().put(key, item, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 向一张hash表中放入数据,如果不存在将创建
         *
         * @param key   键
         * @param item  项
         * @param value 值
         * @param time  时间(秒)  注意:如果已存在的hash表有时间,这里将会替换原有的时间
         * @return true 成功 false失败
         */
        public boolean hset(String key, String item, Object value, long time) {
            try {
                redisTemplate.opsForHash().put(key, item, value);
                if (time > 0) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 删除hash表中的值
         *
         * @param key  键 不能为null
         * @param item 项 可以使多个 不能为null
         */
        public void hdel(String key, Object... item) {
            redisTemplate.opsForHash().delete(key, item);
        }
    
        /**
         * 判断hash表中是否有该项的值
         *
         * @param key  键 不能为null
         * @param item 项 不能为null
         * @return true 存在 false不存在
         */
        public boolean hHasKey(String key, String item) {
            return redisTemplate.opsForHash().hasKey(key, item);
        }
    
        /**
         * hash递增 如果不存在,就会创建一个 并把新增后的值返回
         *
         * @param key  键
         * @param item 项
         * @param by   要增加几(大于0)
         * @return
         */
        public double hincr(String key, String item, double by) {
            return redisTemplate.opsForHash().increment(key, item, by);
        }
    
        /**
         * hash递减
         *
         * @param key  键
         * @param item 项
         * @param by   要减少记(小于0)
         * @return
         */
        public double hdecr(String key, String item, double by) {
            return redisTemplate.opsForHash().increment(key, item, -by);
        }
    
        //============================set=============================
    
        /**
         * 根据key获取Set中的所有值
         *
         * @param key 键
         * @return
         */
        public Set sGet(String key) {
            try {
                return redisTemplate.opsForSet().members(key);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 根据value从一个set中查询,是否存在
         *
         * @param key   键
         * @param value 值
         * @return true 存在 false不存在
         */
        public boolean sHasKey(String key, Object value) {
            try {
                return redisTemplate.opsForSet().isMember(key, value);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 将数据放入set缓存
         *
         * @param key    键
         * @param values 值 可以是多个
         * @return 成功个数
         */
        public long sSet(String key, Object... values) {
            try {
                return redisTemplate.opsForSet().add(key, values);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * 将set数据放入缓存
         *
         * @param key    键
         * @param time   时间(秒)
         * @param values 值 可以是多个
         * @return 成功个数
         */
        public long sSetAndTime(String key, long time, Object... values) {
            try {
                Long count = redisTemplate.opsForSet().add(key, values);
                if (time > 0) {
                    expire(key, time);
                }
                return count;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * 获取set缓存的长度
         *
         * @param key 键
         * @return
         */
        public long sGetSetSize(String key) {
            try {
                return redisTemplate.opsForSet().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * 移除值为value的
         *
         * @param key    键
         * @param values 值 可以是多个
         * @return 移除的个数
         */
        public long setRemove(String key, Object... values) {
            try {
                Long count = redisTemplate.opsForSet().remove(key, values);
                return count;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
        //===============================list=================================
    
        /**
         * 获取list缓存的内容
         *
         * @param key   键
         * @param start 开始
         * @param end   结束  0 到 -1代表所有值
         * @return
         */
        public List lGet(String key, long start, long end) {
            try {
                return redisTemplate.opsForList().range(key, start, end);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 获取list缓存的长度
         *
         * @param key 键
         * @return
         */
        public long lGetListSize(String key) {
            try {
                return redisTemplate.opsForList().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    
        /**
         * 通过索引 获取list中的值
         *
         * @param key   键
         * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
         * @return
         */
        public Object lGetIndex(String key, long index) {
            try {
                return redisTemplate.opsForList().index(key, index);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 将list放入缓存
         *
         * @param key   键
         * @param value 值
         * @return
         */
        public boolean lSet(String key, Object value) {
            try {
                redisTemplate.opsForList().rightPush(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 将list放入缓存
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒)
         * @return
         */
        public boolean lSet(String key, Object value, long time) {
            try {
                redisTemplate.opsForList().rightPush(key, value);
                if (time > 0) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 将list放入缓存
         *
         * @param key   键
         * @param value 值
         * @return
         */
        public boolean lSet(String key, List value) {
            try {
                redisTemplate.opsForList().rightPushAll(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 将list放入缓存
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒)
         * @return
         */
        public boolean lSet(String key, List value, long time) {
            try {
                redisTemplate.opsForList().rightPushAll(key, value);
                if (time > 0) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 根据索引修改list中的某条数据
         *
         * @param key   键
         * @param index 索引
         * @param value 值
         * @return
         */
        public boolean lUpdateIndex(String key, long index, Object value) {
            try {
                redisTemplate.opsForList().set(key, index, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 移除N个值为value
         *
         * @param key   键
         * @param count 移除多少个
         * @param value 值
         * @return 移除的个数
         */
        public long lRemove(String key, long count, Object value) {
            try {
                Long remove = redisTemplate.opsForList().remove(key, count, value);
                return remove;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    }
    
    

    三、SpringBoot项目集成log4j2

    SpringBoot项目在运行的时候可能会产生一些运行信息,如果能将这些信息记录下来,那么对于该项目的运行状态以及错误排查会起到一个非常好的帮助,所以采用log4j2进行日志记录

    1、pom.xml添加依赖

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
        <exclusions>
            
            <exclusion>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-loggingartifactId>
            exclusion>
        exclusions>
    dependency>
    
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-log4j2artifactId>
    dependency>
    

    2、log4j2.xml配置文件,放置于resources文件夹下

    
    <Configuration status="fatal">
        <Properties>
            <Property name="baseDir" value="/home/leilee/Projects/back/logs"/>
        Properties>
    
        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
                
                <ThresholdFilter level="info" onMatch="ACCEPT"
                                 onMismatch="DENY"/>
                <PatternLayout
                        pattern="[%d{MM:dd HH:mm:ss.SSS}] [%level] [%logger{36}] - %msg%n"/>
            Console>
    
            
            <RollingFile name="debug_appender" fileName="${baseDir}/debug.log"
                         filePattern="${baseDir}/debug_%i.log.%d{yyyy-MM-dd}">
                
                <Filters>
                    
                    <ThresholdFilter level="debug"/>
                    <ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>
                Filters>
                
                <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
                
                <Policies>
                    
                    <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                    
                    <SizeBasedTriggeringPolicy size="100 MB"/>
                Policies>
            RollingFile>
    
            
            <RollingFile name="info_appender" fileName="${baseDir}/info.log"
                         filePattern="${baseDir}/info_%i.log.%d{yyyy-MM-dd}">
                
                <Filters>
                    
                    <ThresholdFilter level="info"/>
                    <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
                Filters>
                
                <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
                
                <Policies>
                    
                    <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                    
                    <SizeBasedTriggeringPolicy size="100 MB"/>
                Policies>
            RollingFile>
    
            
            <RollingFile name="error_appender" fileName="${baseDir}/error.log"
                         filePattern="${baseDir}/error_%i.log.%d{yyyy-MM-dd}">
                
                <Filters>
                    
                    <ThresholdFilter level="error"/>
                Filters>
                
                <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
                <Policies>
                    
                    <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                    
                    <SizeBasedTriggeringPolicy size="100 MB"/>
                Policies>
            RollingFile>
        Appenders>
        <Loggers>
            <Root level="debug">
                <AppenderRef ref="Console"/>
                <AppenderRef ref="debug_appender"/>
                <AppenderRef ref="info_appender"/>
                <AppenderRef ref="error_appender"/>
            Root>
        Loggers>
    Configuration>
    

    注意:第四行中value的值即输出的log文件的存放路径

    3、自定义log信息

    如果自己想存入一些自定义的信息,那么采用@Log4j2对类进行注解,然后在类中使用log的方法即可,以该网站的数据库读取过程为例

    package cn.huskysir.Service.Impl;
    
    import cn.huskysir.Dao.DynastyMapper;
    import cn.huskysir.Dao.EmperorMapper;
    import cn.huskysir.Entity.MySQL.Dynasty;
    import cn.huskysir.Entity.MySQL.Emperor;
    import cn.huskysir.Service.EmperorService;
    import cn.huskysir.Utils.RedisUtil;
    import cn.huskysir.Vo.EmperorVo;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import lombok.extern.log4j.Log4j2;
    import org.springframework.beans.BeanUtils;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.Date;
    import java.util.LinkedList;
    import java.util.List;
    
    /**
     * Emperor Service层(实现类)
     */
    @Log4j2
    @Service
    public class EmperorServiceImpl implements EmperorService {
    
        @Resource
        EmperorMapper emperorMapper;
        @Resource
        DynastyMapper dynastyMapper;
        @Resource
        RedisUtil redisUtil;
    
        /**
         * 获得所有EmperorVo对象列表
         *
         * @return
         */
        @Override
        public List getAllEmperorVoList() {
            // 判断Redis是否存在该结果
            String key = "getAllEmperorVoList";
            if (redisUtil.hasKey(key)) {
                List emperorVoList = (List) redisUtil.get(key);
                System.out.println("由Redis得到" + key + "结果");
                // 日志记录
                log.info(new Date() + " 由Redis得到" + key + "数据");
                return emperorVoList;
            }
    
            List emperorList = emperorMapper.selectList(null);
            List emperorVoList = new LinkedList<>();
            for (Emperor emperor : emperorList) {
                EmperorVo emperorVo = new EmperorVo();
                BeanUtils.copyProperties(emperor, emperorVo);
                Dynasty dynasty = dynastyMapper.selectById(emperor.getDynastyId());
                emperorVo.setDynastyName(dynasty.getName());
                emperorVo.calculateTime();
                emperorVoList.add(emperorVo);
            }
            System.out.println("由MySQL得到" + key + "结果");
            // 日志记录
            log.info(new Date() + " 由MySQL得到" + key + "数据");
            if (redisUtil.set(key, emperorVoList, 600)) {
                System.out.println("Redis已存入" + key + "数据");
                // 日志记录
                log.info(new Date() + " Redis已存入" + key + "数据");
            }
    
            return emperorVoList;
        }
    
        /**
         * 根据id获得EmperorVo对象
         *
         * @param id
         * @return
         */
        @Override
        public EmperorVo getEmperorVoById(Integer id) {
            // 判断Redis是否存在该结果
            String key = "getEmperorVoById_" + String.valueOf(id);
            if (redisUtil.hasKey(key)) {
                EmperorVo emperorVo = (EmperorVo) redisUtil.get(key);
                System.out.println("由Redis得到" + key + "结果");
                // 日志记录
                log.info(new Date() + " 由Redis得到" + key + "数据");
                return emperorVo;
            }
    
            Emperor emperor = emperorMapper.selectById(id);
            EmperorVo emperorVo = new EmperorVo();
            BeanUtils.copyProperties(emperor, emperorVo);
            Dynasty dynasty = dynastyMapper.selectById(emperor.getDynastyId());
            emperorVo.setDynastyName(dynasty.getName());
            emperorVo.calculateTime();
            System.out.println("由MySQL得到" + key + "结果");
            // 日志记录
            log.info(new Date() + " 由MySQL得到" + key + "数据");
            if (redisUtil.set(key, emperorVo, 600)) {
                System.out.println("Redis已存入" + key + "数据");
                // 日志记录
                log.info(new Date() + " Redis已存入" + key + "数据");
            }
    
            return emperorVo;
        }
    
        /**
         * 根据dynastyId获得所有EmperorVo对象列表
         *
         * @param dynastyId
         * @return
         */
        @Override
        public List getEmperorListByDynastyId(Integer dynastyId) {
            // 判断Redis是否存在该结果
            String key = "getEmperorListByDynastyId_" + String.valueOf(dynastyId);
            if (redisUtil.hasKey(key)) {
                List emperorVoList = (List) redisUtil.get(key);
                System.out.println("由Redis得到" + key + "结果");
                // 日志记录
                log.info(new Date() + " 由Redis得到" + key + "数据");
                return emperorVoList;
            }
    
            QueryWrapper queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("dynasty_id", dynastyId);
            List emperorList = emperorMapper.selectList(queryWrapper);
            List emperorVoList = new LinkedList<>();
            String nastyName = dynastyMapper.selectById(dynastyId).getName();
            for (Emperor emperor : emperorList) {
                EmperorVo emperorVo = new EmperorVo();
                BeanUtils.copyProperties(emperor, emperorVo);
                emperorVo.setDynastyName(nastyName);
                emperorVo.calculateTime();
                emperorVoList.add(emperorVo);
            }
            System.out.println("由MySQL得到" + key + "结果");
            // 日志记录
            log.info(new Date() + " 由MySQL得到" + key + "数据");
            if (redisUtil.set(key, emperorVoList, 600)) {
                System.out.println("Redis已存入" + key + "数据");
                // 日志记录
                log.info(new Date() + " Redis已存入" + key + "数据");
            }
    
            return emperorVoList;
        }
    }
    

    以“getEmperorListByDynastyId(Integer dynastyId)”方法为例,该方法是根据dynastyId获得List对象,首先会根据方法名及dynastyIdRedis数据库中查找,若存在则直接返回,否则从MySQL数据库中读取,并将结果存入Redis数据库中然后返回。使用log.info()记录数据库读取过程,该记录会存储于info.log文件中

    该网站后台的info.log日志记录如下

    [00:54:31:770] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:141) - Wed Sep 20 00:54:31 CST 2023 由MySQL得到getEmperorListByDynastyId_1数据
    [00:54:31:773] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:145) - Wed Sep 20 00:54:31 CST 2023 Redis已存入getEmperorListByDynastyId_1数据
    [00:54:35:853] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:141) - Wed Sep 20 00:54:35 CST 2023 由MySQL得到getEmperorListByDynastyId_2数据
    [00:54:35:863] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:145) - Wed Sep 20 00:54:35 CST 2023 Redis已存入getEmperorListByDynastyId_2数据
    [00:54:37:363] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:123) - Wed Sep 20 00:54:37 CST 2023 由Redis得到getEmperorListByDynastyId_1数据
    [00:54:38:043] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:123) - Wed Sep 20 00:54:38 CST 2023 由Redis得到getEmperorListByDynastyId_2数据
    [00:54:39:214] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:123) - Wed Sep 20 00:54:39 CST 2023 由Redis得到getEmperorListByDynastyId_1数据
    [00:54:39:936] [INFO] - cn.huskysir.Service.Impl.EmperorServiceImpl.getEmperorListByDynastyId(EmperorServiceImpl.java:123) - Wed Sep 20 00:54:39 CST 2023 由Redis得到getEmperorListByDynastyId_2数据
    

    四、总结

    关于SpringBoot项目配置Redis与log4j2是查询官方文档以及他人博客得到的,本文中的Redis配置类、Redis工具类以及log4j2.xml配置文件来自网络,查证源自何处比较麻烦,所以在此感谢所有人的分享!

  • 相关阅读:
    消息队列实现AB进程对话;共享内存和信号量集完成多进程字符串翻转与输出
    可分矩阵和k-拟可分矩阵
    Nginx之Openresty缓存解读
    面试Java后端
    gitlab安装和使用
    【Web_自动化测试_Python3_webdriver_etree_批量下载京东图片】通过地址抓取静态网页+解析标题和链接+通过链接批量下载图片
    7.9 混合背包问题7.10 特殊要求7.11 背包问题的搜索解法
    【AGC】【Connect API】如何获取应用的报表分析数据
    医疗器械设计时需要注意的事项
    【C++/STL】list(常见接口、模拟实现、反向迭代器)
  • 原文地址:https://www.cnblogs.com/huskysir/p/17716281.html