springboot2.1.0、Redis简单使用

一)背景

redis在springboot2.x中语法有一些变化,所以该章编写的时间花费的久一点,以此来记录。

二)在pom.xml文件中引入redis需要的jar



	4.0.0

	com.oysept.springboot
	oysept-springboot-redis
	0.0.1-SNAPSHOT
	jar

	oysept-springboot-redis

	
		org.springframework.boot
		spring-boot-starter-parent
		2.1.0.RELEASE
		
	

	
		UTF-8
		UTF-8
		1.8
	

	
		
			org.springframework.boot
			spring-boot-starter
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
		
			org.springframework.boot
			spring-boot-starter-web
		
		
		
		
    		org.springframework.boot
    		spring-boot-starter-data-redis
		
		
		
        
            org.springframework.session
            spring-session-data-redis
        

		
        
		    com.alibaba
		    fastjson
		    1.2.49
		
		
	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	


三)在application.properties中添加redis配置

server.port=8080

spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=60000

四)添加一个redis配置工具类

package com.oysept.springboot.conf;

import java.lang.reflect.Method;
import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
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.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * redis配置类
 * @author ouyangjun
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

	/**
	 * 自定义redis key生成规则
	 * 使用时,需要指定keyGenerator
	 */
	@Bean
	public KeyGenerator keyGenerator() {
		return new KeyGenerator() {

			@Override
			public Object generate(Object target, Method method, Object... params) {
				StringBuilder builder = new StringBuilder();
				builder.append(target.getClass().getName());
				builder.append(method.getName());
				for(Object obj : params) {
					// 由于参数可能不同, hashCode肯定不一样
					builder.append(JSON.toJSONString(obj).hashCode());
				}
				return builder.toString();
			}
			
		};
	}
	
	/**
	 * redis全局缓存配置
	 * 备注: 2.X的版本相对于1.X的版本有变化,在初始化RedisCacheManager不一样
	 * @param redisTemplate
	 * @return
	 */
	@Bean
	public CacheManager cacheManager(RedisConnectionFactory factory) {
		//默认配置
		/*
		RedisCacheManager redisCacheManager = RedisCacheManager.create(factory);
		return redisCacheManager;
		*/
		
		// 自定义配置
		/*
		RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
		// 设置过期时间,并不缓存空值,分钟
		config = config.entryTtl(Duration.ofMinutes(10)).disableCachingNullValues();
		
		// 设置一个初始化的缓存空间set集合
		Set cacheNames = new HashSet<>();
		cacheNames.add("redis-cache1");
		cacheNames.add("redis-cache2");
		// 对每个缓存空间应用不同的配置
		Map configMap = new HashMap<>();
		configMap.put("redis-cache1", config);
		configMap.put("redis-cache2", config.entryTtl(Duration.ofMinutes(60)).disableCachingNullValues());
		
		RedisCacheManager redisCacheManager = RedisCacheManager.builder(factory).initialCacheNames(cacheNames)
				.withInitialCacheConfigurations(configMap).build();
        return redisCacheManager;
        */
		
		// 自定义配置
		RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(factory);
		RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
		// 需要重新赋值,否则无效果
		// 设置过期时间,并不缓存空值,分钟。如果系统访问量非常大,建议单独做时间有效期控制,放置redis缓存雪崩
		config = config.entryTtl(Duration.ofMinutes(10)).disableCachingNullValues();
		
		RedisCacheManager redisCacheManager = new RedisCacheManager(redisCacheWriter, config);
        return redisCacheManager;
	}
	
	/**
	 * 自定义序列化方式
	 * @param factory
	 * @return
	 */
	@Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {

        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.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序列化
        redisTemplate.setValueSerializer(jacksonSeial);
        //使用StringRedisSerializer来序列化和反序列化redis的key值, 默认方式容易出现乱码
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        // 设置hash key 和value序列化模式
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jacksonSeial);
        redisTemplate.afterPropertiesSet();
        
        return redisTemplate;
    }
	
}

五)编写一个Controller测试类,方便通过浏览器和测试工具来测试

package com.oysept.springboot.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;

/**
 * redis web访问接口类
 * @author ouyangjun
 */
@RestController
@RequestMapping(value="/redis")
public class RedisController {

	// 自动redis缓存-----------------------------------------------------------------------------
	/**
	 * @Cacheable可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。
	 * value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。
	 * key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key。
	 * 请求地址: http://localhost:8080/redis/hello
	 * @return
	 */
	@RequestMapping(value="/hello")
	@Cacheable(value="hello-world", keyGenerator="keyGenerator")
	public @ResponseBody String helloWorld() {
		System.out.println("-------------------aaaa--------------------");
		return "Hello oysept springboot redis!";
	}
	
