Spring Boot 整合Redis缓存

目录

1|0准备工作

2|0修改redis,开启远程访问

3|0 Java代码编写

3|1 目录结构

3|2 代码


1|0准备工作

1.Linux系统

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

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

2|0修改redis,开启远程访问

 

找到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密码不要写空,否则报错)

3|0 Java代码编写

 

3|1 目录结构

 

项目源码结构

一个user表

 

 

3|2 代码

 

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-casetrue

 

    #另外一种打印语句的方式

    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就是从缓存中获取保存的数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值