当前位置: 首页 > news >正文

Java 实现自动获取法定节假日

一、背景

在实现业务需求的过程中,遇到了需要计算 x 个工作日后的日期需求。由于工作日是每年国务院发布的,调休和休假都没有规律,所以无法使用算法进行计算。

一般的实现方案是自己维护一个工作日和调休的表,或者去爬取国务院发布的数据。但前者实现起来麻烦,每年都得搞一遍;后者可能涉及法律风险,爬虫的识别策略也不太可靠。

所以还是考虑使用由专人维护的接口,找到了天行数据的接口,个人用户有10个免费接口的额度,每个接口每天限制调用100次。

因为节假日一旦定下来就不会轻易改变,所以可以把获取到的数据存在本地,这样每天100次的接口额度完全够用,不需要进行付费。

二、技术实现方案

整体流程:
  1. 读取节假日配置:从本地文件中读取节假日,如果本地没有文件,则调用天行接口获取。
  2. 解析数据:从天行返回的数据里,获取该年份里需要调休的日期和补班的日期。
  3. 计算日期:循环获取日期,判断是否为工作日,计算x个工作日后的日期。
实现细节:
  1. 文件名:保存下来的文件,名字里要包含特定的年份。
  2. 计算逻辑:计算日期的时候,需要考虑到跨年的情况,跨年需要重新获取下一年的数据,再继续进行计算日期。
  3. 日期判断:工作日=不休假的周一至周五+补班的周六周末。

三、详细代码

Java 代码

主要有五个类,HolidayResponse 是封装天行API的返回结果;TianApiProperties 是获取天行API的key;TianApiHolidayService 是接口;TianApiHolidayServiceImpl 里是具体实现;HttpConnector 是接口请求,这个换成任何一个能发起http请求的库都行。

目前代码是基于SpringBoot写的,但纯粹只是为了方便,实际是可以转成纯Java工具代码,不依赖于SpringBoot。

