SpringBoot根據(jù)各地區(qū)時間設(shè)置接口有效時間的實現(xiàn)方式
之前接到需求,需要給APP內(nèi)的H5活動的接口加上時效性,防止活動后還有用戶調(diào)用接口;
因為有些H5活動是長期的,有些是短期的,所以我需要做好區(qū)分,因為我們的app是國外用戶在用的,所以還要考慮的時區(qū)的問題;
想了一下決定用注解+`攔截器的方式去實現(xiàn)
默認已經(jīng)創(chuàng)建好了SpringBoot項目
一、獲取不同時區(qū)的時間方式
1、通過時區(qū)獲取所在時區(qū)時間
/**
* 獲得東八區(qū)時間
*
* @return
*/
public static String getChinaTime() {
TimeZone timeZone = TimeZone.getTimeZone("GMT+8:00");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.setTimeZone(timeZone);
return simpleDateFormat.format(new Date());
}
2、通過地區(qū)獲取所在時區(qū)時間
根據(jù)ZoneId 獲取當(dāng)?shù)貢r間
ZonedDateTime是結(jié)合了LocalDateTime類與 ZoneId 類。它用于表示具有時區(qū)(地區(qū)/城市,如歐洲/巴黎)的完整日期(年,月,日)和時間(小時,分鐘,秒,納秒)
ZoneId pstZoneId = ZoneId.of("America/Los_Angeles");
DateTimeFormatter pstDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(pstZoneId);
ZonedDateTime pstZonedDateTime = ZonedDateTime.parse(time, pstDateTimeFormatter);
3、獲取所在時區(qū)的時間戳
String region = "America/Los_Angeles"; ZoneId pstZoneId = ZoneId.of(region); long nowTime = ZonedDateTime.now(pstZoneId).toInstant().toEpochMilli(); //nowTime時間戳
當(dāng)然還有其他方式獲取得到,網(wǎng)上有很多工具類~~~
二、創(chuàng)建地區(qū)/時區(qū)枚舉類
region屬性表示時間,timeZone表示時區(qū)
還有一點要注意的,一些國家有冬令時和夏令時的區(qū)分,比如美國、德國、法國等,這里我同一用了協(xié)同世界時

public enum TimeZoneEnum {
?
Asia_Shanghai("Asia/Shanghai","+8:00"),//中國-上海
Asia_Hong_Kong("Asia/Hong_Kong","+8:00"),//香港
Asia_Macau("Asia/Macau","+8:00"),//澳門
Asia_Taipei("Asia/Taipei","+8:00"),//臺灣
Asia_Singapore("Asia/Singapore","+8:00"),//新加坡
Asia_Bangkok("Asia/Bangkok","+7:00"),//泰國-曼谷
Asia_Calcutta("Asia/Calcutta","+5:30"),//印度-加爾各答
Asia_Tokyo("Asia/Tokyo","+9:00"),//日本-東京
Asia_Seoul("Asia/Seoul","+9:00"),//韓國-首爾
Asia_Karachi("Asia/Karachi","+5:00"),//巴基斯坦
America_Los_Angeles("America/Los_Angeles","-8:00"),//洛杉磯
America_New_York("America/New_York","-5:00"),//紐約
Europe_London("Europe/London","+0:00"),//英國-倫敦
Europe_Paris("Europe/Paris","+1:00"),//法國-巴黎
Europe_Berlin("Europe/Berlin","+1:00"),//德國-柏林
Asia_Jakarta("Asia/Jakarta","+7:00"),//印度尼西亞-雅加達
Asia_Kuala_Lumpur("Asia/Kuala_Lumpur","+8:00");//馬來西亞-吉隆坡
?
private String region;
private String timeZone;
?
TimeZoneEnum(String region, String timeZone) {
this.region = region;
this.timeZone = timeZone;
}
?
public String getRegion() {
return region;
}
?
public TimeZoneEnum setRegion(String region) {
this.region = region;
return this;
}
?
public String getTimeZone() {
return timeZone;
}
?
public TimeZoneEnum setTimeZone(String timeZone) {
this.timeZone = timeZone;
return this;
}
}
三、創(chuàng)建有效時間注解
創(chuàng)建API有效時間注解
@Target來指定ApiValidTime可以應(yīng)用的范圍,表示注解可以用在那些地方上
@Retention(RetentionPolicy.RUNTIME)注解的生命周期,生效時間
@Retention(RetentionPolicy)
RetentionPolicy.SOURCE 僅編譯期
RetentionPolicy.CLASS (默認) 僅class文件
RetentionPolicy.RUNTIME 運行期
通常我們自定義的Annotation都是RUNTIME所以,務(wù)必加上@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType)
- ELementType.TYPE 類或接口
- ELementType.FIELD 字段
- ElementType.METHOD 方法
- ElementType.PARAMETER 方法參數(shù)
- ElementType.CONSTRUCTOR 構(gòu)造方法
在注解中定義2個屬性,time和 TIME_ZONE_ENUM,
time表示接口生效時間格式為"yyyy-MM-dd HH:mm:ss",
TIME_ZONE_ENUM指地區(qū)枚舉類TimeZoneEnum
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
?
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiValidTime {
/**
* PST 時間
* @return pst時間 yyyy-MM-dd HH:mm:ss
*/
String time() default "";
?
/**
* 地區(qū) timeZone
* @return 地區(qū)
*/
TimeZoneEnum TIME_ZONE_ENUM();
}
四、攔截器
1、創(chuàng)建ApiValidTime攔截器
處理邏輯:
1、攔截設(shè)置路徑的請求
2、獲取攔截到的方法HandlerMethod
3、判斷方法對應(yīng)的類上有沒有ApiValidTime注解,沒有在去判斷方法上有沒有ApiValidTime注解
4、沒有ApiValidTime注解,就放行
5、如果有,就獲取ApiValidTime注解中的time和TIME_ZONE_ENUM屬性值
6、獲取當(dāng)前TIME_ZONE_ENUM對應(yīng)時區(qū)的時間
7、TIME_ZONE_ENUM對應(yīng)時區(qū)的時間,與time的時間比較,TIME_ZONE_ENUM對應(yīng)時區(qū)的時間小于time的時間放行,大于攔截,攔截后將自定的響應(yīng)性信息falseResult返回
這里我直接根據(jù)地區(qū)去獲取地區(qū)所在時區(qū)的時間了,有興趣的jym可以試試其他方式。
import liu.qingxu.constant.ApiValidTime;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
?
/**
* @module 接口有效時間攔截器
* @author: qingxu.liu
* @date: 2022-10-10 22:01
* @copyright
**/
@Component
@Slf4j
public class ApiValidTimeInterceptor implements HandlerInterceptor {
?
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判斷是否需要攔截
if (!(handler instanceof HandlerMethod)){
return true;
}
HandlerMethod hm = (HandlerMethod) handler;
//獲取類上的注解
ApiValidTime annotation = hm.getBeanType().getAnnotation(ApiValidTime.class);
if (Objects.isNull(annotation)){
//類上沒有獲取方法上的
annotation = hm.getMethod().getAnnotation(ApiValidTime.class);
}
//判斷類上是否有打該注解
//boolean clazzAnnotationPresent = hm.getBeanType().isAnnotationPresent(ApiValidTime.class);
//判斷類上或注解上有沒有注解
if (Objects.isNull(annotation)){
//沒有放行
return true;
}else {
//有注解,獲取注解信息,比較時間大小
String time = annotation.time();
String region = annotation.TIME_ZONE_ENUM().getRegion();
ZoneId pstZoneId = ZoneId.of(region);
DateTimeFormatter pstDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(pstZoneId);
ZonedDateTime pstZonedDateTime = ZonedDateTime.parse(time, pstDateTimeFormatter);
//獲取所在時間的時間戳
long nowTime = ZonedDateTime.now(pstZoneId).toInstant().toEpochMilli();
boolean checkResult = pstZonedDateTime.toInstant().toEpochMilli() > nowTime;
if (checkResult){
return true;
}else {
falseResult(response);
return false;
}
}
}
/**
* 攔截后處理
*/
private void falseResult(HttpServletResponse response) throws IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
response.getWriter().println("This event has ended, please do not visit again!");
}
}
2、注冊攔截器,設(shè)置攔截路徑
攔截路徑為:/activity/h5/...下的所有路徑
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
?
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
?
final ApiValidTimeInterceptor apiValidTimeInterceptor;
public WebMvcConfig(ApiValidTimeInterceptor apiValidTimeInterceptor) {
this.apiValidTimeInterceptor = apiValidTimeInterceptor;
}
?
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(apiValidTimeInterceptor)
.addPathPatterns("/activity/h5**"); //攔截路徑
?
}
}
五、驗證結(jié)果
新建一個Controller
@RestController
@RequestMapping("/activity/h5")
public class ApiValidController {
?
@GetMapping("/test/run")
@ApiValidTime(time = "2023-02-28 10:00:00", TIME_ZONE_ENUM = Asia_Shanghai)
public void runTest(){
System.out.println(new Date());
}
}
現(xiàn)在是北京時間:2023-02-28 21:30:45 已經(jīng)過接口有效時間

重新設(shè)置接口時間為:2023-04-20 10:00:00,重啟服務(wù),再次請求:
@GetMapping("/test/run")
@ApiValidTime(time = "2023-04-20 10:00:00", TIME_ZONE_ENUM = Asia_Shanghai)
public void runTest(){
System.out.println(new Date());
}
此時就可以看到?jīng)]有接口過期提醒,在控制臺也可以看到時間打印了


以上就是SpringBoot根據(jù)各地區(qū)時間設(shè)置接口有效時間的實現(xiàn)方式的詳細內(nèi)容,更多關(guān)于SpringBoot設(shè)置接口有效時間的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java學(xué)習(xí)之junit單元測試案例(經(jīng)典版)
這篇文章主要介紹了java學(xué)習(xí)之junit單元測試的相關(guān)資料,文中講解了JUnit單元測試的基本概念、作用、使用assert進行驗證、覆蓋率分析、BeforeEach和AfterAll的使用、通過反射和注解實現(xiàn)測試,需要的朋友可以參考下2024-12-12
spring boot整合Shiro實現(xiàn)單點登錄的示例代碼
本篇文章主要介紹了spring boot整合Shiro實現(xiàn)單點登錄的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
Java利用ElasticSearch實現(xiàn)自動補全功能
這篇文章主要為大家詳細介紹了Java如何利用ElasticSearch實現(xiàn)跟谷歌和百度類似的下拉補全提示功能,文中的示例代碼講解詳細,需要的可以參考一下2023-08-08
SpringBoot整合達夢數(shù)據(jù)庫的教程詳解
這篇文章主要給大家介紹了SpringBoot整合達夢數(shù)據(jù)庫的詳細教程,文章中有詳細的圖片介紹和代碼示例供大家參考,具有一定的參考價值,需要的朋友可以參考下2023-08-08
idea中acitviti使用acitBPM插件出現(xiàn)亂碼問題及解決方法
這篇文章主要介紹了idea中acitviti使用acitBPM插件出現(xiàn)亂碼問題及解決方法,通過將File Encodings內(nèi)容設(shè)置為UTF-8,本文通過圖文展示,需要的朋友可以參考下2021-06-06
Swagger2配置Security授權(quán)認證全過程
這篇文章主要介紹了Swagger2配置Security授權(quán)認證全過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
Mybatis-Plus集成Sharding-JDBC與Flyway實現(xiàn)多租戶分庫分表實戰(zhàn)
這篇文章主要為大家介紹了Mybatis-Plus集成Sharding-JDBC與Flyway實現(xiàn)多租戶分庫分表實戰(zhàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11

