调用电商集成平台 聚水潭 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面则是零售、物流、制造、银行保险等全产业链面对海量流量之下,以强大的心力、脑力与体力应对流量增加和交易陡增的…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