HolidayResponse.java

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;import java.util.List;/*** @author jing* @version 1.0* @desc 返回结果* @date 2023/12/19 11:40**/
@Data
public class HolidayResponse {@JsonProperty("code")private int code; // 公共参数 - 状态码@JsonProperty("msg")private String msg; // 公共参数 - 错误信息@JsonProperty("result")private Result result; // 公共参数 - 返回结果集// Getters and setters/*** Represents the result section of the response.*/@Datapublic static class Result {@JsonProperty("update")private boolean update; // 公共参数 - 是否更新法定节假日@JsonProperty("list")private List<HolidayItem> list; // 应用参数 - 节假日列表// Getters and setters}/*** Represents an item in the list of holidays.*/@Datapublic static class HolidayItem {@JsonProperty("holiday")private String holiday; // 应用参数 - 节日日期@JsonProperty("name")private String name; // 应用参数 - 节假日名称(中文)@JsonProperty("vacation")private String vacation; // 应用参数 - 节假日数组@JsonProperty("remark")private String remark; // 应用参数 - 调休日数组@JsonProperty("wage")private String wage; // 应用参数 - 薪资法定倍数/按年查询时为具体日期@JsonProperty("start")private int start; // 应用参数 - 假期起点计数@JsonProperty("now")private int now; // 应用参数 - 假期当前计数@JsonProperty("end")private int end; // 应用参数 - 假期终点计数@JsonProperty("tip")private String tip; // 应用参数 - 放假提示@JsonProperty("rest")private String rest; // 应用参数 - 拼假建议}}

TianApiProperties.java

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** @author jing* @version 1.0* @desc 配置* @date 2023/12/19 11:25**/
@Component
@Data
@ConfigurationProperties(prefix = "tianapi")
public class TianApiProperties {/*** 天行数据凭证key*/private String key;
}

TianApiHolidayService.java

import org.springframework.stereotype.Service;import java.io.IOException;
import java.time.LocalDateTime;/*** @author jing* @version 1.0* @desc 天行接口获取节假日,目前使用的是免费接口,每天只能调用100次,后续如果需要调用更多次数,可以考虑购买付费接口。只能获取到今年和明年的节假日,明年的节假日需要在今年11月份左右才能获取到* @date 2023/12/19 11:25**/
@Service
public interface TianApiHolidayService {/*** 计算x个工作日后的日期,跳过节假日** @param startTime     开始日期* @param workdaysToAdd 需要跳过的工作日天数*/LocalDateTime jumpWorkDay(LocalDateTime startTime, int workdaysToAdd) throws IOException;}

TianApiHolidayServiceImpl.java (核心逻辑)


import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.xxx.app.common.library.holiday.domain.HolidayResponse;
import com.xxx.app.common.library.holiday.properties.TianApiProperties;
import com.xxx.app.common.utils.http.HttpConnector;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author jing* @version 1.0* @desc 天行接口获取节假日,目前使用的是免费接口,每天只能调用100次,后续如果需要调用更多次数,可以考虑购买付费接口。只能获取到今年和明年的节假日,明年的节假日需要在今年11月份左右才能获取到* @date 2023/12/19 11:25**/
@Slf4j
@Service
public class TianApiHolidayServiceImpl implements TianApiHolidayService {@Resourceprivate TianApiProperties tianApiProperties;@Resourceprivate HttpConnector httpConnector;private final String FILE_FORMAT = "./.holiday/%s_holiday.json";/*** 计算x个工作日后的日期,跳过节假日** @param startTime     开始日期* @param workdaysToAdd 需要跳过的工作日天数*/public LocalDateTime jumpWorkDay(LocalDateTime startTime, int workdaysToAdd) throws IOException {// 从文件中读取节假日HolidayResponse response = getHolidayConfig(startTime);if (response == null) {return null;}// 节假日,只算周一到周五的List<LocalDate> vacationList = new ArrayList<>();// 补班列表,表示周末补班的List<LocalDate> workDayList = new ArrayList<>();extracted(response, vacationList, workDayList);return workDayAdd(startTime, workdaysToAdd, vacationList, workDayList);}/*** 提取返回数据里的节假日和调休列表** @param response     返回数据* @param vacationList 节假日列表* @param workDayList  补班列表*/private static void extracted(HolidayResponse response, List<LocalDate> vacationList, List<LocalDate> workDayList) {// 节假日列表response.getResult().getList().forEach(item -> {if (StringUtils.isNotEmpty(item.getWage())) {String[] vList = item.getVacation().split("\\|");for (String wage : vList) {// 不需要上班的工作日vacationList.add(LocalDate.parse(wage, DateTimeFormatter.ofPattern("yyyy-MM-dd")));}}if (StringUtils.isNotEmpty(item.getRemark())) {String[] workList = item.getRemark().split("\\|");for (String work : workList) {// 需要上班的周末workDayList.add(LocalDate.parse(work, DateTimeFormatter.ofPattern("yyyy-MM-dd")));}}});}/*** 添加工作日** @param startTime     开始时间* @param workdaysToAdd 需要添加的工作日天数* @param vacationList  节假日列表* @param workDayList   补班列表* @return LocalDateTime 返回添加工作日后的时间* @throws IOException 异常*/private LocalDateTime workDayAdd(LocalDateTime startTime, int workdaysToAdd, List<LocalDate> vacationList, List<LocalDate> workDayList) throws IOException {LocalDateTime result = startTime;// 今年最后一天LocalDateTime lastDayOfYear = LocalDateTime.of(LocalDate.of(startTime.getYear(), 12, 31), LocalTime.MAX);// 循环计算,直到工作日天数为0,或者到了今年最后一天while (workdaysToAdd > 0 && result.isBefore(lastDayOfYear)) {// 判断周一到周五,是否会放假,周六周日是否会补班result = result.plusDays(1);if (workDayNeedToWork(vacationList, result) && holidayNeedToWork(workDayList, result)) {workdaysToAdd--;}}// 如果还有剩余的工作日,就继续往后推if (workdaysToAdd > 0) {// 如果还有剩余的工作日,就继续往后推return jumpWorkDay(result, workdaysToAdd);}return result;}/*** 工作日需要去上班** @param vacationList 节假日列表* @param date         日期* @return boolean    工作日是否需要上班*/private boolean workDayNeedToWork(List<LocalDate> vacationList, LocalDateTime date) {DayOfWeek dayOfWeek = date.getDayOfWeek();boolean isWork = dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY;if (isWork) {// 如果是工作日,还需要判断是否会放假LocalDate localDate = LocalDate.from(date);return !vacationList.contains(localDate);}return true;}/*** 周六末需要去补班** @param workDayList 补班列表* @param date        日期* @return boolean    是否为休息日*/private boolean holidayNeedToWork(List<LocalDate> workDayList, LocalDateTime date) {DayOfWeek dayOfWeek = date.getDayOfWeek();boolean isHoliday = dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY;if (isHoliday) {// 如果是节假日,还需要判断是否是补班LocalDate localDate = LocalDate.from(date);return workDayList.contains(localDate);}return true;}/*** 获取某个日期所在年份的节假日配置数据,注:节假日指来自官方发布的有假节日,每年底政府公布后同步更新** @param date 日期* @return boolean*/public HolidayResponse getHolidayConfig(LocalDateTime date) throws IOException {// 节假日文件路径String savePath = String.format(FILE_FORMAT, DateUtil.format(date, "yyyy"));try {// 从文件中读取节假日HolidayResponse response = readJsonFromFile(savePath);if (response == null) {String url = "https://apis.tianapi.com/jiejiari/index";// 获取当年的节假日列表Map<String, String> params = new HashMap<>();params.put("key", tianApiProperties.getKey());params.put("date", DateUtil.format(date, "yyyy-MM-dd"));params.put("type", "1");String formData = httpConnector.fromData(params);String rspBody = httpConnector.doFormPost(url, formData);// 将json转换为对象Gson gson = new Gson();response = gson.fromJson(rspBody, HolidayResponse.class);// 将对象写入文件writeJsonToFile(response, savePath);}return response;} catch (IOException e) {log.error("Error during holiday configuration retrieval : {} , {}", savePath, e.getMessage());}return null;}/*** 将json写入文件** @param jsonObject jsonObject* @param filePath   文件路径*/private void writeJsonToFile(HolidayResponse jsonObject, String filePath) {try {// Create directory if it doesn't existPath parentDirectory = FileSystems.getDefault().getPath(filePath).getParent();if (parentDirectory != null && !Files.exists(parentDirectory)) {Files.createDirectories(parentDirectory);}try (FileOutputStream fos = new FileOutputStream(filePath)) {ObjectMapper objectMapper = new ObjectMapper();objectMapper.writeValue(fos, jsonObject);log.info("节假日文件写入成功 : {} , {}", filePath, jsonObject);} catch (Exception e) {log.error("节假日文件写入失败 : {} , {}", filePath, e.getMessage());}} catch (IOException e) {log.error("Error creating directory structure: {}", e.getMessage());}}/*** 从文件中读取节假日** @param filePath 文件路径* @return 节假日*/private HolidayResponse readJsonFromFile(String filePath) {try {// Create directory if it doesn't existPath parentDirectory = FileSystems.getDefault().getPath(filePath).getParent();if (parentDirectory != null && !Files.exists(parentDirectory)) {Files.createDirectories(parentDirectory);}try (FileInputStream fis = new FileInputStream(filePath)) {ObjectMapper objectMapper = new ObjectMapper();return objectMapper.readValue(fis, HolidayResponse.class);} catch (Exception e) {log.error("节假日文件读取失败 : {} , {}", filePath, e.getMessage());}} catch (IOException e) {log.error("Error creating directory structure: {}", e.getMessage());}return null;}
}

HttpConnector.java  (不重要,只是发起请求,可替换)

package com.xxx.app.common.utils.http;import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;/*** @author Jing* @desc http 连接工具类* https json post 请求用 doSSlPostRsp接口*/
@Setter
@Slf4j
@Service
public class HttpConnector {@Resourceprivate HttpClient httpClient;/*** 转拼接参数** @param url    接口地址* @param params 参数* @return 拼接后的参数*/public String addUrlParam(String url, Map<String, String> params) {if (MapUtils.isNotEmpty(params)) {StringBuilder sb = new StringBuilder(url);sb.append("?");for (String key : params.keySet()) {sb.append(key).append("=").append(params.get(key)).append("&");}url = sb.substring(0, sb.length() - 1);}return url;}/*** 发送带参数post请求 表单请求头** @param url      接口地址* @param postJson 传参* @return 响应数据*/public String doFormPost(String url, String postJson) throws IOException {HttpPost httpPost = new HttpPost(url);if (postJson != null) {httpPost.setHeader("Accept", "application/json");httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");httpPost.setEntity(new StringEntity(postJson, Consts.UTF_8));}Map<String, String> headers = new HashMap<>();return doRequest(headers, httpPost);}/*** 发送带参数post请求 表单请求头** @param url      接口地址* @param formData 传参* @return 响应数据*/public String doFormPost(String url, Map<String, String> headers, String formData) throws IOException {HttpPost httpPost = new HttpPost(url);if (formData != null) {httpPost.setHeader("Accept", "application/json");httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");httpPost.setEntity(new StringEntity(formData, Consts.UTF_8));}return doRequest(headers, httpPost);}/*** 发送带文件和请求头的post请求** @param url      接口地址* @param headers  请求头* @param file     文件* @param fileName 文件名* @return 响应数据*/public String doPost(String url, Map<String, String> headers, File file, String fileName) throws IOException {HttpPost httpPost = new HttpPost(url);if (file != null) {httpPost.setEntity(assemblyFileEntity(file, fileName));}return doRequest(headers, httpPost);}/*** 生成文件请求包** @param file 文件* @return http 请求体*/protected HttpEntity assemblyFileEntity(File file, String fileName) {MultipartEntityBuilder build = MultipartEntityBuilder.create();build.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);build.addBinaryBody("file", file);build.addTextBody("filename", StringUtils.isBlank(fileName) ? file.getName() : fileName);HttpEntity entity = build.build();return entity;}/*** 发送请求** @param headers     请求头* @param httpRequest request* @return 响应数据*/private String doRequest(Map<String, String> headers, HttpRequestBase httpRequest) throws IOException {HttpRspBO rspBO = doRequestRsp(headers, httpRequest);return rspBO.getBodyStr();}/*** 发送request 请求** @param headers* @param httpRequest 注意这个方法需要自己关闭*                    finally {*                    httpRequest.releaseConnection();*                    }* @return 带请求头的响应数据封装*/private HttpRspBO doRequestRsp(Map<String, String> headers, HttpRequestBase httpRequest) throws IOException {if (headers != null) {for (String key : headers.keySet()) {httpRequest.addHeader(key, headers.get(key));}}try {HttpResponse response = httpClient.execute(httpRequest);int statusCode = response.getStatusLine().getStatusCode();if (statusCode == HttpStatus.SC_OK) {HttpRspBO bo = new HttpRspBO();bo.setBodyStr(getEntity(response));HashMap<String, String> map = new HashMap<>();Header[] rspHeaders = response.getAllHeaders();int i = 0;while (i < rspHeaders.length) {map.put(rspHeaders[i].getName(), rspHeaders[i].getValue());i++;}bo.setHeaders(map);return bo;} else {String entity = getEntity(response);log.info("result msg " + entity);throw new FinMgwException("");}} finally {httpRequest.releaseConnection();}}/*** 解析返回请求体** @param response 返回参数* @return 字符串类型的请求体*/public String getEntity(HttpResponse response) throws IOException {HttpEntity entity = response.getEntity();if (entity == null) {throw new FinMgwException(ResultCodeEnum.HTTP_EXECUTE_EX.getCode(),ResultCodeEnum.HTTP_EXECUTE_EX.getDesc() + ", http response entity is null.");}String result;// 去掉首尾的 ""result = EntityUtils.toString(entity, Consts.UTF_8);String delStr = "\"";if (result.indexOf(delStr) == 0) {result = result.substring(1);}if (result.lastIndexOf(delStr) == result.length() - 1) {result = result.substring(0, result.length() - 1);}return result;}/*** 将参数转换为form data传参** @param param map集合* @return form data*/public String fromData(Map<String, String> param) {StringJoiner joiner = new StringJoiner("&");for (Map.Entry<String, String> map : param.entrySet()) {String data = String.format("%s=%s", map.getKey(), map.getValue());joiner.add(data);}return joiner.toString();}
}
 使用示例:

application.yml 配置

# 天行api
tianapi:# API密钥key: xxxxxxxxxxxxxxxxxxxxxxxxxxx

demo 代码:


@Slf4j
@Service
public class Demo {@Resourceprivate TianApiHolidayService tianApiHolidayService;public void get(){LocalDateTime publishTime = LocalDateTime.now()// 计算五个工作日后的日期LocalDateTime deadlineTime = tianApiHolidayService.jumpWorkDay(publishTime, 5);}}

理论上可以扩展很多方法,比如判断当前是否工作日/节假日,减去x个工作日之类的。但不太想写了,暂时用不着。

四、相关依赖

天行API申请:

节假日API接口 - 天行数据TianAPI

代码依赖:

Java 版本 = 1.8 

Maven 版本 = 3.9.2 

涉及maven依赖版本:

<!--SpringBoot 启动插件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.3.4.RELEASE</version><exclusions><exclusion><artifactId>log4j-api</artifactId><groupId>org.apache.logging.log4j</groupId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.4.RELEASE<</version></dependency><!--简化开发的jar 包--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional><version>1.18.16</version></dependency><!--日期转化--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.10</version></dependency><!--json解析--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.10.2</version></dependency><!--json解析--><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.9</version></dependency>

五、补充

附带上2024年的节假日数据,如果只是要判断2024年的,那直接把文件放在项目目录/.holiday 目录下即可,不需要再申请天行的API接口权限。

或者拿这个去调试代码也可以,但需要保证日期范围在2024年内,否则会自动调用天行API接口获取其他年份的数据。

文件名:2024_holiday.json

{"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天长假。"}]}
}

