SpringBoot框架中使用Redis缓存

8 篇文章 0 订阅

简介

为什么要使用缓存?

一般我们的网站开发完成,上线之后,服务器的读写效率是网站运行速度的重要条件,当然还有服务器的带宽等,但是这些东西都可以通过硬件的更新升级来解决。其实与网站运行效率息息相关的东西,就是我们的------数据库。数据库处理数据的速度,与网站速度息息相关,而数据查询、数据处理等等,都和数据库处理速度有关。提高数据库的处理数据的能力,其中一个方案就是sql语句的优化技术,sql语句写的处理效率比较高,数据库处理能力就会上去,而网站的数据处理能力也会快些。

但是,当网站的处理和访问量非常大的时候,我们的数据库的压力就变大了,数据库的连接池,数据库同时处理数据的能力就会受到很大的挑战,一旦数据库承受了其最大承受能力,网站的数据处理效率就会大打折扣。此时就要使用高并发处理、负载均衡和分布式数据库,而这些技术既花费人力,又花费资金。如果我们的网站不是非常大的网站,而有想要提高网站的效率,降低数据库的读写次数,我们就需要引入缓存技术。

缓存的作用是什么?
缓存就是在内存中存储的数据备份,当数据没有发生本质改变的时候,我们就不让数据的查询去数据库进行操作,而去内存中取数据,这样就大大降低了数据库的读写次数,而且从内存中读数据的速度比去数据库查询要快一些,这样同时又提高了效率。
 

Redis介绍
我们要学习的一个缓存技术就是----Redis是Remote Dictionary Server(远程数据服务)的缩写,由意大利人antirez(Salvatore Sanfilippo)开发的一款内存高速缓存数据库,该软件使用C语言编写,它的数据模型为key-value。它支持丰富的数据结构(类型),比如String/List/Hash/Set/Sorted Set。可持久化(一边运行,一边把数据往硬盘中备份一份,防止断电等情况导致数据丢失,等断电情况恢复之后,Redis再把硬盘中的数据恢复到内存中),保证了数据的安全。

实例

首先在maven项目中的pom.xml文件中引入依赖

<?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>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		
		<dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>

         <dependency>
		    <groupId>junit</groupId>
		    <artifactId>junit</artifactId>
		    <version>4.12</version>
		</dependency>
		
		<dependency>
		   <groupId>org.springframework.boot</groupId>
		   <artifactId>spring-boot-starter-thymeleaf</artifactId>
		</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>
        
        <dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.28</version>
		</dependency>
      
	</dependencies>

	<build>
		 <resources>
	        <resource>
	            <directory>src/main/java</directory>
	            <includes>
	                <include>**/*.*</include>
	            </includes>
	        </resource>
	        <resource>
	            <directory>src/main/resources</directory>
	            <includes>
	                <include>**/*.*</include>
	            </includes>
	        </resource>
	    </resources>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

创建名为RedisCacheConfig的类,做为Redis的配置类。

package com.example.demo.util;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
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.StringRedisSerializer;

import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;

import redis.clients.jedis.JedisPoolConfig;

@Configuration
@EnableAutoConfiguration
public class RedisCacheConfig extends CachingConfigurerSupport {

   /* @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.database}")
    private int database;

    @Value("${spring.redis.password}")
    private String password;*/


    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration redisStandaloneConfiguration =
                new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName("192.168.30.15");
        redisStandaloneConfiguration.setDatabase(0);
        //redisStandaloneConfiguration.setPassword(RedisPassword.of("123456"));
        redisStandaloneConfiguration.setPort(6379);
        return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

    @Bean
    public StringRedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        return new StringRedisTemplate(redisConnectionFactory);
    }

    /**
     * 连接池配置信息
     * @return
     */
    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //最大连接数
        jedisPoolConfig.setMaxTotal(100);
        //最小空闲连接数
        jedisPoolConfig.setMinIdle(20);
        //当池内没有可用的连接时,最大等待时间
        jedisPoolConfig.setMaxWaitMillis(10000);
        //------其他属性根据需要自行添加-------------
        return jedisPoolConfig;
    }
    
    /**
     * jedis连接工厂
     * @param jedisPoolConfig
     * @return
     */
    @Bean
    public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
        //单机版jedis
        RedisStandaloneConfiguration redisStandaloneConfiguration =
                new RedisStandaloneConfiguration();
        //设置redis服务器的host或者ip地址
        redisStandaloneConfiguration.setHostName("192.168.30.15");
        //设置默认使用的数据库
        redisStandaloneConfiguration.setDatabase(0);
        //设置密码
        //redisStandaloneConfiguration.setPassword(RedisPassword.of("123456"));
        //设置redis的服务的端口号
        redisStandaloneConfiguration.setPort(6379);
        //获得默认的连接池构造器(怎么设计的,为什么不抽象出单独类,供用户使用呢)
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb =
                (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder)JedisClientConfiguration.builder();
        //指定jedisPoolConifig来修改默认的连接池构造器(真麻烦,滥用设计模式!)
        jpcb.poolConfig(jedisPoolConfig);
        //通过构造器来构造jedis客户端配置
        JedisClientConfiguration jedisClientConfiguration = jpcb.build();
        //单机配置 + 客户端配置 = jedis连接工厂
        return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
    }
    
}

