feat: add daily password endpoint with Redis caching
This commit is contained in:
@@ -57,7 +57,8 @@ public class SecurityConfig {
|
||||
).permitAll()
|
||||
.requestMatchers(HttpMethod.GET,
|
||||
"/firearms", "/firearms/*",
|
||||
"/modifications", "/modifications/*"
|
||||
"/modifications", "/modifications/*",
|
||||
"/daily-passwords", "/daily-passwords/*"
|
||||
).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.onixbyte.deltaforceguide.controller;
|
||||
|
||||
import com.onixbyte.deltaforceguide.domain.dto.DailyPasswordResponse;
|
||||
import com.onixbyte.deltaforceguide.service.DailyPasswordService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "每日密码", description = "获取每日密码信息")
|
||||
@RestController
|
||||
@RequestMapping("/daily-passwords")
|
||||
public class DailyPasswordController {
|
||||
|
||||
private final DailyPasswordService dailyPasswordService;
|
||||
|
||||
public DailyPasswordController(DailyPasswordService dailyPasswordService) {
|
||||
this.dailyPasswordService = dailyPasswordService;
|
||||
}
|
||||
|
||||
@Operation(description = "获取当日的每日密码数据,该数据将被缓存一天")
|
||||
@GetMapping
|
||||
public DailyPasswordResponse getDailyPassword() {
|
||||
return dailyPasswordService.getDailyPassword();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.onixbyte.deltaforceguide.domain.dto;
|
||||
|
||||
public record DailyPassword(
|
||||
String mapName,
|
||||
String password
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.onixbyte.deltaforceguide.domain.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public record DailyPasswordData(
|
||||
String updateDate,
|
||||
Integer totalCount,
|
||||
List<DailyPassword> passwords,
|
||||
String source,
|
||||
LocalDateTime lastUpdated,
|
||||
Long timestamp
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.onixbyte.deltaforceguide.domain.dto;
|
||||
|
||||
public record DailyPasswordMetadata(
|
||||
String version,
|
||||
String author
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.onixbyte.deltaforceguide.domain.dto;
|
||||
|
||||
public record DailyPasswordResponse(
|
||||
String status,
|
||||
String message,
|
||||
DailyPasswordData data,
|
||||
DailyPasswordMetadata metadata
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.onixbyte.deltaforceguide.manager;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
||||
import com.onixbyte.deltaforceguide.domain.dto.DailyPasswordResponse;
|
||||
import com.onixbyte.deltaforceguide.exeption.BizException;
|
||||
import com.onixbyte.deltaforceguide.shared.JacksonModules;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
|
||||
@Component
|
||||
public class DailyPasswordManager {
|
||||
|
||||
private static final String CACHE_KEY_PREFIX = "daily-password:";
|
||||
|
||||
private final RestClient restClient;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
public DailyPasswordManager(
|
||||
RestClient.Builder restClientBuilder,
|
||||
RedisTemplate<String, Object> redisTemplate
|
||||
) {
|
||||
var snakeCaseMapper = new ObjectMapper();
|
||||
snakeCaseMapper.setPropertyNamingStrategy(
|
||||
PropertyNamingStrategies.SnakeCaseStrategy.INSTANCE);
|
||||
snakeCaseMapper.configure(
|
||||
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
snakeCaseMapper.registerModule(JacksonModules.DATE_TIME_MODULE);
|
||||
|
||||
this.restClient = restClientBuilder
|
||||
.baseUrl("https://tmini.net/api")
|
||||
.messageConverters(converters -> {
|
||||
converters.removeIf(
|
||||
MappingJackson2HttpMessageConverter.class::isInstance);
|
||||
converters.add(
|
||||
new MappingJackson2HttpMessageConverter(snakeCaseMapper));
|
||||
})
|
||||
.build();
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
public DailyPasswordResponse getDailyPassword() {
|
||||
var key = CACHE_KEY_PREFIX + LocalDate.now();
|
||||
|
||||
var cached = redisTemplate.opsForValue().get(key);
|
||||
if (cached != null) {
|
||||
return (DailyPasswordResponse) cached;
|
||||
}
|
||||
|
||||
var response = restClient.get()
|
||||
.uri((uriBuilder) -> uriBuilder
|
||||
.path("/sjzmm")
|
||||
.queryParam("ckey", "")
|
||||
.queryParam("type", "json")
|
||||
.build())
|
||||
.retrieve()
|
||||
.body(DailyPasswordResponse.class);
|
||||
|
||||
if (Objects.isNull(response)) {
|
||||
throw new BizException(HttpStatus.INTERNAL_SERVER_ERROR, "暂无每日密码数据。");
|
||||
}
|
||||
|
||||
redisTemplate.opsForValue().set(key, response, Duration.ofDays(1L));
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.onixbyte.deltaforceguide.service;
|
||||
|
||||
import com.onixbyte.deltaforceguide.domain.dto.DailyPasswordResponse;
|
||||
import com.onixbyte.deltaforceguide.manager.DailyPasswordManager;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class DailyPasswordService {
|
||||
|
||||
private final DailyPasswordManager dailyPasswordManager;
|
||||
|
||||
public DailyPasswordService(DailyPasswordManager dailyPasswordManager) {
|
||||
this.dailyPasswordManager = dailyPasswordManager;
|
||||
}
|
||||
|
||||
public DailyPasswordResponse getDailyPassword() {
|
||||
return dailyPasswordManager.getDailyPassword();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user