相关文章:

Java 实现自动获取法定节假日

一、背景 在实现业务需求的过程中&#xff0c;遇到了需要计算 x 个工作日后的日期需求。由于工作日是每年国务院发布的&#xff0c;调休和休假都没有规律&#xff0c;所以无法使用算法进行计算。 一般的实现方案是自己维护一个工作日和调休的表&#xff0c;或者去爬取国务院发…...

湘潭大学-2023年下学期-c语言-作业0x0a-综合1

A 求最小公倍数 #include<stdio.h>int gcd(int a,int b) {return b>0?gcd(b,a%b):a; }int main() {int a,b;while(~scanf("%d%d",&a,&b)){if(a0&&b0) break;printf("%d\n",a*b/gcd(a,b));}return 0; }记住最大公约数的函数&…...

网络协议-BIO实战和NIO编程

网络通信编程基本常识 在开发过程中&#xff0c;如果类的名字有 Server 或者 ServerSocket 的&#xff0c;表示这个类是给服务端容纳网络 服务用的&#xff0c;如果类的名字只包含 Socket 的&#xff0c;那么表示这是负责具体的网络读写的。 ServerSocket 并不负责具体的网络读…...

Word 将页面方向更改为横向或纵向

文章目录 更改整个文档的方向更改部分页面的方向方法1&#xff1a;方法2&#xff1a; 参考链接 更改整个文档的方向 选择“布局”>“方向”&#xff0c;选择“纵向”或“横向”。 更改部分页面的方向 需要达到下图结果&#xff1a; 方法1&#xff1a; 选:中你要在横向页面…...