创建Redis工具类RedisUtil

 
package com.example.demo.util;
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.Car;




 
/**
 * 
 * @Description: spring boot 的redis工具类
 */
@SuppressWarnings("unchecked")
@Component
public class RedisUtil {
    @SuppressWarnings("rawtypes")
    @Autowired
    private RedisTemplate redisTemplate;
 
    /**
     * 批量删除对应的value
     * 
     * @param keys
     */
    public void remove(final String... keys) {
        for (String key : keys) {
            remove(key);
        }
    }
 
    /**
     * 批量删除key
     * 
     * @param pattern
     */
    public void removePattern(final String pattern) {
        Set<Serializable> keys = redisTemplate.keys(pattern);
        if (keys.size() > 0)
            redisTemplate.delete(keys);
    }
 
    /**
     * 删除对应的value
     * 
     * @param key
     */
    public void remove(final String key) {
        if (exists(key)) {
            redisTemplate.delete(key);
        }
    }
 
    /**
     * 判断缓存中是否有对应的value
     * 
     * @param key
     * @return
     */
    public boolean exists(final String key) {
        return redisTemplate.hasKey(key);
    }
 
    /**
     * 读取缓存
     * 
     * @param key
     * @return
     */
    public String get(final String key) {
        Object result = null;
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        result = operations.get(key);
        if (result == null) {
            return null;
        }
        return result.toString();
    }
 
