中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

SpringBoot | 第十一章:Redis 的集成和簡(jiǎn)單使用

2018-08-25    來(lái)源:importnew

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

前言

上幾節(jié)講了利用Mybatis-Plus這個(gè)第三方的ORM框架進(jìn)行數(shù)據(jù)庫(kù)訪問(wèn),在實(shí)際工作中,在存儲(chǔ)一些非結(jié)構(gòu)化或者緩存一些臨時(shí)數(shù)據(jù)及熱點(diǎn)數(shù)據(jù)時(shí),一般上都會(huì)用上mongodbredis進(jìn)行這方面的需求。所以這一章節(jié)準(zhǔn)備講下緩存數(shù)據(jù)庫(kù)Redis的集成,同時(shí)會(huì)介紹下基于Redis和注解驅(qū)動(dòng)的Spring Cache的簡(jiǎn)單使用。

Redis 介紹

大家應(yīng)該對(duì)Redis應(yīng)該比較熟悉了。這幾年也是大行其道的緩存數(shù)據(jù)庫(kù),目前的memcached由于使用場(chǎng)景及其存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)的單一(不知道現(xiàn)在是否有改善,現(xiàn)在基本沒(méi)有接觸了),在工作中也使用的少了。引用官網(wǎng)的簡(jiǎn)介,Redis是一個(gè)開(kāi)源的使用ANSI C語(yǔ)言編寫(xiě)、遵守BSD協(xié)議、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫(kù),并提供多種語(yǔ)言的API。

推薦redis中國(guó)社區(qū):http://www.redis.cn/

SpringBoot的Redis集成

0.本章節(jié)以上一章節(jié)的示例基礎(chǔ)上進(jìn)行集成。所以大家可下載第十章節(jié)示例或者在章節(jié)末尾直接下載本章節(jié)示例。

1.pom依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

直接引入,相關(guān)依賴會(huì)自動(dòng)加載的,這就是springboot讓人愉悅之處呀。

2.application.properties配置加入redis相關(guān)配置

配置自動(dòng)加載類為:org.springframework.boot.autoconfigure.data.redis.RedisProperties,可在屬性文件中點(diǎn)擊某屬性快捷跳轉(zhuǎn)。注意到其啟動(dòng)類為org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration。這里就不介紹了,后面會(huì)寫(xiě)一篇關(guān)于Springboot自動(dòng)加載配置的文章。

 

# REDIS (RedisProperties)
# Redis數(shù)據(jù)庫(kù)索引(默認(rèn)為0)
spring.redis.database=0
# Redis服務(wù)器地址
spring.redis.host=127.0.0.1
# Redis服務(wù)器連接端口
spring.redis.port=6379  
# Redis服務(wù)器連接密碼(默認(rèn)為空)
spring.redis.password=
# 連接池最大連接數(shù)(使用負(fù)值表示沒(méi)有限制)
spring.redis.pool.max-active=8  
# 連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制)
spring.redis.pool.max-wait=-1  
# 連接池中的最大空閑連接
spring.redis.pool.max-idle=8  
# 連接池中的最小空閑連接
spring.redis.pool.min-idle=0  
# 連接超時(shí)時(shí)間(毫秒)
spring.redis.timeout=0

3.一般上通過(guò)以上兩步就可使用了,但工作中一般上是通過(guò)StringRedisTemplate(默認(rèn)采用string的序列化,保存key和值時(shí)都是通過(guò)此序列化策略)接口進(jìn)行操作,所以這里直接配置了StringRedisTemplatebean類。
RedisConfig.java

/**
 * 
 * @author oKong
 *
 */
@Configuration
public class RedisConfig {
    
    /**
     *  定義 StringRedisTemplate ,指定序列化和反序列化的處理類
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(
                Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        //序列化 值時(shí)使用此序列化方法
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

4.編寫(xiě)控制類,測(cè)試集成是否生效。
RedisController.java

@RestController
@RequestMapping("/redis")
@Api(tags = "redis 測(cè)試API")
public class RedisController {

	@Autowired
	StringRedisTemplate redisTemplate;
	
	@GetMapping("set/{key}/{value}")
	@ApiOperation(value="設(shè)置緩存")
	public String set(@PathVariable("key")String key,@PathVariable("value") String value) {
		//注意這里的 key不能為null spring 內(nèi)部有檢驗(yàn)
		redisTemplate.opsForValue().set(key, value);
		return key + "," + value;
	}
	
	@GetMapping("get/{key}")
	@ApiOperation(value="根據(jù)key獲取緩存")
	public String get(@PathVariable("key") String key) {
		
		return "key=" + key + ",value=" + redisTemplate.opsForValue().get(key);
	}
}

5.訪問(wèn):http://127.0.0.1:8080/swagger-ui.html。?也可直接瀏覽器輸入:

set值
set值set值

get值
get值get值

瀏覽器訪問(wèn)

查看redis記錄:

redis記錄redis記錄

至此,redis就集成好了。實(shí)際中可根據(jù)業(yè)務(wù)需要進(jìn)行相關(guān)操作,比如緩存session記錄,緩存菜單列表等。

Spring Cache 和 redis 使用。

Spring CacheSpring框架提供的對(duì)緩存使用的抽象類,支持多種緩存,比如Redis、EHCache等,集成很方便。同時(shí)提供了多種注解來(lái)簡(jiǎn)化緩存的使用,可對(duì)方法進(jìn)行緩存。

0.修改RedisConfig配置類,加入注解@EnableCaching,同時(shí)設(shè)置CacheManager緩存管理類,這里使用RedisCacheManager,其他的管理類還有:SimpleCacheManager、ConcurrentMapCacheManager等,默認(rèn)提供的在類org.springframework.cache.support下,可自行查閱。

/**
 * 
 * @author oKong
 *
 */
@Configuration
@EnableCaching
public class RedisConfig {
    
