当前位置:   article > 正文

Spring Boot 集成 Cache缓存_cacheservice 使用

cacheservice 使用

一、Spring Boot 集成 Cache缓存

配置文件pom.xml:

        <!-- cache springboot缓存-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

配置文件application.properties:

##cache springboot缓存配置
#simple:使用springboot自带的缓存;适合单体应用或者开发环境使用
#none:关闭缓存
#redis:使用redis作为缓存
spring.cache.type=redis
#基于redis缓存的缓存过期时间为1分钟
spring.cache.redis.time-to-live=60000
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

二、Cache缓存在Spring Boot中的测试代码

CacheController文件代码如下:

package com.example.shopgoods.controller.cache;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @Author: zp
 * @Date: 2019/6/19 14:48
 * @Description:
 */
@RestController
@RequestMapping("/cache")
public class CacheController {


    @Autowired
    private CacheService cacheService;


    @PostMapping("/test_1")
    public String cacheTest1(@RequestParam(value = "id") int id){

        String str = cacheService.getCache(id);

        return str;
    }

    @PostMapping("/test_2")
    public String cacheTest2(@RequestParam(value = "id") int id){

        String str = cacheService.getCacheName(id);

        return str;
    }
}

  • 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

CacheService文件代码如下:

package com.example.shopgoods.controller.cache;

/**
 * @Author: zp
 * @Date: 2019/6/19 14:50
 * @Description:
 */
public interface CacheService {

    String getCache(int id);

    String getCacheName(int id);

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

CacheServiceImpl文件代码如下:

package com.example.shopgoods.controller.cache.Impl;

import com.example.shopgoods.controller.cache.CacheService;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * @Author: zp
 * @Date: 2019/6/19 14:50
 * @Description:
 */

@Service
//该注解作用于类上,为此类里的方法的缓存注解提供默认值
@CacheConfig(cacheNames = "cache")
public class CacheServiceImpl implements CacheService {

    @Override
    //id小于5的都需要缓存
    @Cacheable(cacheNames = "getCache", condition = "#id < 5")
    public String getCache(int id) {
        String str = "";
        if (id == 1) {
            str = "C_1 ---->" + id;
        } else if (id == 2) {
            str = "C_2 ---->" + id;
        } else {
            str = "cache ---->" + id;
        }
        return str;
    }

    @Override
    @Cacheable()
    public String getCacheName(int id) {
        return String.valueOf(id);
    }
}

  • 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

CacheConfig文件代码如下:(此配置介绍了实现Redis两级缓存的原理)

package com.example.shopgoods.controller.cache.config;

import java.io.UnsupportedEncodingException;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCache;
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.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair;

/**
 * 支持一二级缓存,使得性能到达极致,
 * @author xiandafu
 *
 */
//@Configuration
public class CacheConfig {
	// 定义一个redis 的频道,默认叫cache,用于pub/sub
	@Value("${springext.cache.redis.topic:cache}")
	String topicName;

	@Bean
	public TwoLevelCacheManager cacheManager(StringRedisTemplate redisTemplate) {

		//RedisCache需要一个RedisCacheWriter来实现读写Redis
		RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(redisTemplate.getConnectionFactory());
		/*SerializationPair用于Java和Redis之间的序列化和反序列化*/
		SerializationPair pair = SerializationPair.fromSerializer(new JdkSerializationRedisSerializer(this.getClass().getClassLoader()));
		/*构造一个RedisCache的配置。*/
		RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
		/*创建CacheManager,并返回给Spring容器*/
		TwoLevelCacheManager cacheManager = new TwoLevelCacheManager(redisTemplate,writer,config);
		return cacheManager;
	}

	// Redis message,参考Redis一章
	@Bean
	RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
			MessageListenerAdapter listenerAdapter) {

		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
		container.setConnectionFactory(connectionFactory);
		container.addMessageListener(listenerAdapter, new PatternTopic(topicName));
		return container;
	}

	@Bean
	MessageListenerAdapter listenerAdapter(final TwoLevelCacheManager cacheManager) {
		return new MessageListenerAdapter(new MessageListener() {

			public void onMessage(Message message, byte[] pattern) {
				byte[] bs = message.getChannel();
				
				try {
					// Sub 一个消息,通知缓存管理器
					String type = new String(bs, "UTF-8");
					String cacheName = new String(message.getBody(),"UTF-8");
					cacheManager.receiver(cacheName);
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
					// 不可能出错,忽略
				}

			}

		});
	}

	class TwoLevelCacheManager extends RedisCacheManager {
		RedisTemplate redisTemplate;
		public TwoLevelCacheManager(RedisTemplate redisTemplate,RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
			super(cacheWriter,defaultCacheConfiguration);
			this.redisTemplate = redisTemplate;
		}
		//使用RedisAndLocalCache代替Spring Boot自带的RedisCache
		@Override
		protected Cache decorateCache(Cache cache) {
			return new RedisAndLocalCache(this, (RedisCache) cache);
		}
		//通过其他分布式节点,缓存改变
		public void publishMessage(String cacheName) {
			this.redisTemplate.convertAndSend(topicName, cacheName);
		}
		// 接受一个消息清空本地缓存
		public void receiver(String name) {
			RedisAndLocalCache cache = ((RedisAndLocalCache) this.getCache(name));
			if(cache!=null){
				cache.clearLocal();
			}
		}

	}

	class RedisAndLocalCache implements Cache {
		// 本地缓存提供
		ConcurrentHashMap<Object, Object> local = new ConcurrentHashMap<Object, Object>();
		RedisCache redisCache;
		TwoLevelCacheManager cacheManager;

		public RedisAndLocalCache(TwoLevelCacheManager cacheManager, RedisCache redisCache) {
			this.redisCache = redisCache;
			this.cacheManager = cacheManager;
		}

		@Override
		public String getName() {
			return redisCache.getName();
		}

		@Override
		public Object getNativeCache() {
			return redisCache.getNativeCache();
		}

		@Override
		public ValueWrapper get(Object key) {
			//一级缓存先取
			ValueWrapper wrapper = (ValueWrapper) local.get(key);
			if (wrapper != null) {
				return wrapper;
			} else {
				// 二级缓存取
				wrapper = redisCache.get(key);
				if (wrapper != null) {
					local.put(key, wrapper);
				}
				
				return wrapper;
			}

		}

		@Override
		public <T> T get(Object key, Class<T> type) {

			return redisCache.get(key, type);
		}

		@Override
		public <T> T get(Object key, Callable<T> valueLoader) {
			return redisCache.get(key, valueLoader);
		}

		@Override
		public void put(Object key, Object value) {
			System.out.println(value.getClass().getClassLoader());
			redisCache.put(key, value);
			//通知其他节点缓存更更新
			clearOtherJVM();

		}

		@Override
		public ValueWrapper putIfAbsent(Object key, Object value) {
			ValueWrapper v = redisCache.putIfAbsent(key, value);
			clearOtherJVM();
			return v;

		}

		@Override
		public void evict(Object key) {
			redisCache.evict(key);
			//通知其他节点缓存更更新
			clearOtherJVM();

		}

		@Override
		public void clear() {
			redisCache.clear();

		}

		/**
		 * 提供给CacheManager清空一级缓存
		 */
		public void clearLocal() {
			this.local.clear();
		}

		/**
		 * 通知其他节点缓存更更新
		 */
		protected void clearOtherJVM() {
			cacheManager.publishMessage(redisCache.getName());
		}


	}
}

  • 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
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/929731
推荐阅读
相关标签
  

闽ICP备14008679号