徽章获取接口开发
在用户的个人页面,我们需要显示所有徽章 ,并区分哪些已经获得,哪些还没获得(已获得的显示亮色,未获得的显示灰色)。为此,我们需要开发一个获取徽章的接口 ,整个流程可以拆分为 两步:
1. 获取所有徽章列表
首先,我们要从数据库中查出所有的徽章,因为徽章是固定的,不会变 ,所以我们可以缓存它,减少数据库查询的次数,提高性能。
java
@Cacheable(value = "badges", key = "'all'")
public List<Badge> getAllBadges() {
return badgeMapper.selectList(null); // 查询所有徽章
}
⚡ 这里用了
@Cacheable
,表示把徽章列表缓存起来,避免每次都查数据库,提高访问速度!
2. 判断用户拥有的徽章
获取所有徽章后,我们还要检查当前用户拥有的徽章,并调整它们的显示状态。
java
public List<UserBadgeVO> getUserBadges(Long userId) {
List<Badge> allBadges = getAllBadges(); // 获取所有徽章
List<Long> userBadgeIds = userBadgeMapper.getUserBadgeIds(userId); // 查询用户已获得的徽章ID
return allBadges.stream()
.map(badge -> new UserBadgeVO(badge, userBadgeIds.contains(badge.getId())))
.sorted(Comparator.comparing(UserBadgeVO::isOwned).reversed()) // 已获得的排前面
.collect(Collectors.toList());
}
✅ 这里的关键点:
先查出所有徽章
查出用户拥有的徽章ID列表
对比徽章ID ,已获得的标记为
亮色
,未获得的标记为灰色
排序:已获得的放前面,未获得的放后面
最终接口
@GetMapping("/user/badges")
public List<UserBadgeVO> getUserBadges(@RequestParam Long userId) {
return badgeService.getUserBadges(userId);
}
这样做的好处
✅ 查询徽章时优先用缓存,减少数据库压力
✅ 只查询用户的徽章ID,提高效率
✅ 已获得的放前面,未获得的放后面,显示更友好
这样,徽章获取接口就开发完成啦!🚀
本地缓存优化
在开发中,我们通常会使用缓存 来提高性能,避免每次都去数据库查询。Spring 提供了缓存功能,可以将数据存储在内存中,让访问变得更快。但是,如何优化缓存,才能提高效率和减少内存消耗呢?下面我们就来介绍 本地缓存优化。
1. 使用 Spring 缓存 + Caffeine
Spring 的缓存功能很方便,但我们可以通过结合 Caffeine(一个高效的本地缓存库)来实现更灵活、更高效的缓存管理。
首先,添加依赖:
java
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.9.1</version>
</dependency>
然后,启用 Spring 缓存功能:
java
@EnableCaching // 启用缓存
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.initialCapacity(100) // 初始大小
.maximumSize(200) // 最大缓存数
.expireAfterWrite(5, TimeUnit.MINUTES)); // 缓存5分钟后自动过期
return cacheManager;
}
}
这里,我们使用了 Caffeine 来优化缓存管理,设置了:
-
初始大小:缓存初始时存储 100 条数据
-
最大缓存大小:缓存最多只能存 200 条数据
-
缓存过期时间:缓存数据会在 5 分钟后自动失效
2. 使用 @Cacheable 缓存数据
当我们需要缓存某些数据时,可以在方法上加上 @Cacheable
注解,这样每次调用时,Spring 会自动检查缓存中是否有数据,如果有就直接取缓存,没有的话再去数据库查询,并把查询结果缓存起来。
java
@Cacheable(value = "badges", key = "'all'")
public List<Badge> getAllBadges() {
return badgeMapper.selectList(null); // 查询所有徽章
}
在这里,我们把 所有徽章 列表缓存起来,并设置缓存的名字为 badges
,缓存的键为 'all'
。这样就可以避免每次都去查询数据库,提升了性能。
3. 缓存更新与删除
有时候,我们需要更新 缓存或删除 缓存,比如在用户获得新徽章后,我们要更新缓存。可以使用 @CachePut
和 @CacheEvict
注解来做这些操作。
-
@CachePut
:更新缓存 -
@CacheEvict
:清空缓存
java
@CachePut(value = "badges", key = "'all'")
public List<Badge> updateBadges() {
return badgeMapper.selectList(null); // 更新缓存
}
@CacheEvict(value = "badges", key = "'all'")
public void clearCache() {
// 清空缓存
}
这样做的好处
✅ 提高性能 :减少数据库查询,直接从内存中获取数据
✅ 自动管理缓存 :设置缓存大小、过期时间,自动清理过期数据
✅ 灵活控制缓存:可以更新或删除缓存,保证数据的一致性
通过 Caffeine 和 Spring 缓存的结合,我们就可以实现更高效、灵活的缓存管理,显著提高系统的性能!🚀
Spring 缓存三件套
在使用 Spring 缓存时,我们常常会用到 三件套 :@Cacheable
、@CachePut
和 @CacheEvict
。它们分别用于不同的缓存场景,下面我们逐个来看它们的用途和使用方法。
1. @Cacheable:缓存数据
@Cacheable
用来标记一个方法,表示当方法被调用时,先去缓存中查找数据,如果缓存中有数据,就直接返回缓存中的数据;如果没有,就执行方法逻辑并将结果缓存起来,以便下次使用。
使用示例
假设我们有一个方法用来查询所有徽章,我们希望将查询结果缓存起来,避免每次查询都去数据库。
java
@Cacheable(value = "badges", key = "'all'")
public List<Badge> getAllBadges() {
return badgeMapper.selectList(null); // 查询所有徽章
}
-
value = "badges"
:缓存的名称是badges
-
key = "'all'"
:缓存的键是'all'
,表示所有徽章列表缓存用这个键来存储
这样,第一次查询会从数据库获取数据并存入缓存,之后的查询会直接从缓存中获取数据,提升性能。
2. @CachePut:更新缓存
@CachePut
用来更新缓存中的数据。每次调用标记的方法时,都会执行方法,并更新对应的缓存。通常用在更新数据的场景中。
使用示例
假设用户获得了一个新的徽章,我们需要更新缓存中的徽章列表:
@CachePut(value = "badges", key = "'all'")
public List<Badge> updateBadges() {
return badgeMapper.selectList(null); // 更新缓存中的所有徽章
}
- 每次调用
updateBadges()
时,都会执行方法,并更新缓存中的数据。
3. @CacheEvict:清除缓存
@CacheEvict
用来清除缓存中的数据。通常在数据更新或删除后,调用该方法来删除缓存,确保缓存数据是最新的。你可以选择删除特定的缓存,也可以删除所有缓存。
使用示例
假设我们删除了一个徽章后,需要清空缓存中的徽章列表,以便下次重新加载:
java
@CacheEvict(value = "badges", key = "'all'")
public void clearCache() {
// 清空缓存中的所有徽章
}
-
value = "badges"
:指定要清空的缓存名称是badges
-
key = "'all'"
:指定要清除的缓存键是'all'
总结:三件套的作用
-
@Cacheable
:查询数据时,先查缓存,没有再查数据库,查询结果缓存起来。 -
@CachePut
:更新缓存数据,每次调用都会更新缓存。 -
@CacheEvict
:清空缓存,用于数据删除或更新后的缓存清理。
通过这三件套,我们可以方便地管理缓存,提高系统性能,同时保持数据的一致性!
获取徽章列表
· 在开发中,我们需要展示所有的徽章列表,并告诉用户哪些已经获得,哪些还没有。这个功能我们可以通过一个简单的接口来实现。我们分为两个主要步骤:
1. 获取所有徽章数据
首先,我们需要从数据库中获取所有的徽章。由于徽章数据通常是固定的,不会频繁变化,所以可以缓存这个数据,以便更高效地获取。
java
@Cacheable(value = "badges", key = "'all'")
public List<Badge> getAllBadges() {
return badgeMapper.selectList(null); // 查询所有徽章
}
-
@Cacheable
:表示当查询徽章时,首先会检查缓存中是否有数据。如果有就直接从缓存获取,否则会去数据库查询,并将结果缓存起来。 -
value = "badges"
:缓存的名字是badges
。 -
key = "'all'"
:缓存的键是'all'
,表示缓存的是所有徽章。
这样,后续每次请求徽章数据时,都会直接从缓存中获取,避免了频繁的数据库查询,提高了性能。
2. 获取用户的徽章状态
获取所有徽章后,我们还需要检查每个用户是否已经获得某些徽章,并返回他们的状态(已获得/未获得)。假设每个用户的徽章信息存在 user_badge
表中,我们可以查询出用户已经获得的徽章,并标记它们。
java
public List<UserBadgeVO> getUserBadges(Long userId) {
List<Badge> allBadges = getAllBadges(); // 获取所有徽章
List<Long> userBadgeIds = userBadgeMapper.getUserBadgeIds(userId); // 查询用户已获得的徽章ID
return allBadges.stream()
.map(badge -> new UserBadgeVO(badge, userBadgeIds.contains(badge.getId())))
.sorted(Comparator.comparing(UserBadgeVO::isOwned).reversed()) // 已获得的放前面
.collect(Collectors.toList());
}
-
userBadgeMapper.getUserBadgeIds(userId)
:查询当前用户已获得的徽章ID列表。 -
UserBadgeVO
:用于包装徽章信息和用户是否已获得该徽章的状态。 -
sorted()
:将已获得的徽章排在前面,未获得的放后面。
3. 返回徽章列表给前端
最后,定义一个接口方法,返回给前端所有徽章的状态:
java
@GetMapping("/user/badges")
public List<UserBadgeVO> getUserBadges(@RequestParam Long userId) {
return badgeService.getUserBadges(userId); // 获取用户的徽章列表
}
总结
通过以上步骤,我们实现了获取所有徽章并判断用户是否拥有这些徽章的功能。
-
缓存所有徽章数据,提高查询效率。
-
查询用户已获得的徽章,标记徽章状态。
-
返回徽章列表,供前端展示。
这样一来,用户就能看到自己拥有的徽章和未获得的徽章,并且能高效地加载这些数据!🚀
佩戴徽章接口
在系统中,用户可以选择佩戴一个徽章,我们需要实现一个接口来处理这个功能。佩戴徽章时,我们首先要确认用户是否拥有该徽章,并且确认该徽章是否是一个有效的徽章。然后,我们将徽章的佩戴状态更新到数据库中。
1. 接口设计
我们首先需要设计一个接口,接收用户请求佩戴某个徽章。这个接口会检查用户是否拥有该徽章,且确保这个徽章是有效的。
java
@PostMapping("/user/badge/{badgeId}/wear")
public String wearBadge(@PathVariable Long badgeId, @RequestParam Long userId) {
badgeService.wearBadge(badgeId, userId); // 调用服务层佩戴徽章
return "佩戴成功";
}
-
badgeId
:徽章的 ID,表示用户要佩戴的徽章。 -
userId
:用户的 ID,表示要佩戴徽章的用户。
2. 服务层逻辑
在服务层,我们需要编写逻辑,处理徽章的佩戴。首先,我们需要检查用户是否拥有该徽章,然后判断它是否为有效的徽章,最后更新数据库中的佩戴状态。
java
public void wearBadge(Long badgeId, Long userId) {
// 1. 检查徽章是否存在
Badge badge = badgeMapper.selectById(badgeId);
if (badge == null) {
throw new RuntimeException("徽章不存在");
}
// 2. 检查用户是否拥有此徽章
boolean hasBadge = userBadgeMapper.userHasBadge(userId, badgeId);
if (!hasBadge) {
throw new RuntimeException("用户没有该徽章");
}
// 3. 确保徽章是有效的
if (!badge.isValid()) {
throw new RuntimeException("该徽章无效");
}
// 4. 更新用户佩戴的徽章
userBadgeMapper.updateBadgeStatus(userId, badgeId, true); // 将徽章状态设置为已佩戴
}
-
badgeMapper.selectById(badgeId)
:查询徽章信息,检查徽章是否存在。 -
userBadgeMapper.userHasBadge(userId, badgeId)
:检查用户是否拥有该徽章。 -
badge.isValid()
:检查徽章是否有效。 -
userBadgeMapper.updateBadgeStatus(userId, badgeId, true)
:更新数据库,将徽章的佩戴状态设置为已佩戴。
3. 错误处理
为了确保流程顺畅,我们还需要处理一些常见的错误情况:
-
用户尝试佩戴一个不存在的徽章。
-
用户没有获得该徽章。
-
徽章无效。
这些错误我们通过抛出 RuntimeException
来进行处理,并给出相应的错误信息。
总结
通过这个接口,用户可以佩戴自己已获得的有效徽章,系统会先检查用户是否拥有该徽章,并确保徽章有效。如果条件满足,就更新徽章的佩戴状态。
-
查询徽章,确保徽章存在且有效。
-
检查用户是否拥有徽章。
-
更新佩戴状态,将徽章标记为已佩戴。
这样就能顺利地让用户佩戴徽章啦!🎖