关键字:abstract关键字

在 Java 中&#xff0c;abstract是一个关键字&#xff0c;用于修饰类和方法。当一个类被声明为抽象类时&#xff0c;它不能被实例化&#xff0c;只能被其他类继承。同时&#xff0c;抽象类可以包含抽象方法&#xff0c;抽象方法没有方法体&#xff0c;只包含方法的签名&#xf…...

从PDF中提取图片

由于工作需要&#xff0c;要从pdf文件中提取出图片保存到本地&#xff0c;项目中就引用到了Apache PDFBox库。 1 什么是Apache PDFBox? Apache PDFBox库&#xff0c;一个用于处理PDF文档的开源Java工具。它允许用户创建全新的PDF文件&#xff0c;操作现有的PDF文档&#xff0…...

推荐:一个不错的介绍Apache Doris的PPT

原来Apache Doris居然是百度开源出来的&#xff0c;不错。部分节选&#xff1a;完整下载地址网盘&#xff1a; 链接: https://pan.baidu.com/s/18WR70R_f72GxCjh0lykStQ 提取码: umd3 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 --来自百度网盘超级会员v7的分…...

【Python_PySide2学习笔记(二十二)】进度对话框QProgressDialog类的基本用法

进度对话框QProgressDialog类的基本用法 进度对话框QProgressDialog类的基本用法前言一、QProgressDialog 的常用方法1、创建进度对话框2、进度对话框设置窗口标题3、进度对话框隐藏"最大化"、"最小化"、"关闭"4、进度对话框设置是否自动关闭5、…...

