调用电商集成平台 聚水潭 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面则是零售、物流、制造、银行保险等全产业链面对海量流量之下,以强大的心力、脑力与体力应对流量增加和交易陡增的…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...

如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...
【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析
1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器(TI)推出的一款 汽车级同步降压转换器(DC-DC开关稳压器),属于高性能电源管理芯片。核心特性包括: 输入电压范围:2.95V–6V,输…...

2025-05-08-deepseek本地化部署
title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...

作为点的对象CenterNet论文阅读
摘要 检测器将图像中的物体表示为轴对齐的边界框。大多数成功的目标检测方法都会枚举几乎完整的潜在目标位置列表,并对每一个位置进行分类。这种做法既浪费又低效,并且需要额外的后处理。在本文中,我们采取了不同的方法。我们将物体建模为单…...