    /**
     *  定義 StringRedisTemplate ,指定序列號(hào)和反序列化的處理類
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(
                Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        //序列化 值時(shí)使用此序列化方法
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
    
    @Bean
    public CacheManager cacheManager(RedisTemplate<String,String> redisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
        //使用前綴
        rcm.setUsePrefix(true);
        //緩存分割符 默認(rèn)為 ":"
//        rcm.setCachePrefix(new DefaultRedisCachePrefix(":"));
        //設(shè)置緩存過(guò)期時(shí)間
        //rcm.setDefaultExpiration(60);//秒
        return rcm;
    }
}

1.改造UserController控制層,引入@Cacheable等注解。

/**
 * 用戶控制層 簡(jiǎn)單演示增刪改查及分頁(yè)
 * 新增了swagger文檔內(nèi)容 2018-07-21
 * 新增了@caching使用 2018-07-23
 * @author oKong
 *
 */
@RestController
@RequestMapping("/user")
@Api(tags="用戶API")
public class UserController {

    @Autowired
    IUserService userService;
    
    @PostMapping("add")
    @ApiOperation(value="用戶新增")
    //正常業(yè)務(wù)時(shí), 需要在user類里面進(jìn)行事務(wù)控制,控制層一般不進(jìn)行業(yè)務(wù)控制的。
    //@Transactional(rollbackFor = Exception.class)
    public Map<String,String> addUser(@Valid @RequestBody UserReq userReq){
        
        User user = new User();
        user.setCode(userReq.getCode());
        user.setName(userReq.getName());
        //由于設(shè)置了主鍵策略 id可不用賦值 會(huì)自動(dòng)生成
        //user.setId(0L);
        userService.insert(user);
        Map<String,String> result = new HashMap<String,String>();
        result.put("respCode", "01");
        result.put("respMsg", "新增成功");
        //事務(wù)測(cè)試
        //System.out.println(1/0);
        return result;
    }
    
    @PostMapping("update")
    @ApiOperation(value="用戶修改")    
    //更新時(shí) 直接刪除緩存 以保證下次獲取時(shí)先從數(shù)據(jù)庫(kù)中獲取最新數(shù)據(jù)
    @CacheEvict(value="OKONG", key="#userReq.id")
    public Map<String,String> updateUser(@Valid @RequestBody UserReq userReq){
        
        if(userReq.getId() == null || "".equals(userReq.getId())) {
            throw new CommonException("0000", "更新時(shí)ID不能為空");
        }
        User user = new User();
        user.setCode(userReq.getCode());
        user.setName(userReq.getName());
        user.setId(Long.parseLong(userReq.getId()));        
        userService.updateById(user);
        Map<String,String> result = new HashMap<String,String>();
        result.put("respCode", "01");
        result.put("respMsg", "更新成功");
        return result;
    }
    
    @GetMapping("/get/{id}")
    @ApiOperation(value="用戶查詢(ID)")    
    @ApiImplicitParam(name="id",value="查詢ID",required=true)
    @Cacheable(value="OKONG",key="#id")
    public Map<String,Object> getUser(@PathVariable("id") String id){
        //查詢
        User user = userService.selectById(id);
        if(user == null) {
            throw new CommonException("0001", "用戶ID:" + id + ",未找到");
        }
        UserResp resp = UserResp.builder()
                .id(user.getId().toString())
                .code(user.getCode())
                .name(user.getName())
                .status(user.getStatus())
                .build();
        Map<String,Object> result = new HashMap<String,Object>();
        result.put("respCode", "01");
        result.put("respMsg", "成功");
        result.put("data", resp);
        return result;
    }
    
