安全电子商务网站设计,手机之家论坛官网,数字营销的定义是,注册公司流程需要多久文章目录一、本地缓存介绍二、缓存组件 Caffeine 介绍2.1. Caffeine 性能2.2. Caffeine 配置说明2.3. 软引用与弱引用三、SpringBoot 集成 Caffeine 方式一3.1. Maven 引入相关依赖3.2. 配置缓存配置类3.3. 定义实体对象3.4. 定义服务接口类3.5. 定义服务接口实现类3.6. Caffei…
文章目录一、本地缓存介绍二、缓存组件 Caffeine 介绍2.1. Caffeine 性能2.2. Caffeine 配置说明2.3. 软引用与弱引用三、SpringBoot 集成 Caffeine 方式一3.1. Maven 引入相关依赖3.2. 配置缓存配置类3.3. 定义实体对象3.4. 定义服务接口类3.5. 定义服务接口实现类3.6. Caffeine工具类3.7. 测试案例四、测试案例4.1. 添加用户4.2. 查询用户4.3. 更新用户4.4. 删除用户4.5. 效果图五、第二种整合方式5.1. 依赖5.2. 接口实现类替换一、本地缓存介绍
缓存在日常开发中启动至关重要的作用由于是存储在内存中数据的读取速度是非常快的能大量减少对数据库的访问减少数据库的压力。
之前介绍过 Redis 这种 NoSql 作为缓存组件它能够很好的作为分布式缓存组件提供多个服务间的缓存但是 Redis 这种还是需要网络开销增加时耗。本地缓存是直接从本地内存中读取没有网络开销例如秒杀系统或者数据量小的缓存等比远程缓存更合适。
二、缓存组件 Caffeine 介绍
按 Caffeine Github 文档描述Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x) 后spring 官方放弃了 Guava而使用了性能更优秀的 Caffeine 作为默认缓存组件。
2.1. Caffeine 性能
可以通过下图观测到在下面缓存组件中 Caffeine 性能是其中最好的。 2.2. Caffeine 配置说明 注意
weakValues 和 softValues 不可以同时使用。 maximumSize 和 maximumWeight 不可以同时使用。 expireAfterWrite 和 expireAfterAccess 同事存在时以 expireAfterWrite 为准。
2.3. 软引用与弱引用
软引用如果一个对象只具有软引用则内存空间足够垃圾回收器就不会回收它如果内存空间不足了就会回收这些对象的内存。
弱引用弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中一旦发现了只具有弱引用的对象不管当前内存空间足够与否都会回收它的内存.
// 软引用
Caffeine.newBuilder().softValues().build();// 弱引用
Caffeine.newBuilder().weakKeys().weakValues().build();三、SpringBoot 集成 Caffeine 方式一
3.1. Maven 引入相关依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--字符串工具类--dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-lang3/artifactIdversion3.12.0/version/dependencydependencygroupIdcom.github.ben-manes.caffeine/groupIdartifactIdcaffeine/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependency3.2. 配置缓存配置类
package com.gblfy.config;import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.TimeUnit;/*** 本地caffeine缓存配置** author gblfy* date 2022-03-15*/
Configuration
public class CaffeineCacheConfig {Beanpublic CacheString, Object caffeineCache() {return Caffeine.newBuilder()// 设置最后一次写入或访问后经过固定时间过期.expireAfterWrite(6000, TimeUnit.SECONDS)// 初始的缓存空间大小.initialCapacity(100)// 缓存的最大条数.maximumSize(1000).build();}
}
3.3. 定义实体对象
package com.gblfy;import lombok.Data;
import lombok.ToString;Data
ToString
public class UserInfo {private Integer id;private String name;private String sex;private Integer age;
}
3.4. 定义服务接口类
package com.gblfy.service;import com.gblfy.entity.UserInfo;/*** 用户模块接口** author gblfy* date 2022-03-15*/
public interface UserInfoService {/*** 增加用户信息** param userInfo 用户信息*/void addUserInfo(UserInfo userInfo);/*** 获取用户信息** param id 用户ID* return 用户信息*/UserInfo getByName(Integer id);/*** 修改用户信息** param userInfo 用户信息* return 用户信息*/UserInfo updateUserInfo(UserInfo userInfo);/*** 删除用户信息** param id 用户ID*/void deleteById(Integer id);}
3.5. 定义服务接口实现类
package com.gblfy.service.impl;import com.gblfy.entity.UserInfo;
import com.gblfy.service.UserInfoService;
import com.gblfy.uitls.CaffeineUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** 用户模块接口实现类** author gblfy* date 2022-03-15*/
Slf4j
Service
public class UserInfoServiceImpl implements UserInfoService {/*** 模拟数据库存储数据*/private MapInteger, UserInfo userInfoMap new ConcurrentHashMap();Autowiredprivate CaffeineUtils caffeineUtils;Overridepublic void addUserInfo(UserInfo userInfo) {log.info(create);userInfoMap.put(userInfo.getId(), userInfo);// 加入缓存caffeineUtils.putAndUpdateCache(String.valueOf(userInfo.getId()), userInfo);}Overridepublic UserInfo getByName(Integer userId) {// 先从缓存读取UserInfo userInfo caffeineUtils.getObjCacheByKey(String.valueOf(userId), UserInfo.class);if (userInfo ! null) {return userInfo;}// 如果缓存中不存在则从库中查找log.info(get);userInfo userInfoMap.get(userId);// 如果用户信息不为空则加入缓存if (userInfo ! null) {caffeineUtils.putAndUpdateCache(String.valueOf(userInfo.getId()), userInfo);}return userInfo;}Overridepublic UserInfo updateUserInfo(UserInfo userInfo) {log.info(update);if (!userInfoMap.containsKey(userInfo.getId())) {return null;}// 取旧的值UserInfo oldUserInfo userInfoMap.get(userInfo.getId());// 替换内容if (StringUtils.isNotBlank(oldUserInfo.getName())) {oldUserInfo.setName(userInfo.getName());}if (StringUtils.isNotBlank(oldUserInfo.getSex())) {oldUserInfo.setSex(userInfo.getSex());}oldUserInfo.setAge(userInfo.getAge());// 将新的对象存储更新旧对象信息userInfoMap.put(oldUserInfo.getId(), oldUserInfo);// 替换缓存中的值caffeineUtils.putAndUpdateCache(String.valueOf(oldUserInfo.getId()), oldUserInfo);return oldUserInfo;}Overridepublic void deleteById(Integer id) {log.info(delete);userInfoMap.remove(id);// 从缓存中删除caffeineUtils.removeCacheByKey(String.valueOf(id));}}
3.6. Caffeine工具类
package com.gblfy.uitls;import com.github.benmanes.caffeine.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** Caffeine缓存工具类** Author gblfy* Date 2022-03-15 14:58**/
Component
public class CaffeineUtils {AutowiredCacheString, Object caffeineCache;/*** 添加或更新缓存** param key* param value*/public void putAndUpdateCache(String key, Object value) {caffeineCache.put(key, value);}/*** 获取对象缓存** param key* return*/public T T getObjCacheByKey(String key, ClassT t) {caffeineCache.getIfPresent(key);return (T) caffeineCache.asMap().get(key);}/*** 根据key删除缓存** param key*/public void removeCacheByKey(String key) {// 从缓存中删除caffeineCache.asMap().remove(key);}
}
3.7. 测试案例
package com.gblfy;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** 用户模块入口** author gblfy* date 2022-03-15*/
RestController
RequestMapping
public class UserInfoController {Autowiredprivate UserInfoService userInfoService;GetMapping(/userInfo/{id})public Object getUserInfo(PathVariable Integer id) {UserInfo userInfo userInfoService.getByName(id);if (userInfo null) {return 没有该用户;}return userInfo;}PostMapping(/userInfo)public Object createUserInfo(RequestBody UserInfo userInfo) {userInfoService.addUserInfo(userInfo);return SUCCESS;}PutMapping(/userInfo)public Object updateUserInfo(RequestBody UserInfo userInfo) {UserInfo newUserInfo userInfoService.updateUserInfo(userInfo);if (newUserInfo null) {return 不存在该用户;}return newUserInfo;}DeleteMapping(/userInfo/{id})public Object deleteUserInfo(PathVariable Integer id) {userInfoService.deleteById(id);return SUCCESS;}}四、测试案例
4.1. 添加用户
请求方式POST
content-typeapplication/json
测试地址:localhost:8080/userInfo报文内容
{id:1,name:yx,sex:女,age:2
}4.2. 查询用户
请求方式GET
测试地址:localhost:8080/userInfo/14.3. 更新用户
请求方式PUT
content-typeapplication/json
测试地址:localhost:8080/userInfo报文内容
{id:1,name:gblfy,sex:男,age:22
}4.4. 删除用户
请求方式DELETE
测试地址:localhost:8080/userInfo/14.5. 效果图 五、第二种整合方式
5.1. 依赖
上面基础上添加 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-cache/artifactId/dependency5.2. 接口实现类替换
package com.gblfy;import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.HashMap;/*** 用户模块接口实现类** author gblfy* date 2022-03-15*/
Slf4j
Service
CacheConfig(cacheNames caffeineCacheManager)
public class UserInfoServiceImpl implements UserInfoService {/*** 模拟数据库存储数据*/private HashMapInteger, UserInfo userInfoMap new HashMap();OverrideCachePut(key #userInfo.id)public void addUserInfo(UserInfo userInfo) {log.info(create);userInfoMap.put(userInfo.getId(), userInfo);}OverrideCacheable(key #id)public UserInfo getByName(Integer id) {log.info(get);return userInfoMap.get(id);}OverrideCachePut(key #userInfo.id)public UserInfo updateUserInfo(UserInfo userInfo) {log.info(update);if (!userInfoMap.containsKey(userInfo.getId())) {return null;}// 取旧的值UserInfo oldUserInfo userInfoMap.get(userInfo.getId());// 替换内容if (!StringUtils.isEmpty(oldUserInfo.getAge())) {oldUserInfo.setAge(userInfo.getAge());}if (!StringUtils.isEmpty(oldUserInfo.getName())) {oldUserInfo.setName(userInfo.getName());}if (!StringUtils.isEmpty(oldUserInfo.getSex())) {oldUserInfo.setSex(userInfo.getSex());}// 将新的对象存储更新旧对象信息userInfoMap.put(oldUserInfo.getId(), oldUserInfo);// 返回新对象信息return oldUserInfo;}OverrideCacheEvict(key #id)public void deleteById(Integer id) {log.info(delete);userInfoMap.remove(id);}}