调用电商集成平台 聚水潭 api接口示例
先上工具类
package com.zuodou.utlis;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import javax.xml.crypto.Data;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.*;
import java.util.Map.Entry;
import java.util.zip.GZIPInputStream;
@Component
public class ApiUtils {private static final String SIGN_METHOD_MD5 = "md5";private static final String CHARSET_UTF8 = "utf-8";private static final String CONTENT_ENCODING_GZIP = "gzip";// TOP服务地址,正式环境需要设置为https://openapi.jushuitan.com
// @Value("${erp.serverUrl}")
// public String serverUrl;
//
// @Value("${erp.appKey}")
// public String appKey; // 可替换为您的应用的appKey
//
// @Value("${erp.appSecret}")
// public String appSecret; // 可替换为您的应用的appSecret
//
// @Value("${erp.accessToken}")
// public String accessToken; // 必须替换为授权得到的真实有效accessTokenpublic static String serverUrl;public static String appKey;public static String appSecret;public static String accessToken;@Value("${erp.serverUrl}")public void setServerUrl(String serverUrl) {ApiUtils.serverUrl = serverUrl;}@Value("${erp.appKey}")public void setAppKey(String appKey) {ApiUtils.appKey = appKey;}@Value("${erp.appSecret}")public void setAppSecret(String appSecret) {ApiUtils.appSecret = appSecret;}@Value("${erp.accessToken}")public void setAccessToken(String accessToken) {ApiUtils.accessToken = accessToken;}/**** @param fangfa* @return* @throws IOException*/public static String getSellerItem(String fangfa, String biz) throws IOException {Map<String, String> params = new HashMap<String, String>();// 公共参数params.put("app_key",appKey);params.put("access_token", accessToken);params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));params.put("version", "2");params.put("charset", "utf-8");// 业务参数params.put("biz", biz);// 签名参数params.put("sign", signTopRequest(params, appSecret, SIGN_METHOD_MD5));// 调用APIreturn callApi(new URL(serverUrl+fangfa), params);}/*** 对TOP请求进行签名。*/private static String signTopRequest(Map<String, String> params, String secret, String signMethod) throws IOException {// 第一步:检查参数是否已经排序String[] keys = params.keySet().toArray(new String[0]);Arrays.sort(keys);// 第二步:把所有参数名和参数值串在一起StringBuilder query = new StringBuilder();if (SIGN_METHOD_MD5.equals(signMethod)) {query.append(secret);}for (String key : keys) {String value = params.get(key);if (isNotEmpty(key) && isNotEmpty(value)) {query.append(key).append(value);}}return createSign(query.toString());}/*** 生成新sign** @param str 字符串* @return String*/private static String createSign(String str) {if (str == null || str.length() == 0) {return null;}char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};try {MessageDigest mdTemp = MessageDigest.getInstance(SIGN_METHOD_MD5);mdTemp.update(str.getBytes("UTF-8"));byte[] md = mdTemp.digest();int j = md.length;char[] buf = new char[j * 2];int k = 0;int i = 0;while (i < j) {byte byte0 = md[i];buf[k++] = hexDigits[byte0 >>> 4 & 0xf];buf[k++] = hexDigits[byte0 & 0xf];i++;}return new String(buf);} catch (Exception e) {return null;}}private static String callApi(URL url, Map<String, String> params) throws IOException {String query = buildQuery(params, CHARSET_UTF8);byte[] content = {};if (query != null) {content = query.getBytes(CHARSET_UTF8);}HttpURLConnection conn = null;OutputStream out = null;String rsp = null;try {conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("POST");conn.setDoInput(true);conn.setDoOutput(true);conn.setRequestProperty("Host", url.getHost());conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + CHARSET_UTF8);out = conn.getOutputStream();out.write(content);rsp = getResponseAsString(conn);} finally {if (out != null) {out.close();}if (conn != null) {conn.disconnect();}}return rsp;}private static String buildQuery(Map<String, String> params, String charset) throws IOException {if (params == null || params.isEmpty()) {return null;}StringBuilder query = new StringBuilder();Set<Entry<String, String>> entries = params.entrySet();boolean hasParam = false;for (Entry<String, String> entry : entries) {String name = entry.getKey();String value = entry.getValue();// 忽略参数名或参数值为空的参数if (isNotEmpty(name) && isNotEmpty(value)) {if (hasParam) {query.append("&");} else {hasParam = true;}query.append(name).append("=").append(URLEncoder.encode(value, charset));}}return query.toString();}private static String getResponseAsString(HttpURLConnection conn) throws IOException {String charset = getResponseCharset(conn.getContentType());if (conn.getResponseCode() < 400) {String contentEncoding = conn.getContentEncoding();if (CONTENT_ENCODING_GZIP.equalsIgnoreCase(contentEncoding)) {return getStreamAsString(new GZIPInputStream(conn.getInputStream()), charset);} else {return getStreamAsString(conn.getInputStream(), charset);}} else {// Client Error 4xx and Server Error 5xxthrow new IOException(conn.getResponseCode() + " " + conn.getResponseMessage());}}private static String getStreamAsString(InputStream stream, String charset) throws IOException {try {Reader reader = new InputStreamReader(stream, charset);StringBuilder response = new StringBuilder();final char[] buff = new char[1024];int read = 0;while ((read = reader.read(buff)) > 0) {response.append(buff, 0, read);}return response.toString();} finally {if (stream != null) {stream.close();}}}private static String getResponseCharset(String ctype) {String charset = CHARSET_UTF8;if (isNotEmpty(ctype)) {String[] params = ctype.split(";");for (String param : params) {param = param.trim();if (param.startsWith("charset")) {String[] pair = param.split("=", 2);if (pair.length == 2) {if (isNotEmpty(pair[1])) {charset = pair[1].trim();}}break;}}}return charset;}private static boolean isNotEmpty(String value) {int strLen;if (value == null || (strLen = value.length()) == 0) {return false;}for (int i = 0; i < strLen; i++) {if ((Character.isWhitespace(value.charAt(i)) == false)) {return true;}}return false;}public static void main(String[] args) {int pageNo = 1;int pageSize = 100;boolean hasMoreData = true;List<Data> allData = new ArrayList<>();while (hasMoreData) {List<Data> currentPageData = callThirdPartyApi(pageNo, pageSize); // 调用第三方API获取当前页数据allData.addAll(currentPageData); // 将当前页数据加入总数据集合if (currentPageData.size() < pageSize) {hasMoreData = false; // 当前页数据不足pageSize,表示已获取所有数据} else {pageNo++; // 继续获取下一页数据}}// 所有数据已获取完成System.out.println("Total data count: " + allData.size());// 进一步处理allData集合...}// 调用第三方API获取指定页数据的示例方法private static List<Data> callThirdPartyApi(int pageNo, int pageSize) {// 调用第三方API获取指定页的数据// 返回数据列表return new ArrayList<>(); // 这里仅作示例,实际应调用API并返回数据}}
需求说明,需要把聚水潭所有的售后数据拉取到自研平台进行进一步操作。
调用接口的限制:分页,每页数量50,请求限制,一秒钟不能超过5次,一分钟不能超过一百次。
注意代码待完善:accessToken是有过期时间的,但可以在主账号设置,如果超过限制我不会进行记录会漏掉这条数据。有一些注入的地方可以删掉。我定义了一个erpDatas和erpItems类来接收数据,由于返回值是下划线的,而我项目架构是驼峰命名,会导致映射值失败,最下面是处理方法(可以不用的自行删除)。
package com.zuodou.job;import com.zuodou.mapper.ZuodouTaskDatasMapper;import com.zuodou.utlis.DataUtil;
import com.zuodou.utlis.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;import java.util.*;/*** 售后*/@Slf4j
//禁止并发执行
@DisallowConcurrentExecution
public class TaskDatas implements Job {@Autowiredprivate ZuodouTaskDatasMapper zuodouTaskDatasMapper;@Autowiredprivate threadService threadService;/*** 若参数变量名修改 QuartzJobController中也需对应修改*/private String parameter;public void setParameter(String parameter) {this.parameter = parameter;}private String parameterstartime;public void setParameterstartime(String parameterstartime) {this.parameterstartime = parameterstartime;}/*** 拿售后数据* @param jobExecutionContext* @throws JobExecutionException** token过期* 1.请求状态* 2.时间间隔七天* 3.分页数据* /open/refund/single/query**/@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {try {//1.拿到数据库中最大时间 如果没有,默认多少,如果有生成一个七天时间lsit//1.1 先判断数据库时间和当前时间是否相差七天,相差七天就减,没有相差就用当前时间当作结束时间//2.在每个七天里面分页拿取数据,data_count 总数,page_count 有多少页//3.把分页数据整合到list中// for (String shopId : Shop_id) {String start = zuodouTaskDatasMapper.maxOrdersDate(null);String end = TimeUtils.getStringDate();//比当前时间少一分钟,防止数据重复if (StringUtils.isBlank(start)) {start = this.parameterstartime;}log.info("聚水潭售后数据拉取开始-------"+TimeUtils.date2Str(new Date()));Date CalendarstartTime = TimeUtils.DateSwitch(start);Date CalendarendTime = TimeUtils.DateSwitch(end);Calendar startCal = Calendar.getInstance();startCal.setTime(CalendarstartTime) ;Calendar endCal = Calendar.getInstance();endCal.setTime(CalendarendTime);String startTime =start;String endTime =null;while (!start.equals(end)) { //当开始时间大于或者等于结束时间Integer day = DataUtil.countDaynew(start,end );if (day>7) {startCal.add(Calendar.DAY_OF_MONTH, 7);endTime = TimeUtils.date2Str(startCal.getTime());Integer daya = DataUtil.countDaynew(endTime, end); //判断结束时间加上七天跟当前时间的间隔if (daya <1) { //如果加上七天大于当前时间或者等于endTime=end;}}if (StringUtils.isBlank(endTime)){endTime=end;}System.out.println(startTime+"-----3---"+endTime);String finalStartTime = startTime;String finalEndTime = endTime;threadService.apithread(finalStartTime, finalEndTime);Integer days = DataUtil.countDaynew(startTime,endTime );Integer daya = DataUtil.countDaynew(endTime, end);if (days==7){ //超过七天startTime = endTime;} else if (days>0&&daya==0){startTime = endTime;//累计七天的结束时间endTime = end; //结束时间为当前时间start = end; //设置停止循环}else if(daya<7){endTime=end;start=end;//用于结束循环}}// }} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) {String start = "2023-10-09 13:41:20";String end = TimeUtils.getStringDate();//比当前时间少一分钟,防止数据重复if (StringUtils.isBlank(start)) {start = "2023-08-01 00:00:00";}Date CalendarstartTime = TimeUtils.DateSwitch(start);Date CalendarendTime = TimeUtils.DateSwitch(end);Calendar startCal = Calendar.getInstance();startCal.setTime(CalendarstartTime) ;Calendar endCal = Calendar.getInstance();endCal.setTime(CalendarendTime);String startTime =start;String endTime =null;while (!start.equals(end)) { //当开始时间大于或者等于结束时间Integer day = DataUtil.countDaynew(start,end );if (day>7) {startCal.add(Calendar.DAY_OF_MONTH, 7);endTime = TimeUtils.date2Str(startCal.getTime());Integer daya = DataUtil.countDaynew(endTime, end); //判断结束时间加上七天跟当前时间的间隔if (daya <1) { //如果加上七天大于当前时间或者等于endTime=end;}}if (StringUtils.isBlank(endTime)){endTime=end;}System.out.println(startTime+"-----3---"+endTime);Integer days = DataUtil.countDaynew(startTime,endTime );Integer daya = DataUtil.countDaynew(endTime, end);if (days==7){ //超过七天startTime = endTime;} else if (days>0&&daya==0){startTime = endTime;//累计七天的结束时间endTime = end; //结束时间为当前时间start = end; //设置停止循环}else if(daya<7){endTime=end;start=end;//用于结束循环}}}}
package com.zuodou.job;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.zuodou.entity.ZuodouTaskDatas;
import com.zuodou.entity.ZuodouTaskItem;
import com.zuodou.enums.CommonConstant;
import com.zuodou.enums.ErpStatusEnum;
import com.zuodou.erpmodel.erpData;
import com.zuodou.erpmodel.erpDatas;
import com.zuodou.erpmodel.erpItems;
import com.zuodou.mapper.ZuodouTaskDatasMapper;
import com.zuodou.model.*;
import com.zuodou.service.IZuodouTaskDatasService;
import com.zuodou.service.IZuodouTaskItemService;
import com.zuodou.utlis.BaseUtlis;
import com.zuodou.utlis.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import java.io.IOException;
import java.util.*;import static com.zuodou.utlis.ApiUtils.getSellerItem;@Service
@Slf4j
public class threadService {@Autowiredprivate IZuodouTaskItemService zuodouTaskItemService;@Autowiredprivate IZuodouTaskDatasService iZuodouTaskDatasService;@Autowiredprivate ZuodouTaskDatasMapper zuodouTaskDatasMapper;public void apithread(String finalStartTime, String finalEndTime) {log.info("执行售后任务时间"+finalStartTime+"----"+finalEndTime);List<ZuodouTaskDatas> zuodouTaskDatas = new ArrayList<>();List<ZuodouTaskDatas> updatezuodouTaskDatas = new ArrayList<>();List<ZuodouTaskItem> zuodouTaskItemList = new ArrayList<>();List<ZuodouTaskItem> updatezuodouTaskItemList = new ArrayList<>();List<erpDatas> orders = new ArrayList<>();ObjectMapper objectMapper=new ObjectMapper();OrderQueryParams queryParams = new OrderQueryParams();queryParams.setModified_begin(finalStartTime).setModified_end(finalEndTime).setPage_index(1).setPage_size(50);try {String valueAsString = objectMapper.writeValueAsString(queryParams);JsonNode jsonNode = objectMapper.readTree(getSellerItem("/open/refund/single/query", valueAsString));String msg = jsonNode.get("msg").asText();String code = jsonNode.get("code").asText();if (StringUtils.equals(msg, "执行成功") && StringUtils.equals(code, "0")) {Integer page_count = 0;//有多少页JsonNode dataNode = jsonNode.get("data");erpData erpData = null;erpData = objectMapper.treeToValue(dataNode, erpData.class);page_count += erpData.getPage_count();if (page_count > 0) {for (int j = 1; j <= page_count; j++) {OrderQueryParams queryParamsdata_count = new OrderQueryParams();queryParamsdata_count.setModified_begin(finalStartTime).setModified_end(finalEndTime).setPage_index(j).setPage_size(50);String valueAsStrings = null;valueAsStrings = objectMapper.writeValueAsString(queryParamsdata_count);JsonNode jsonNodes = objectMapper.readTree(getSellerItem("/open/refund/single/query", valueAsStrings));String msgs = jsonNodes.get("msg").asText();String codes = jsonNodes.get("code").asText();JsonNode dataNodea = jsonNodes.get("data");if (StringUtils.equals(msgs, "执行成功") && StringUtils.equals(codes, "0")) {log.info("售后数据执行成功"+msgs);JsonNode dataNodes = dataNodea.get("datas");//拿到数据结构if (dataNodes instanceof ArrayNode) {ArrayNode ordersArrayNode = (ArrayNode) dataNodes;for (JsonNode orderNode : ordersArrayNode) {erpDatas order = objectMapper.treeToValue(orderNode, erpDatas.class);orders.add(order);}}} else {log.info("售后数据执行失败"+msgs);}try {// 在apithread方法中休息两秒Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}log.info("聚水潭售后数据拉取结束-----"+ TimeUtils.date2Str(new Date()));} else {log.info("外层分页售后"+msg);}try {// 在apithread方法中休息两秒Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}insertOrdersData(orders, zuodouTaskDatas,updatezuodouTaskDatas, zuodouTaskItemList,updatezuodouTaskItemList);log.info("开始插入售后数据----"+zuodouTaskDatas.size() + "商品数据---"+zuodouTaskItemList.size()+"需要修改售后数据--"+updatezuodouTaskDatas.size());iZuodouTaskDatasService.saveBatch(zuodouTaskDatas);zuodouTaskItemService.saveBatch(zuodouTaskItemList);iZuodouTaskDatasService.updateBatchById(updatezuodouTaskDatas);zuodouTaskItemService.updateBatchById(updatezuodouTaskItemList);} catch (JsonProcessingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}catch (Exception e){e.printStackTrace();}}private void insertOrdersData(List<erpDatas> orders, List<ZuodouTaskDatas> zuodouTaskOrdersList, List<ZuodouTaskDatas> updatezuodouTaskOrdersList, List<ZuodouTaskItem> zuodouTaskItemList,List<ZuodouTaskItem> updatezuodouTaskItemList ) throws IllegalAccessException, IOException, InterruptedException {if (!CollectionUtils.isEmpty(orders)){for (erpDatas order : orders) {ZuodouTaskDatas zuodouTaskDatas=new ZuodouTaskDatas();BaseUtlis.copyProperties(order,zuodouTaskDatas);String asId = zuodouTaskDatasMapper.oIdasIddatas(order.getO_id(), order.getAs_id());
// boolean exists = zuodouTaskOrdersList.stream()
// .anyMatch(obj -> obj.getOId().equals(order.getO_id()) && obj.getAsId() .equals(order.getAs_id()));boolean exists = zuodouTaskOrdersList.stream().anyMatch(obj -> obj.getAsId() .equals(order.getAs_id()));if (exists) {//如果插入的list中有那个值就直接跳过continue;}else if (StringUtils.isNotBlank(asId)) {zuodouTaskDatas.setAsId(asId);zuodouTaskDatas.setStatusName(ErpStatusEnum.getValueName(order.getStatus(), CommonConstant.STATUS));zuodouTaskDatas.setShopStatusName(ErpStatusEnum.getValueName(order.getShop_status(),CommonConstant.SHOP_STATUS));zuodouTaskDatas.setGoodStatusName(ErpStatusEnum.getValueName(order.getGood_status(),CommonConstant.GOOD_STATUS));zuodouTaskDatas.setOrderStatusName(ErpStatusEnum.getValueName(order.getOrder_status(),CommonConstant.ORDER_STATUS));zuodouTaskDatas.setOrderlabels(String.join(",",order.getOrder_labels()));updatezuodouTaskOrdersList.add(zuodouTaskDatas);for (erpItems item : order.getItems()) {ZuodouTaskItem zuodouTaskItem=new ZuodouTaskItem();BaseUtlis.copyProperties(item,zuodouTaskItem);zuodouTaskItem.setSkuTypeName(ErpStatusEnum.getValueName(item.getSku_type(),CommonConstant.SKU_TYPE));zuodouTaskItem.setSkuType(item.getSku_type());updatezuodouTaskItemList.add(zuodouTaskItem);}}else{zuodouTaskDatas.setStatusName(ErpStatusEnum.getValueName(order.getStatus(),CommonConstant.STATUS));zuodouTaskDatas.setShopStatusName(ErpStatusEnum.getValueName(order.getShop_status(),CommonConstant.SHOP_STATUS));zuodouTaskDatas.setGoodStatusName(ErpStatusEnum.getValueName(order.getGood_status(),CommonConstant.GOOD_STATUS));zuodouTaskDatas.setOrderStatusName(ErpStatusEnum.getValueName(order.getOrder_status(),CommonConstant.ORDER_STATUS));zuodouTaskDatas.setOrderlabels(String.join(",",order.getOrder_labels()));if (!CollectionUtils.isEmpty(order.getItems())){for (erpItems item : order.getItems()) {ZuodouTaskItem zuodouTaskItem=new ZuodouTaskItem();BaseUtlis.copyProperties(item,zuodouTaskItem);zuodouTaskItem.setSkuTypeName(ErpStatusEnum.getValueName(item.getSku_type(),CommonConstant.SKU_TYPE));zuodouTaskItem.setSkuType(item.getSku_type());zuodouTaskItemList.add(zuodouTaskItem);}}zuodouTaskOrdersList.add(zuodouTaskDatas);}}}}}
public static void copyProperties(Object source, Object destination) throws IllegalAccessException {Field[] sourceFields = source.getClass().getDeclaredFields();Field[] destinationFields = destination.getClass().getDeclaredFields();for (Field sourceField : sourceFields) {sourceField.setAccessible(true);String sourceFieldName = sourceField.getName();String destinationFieldName = convertToCamelCase(sourceFieldName); // 将下划线命名转换为驼峰命名for (Field destinationField : destinationFields) {if (destinationField.getName().equals(destinationFieldName)) {destinationField.setAccessible(true);destinationField.set(destination, sourceField.get(source));break;}}} }
相关文章:
调用电商集成平台 聚水潭 api接口示例
先上工具类 package com.zuodou.utlis;import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;import javax.xml.crypto.Data; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import j…...

深入Rust:探索所有权和借用机制
大家好!我是lincyang。 今天,我们将一起深入探索Rust语言中的一个核心概念:所有权和借用机制。 这些特性是Rust区别于其他语言的重要特点,它们在内存管理和并发编程中扮演着关键角色。 一、Rust所有权机制 1. 什么是所有权&#x…...
Python之冒泡排序(AI自动写文章项目测试)
全自动AI生成文章测试,如有不合理地方,请见谅。 一、冒泡排序简介 1.1 冒泡排序概述 冒泡排序(Bubble Sort)是一种简单的排序算法,通过不断交换相邻元素的位置,将最大(或最小)的元…...

spring cloud微服务中多线程下,子线程通过feign调用其它服务,请求头token等丢失
在线程池中,子线程调用其他服务,请求头丢失,token为空的情况 看了很多篇文章的处理方法和在自己亲测的情况下做出说明: 第一种: 这种方式只支持在主线程情况下,能够处理,在多线程情况下&#…...
Nacos 高级玩法:深入探讨分布式配置和服务发现
🎏:你只管努力,剩下的交给时间 🏠 :小破站 Nacos 高级玩法:深入探讨分布式配置和服务发现 前言第一:nacos高级配置管理1. 动态配置的基本使用:2. 监听策略的原理和实现:3…...

CCF CSP认证历年题目自练Day45
这几天搞泰迪杯数据分析技能赛去了。等拿国奖了就出一期关于泰迪杯的。 题目 试题编号: 201703-3 试题名称: Markdown 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 Markdown 是一种很流行的轻量级标记…...
outlook群发邮件
一米群发软件使用Outlook进行群发邮件的步骤如下: 打开Outlook软件,点击页面上方的“新建电子邮件”选项。在弹出的新邮件中,输入收件人和邮件主题,在收件人输入框中输入多个需要接收邮件的邮箱地址,用分号࿰…...

【Attack】针对GNN-based假新闻检测器
Attacking Fake News Detectors via Manipulating News Social Engagement AbstractMotivationContributions FormulationMethodologyAttacker Capability(针对挑战1)Agent Configuration(针对挑战3) WWW’23, April 30-May 4, 20…...

APIcloud 【现已更名 用友开发中心】 iOS发版 应用程序请求用户同意访问相机和照片,但没有在目的字符串中充分说明相机和照片的使用。
iOS 审核时 提示 首次安装软件 获取相机 相册 提示信息 怎么修改 我们注意到你的应用程序请求用户同意访问相机和照片,但没有在目的字符串中充分说明相机和照片的使用。 为了解决这个问题,修改应用信息中的目的字符串是合适的。相机和照片的Plist文件&a…...
记一次弱口令之后引发的获取服务器权限
文章目录 一、漏洞原因二、漏洞成果三、漏洞利用1、管理员权限2、信息泄露3、服务器权限4、数据库权限5、 PHPMyadmin后台管理系统四、总结五、免责声明一、漏洞原因 由于网站登录口未做双因子校验,导致可以通过暴力破解获取管理员账号,成功进入系统;由于未对个人信息进行脱…...

AJAX入门Day01笔记
Day01_Ajax入门 知识点自测 如下对象取值的方式哪个正确? let obj {name: 黑马 }A: obj.a B: obj()a 答案 A选项正确 哪个赋值会让浏览器解析成标签显示? let ul document.querySelector(#ul) let str <span>我是span标签</span>A: ul.innerText str B: ul…...
spring boot 环境变量问题
org.yaml.snakeyaml.scanner.ScannerException: while scanning for the next token found character that cannot start any token. (Do not use for indentation) in reader, line 4, column 13: active: spring.profiles.active 添加 以下依赖即可 <!-- 解决环…...

Javaweb开发 利用servlet+jsp+jdbc+tomcat数据库实现登录功能
前言:很久没更新了,今天给大家分享一个Java web的小案例,是一个登录页面,利用Login控制类和JDBC连接数据库,并判断用户名密码是否正确,项目最终部署在Tomcat上。 先看效果 正文 一、前期工作 1.首先我们…...

flutter下拉列表
下拉列表 内容和下拉列表的标题均可滑动 Expanded: 内容限制组件,将其子类中的无限扩展的界面限制在一定范围中。在此使用,是为了防止下拉列表中的内容超过了屏幕限制。 SingleChildScrollView: 这个组件,从名字中可…...
ElastaticSearch -- es深度分页 searchAfter
searchAfter深度分页 es一次只能查1万条数据,如果超过1万,会报错如下: "reason": {"type": "query_phase_execution_exception","reason": "Result window is too large, from size must be …...

【2021集创赛】Arm杯二等奖-基于Arm核的智慧病房手势识别方案
团队介绍 参赛单位:上海交通大学 队伍名称:芯灵手巧 指导老师:王琴、景乃锋 参赛队员:林圣凯、林新源、莫志文 总决赛奖项:二等奖 1.项目概述 1.1 选题背景 我们的选题背景是考虑到很多卧床病人不便于独自向医护人…...
通过注解统计接口调用耗时
要通过注解统计接口调用耗时,可以按照以下步骤进行操作: 首先,在您的项目中引入一个AOP(面向切面编程)框架,比如Spring AOP或AspectJ。这些框架可以帮助您在方法执行前后插入额外的逻辑。 创建一个自定义的…...

Oracle-动态sql学习笔记,由易至难讲解七个例子
本文章的内容来源于对oracle课堂上讲的内容做出的笔记 静态sql和动态sql 静态sql: 静态 SQL 是在编译时写死的 SQL 语句,即在程序编写阶段,SQL 语句已经被固定下来。 特点: 1.预编译: SQL 语句在程序编译时就会被…...

Kafka 的应用场景
Kafka 是一个开源的分布式流式平台,它可以处理大量的实时数据,并提供高吞吐量,低延迟,高可靠性和高可扩展性。 Kafka 最初是为分布式系统中海量日志处理而设计的。它可以通过持久化功能将消息保存到磁盘,并让消费者按…...

保驾“双十一” 博睿数据助力电商零售迎高峰无烦忧
如果说“双十一”大战的A面是由天猫、京东、拼多多、唯品会等电商平台,以及一些MCN机构、头部主播拉动的一系列购物狂潮,那么B面则是零售、物流、制造、银行保险等全产业链面对海量流量之下,以强大的心力、脑力与体力应对流量增加和交易陡增的…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...