    @GetMapping("/page")
    @ApiOperation(value="用戶查詢(分頁(yè))")        
    public Map<String,Object> pageUser(int current, int size){
        //分頁(yè)
        Page<User> page = new Page<>(current, size);
        Map<String,Object> result = new HashMap<String,Object>();
        result.put("respCode", "01");
        result.put("respMsg", "成功");
        result.put("data", userService.selectPage(page));
        return result;
    }
        
}

2.利用Swagger控制頁(yè)面,新增一個(gè)用戶,然后獲取用戶,會(huì)發(fā)現(xiàn)緩存里已經(jīng)有此id的用戶數(shù)據(jù)了。

第一次獲取第一次獲取

redis查看:
redisredis

再次獲取,會(huì)發(fā)現(xiàn)這次沒(méi)有直接訪問(wèn)數(shù)據(jù)庫(kù)了,而是直接從緩存讀取。大家可在觀察下控制臺(tái)的輸出情況(可先清空控制臺(tái),然后在請(qǐng)求)。

控制臺(tái)控制臺(tái)

此時(shí)控制臺(tái)無(wú)任何輸出,但前端已經(jīng)獲取到值了。

關(guān)于SpringCache 注解的簡(jiǎn)單介紹

  • @Cacheable:標(biāo)記在一個(gè)方法上,也可以標(biāo)記在一個(gè)類上。主要是緩存標(biāo)注對(duì)象的返回結(jié)果,標(biāo)注在方法上緩存該方法的返回值,標(biāo)注在類上,緩存該類所有的方法返回值。
    參數(shù): value緩存名、 key緩存鍵值、 condition滿足緩存條件、unless否決緩存條件

  • @CacheEvict:從緩存中移除相應(yīng)數(shù)據(jù)。

  • @CachePut:方法支持緩存功能。與@Cacheable不同的是使用@CachePut標(biāo)注的方法在執(zhí)行前不會(huì)去檢查緩存中是否存在之前執(zhí)行過(guò)的結(jié)果,而是每次都會(huì)執(zhí)行該方法,并將執(zhí)行結(jié)果以鍵值對(duì)的形式存入指定的緩存中。

  • @Caching:多個(gè)Cache注解使用,比如新增用戶時(shí),刪除用戶屬性等需要?jiǎng)h除或者更新多個(gè)緩存時(shí),集合以上三個(gè)注解。

常用的就以上幾個(gè),對(duì)于@CacheConfig沒(méi)使用過(guò),這里就不說(shuō)明了。

對(duì)于對(duì)幾個(gè)注解類的簡(jiǎn)單使用就結(jié)束了,相關(guān)的詳細(xì)用法,比如自定義條件緩存,自定義注解等,這里就不闡述了,請(qǐng)讀者自行

SpEL上下文數(shù)據(jù)

Spring Cache提供了一些供我們使用的SpEL上下文數(shù)據(jù),下表直接摘自互聯(lián)網(wǎng)

名稱 位置 描述 示例
methodName root對(duì)象 當(dāng)前被調(diào)用的方法名 root.methodName
method root對(duì)象 當(dāng)前被調(diào)用的方法 root.method.name
target root對(duì)象 當(dāng)前被調(diào)用的目標(biāo)對(duì)象 root.target
targetClass root對(duì)象 當(dāng)前被調(diào)用的目標(biāo)對(duì)象類 root.targetClass
args root對(duì)象 當(dāng)前被調(diào)用的方法的參數(shù)列表 root.args[0]
caches root對(duì)象 當(dāng)前方法調(diào)用使用的緩存列表(如@Cacheable(value={“cache1”, “cache2”})),則有兩個(gè)cache root.caches[0].name
argument name 執(zhí)行上下文 當(dāng)前被調(diào)用的方法的參數(shù),如findById(Long id),我們可以通過(guò)#id拿到參數(shù) user.id
result 執(zhí)行上下文 方法執(zhí)行后的返回值(僅當(dāng)方法執(zhí)行之后的判斷有效,如‘unless’,’cache evict’的beforeInvocation=false) result
@CacheEvict(value = "user", key = "#user.id", condition = "#root.target.canCache() and #root.caches[0].get(#user.id).get().username ne #user.username", beforeInvocation = true) public  void  conditionUpdate(User user)

總結(jié)

本章節(jié)主要是對(duì)redis結(jié)合Spring Cache的集成和簡(jiǎn)單使用進(jìn)行了說(shuō)明,詳細(xì)的用法,可自行搜索相關(guān)資料下,這里就不闡述了。因?yàn)閷?duì)于百分之八十之上的緩存要求基本能滿足了。使用緩存時(shí),一定要注意緩存生命周期的控制,不然容易出現(xiàn)數(shù)據(jù)不一致的情況,謹(jǐn)記!

最后

目前互聯(lián)網(wǎng)上很多大佬都有SpringBoot系列教程,如有雷同,請(qǐng)多多包涵了。本文是作者在電腦前一字一句敲的,每一步都是實(shí)踐的。若文中有所錯(cuò)誤之處,還望提出,謝謝。

標(biāo)簽: isp 服務(wù)器 服務(wù)器地址 互聯(lián)網(wǎng) 數(shù)據(jù)庫(kù) 搜索 網(wǎng)絡(luò)

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:SpringBoot | 第十二章:RabbitMQ 的集成和使用

下一篇:SpringBoot | 第十四章:基于Docker的簡(jiǎn)單部署