	/**
	 * @CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。
	 * value表示清除操作是发生在哪些Cache上的(对应Cache的名称)
	 * key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key
	 * allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。
	 * 请求地址: http://localhost:8080/redis/hello/clean
	 * @return
	 */
	@RequestMapping(value="/hello/clean")
	@CacheEvict(value = "hello-world", allEntries = true)
    public String cleanCache() {
        return "success";
    }
	
	// 手动redis缓存-----------------------------------------------------------------------------
	@Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    @Autowired
    private RedisTemplate redisTemplate;
    
    /**
     * 缓存字符串
     * 请求地址: http://localhost:8080/redis/hm/string
     * @return
     */
    @RequestMapping(value="hm/string")
    public @ResponseBody String hmString() {
    	// key
    	String key = "redisString";
    	// String缓存
    	stringRedisTemplate.opsForValue().set(key, "wwwwwwww");
    	// 生效时间,3分钟
    	stringRedisTemplate.expire(key, 3, TimeUnit.MINUTES);
    	
    	// 返回
    	return stringRedisTemplate.opsForValue().get(key);
    }
    
    /**
     * 缓存List
     * 请求地址: http://localhost:8080/redis/hm/list
     * @return
     */
    @RequestMapping(value="hm/list")
    public @ResponseBody String hmList() {
    	List> list = new ArrayList>();
    	
    	Map map1 = new HashMap();
    	map1.put("A", "1111");
    	map1.put("B", "2222");
    	map1.put("C", "3333");
    	list.add(map1);
    	
    	Map map2 = new HashMap();
    	map2.put("A", "444");
    	map2.put("B", "555");
    	map2.put("C", "666");
    	list.add(map2);
    	
    	Map map3 = new HashMap();
    	map3.put("A", "777");
    	map3.put("B", "888");
    	map3.put("C", "999");
    	list.add(map3);
    	
    	// key
    	String key = "redisList";
    	// List缓存
    	boolean bool = redisTemplate.hasKey(key);
    	if(!bool) {
    		redisTemplate.opsForList().leftPush(key, list);
    	} else {
    		// 如果key不存在,直接set会报错
    		redisTemplate.opsForList().set(key, 0, list);
    	}
    	// 生效时间,3分钟
    	stringRedisTemplate.expire(key, 3, TimeUnit.MINUTES);
    	
    	// 返回缓存的内容
    	return JSON.toJSONString(redisTemplate.opsForList().range(key, 0, -1));
    }
    
    /**
     * 缓存Hash
     * 请求地址: http://localhost:8080/redis/hm/hash
     * @return
     */
    @RequestMapping(value="hm/hash")
    public @ResponseBody String hmHash() {
    	// key
    	String key = "redisHash";
    	// Hash缓存
    	redisTemplate.opsForHash().put(key, "name", "ouyangjun");
    	redisTemplate.opsForHash().put(key, "age", 27);
    	redisTemplate.opsForHash().put(key, "phone", "13600425791");
    	// 生效时间,3分钟
    	stringRedisTemplate.expire(key, 3, TimeUnit.MINUTES);
    	
    	// 打印
    	Map map = redisTemplate.opsForHash().entries(key);
    	for(Object keyStr : map.keySet()) {
    		System.out.println("key: " + keyStr + ", value: " + map.get(keyStr));
    	}
    	// 返回缓存的内容
    	return JSON.toJSONString(map);
    }
}

六)编写一个main方法测试类

package com.oysept.springboot.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import com.oysept.springboot.controller.RedisController;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
	
	private MockMvc mvc;
	
	@Before
	public void setHelloWord() {
		mvc = MockMvcBuilders.standaloneSetup(new RedisController()).build();
	}

	@Test
	public void getHelloWord() {
		RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/redis/hello").accept(MediaType.APPLICATION_JSON);
		try {
            MvcResult result = mvc.perform(requestBuilder).andReturn();
            MockHttpServletResponse response = result.getResponse();
            System.out.println("返回值: "+response.getContentAsString());
        } catch (Exception e){
            System.out.println(e.fillInStackTrace());
        }
	}

}

七)添加springboot启动类,并展示项目结构图

package com.oysept.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * springboot启动类
 * @author ouyangjun
 */
@SpringBootApplication
public class RedisApplication {

	public static void main(String[] args) {
		SpringApplication.run(RedisApplication.class, args);
	}
}

springboot2.1.0、Redis简单使用_第1张图片

最后启动RedisApplication类,可用main方法测试类测试,也可以用浏览器和测试工具测试。

本章完结,待续!
 
本文说明:该文章属于原创,如需转载,请标明文章转载来源

你可能感兴趣的:(springboot)