SpringBoot根據(jù)各地區(qū)時間設(shè)置接口有效時間的實現(xiàn)方式
之前接到需求,需要給APP內(nèi)的H5活動的接口加上時效性,防止活動后還有用戶調(diào)用接口;
因為有些H5活動是長期的,有些是短期的,所以我需要做好區(qū)分,因為我們的app是國外用戶在用的,所以還要考慮的時區(qū)的問題;
想了一下決定用注解
+`攔截器
的方式去實現(xiàn)
默認(rè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"),//印度尼西亞-雅加達(dá) 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 (默認(rèn)) 僅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)方式的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot設(shè)置接口有效時間的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
spring-boot-maven-plugin引入出現(xiàn)爆紅(已解決)
這篇文章主要介紹了spring-boot-maven-plugin引入出現(xiàn)爆紅(已解決),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03Spring Data Jpa 復(fù)合主鍵的實現(xiàn)
這篇文章主要介紹了Spring Data Jpa 復(fù)合主鍵的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04Mybatis使用foreach批量更新數(shù)據(jù)報無效字符錯誤問題
這篇文章主要介紹了Mybatis使用foreach批量更新數(shù)據(jù)報無效字符錯誤問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08- 在Java中,生成隨機(jī)數(shù)有兩種方法。1是使用Random類。2是使用Math類中的random方法??聪旅娴睦邮褂冒?/div> 2013-11-11
IDEA 中 maven 的 Lifecycle 和Plugins&n
IDEA 主界面右側(cè) Maven 標(biāo)簽欄有同樣的命令,比如 install,既在 Plugins 中存在,也在 Lifecycle中存在,到底選哪個?二者又有什么區(qū)別呢?下面小編給大家介紹下IDEA 中 maven 的 Lifecycle 和Plugins 的區(qū)別,感興趣的朋友一起看看吧2023-03-03最新評論