使用rust读取usb设备ACR122U的nfc卡片id

rust及其高效和安全著称&#xff0c;而且支持跨平台&#xff0c;所以就想使用这个rust开发一个桌面端程序&#xff0c;来读取nfc设备的nfc卡片的id信息&#xff0c;下面就做一个最简单的入门教程吧&#xff0c;也是我写的第三个rust应用。 当你电脑上安装好了rust环境之后&…...

servlet总结

目录 1.生命周期 2.线程总结 3.配置 4.请求和响应 5.会话管理 6.过滤和监听器 7.处理表单数据 8.与JSP集成 9.异常处理 10.安全性和认证 Servlet是一种基于Java的Web组件&#xff0c;用于处理客户端请求并生成动态Web内容。以下是关于Servlet的一些总结 1.生命周期 …...

Nacos2.1.2改造适配达梦数据库7.0

出于业务需求&#xff0c;现将Nacos改造适配达梦数据库7.0&#xff0c;记录本次改造过程。 文章目录 一、前期准备二、适配流程1、项目初始化2、引入驱动3、源码修改 三、启动测试四、打包测试 一、前期准备 Nacos源码&#xff0c;版本&#xff1a;2.1.2&#xff1a;源码下载…...

TPRI-DMP平台介绍

TPRI-DMP平台介绍 1 TPRI-DMP平台概述 TPRI-DMP为华能集团西安热工院自主产权的工业云PaaS平台&#xff0c;已经过13年的发展和迭代&#xff0c;其具备大规模能源电力行业生产应用软件开发和运行能力。提供TPRI-DMP平台主数据管理、业务系统开发与运行、应用资源管理…...