    /**
     * 写入缓存
     * 
     * @param key
     * @param value
     * @return
     */
    public boolean set(final String key, Object value) {
        boolean result = false;
        try {
        	
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
 
    /**
     * 写入缓存
     * 
     * @param key
     * @param value
     * @return
     */
    public boolean set(final String key, Object value, Long expireTime) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
 
    public boolean hmset(String key, Map<String, String> value) {
        boolean result = false;
        try {
            redisTemplate.opsForHash().putAll(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
 
    public Map<String, String> hmget(String key) {
        Map<String, String> result = null;
        try {
            result = redisTemplate.opsForHash().entries(key);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    
}
 

创建实体类Car

package com.example.demo.entity;

public class Car {

	private Integer id;
	private String name;
	private String vin;
	private String platenumber;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getVin() {
		return vin;
	}
	public void setVin(String vin) {
		this.vin = vin;
	}
	public String getPlatenumber() {
		return platenumber;
	}
	public void setPlatenumber(String platenumber) {
		this.platenumber = platenumber;
	}
	
	
}

创建CarController类

package com.example.demo.controller;

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 com.example.demo.entity.Car;
import com.example.demo.service.CarService;

@Controller
@RequestMapping("/car")
public class CarController {

	@Autowired
    private CarService carService;

    @ResponseBody
    @RequestMapping("/findById")
    public Car findCarById(@RequestParam int id){
        Car car = carService.findById(id);
        return car;
    }

    @ResponseBody
    @RequestMapping("/updateCar")
    public String updateCar(@RequestParam int id){
        Car car = new Car();
        car.setId(id);
        car.setName("奥迪");
        car.setPlatenumber("W2K3111");
        car.setVin("120056");
        int result = carService.updateCar(car);
        if(result == 1){
            return "update car success";
        }
        return "update car error";
    }

    @ResponseBody
    @RequestMapping("/deleteById")
    public String deleteCarById(@RequestParam int id){
        int result = carService.deleteById(id);
        if(result == 1){
            return "delete car success";
        }
        return "delete car error";
    }

}

创建接口CarService

package com.example.demo.service;

import com.example.demo.entity.Car;

public interface CarService {

	Car findById(int id);

	int updateCar(Car car);

	int deleteById(int id);

}

创建实现类

package com.example.demo.service.impl;

import java.util.List;
import java.util.concurrent.TimeUnit;

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 com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.entity.Car;
import com.example.demo.service.CarService;
import com.example.demo.util.RedisUtil;
@Service
public class CarServiceImpl implements CarService{

	  @Autowired
	  private RedisTemplate redisTemplate;
	  @Autowired
	  private RedisUtil redisUtil;
	  
	  /**
	    * 先从缓存中获取车辆信息,没有则取数据表中的数据,然后再将数据写入缓存中
	    */
	  public Car findById(int id) {
	        String key = "car_" + id;

	       // ValueOperations<String, Car> operations = redisTemplate.opsForValue();

	        boolean hasKey = redisUtil.exists(key);
	        if (hasKey) {
	        	String carStr = redisUtil.get(key);
	        	JSONObject jsonObject=JSONObject.parseObject(carStr);
	            Car car=jsonObject.toJavaObject(Car.class);
	            System.out.println("==========从缓存中获得数据=========");
	            System.out.println(car.getId());
	            System.out.println(car.getName());
	            System.out.println(car.getPlatenumber());
	            System.out.println(car.getVin());
	            return car;
	        } else {
	            System.out.println("==========从数据表中获得数据=========");
	            //模拟数据库数据
	            Car car = new Car();
	            car.setId(1);
	            car.setName("大众");
	            car.setPlatenumber("W2YHF10");
	            car.setVin("120051");
	            // 写入缓存
	            redisUtil.set(key, JSON.toJSONString(car));
	            return car;
	        }
	}

    /**
     * 先更新数据表,成功之后,删除原来的缓存,再更新缓存
     */
    @Override
    public int updateCar(Car car) {
        try {
        	ValueOperations<String, Car> operations = redisTemplate.opsForValue();
 	        System.out.println("==========数据库中更新车辆信息=========");
 	        String key = "car_" + car.getId();
 	        boolean haskey = redisUtil.exists(key);
            if (haskey) {
            	redisUtil.remove(key);
                System.out.println("删除缓存中的key=========>" + key);
            }
 	        // 再将更新后的数据加入缓存
            redisUtil.set(key,  JSON.toJSONString(car));
            return 1;
    	}catch (Exception e) {
    		return 0;
		}
    }

    /**
     * 删除用户策略:删除数据表中数据,然后删除缓存
     */
    @Override
    public int deleteById(int id) {
    	try {
    		System.out.println("==========数据库中删除车辆信息=========");
	        String key = "car_" + id;
	     
	        boolean haskey = redisUtil.exists(key);
            if (haskey) {
            	redisUtil.remove(key);
                System.out.println("删除了缓存中的key:" + key);
            }
            return 1;
    	}catch (Exception e) {
    		return 0;
		}
    }

}

启动SpringBoot项目,用Postman测试

发起http://localhost:8080/car/findById?id=1第一次请求,缓存中没有数据所以返回从数据表中获得数据

再次发起http://localhost:8080/car/findById?id=1请求,返回从”缓存中获得数据“

发起http://localhost:8080/car/updateCar?id=1更新请求,更新成功后,

再次发起http://localhost:8080/car/findById?id=1请求,从缓存中获得更新后的数据

发起http://localhost:8080/car/deleteById?id=1删除请求后,在redis数据库中删除该数据

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
很高兴为您解答问题。但是,需要说明的是,关于Spring Boot和Redis使用,需要具体的场景和需求,才能给出更加准确的答案。我可以为您提供一些参考资料和建议,供您参考: 首先,Spring Boot已经内置了对Redis的支持,它通过Spring Data Redis框架Redis进行封装,提供了一系列的API来操作Redis的数据。您可以通过在pom.xml文件添加依赖,来引入Spring Data Redis: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 接下来,在application.properties或application.yml配置Redis的连接信息。例如: ``` spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= spring.redis.database=0 ``` 配置完成后,您就可以在代码使用Redis了。例如: ``` @Autowired private RedisTemplate<String, Object> redisTemplate; ``` 上面的代码,首先通过@Autowired注解注入了一个RedisTemplate来操作Redis。然后,您可以使用RedisTemplate提供的方法来对Redis进行读写操作,例如: ``` redisTemplate.opsForValue().set("key", "value"); String value = (String) redisTemplate.opsForValue().get("key"); ``` 上面的代码,首先使用opsForValue方法获取一个ValueOperations对象,然后通过set方法将键值对写入Redis。接着,通过get方法获取Redis的值。 当然,在实际的应用场景,您可能需要根据具体的需求来对Redis进行更加复杂的读写操作。例如,您可以使用Redis的hash数据结构来存储对象,使用Redis的list数据结构来实现消息队列等等。对于这些更加复杂的操作,可以参考Spring Data Redis官方文档或者其他相关的参考资料。 希望上面的回答能够为您提供一些帮助,如果您还有其他问题,欢迎继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值