SpringBoot框架中使用Redis缓存

简介

为什么要使用缓存?

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

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

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

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

实例

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



	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.1.4.RELEASE
		 
	
	com.example
	demo
	0.0.1-SNAPSHOT
	demo
	Demo project for Spring Boot

	
		1.8
	

	
		
			org.springframework.boot
			spring-boot-starter-web
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
		
            redis.clients
            jedis
            2.9.0
        

         
		    junit
		    junit
		    4.12
		
		
		
		   org.springframework.boot
		   spring-boot-starter-thymeleaf
		
		
		
            org.springframework.boot
            spring-boot-starter-data-redis
        
 		
        
            org.springframework.boot
            spring-boot-starter-cache
        
        
        
			com.alibaba
			fastjson
			1.2.28
		
      
	

	
		 
	        
	            src/main/java
	            
	                **/*.*
	            
	        
	        
	            src/main/resources
	            
	                **/*.*
	            
	        
	    
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	


创建名为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 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 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 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 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 value) {
        boolean result = false;
        try {
            redisTemplate.opsForHash().putAll(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
 
    public Map hmget(String key) {
        Map 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 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 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第一次请求,缓存中没有数据所以返回从数据表中获得数据

SpringBoot框架中使用Redis缓存_第1张图片

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

SpringBoot框架中使用Redis缓存_第2张图片

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

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

SpringBoot框架中使用Redis缓存_第3张图片

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

你可能感兴趣的:(java,redis)