oracle-存储结构

文件包括 控制文件.ctl、数据文件.dbf、日志文件.log这三类放在存储上。 参数文件&#xff1a;空间的划分&#xff0c;进程的选用&#xff08;.ora&#xff09; oracle启动的时候需要读一下&#xff0c;数据库启动后&#xff0c;参数文件并不关闭&#xff0c;但即使文件丢了&a…...

获取PG库 database与 user 创建时间以及cluster初始化时间

代码实现 echo "获取数据库创建时间" data_dir$(psql -U postgres -d postgres -X -qAt -c "show data_directory" ) db_dirs$(ls $data_dir/base |grep -v pgsql_tmp) for db_oid in $db_dirs dodb_exists$(psql -U postgres -d postgres -X -qAt -c &qu…...

【12.29】转行小白历险记-刷算法05

242.有效的字母异位词 数组、set、map&#xff0c;数组是比较高效查找的 函数功能 判断字符串 s 和 t 是否互为字母异位词。如果它们包含相同的字符且每个字符出现的次数也相同&#xff0c;那么它们互为字母异位词。 代码逻辑 长度检查&#xff1a; if (s.length ! t.lengt…...

docker部署kafka zookeeper模式集群

单机模式链接&#xff1a;https://blog.csdn.net/wsdhla/article/details/133032238 kraft集群模式链接&#xff1a;部署Kafka_kafka 部署-CSDN博客 zookeeper选举机制举例&#xff1a; 目前有5台服务器&#xff0c;每台服务器均没有数据&#xff0c;它们的编号分别是1,2,3,4,5…...

Apache Flink连载(二十一):Flink On Yarn运行原理-Yarn Application模式

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1. 任务提交命令...

《深入理解C++11:C++11新特性解析与应用》笔记五

第五章 提高类型安全 5.1 强类型枚举 5.1.1 枚举&#xff1a;分门别类与数值的名字 具名枚举类型一般声明类似&#xff1a;enum Gender { Male, Female }。 匿名枚举类型可以使用三种方式实现&#xff1a; 第一种方式时宏&#xff0c;比如 #define Male 0 #define Femal…...

Y9000P + ubuntu22.04 配置Anaconda+pycharm +pytorch

Anaconda3 的安装及使用方法安装 Anaconda3 Anaconda3 是 Anaconda 的具体版本 Anaconda3 中的 Python 解释器默认使用的是 Python3.x 版本&#xff0c;而不是 Python2.x 版本 Python2.x 版本中&#xff0c;字符串是以 ASCII 编码处理的&#xff0c;而在 Python3.x 版本中&am…...

使用Ubuntu编译FFmpeg生成Android动态库/静态库

环境 我这里使用windows里的wsl2的ubuntu&#xff0c;使用物理机或者vmware&#xff0c;vbox之类的安装的ubuntu理论上也可以. gcc编译使用的环境如下: Ndk使用17 FFmpeg使用4.0.2. clang编译使用的环境如下: Ndk使用21.4 FFmpeg使用6.1 FFmpeg下载地址:https://ffmpeg.org/…...

【AIGC-图片生成视频系列-2】八仙过海,各显神通:AI生成视频相关汇总剖析

最近「图片生成视频系列」层出不穷&#xff0c;我拜读并结合实践&#xff08;对&#xff0c;就是手撕代码&#xff0c;有开源就撕&#xff09;&#xff0c;并对以下几篇文章的相似点以及关键点稍微做个总结&#xff1a; 一. 生成视频中图像的一致性 在图像生成视频的这个过程…...

SpringBoot集成RabbitMq消息队列【附源码】

1. 项目背景 要啥项目背景&#xff0c;就是干&#xff01;&#xff01;&#xff01; SpringBoot版本&#xff1a;2.7.12 2. Rabbit MQ安装 这里讲解使用docker安装RabbitMQ&#xff0c;如果在windows下面安装RabbitMQ&#xff0c;参考下文 【笑小枫的按步照搬系列】Window…...

MySQL数据库的安装与环境配置

下载 下载MySQL8 安装 解压 配置MySQL环境变量 系统环境变量path D:\ProgramFiles\mysql-8.0.20-winx64\bin 1.点击属性 2.点击高级系统设置 3.点击环境变量 4.在系统变量中找到path 注意这里不是用户变量 5.新建后输入解压的地址 MySQL初始化和启动 以管理员身份运行cmd…...

【广州华锐互动】VR科技科普展厅平台:快速、便捷地创建出属于自己的虚拟展馆

随着科技的不断进步&#xff0c;虚拟现实(VR)技术已经在许多领域取得了显著的成果。尤其是在展馆设计领域&#xff0c;VR科技科普展厅平台已经实现了许多令人瞩目的新突破。 VR科技科普展厅平台是广州华锐互动专门为企业和机构提供虚拟展馆设计和制作的在线平台。通过这个平台&…...

XML Extension Supplement

LEGAL ISSUES, COMPANY POLICIES AND STANDARDS Web Services A Web service is a software system designed to support interoperable machine-to-machine interaction over a network. URI和URL URI&#xff0c;全称是统一资源标识符&#xff08;Uniform Resource Ident…...

手拉手Springboot获取yml配置文件信息

环境介绍 技术栈 springboot3 软件 版本 mysql 8 IDEA IntelliJ IDEA 2022.2.1 JDK 17 Spring Boot 3.1.7 配置文件说明&#xff1a;启动配置文件优先级&#xff1a;properties高于yml 配置文件application.yml yml是 JSON 的超集&#xff0c;简洁而强大&#xf…...

行人重识别(ReID)基础知识入门

这里写目录标题 1、ReID技术概述1.1 基本原理1.2 实现流程1.3 重识别存在的技术挑战 2、训练数据格式介绍 1、ReID技术概述 1.1 基本原理 ReID&#xff0c;全称Re-identification&#xff0c;目的是利用各种智能算法在图像数据库中找到与要搜索的目标相似的对象。ReID是图像检…...

【音视频 ffmpeg 学习】 跑示例程序 持续更新中

环境准备 在上一篇文章 把mux.c 拷贝到main.c 中 使用 attribute(unused) 消除警告 __attribute__(unused)/** Copyright (c) 2003 Fabrice Bellard** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated docu…...

前端axios与python库requests的区别

当涉及到发送HTTP请求时&#xff0c;Axios和Python中的requests库都是常用的工具。下面是它们的详细说明&#xff1a; Axios&#xff1a; Axios是一个基于Promise的HTTP客户端&#xff0c;主要用于浏览器和Node.js环境中发送HTTP请求。以下是Axios的一些特点和用法&#xff1…...

达梦数据库文档

1&#xff1a;达梦数据库(DM8)简介 达梦数据库管理系统是武汉达梦公司推出的具有完全自主知识产权的高性能数据库管理系统&#xff0c;简称DM。达梦数据库管理系统目前最新的版本是8.0版本&#xff0c;简称DM8。 DM8是达梦公司在总结DM系列产品研发与应用经验的基础上&#xf…...

CorelDRAW2024新功能有哪些?CorelDRAW2024最新版本更新怎么样?

CorelDRAW2024新功能有哪些&#xff1f;CorelDRAW2024最新版本更新怎么样&#xff1f;让我们带您详细了解&#xff01; CorelDRAW Graphics Suite 是矢量制图行业的标杆软件&#xff0c;2024年全新版本为您带来多项新功能和优化改进。本次更新强调易用性&#xff0c;包括更强大…...

基于Mapify的在线艺术地图设计

地图是传递空间信息的有效载体&#xff0c;更加美观、生动的地图产品也是我们追求目标。 那么&#xff0c;我们如何才能制出如下图所示这样一幅艺术性较高的地图呢&#xff1f;今天我们来一探究竟吧&#xff01; 按照惯例&#xff0c;现将网址给出&#xff1a; https://www.m…...

mxxWechatBot微信机器人V2版本文档说明

大家伙&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 先看这里 一、前言二、mxxWechatBot流程图三、怎么使用&#xff1f; 一、前言 经过不断地探索与研究&#xff0c;mxxWechatBot正式上线&#xff0c;届时全面开放使用。 mxxWechatBot&am…...

红队打靶练习:MISDIRECTION: 1

信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:69:c7:bf, IPv4: 192.168.12.128 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.12.1 00:50:56:c0:00:08 …...

Jmeter吞吐量控制器总结

吞吐量控制器(Throughput Controller) 场景&#xff1a; 在同一个线程组里, 有10个并发, 7个做A业务, 3个做B业务,要模拟这种场景,可以通过吞吐量模拟器来实现。 添加吞吐量控制器 用法1: Percent Executions 在一个线程组内分别建立两个吞吐量控制器, 分别放业务A和业务B …...

【XML】TinyXML 详解(二):接口详解

【C】郭老二博文之&#xff1a;C目录 1、XML测试文件&#xff08;laoer.xml&#xff09; <?xml version"1.0" standalone"no" ?> <!-- Hello World !--> <root><child name"childName" id"1"><c_child…...

【机器学习】人工智能概述

人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;是一门研究如何使机器能够像人一样思考、学习和执行任务的学科。它是计算机科学的一个重要分支&#xff0c;涉及机器学习、自然语言处理、计算机视觉等多个领域。 人工智能的概念最早可以追溯到20世…...

flink 实时写入 hudi 参数推荐

数据湖任务并行度计算...

传统项目基于tomcat cookie单体会话升级分布式会话解决方案

传统捞项目基于servlet容器 cookie单体会话改造分布式会话方案 ##引入redis,spring-session依赖 <!--redis依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>&…...

Unity 关于json数据的解析方式(LitJson.dll插件)

关于json数据的解析方式&#xff08;LitJson.dll插件&#xff09; void ParseItemJson(){TextAsset itemText Resources.Load<TextAsset>("Items");//读取Resources中Items文件&#xff0c;需要将Items文件放到Resources文件夹中string itemJson itemText.te…...

智能监控平台/视频共享融合系统EasyCVR海康设备国标GB28181接入流程

TSINGSEE青犀视频监控汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力&…...

expdp到ASM 文件系统 并拷贝

1.创建asm导出数据目录 sql>select name,total_mb,free_mb from v$asm_diskgroup; 确认集群asm磁盘组环境 asmcmd>cd DGDSDB asmcmd>mkdir dpbak asmcmd>ls -l sql>conn / as sysdba create directory expdp_asm_dir as DGDSDB/dpbak; create directory expdp_l…...

【2023】通过docker安装hadoop以及常见报错

&#x1f4bb;目录 1、准备2、安装镜像2.1、创建centos-ssh的镜像2.2、创建hadoop的镜像 3、配置ssh网络3.1、搭建同一网段的网络3.2、配置host实现互相之间可以免密登陆3.3、查看是否成功 4、安装配置Hadoop4.1、添加存储文件夹4.2、添加指定配置4.3、同步数据 5、测试启动5.1…...

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取相机当前实时帧率(C++)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取相机当前实时帧率&#xff08;C&#xff09; Baumer工业相机Baumer工业相机的帧率的技术背景Baumer工业相机的帧率获取方式CameraExplorer如何查看相机帧率信息在NEOAPI SDK里通过函数获取相机帧率&#xff08;C&#xff09; …...

SpringBoot项目部署及多环境

1、多环境 2、项目部署上线 原始前端 / 后端项目宝塔Linux容器容器平台 3、前后端联调 4、项目扩展和规划 多环境 程序员鱼皮-参考文章 本地开发&#xff1a;localhost&#xff08;127.0.0.1&#xff09; 多环境&#xff1a;指同一套项目代码在把不同的阶段需要根据实际…...

WebGL以及wasm的介绍以及简单应用

简介 下面主要介绍了WebGL和wasm,是除了html,css,js以外Web标准所支持的另外两个大件 前者实现复杂的图形处理,后者提供高效的代码迁移以及代码执行效率 WebGL 简介 首先,浏览器里的游戏是怎么做到这种交互又显示不同的画面的? 试想用我们的前端三件套实现一下.好像可以…...

JS和TS的基础语法学习以及babel的基本使用

简介 本文主要介绍了一下js和ts的基础语法,为前端开发zuo JavaScript 更详细的 JavaScript 学习资料&#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/JavaScript 简介 定位 : JavaScript 是一种动态语言&#xff0c;它包含类型、运算符、标准内置&#xff08; bu…...

Centos安装Composer

今天分享下如何在centos系统里安装composer 一、下载composer curl -sS https://getcomposer.org/installer | php二、移动或复制composer到环境下可执行 cp composer.phar /usr/local/bin/composer三、测试看是否安装成功 composer -V四、全局安装 curl -sS https://getc…...

面试题:从 MySQL 读取 100w 数据进行处理,应该怎么做?

文章目录 背景常规查询流式查询MyBatis 流式查询接口为什么要用流式查询&#xff1f; 游标查询OptionsResultType注意&#xff1a;原因&#xff1a; 非流式查询和流式查询区别&#xff1a; 背景 大数据量操作的场景大致如下&#xff1a; 数据迁移数据导出批量处理数据 在实际…...

销售转行上位机编程:我的学习与职业经历分享

同学们好&#xff0c;我是杨工&#xff0c;原先是一名销售。 通过在华山编程培训中心学习&#xff0c;成功转行上位机编程&#xff0c;对此我想分享学习和职业经历。 在职业生涯的早期&#xff0c;我并没有考虑将技术融入到我的工作中。然而&#xff0c;在几次创业的失败后&a…...