zoukankan      html  css  js  c++  java
  • 【项目搭建】SpringBoot整合redis缓存(一)

    准备工作:

    1.Linux系统

    2.安装redis(也可以安装docker,然后再docker中装redis,本文章就直接用Linux安装redis做演示)

      redis下载地址:http://download.redis.io/releases/redis-4.0.14.tar.gz

    找到redis中的redis.conf文件并编辑(在安装路径中找到)

    vim ./redis.conf
     

    1、找到bind 127.0.0.1并注释掉

      默认127.0.0.1只能本地访问,注释掉即可ip访问

    2、修改 protected-mode 属性值为no

      注释掉并把保护模式禁用以后可以IP访问

    3、修改daemonize属性将no 改为yes

      将daemonize设置为yes即启动后台运行

    4、开放6379端口

    /sbin/iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
     

      默认不对外开放6379

    5、启动redis

    redis-server /myconf/redis.conf
     

      redis-server默认在/usr/local/bin路径下,redis.conf在redis的安装路径下

    6、测试连接

    redis-cli -h 192.168.126.129 -p 6379
     

      redis-cli -h redis服务器IP -p 6379 -a 密码(没有设置redis密码不要写空,否则报错)


    项目源码结构

    一个user表

    pom.xml文件(可以根据自己的需要来添加或修改)

    <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- mybatis 与 spring boot 2.x的整合包 -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
    
            <!--mysql JDBC驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.39</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-cache</artifactId>
            </dependency>
        </dependencies>
     

     下面是springboot的配置文件application.yml,配置redis(里面都有注释解释)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    server:
      port: 8081
     
    #数据库连接
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/mytest_springboot_cache?useUnicode=true
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password: lzh
     
      ## Redis 配置
      redis:
        ## Redis数据库索引(默认为0
        database: 0
        ## Redis服务器地址
        host: 192.168.126.129
        ## Redis服务器连接端口
        port: 6379
        ## Redis服务器连接密码(默认为空)
        password:
        jedis:
          pool:
            ## 连接池最大连接数(使用负值表示没有限制)
            #spring.redis.pool.max-active=8
            max-active: 8
            ## 连接池最大阻塞等待时间(使用负值表示没有限制)
            #spring.redis.pool.max-wait=-1
            max-wait: -1
            ## 连接池中的最大空闲连接
            #spring.redis.pool.max-idle=8
            max-idle: 8
            ## 连接池中的最小空闲连接
            #spring.redis.pool.min-idle=0
            min-idle: 0
        ## 连接超时时间(毫秒)
        timeout: 1200
     
      #将themilef的默认缓存禁用,热加载生效
      thymeleaf:
        cache: false
     
      #mybatis的下划线转驼峰配置
      configuration:
        map-underscore-to-camel-case: true
     
        #另外一种打印语句的方式
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
     
    #打印sql时的语句
    logging:
      level:
        com:
          acong:
            dao: debug
      file: d:/logs/bsbdj.log

     接着是实体类,这个比较简单就不多说了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    package com.lzh.springbootstudytest.bean;
     
    import java.io.Serializable;
     
    /**
     * @author lzh
     * create 2019-09-18-22:32
     */
    public class User implements Serializable {
     
        private static final long serialVersionUID = 1L;
        private int uid;
        private String userName;
        private String passWord;
        private int salary;
        public int getUid() {
            return uid;
        }
        public void setUid(int uid) {
            this.uid = uid;
        }
        public String getUserName() {
            return userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
        }
        public String getPassWord() {
            return passWord;
        }
        public void setPassWord(String passWord) {
            this.passWord = passWord;
        }
        public int getSalary() {
            return salary;
        }
        public void setSalary(int salary) {
            this.salary = salary;
        }
        public User(int uid, String userName, String passWord, int salary) {
            super();
            this.uid = uid;
            this.userName = userName;
            this.passWord = passWord;
            this.salary = salary;
        }
        public User() {
            super();
        }
    } 

      这是controller类,用于暴露接口访问

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    package com.lzh.springbootstudytest.controller;
     
    import com.lzh.springbootstudytest.bean.User;
    import com.lzh.springbootstudytest.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
     
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
     
    /**
     * @author lzh
     * create 2019-09-18-22:36
     */
    @RestController
    public class TestController {
     
        @Autowired
        private UserService userService;
     
        @RequestMapping("/queryAll")
        public List<User> queryAll(){
            List<User> lists = userService.queryAll();
            return lists;
        }
     
        @RequestMapping("/findUserById")
        public Map<String, Object> findUserById(@RequestParam int id){
            User user = userService.findUserById(id);
            Map<String, Object> result = new HashMap<>();
            result.put("uid", user.getUid());
            result.put("uname", user.getUserName());
            result.put("pass", user.getPassWord());
            result.put("salary", user.getSalary());
            return result;
        }
     
        @RequestMapping("/updateUser")
        public String updateUser(){
            User user = new User();
            user.setUid(1);
            user.setUserName("cat");
            user.setPassWord("miaomiao");
            user.setSalary(4000);
     
            int result = userService.updateUser(user);
     
            if(result != 0){
                return "update user success";
            }
     
            return "fail";
        }
     
        @RequestMapping("/deleteUserById")
        public String deleteUserById(@RequestParam int id){
            int result = userService.deleteUserById(id);
            if(result != 0){
                return "delete success";
            }
            return "delete fail";
        }
    }

    配置redistemplate序列化 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    package com.lzh.springbootstudytest.config;
     
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.cache.CacheManager;
    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.cache.RedisCacheConfiguration;
    import org.springframework.data.redis.cache.RedisCacheManager;
    import org.springframework.data.redis.cache.RedisCacheWriter;
    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;
     
    import java.time.Duration;
     
    /**
     * @author lzh
     * create 2019-09-24-15:07
     */
    @Configuration
    @EnableCaching
    public class RedisConfig extends CachingConfigurerSupport {
     
        /**
         * 选择redis作为默认缓存工具
         * @param redisConnectionFactory
         * @return
         */
        /*@Bean
        //springboot 1.xx
        public CacheManager cacheManager(RedisTemplate redisTemplate) {
            RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
            return rcm;
        }*/
        @Bean
        public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
            RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时
            return RedisCacheManager
                    .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                    .cacheDefaults(redisCacheConfiguration).build();
        }
     
        /**
         * retemplate相关配置
         * @param factory
         * @return
         */
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
     
            RedisTemplate<String, Object> 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类型的数据操作
         *
         * @param redisTemplate
         * @return
         */
        @Bean
        public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
            return redisTemplate.opsForHash();
        }
     
        /**
         * 对redis字符串类型数据操作
         *
         * @param redisTemplate
         * @return
         */
        @Bean
        public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
            return redisTemplate.opsForValue();
        }
     
        /**
         * 对链表类型的数据操作
         *
         * @param redisTemplate
         * @return
         */
        @Bean
        public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
            return redisTemplate.opsForList();
        }
     
        /**
         * 对无序集合类型的数据操作
         *
         * @param redisTemplate
         * @return
         */
        @Bean
        public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
            return redisTemplate.opsForSet();
        }
     
        /**
         * 对有序集合类型的数据操作
         *
         * @param redisTemplate
         * @return
         */
        @Bean
        public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
            return redisTemplate.opsForZSet();
        }
    }

    接着是Mapper持久层Dao,这里主要用注解写比较方便,也可以使用mybatis的xml配置文件写sql语句

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package com.lzh.springbootstudytest.mapper;
     
    import com.lzh.springbootstudytest.bean.User;
    import org.apache.ibatis.annotations.*;
     
    import java.util.List;
     
    /**
     * @author lzh
     * create 2019-09-18-22:32
     */
    @Mapper
    public interface UserDao {
     
        @Select("select * from user")
        List<User> queryAll();
     
        @Select("select * from user where uid = #{id}")
        User findUserById(int id);
     
        @Update("UPDATE USER SET username = CASE WHEN (#{userName} != NULL) AND (#{userName} != '') THEN #{userName},PASSWORD = CASE WHEN (#{passWord} != NULL) AND (#{passWord} != '') THEN #{passWord},salary = CASE WHEN (#{salary} != 0) THEN #{salary} WHERE uid = #{uid}")
        int updateUser(@Param("user") User user);
     
        @Delete("delete from user where uid = #{id}")
        int deleteUserById(int id);
     
    }

     service层,这里主要是使用redis模板来写

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    package com.lzh.springbootstudytest.service;
     
    import com.lzh.springbootstudytest.bean.User;
    import com.lzh.springbootstudytest.mapper.UserDao;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    import org.springframework.stereotype.Service;
     
    import java.util.List;
    import java.util.concurrent.TimeUnit;
     
    /**
     * @author lzh
     * create 2019-09-18-22:33
     */
    @Service
    public class UserService {
     
        @Autowired
        private UserDao userDao;
     
        @Autowired
        private RedisTemplate redisTemplate;
     
        public List<User> queryAll() {
            return userDao.queryAll();
        }
     
        /**
         * 获取用户策略:先从缓存中获取用户,没有则取数据表中 数据,再将数据写入缓存
         */
        public User findUserById(int id) {
            String key = "user_" + id;
     
            ValueOperations<String, User> operations = redisTemplate.opsForValue();
     
            //判断redis中是否有键为key的缓存
            boolean hasKey = redisTemplate.hasKey(key);
     
            if (hasKey) {
                User user = operations.get(key);
                System.out.println("从缓存中获得数据:"+user.getUserName());
                System.out.println("------------------------------------");
                return user;
            } else {
                User user = userDao.findUserById(id);
                System.out.println("查询数据库获得数据:"+user.getUserName());
                System.out.println("------------------------------------");
     
                // 写入缓存
                operations.set(key, user, 5, TimeUnit.HOURS);
                return user;
            }
        }
     
        /**
         * 更新用户策略:先更新数据表,成功之后,删除原来的缓存,再更新缓存
         */
        public int updateUser(User user) {
            ValueOperations<String, User> operations = redisTemplate.opsForValue();
            int result = userDao.updateUser(user);
            if (result != 0) {
                String key = "user_" + user.getUid();
                boolean haskey = redisTemplate.hasKey(key);
                if (haskey) {
                    redisTemplate.delete(key);
                    System.out.println("删除缓存中的key-----------> " + key);
                }
                // 再将更新后的数据加入缓存
                User userNew = userDao.findUserById(user.getUid());
                if (userNew != null) {
                    operations.set(key, userNew, 3, TimeUnit.HOURS);
                }
            }
            return result;
        }
     
        /**
         * 删除用户策略:删除数据表中数据,然后删除缓存
         */
        public int deleteUserById(int id) {
            int result = userDao.deleteUserById(id);
            String key = "user_" + id;
            if (result != 0) {
                boolean hasKey = redisTemplate.hasKey(key);
                if (hasKey) {
                    redisTemplate.delete(key);
                    System.out.println("删除了缓存中的key:" + key);
                }
            }
            return result;
        }
     
    } 

      

      这里主要是使用RedisTemplate来对远程redis操作,每次访问controller暴露的接口,首先判断redis缓存中是否存在该数据,若不存在就从数据库中读取数据,然后保存到redis缓存中,当下次访问的时候,就直接从缓存中取出来。这样就不用每次都执行sql语句,能够提高访问速度。 但是在保存数据到缓存中,通过设置键和值和超时删除,注意设置超时删除缓存时间不要太长,否则会给服务器带来压力。

    执行spring boot的启动类,访问http://localhost:8081/findUserById?id=1

    再次访问http://localhost:8081/findUserById?id=1就是从缓存中获取保存的数据

  • 相关阅读:
    数学之美系列十八 矩阵运算和文本处理中的分类问题
    数学之美系列一 统计语言模型
    数学之美系列十三 信息指纹及其应用
    数学之美系列十六 谈谈最大熵模型
    数学之美系列十五 繁与简 自然语言处理的几位精英
    数学之美系列十七 谈谈搜索引擎作弊问题(Search Engine AntiSPAM)
    数学之美系列三 隐含马尔可夫模型在语言处理中的应用
    数学之美系列十四 谈谈数学模型的重要性
    数学之美系列十二 余弦定理和新闻的分类
    数学之美系列十一 Google 阿卡 47 的制造者阿米特.辛格博士
  • 原文地址:https://www.cnblogs.com/zzsuje/p/12887359.html
Copyright © 2011-2022 走看看