最近开发遇到检查任务配置工作日类型,包括法定节假日/调休日/周末/工作日类型,因为每年的这些数据是通过国务院发放文件进行得知,不得不用到第三方api进行查询;考虑到次数(实际是给公司节省成本)以及可靠性,最终决定使用天行数据节假日api进行使用,试过阿里云的万易的api,期限以及次数比较鸡肋;
废话不多说,直接上代码,此帖子结合nacos以及表进行编写,可以根据自己的实际使用场景进行更改!
加了一个校验,如果查询的今年没有数据的话会优先去把今年的初始化,如果今年的数据完整会去初始化明年的数据(如果存在的话) 业务不同的可以进行更改
一、在天行数据官网注册并申请节假日api,得到自己账号的key
节假日地址:https://www.tianapi.com/apiview/139
二、我使用的框架是alibabacloud,实此功能实际使用到的其实顶多就是一个nacos,其它的倒是使用的很少,controller->service->mybaties/mybaties-plus
api调用返回结果格式为:
{ "code": 200, "msg": "success", "result": { "update": true, "list": [ { "holiday": "1月1号", "name": "元旦节", "vacation": "2023-12-30|2023-12-31|2024-01-01", "remark": "", "wage": "2024-01-01", "start": 0, "now": 0, "end": 2, "tip": "1月1日放假,与周末连休,共三天。", "rest": "2023年12月28日至12月29日请假2天,与周末连休可拼5天小长假。" }, { "holiday": "2月10号", "name": "春节", "vacation": "2024-02-10|2024-02-11|2024-02-12|2024-02-13|2024-02-14|2024-02-15|2024-02-16|2024-02-17", "remark": "2024-02-04|2024-02-18", "wage": "2024-02-10|2024-02-11|2024-02-12", "start": 0, "now": 0, "end": 7, "tip": "2月10日至17日放假调休,共8天。2月4日(星期日)、2月18日(星期日)上班。鼓励各单位结合带薪年休假等制度落实,安排职工在除夕(2月9日)休息。", "rest": "2月8日至2月9日请假2天,与春节连休可拼10天长假。" }, { "holiday": "4月4号", "name": "清明节", "vacation": "2024-04-04|2024-04-05|2024-04-06", "remark": "2024-04-07", "wage": "2024-04-04", "start": 0, "now": 0, "end": 2, "tip": "4月4日至6日放假调休,共3天。4月7日(星期日)上班。", "rest": "4月3日和4月7日请假2天,与清明节连休可拼5天小长假。" }, { "holiday": "5月1号", "name": "劳动节", "vacation": "2024-05-01|2024-05-02|2024-05-03|2024-05-04|2024-05-05", "remark": "2024-04-28|2024-05-11", "wage": "2024-05-01", "start": 0, "now": 0, "end": 4, "tip": "5月1日至5日放假调休,共5天。4月28日(星期日)、5月11日(星期六)上班。", "rest": "4月28日至4月30日请假3天,周六与劳动节连休可拼9天长假。" }, { "holiday": "6月10号", "name": "端午节", "vacation": "2024-06-08|2024-06-09|2024-06-10", "remark": "", "wage": "2024-06-10", "start": 0, "now": 0, "end": 2, "tip": "6月10日放假,与周末连休,共3天。", "rest": "6月6日至6月7日请假2天,与端午节连休可拼5天小长假。" }, { "holiday": "9月15号", "name": "中秋节", "vacation": "2024-09-15|2024-09-16|2024-09-17", "remark": "2024-09-14", "wage": "2024-09-17", "start": 0, "now": 0, "end": 2, "tip": "9月15日至17日放假调休,共3天。9月14日(星期六)上班。", "rest": "9月13日至9月14日请假2天,与周日连休可拼5天小长假。" }, { "holiday": "10月1号", "name": "国庆节", "vacation": "2024-10-01|2024-10-02|2024-10-03|2024-10-04|2024-10-05|2024-10-06|2024-10-07", "remark": "2024-09-29|2024-10-12", "wage": "2024-10-01|2024-10-02|2024-10-03", "start": 0, "now": 0, "end": 6, "tip": "10月1日至7日放假调休,共7天。9月29日(星期日)、10月12日(星期六)上班。", "rest": "9月29日至9月30号请假2天,周六与国庆节连休可拼10天长假。" } ] } }
直接上代码
controller:
package safe.cloud.luntai.controller; import com.github.pagehelper.PageInfo; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import safe.cloud.luntai.dto.DateInfoDTO; import safe.cloud.luntai.entity.DateInfo; import safe.cloud.luntai.model.BasicResponse; import safe.cloud.luntai.model.BasicTable; import safe.cloud.luntai.service.DateInfoService; import safe.cloud.luntai.vo.DateInfoVO; import javax.annotation.Resource; /** ** 日期详情表(节假日/调休/周末/工作日) 前端控制器 *
* * @author zjc * @since 2024-04-19 16:02:51 */ @RestController @RequestMapping("/dateInfo") public class DateInfoController { @Resource private DateInfoService dateInfoService; /** * 获取全年日期(标注节假日/调休日/周末/工作日) * @return 返回封装 */ @PostMapping("/synDateInfo") public BasicResponse synDateInfo() { boolean operateState = dateInfoService.synDateInfo(); return BasicResponse.createSuccess(operateState); } }
service:
package safe.cloud.luntai.service; import com.github.pagehelper.PageInfo; import safe.cloud.luntai.entity.DateInfo; import safe.cloud.luntai.vo.DateInfoVO; import safe.cloud.luntai.dto.DateInfoDTO; import com.baomidou.mybatisplus.extension.service.IService; import java.io.Serializable; /** ** 日期详情表(节假日/调休/周末/工作日) 服务类 *
* * @author zjc * @since 2024-04-19 16:02:51 */ public interface DateInfoService extends IService{ /** * 获取全年日期(标注节假日/调休日/周末/工作日) * @return 返回封装 */ boolean synDateInfo(); }
impl:
package safe.cloud.luntai.service.impl; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.github.pagehelper.PageInfo; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import safe.cloud.luntai.dto.DateInfoDTO; import safe.cloud.luntai.entity.DateInfo; import safe.cloud.luntai.enums.RiskInfoEnums; import safe.cloud.luntai.exception.CustomServerException; import safe.cloud.luntai.mapper.DateInfoMapper; import safe.cloud.luntai.service.DateInfoService; import safe.cloud.luntai.utils.NacosCommonUtils; import safe.cloud.luntai.utils.PageUtils; import safe.cloud.luntai.vo.DateInfoVO; import javax.annotation.Resource; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Serializable; import java.net.HttpURLConnection; import java.net.URL; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; /** ** 日期详情表(节假日/调休/周末/工作日) 服务实现类 *
* * @author zjc * @since 2024-04-19 16:02:51 */ @Slf4j @Service public class DateInfoServiceImpl extends ServiceImplimplements DateInfoService { @Resource NacosCommonUtils nacosCommonUtils; /** * 获取全年日期(标注节假日/调休日/周末/工作日) * @return 返回封装 */ @Override @Transactional(rollbackFor = Exception.class) public boolean synDateInfo() { int year = LocalDate.now().getYear(); //如果在库里面今年或者明年已经存在数据 那么就直接返回不进行操作 long checkNowYearCount = this.count(new LambdaQueryWrapper ().eq(DateInfo::getYear, year)); long checkTomorrowYearCount = this.count(new LambdaQueryWrapper ().eq(DateInfo::getYear, year + 1)); if((checkNowYearCount == 365 || checkNowYearCount == 366) && (checkTomorrowYearCount == 365 || checkTomorrowYearCount == 366) ){ log.info("系统已存在对应数据,无需再次初始化!"); return true; } String doYear; //库里面查询今年的数据是否存在 如果不存在,那么就先进行初始化今年的数据 if(checkNowYearCount == 365 || checkNowYearCount == 366){ doYear = String.valueOf(year + 1); }else{ doYear = String.valueOf(year); } //获取指定年份的List List datesOfYear = getDatesOfYear(doYear); Assert.isTrue(CollectionUtil.isNotEmpty(datesOfYear), "获取指定年份的日期为空"); //获取指定年份的周末 List yearWeekends = findYearWeekends(doYear); Assert.isTrue(CollectionUtil.isNotEmpty(yearWeekends), "获取指定年份的周末日期为空"); //如果不为0,先执行一次删除操作,避免因为某些原因存入脏数据 long checkDoYearCount = this.count(new LambdaQueryWrapper ().eq(DateInfo::getYear, doYear)); if(checkDoYearCount != 0){ this.remove(new LambdaQueryWrapper ().eq(DateInfo::getYear,doYear)); } String tianApiData = ""; try { URL url = new URL( nacosCommonUtils.getTianXingApiUrl()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); conn.setDoOutput(true); conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); OutputStream outputStream = conn.getOutputStream(); String key = nacosCommonUtils.getTianXingApiKey(); String type = "1"; String content = "key=" + key + "&date=" + doYear + "&type=" + type; outputStream.write(content.getBytes()); outputStream.flush(); outputStream.close(); InputStream inputStream = conn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader (inputStream,"utf-8"); BufferedReader bufferedReader = new BufferedReader (inputStreamReader); StringBuilder tianapi = new StringBuilder(); String temp = null; while ( null != (temp = bufferedReader.readLine())){ tianapi.append(temp); } tianApiData = tianapi.toString(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } // 使用 JSONUtil 将 JSON 字符串转换为 Map 对象 JSONObject jsonObject = JSONUtil.parseObj(tianApiData); int code = jsonObject.getInt("code"); RiskInfoEnums.TianXingApiCodeEnums tianXingApiCodeEnums = RiskInfoEnums.TianXingApiCodeEnums.getByCode(code); if(Boolean.FALSE.equals(tianXingApiCodeEnums.getCode() == 200)){ throw new CustomServerException(tianXingApiCodeEnums.getMsg()); } Map resultMap = jsonObject.getJSONObject("result"); if(CollectionUtil.isEmpty(resultMap)){ log.info("==============================="); log.info("响应body未拿到!"); return false; } List
mapper:
package safe.cloud.luntai.mapper; import safe.cloud.luntai.entity.DateInfo; import safe.cloud.luntai.dto.DateInfoDTO; import safe.cloud.luntai.vo.DateInfoVO; import safe.cloud.luntai.vo.DateInfoVO; import safe.cloud.luntai.dto.DateInfoDTO; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** ** 日期详情表(节假日/调休/周末/工作日) Mapper 接口 *
* * @author zjc * @since 2024-04-19 16:02:51 */ @Mapper public interface DateInfoMapper extends BaseMapper{ }
nacosutil:可以直接自己写死测试,或者更改自己的nacos值配置,关于nacos不再做过多的赘述
package safe.cloud.luntai.utils; import lombok.Getter; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Component; /** * * @ClassName NacosCommonUtils * @date 2022/12/24 15:51 * @Version 1.0 */ @Component @RefreshScope @Getter public class NacosCommonUtils { /** * 天行数据节假日api url */ @Value("${tianXingApi.url}") String tianXingApiUrl; /** * 天行数据节假日api key */ @Value("${tianXingApi.key}") String tianXingApiKey; }
enums:
package safe.cloud.luntai.enums; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import lombok.AllArgsConstructor; import lombok.Getter; import safe.cloud.luntai.exception.CustomClientException; import java.util.Arrays; import java.util.Objects; public class RiskInfoEnums { @AllArgsConstructor public enum DateTypeEnums { /** * 日期类型 */ HOLIDAY("1","假期"), COMPENSATORY("2","调休"), WEEKEND("3","周末"), WORKDAY("4","工作日"), ; @Getter String code; @Getter String msg; public static RiskInfoEnums.DateTypeEnums getByCode(String code) { if (StrUtil.isBlank(code)) { return null; } return Arrays.stream(RiskInfoEnums.DateTypeEnums.values()) .filter(f -> f.code.equals(code)) .findFirst() .orElseThrow(() -> new CustomClientException("暂不支持的业务类型")); } } @AllArgsConstructor public enum TianXingApiCodeEnums { /** * 天行第三方api调用结果状态码 */ NBCW(100, "内部服务器错误"), APIXX(110, "当前API已下线"), APIWH(120, "API暂时维护中"), APICX(130, "API调用频率超限"), APIMYQX(140, "API没有调用权限"), APICSBZ(150, "API可用次数不足"), ZHWSQAPI(160, "账号未申请该API"), REFERERSX(170, "Referer请求来源受限"), IPSX(180, "IP请求来源受限"), KEYBKY(190, "当前key不可用"), KEYCW(230, "key错误或为空"), QSKEY(240, "缺少key参数"), SJWK(250, "数据返回为空"), CSWK(260, "参数值不得为空"), CSBFHYQ(270, "参数值不符合要求"), QSBYCS(280, "缺少必要的参数"), CGCD(290, "超过最大输入限制"), SUCCESS(200, "请求成功"), ; @Getter private final int code; @Getter private final String msg; public static TianXingApiCodeEnums getByCode(int code) { if (ObjectUtil.isNull(code)) { return null; } return Arrays.stream(TianXingApiCodeEnums.values()) .filter(f ->f.code == code).findFirst().orElse(null); } } }
状态响应码以及日期类型枚举:
mysql的创表语句:
CREATE TABLE `tb_date_info` ( `auto_id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id', `date_info` date DEFAULT NULL COMMENT '日期', `day_type_code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '类型(1:假期,2:调休,3:周末,4:工作日) code', `year` year DEFAULT NULL COMMENT '年份', `day_of_week` varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '周几', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `create_user` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `update_user` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '更新人', `day_type_msg` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '类型(1:假期,2:调休,3:周末,4:工作日) 中文', PRIMARY KEY (`auto_id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='日期详情表(节假日/调休/周末/工作日)';
最后执行就可以了,根据自己的业务调整使用定时任务还是powerJob去跑,这里就不过多演示,有疑问的可以进行留言或者加我企鹅2466961646,看到会回复