Spring boot装载模板代码并自动运行
Spring boot装载模板代码
- 涉及的子模块及准备
- 省心Clickhouse批量写
- JSON多层级数据自动映射值
- 模板代码生成及移交控制权给Spring IOC
涉及的子模块及准备
最近比较有空,之前一直好奇,提交到线上考试的代码是如何执行测试的,在实现了基础的demo后,进一步希望加载到Spring上支持动态执行! 经过一段时间琢磨之后,终于完成了基础版本,其中也结合了近来自己封装的消组件,省心Clickhouse批量写、JSON多层级数据自动映射值。
省心Clickhouse批量写
在刚刚使用Clickhouse大批量写入时,经常会出现Clickhouse机器cpu飙升导致查询不可用等情况,在研究了Clickhouse JDBC的官网说明文档以及Clickhouse文档(链接: CK官方文档)后,明白Clickhouse写入方式支持多种,直接使用MyBatis-Plus的批量写入方式就会出现cpu问题,还有一种格式(结构化写入,类似于HBase文件块写入),但是需要知道表字段和类型;
// 消耗比较小的批量写入方式
insert into table_name select %s from input('%s');
第三种写入方式是基于JSON格式(csv等都支持,参考Ck文档的Formats for Input and Output Data部分)写入,Clickhouse会自动匹配表字段和数据的键值对,非空字段严格校验之外,其他字段都会根据数据填充对应的值。
注意:不能做数据更新,只做插入处理,忽略已存在的排序主键数据,更新数据混杂在新增数据时只执行插入数据
//
INSERT INTO afanti_aweme_info_all FORMAT JSONEachRow JSON1\nJSON2
目前只实现第二种写入方式,基本做到了自动生成input 字段及其格式,关键代码如下:
public interface MyIService<T> extends IService<T> {void saveBatchRecordsByInput(List<T> records) throws Exception;}
public class MyServiceImpl<M extends MyBaseMapper<T>, T> extends ServiceImpl<M , T> implements MyIService<T> {protected Log log = LogFactory.getLog(this.getClass());protected Class<M> mapperClass = this.currentMapperClass();protected Class<T> entityClass = this.currentModelClass();@Autowiredprivate SqlSessionTemplate sqlSessionTemplate;@Autowiredprotected M myBaseMapper;protected Logger LOGGER = LoggerFactory.getLogger(this.getClass());private final ConcurrentHashMap<String, String> sqlMap = new ConcurrentHashMap<>();private final ConcurrentHashMap<String, List<String>> columnMap = new ConcurrentHashMap<>();@Overridepublic void saveBatchRecordsByInput(List<T> records) throws Exception {String key = this.mapperClass.getSimpleName() + ".saveBatchRecordsByInput";TableName tableNameAnn = this.entityClass.getAnnotation(TableName.class);// _all结束代表ck的分布式表,此处需要获取本地表的字段和类型String tableName = tableNameAnn.value().endsWith("_all") ? tableNameAnn.value().substring(0, tableNameAnn.value().length() - 4) : tableNameAnn.value();if (!sqlMap.containsKey(key)) {buildSql(tableName, key);}String mapperSql = sqlMap.get(key);Connection connection = getConnection();PreparedStatement ps = connection.prepareStatement(mapperSql);try {List<String> fieldNames = columnMap.get(key);for (T record : records) {int i = 1;for (String column : fieldNames) {Field field;try {field = entityClass.getDeclaredField(column);} catch (NoSuchFieldException e) {field = entityClass.getSuperclass().getDeclaredField(column);}field.setAccessible(true);Object val = field.get(record);// 数组类型处理if (val instanceof String[]) {ps.setArray(i, connection.createArrayOf("String", (String[]) val));} else if (val instanceof Long[]) {ps.setArray(i, connection.createArrayOf("Long", (Long[]) val));} else if (val instanceof Integer[]) {ps.setArray(i, connection.createArrayOf("Integer", (Integer[]) val));} else if (val instanceof Date) {// 特殊字段格式处理if ("statisticsDay".equals(column)) {ps.setObject(i, DateUtils.format((Date) val, DateUtils.SDF_YYYY_MM_DD));} else {ps.setObject(i, DateUtils.format((Date) val));}} else {ps.setObject(i, val);}i++;}ps.addBatch();}ps.executeBatch();ps.clearBatch();} finally {connection.close();}}private synchronized void buildSql(String tableName, String key) throws SQLException {Connection connection = getConnection();PreparedStatement ps = connection.prepareStatement(String.format(query, tableName, "rawdata"));ResultSet set = ps.executeQuery();StringJoiner columns = new StringJoiner(",", "", "");StringJoiner columnAndTypes = new StringJoiner(",", "", "");List<String> columsList = new ArrayList<>();while (set.next()) {String column = set.getString("col_name");String dataType = set.getString("data_type");columns.add(column);columnAndTypes.add(column + " " + dataType);columsList.add(toHumpString(column));}connection.close();// 写入数据时需要写入到分布式表,分布式表根据分布式键规则把数据分发到对应机器的本地表上存储String querySt = String.format(querySQL, tableName + "_all", columns.toString(), columnAndTypes.toString());sqlMap.putIfAbsent(key, querySt);columnMap.putIfAbsent(key, columsList);}private static String toHumpString(String string) {StringBuilder stringBuilder = new StringBuilder();String[] str = string.split("_");for (String string2 : str) {if(stringBuilder.length() == 0){stringBuilder.append(string2);}else {stringBuilder.append(string2.substring(0, 1).toUpperCase());stringBuilder.append(string2.substring(1));}}return stringBuilder.toString();}String querySQL = "insert into %s select %s from input('%s') ";// 获取连接池中的链接public Connection getConnection() {Connection conn = null;try {SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession();conn = sqlSession.getConfiguration().getEnvironment().getDataSource().getConnection();} catch (Exception e) {LOGGER.error("Clickhouse getConnection:{}", e.getMessage());e.printStackTrace();}return conn;}String query = "select name as col_name, `type` as data_type from system.columns where table = '%s' and database = '%s' order by position asc";
}
扩展一下Mybatis-plus的模板方法并重写一段生成input的字段和类型字符串逻辑即可。
JSON多层级数据自动映射值
封装了Json-path包,主要内容录如下
<dependency><groupId>com.jayway.jsonpath</groupId><artifactId>json-path</artifactId><version>2.6.0</version></dependency>
封装未处理格式属性,需要自行处理,代码如下:
public class JsonPathParseUtil {public static Configuration configuration = Configuration.builder().options(Option.DEFAULT_PATH_LEAF_TO_NULL, Option.SUPPRESS_EXCEPTIONS).build();public static Date parseDate(String dateStr) {String parsedDate;if (dateStr.length() == 10) {parsedDate = "yyyy-MM-dd";} else {parsedDate = "yyyy-MM-dd HH:mm:ss";}try {return org.apache.commons.lang3.time.DateUtils.parseDate(dateStr, parsedDate);} catch (ParseException e) {e.printStackTrace();}return null;}public static <T> T Json2DTO(String msgString, Class<T> clazz) {try {T dto = clazz.newInstance();ReadContext ctx = JsonPath.parse(msgString, configuration);Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {JPath path = field.getAnnotation(JPath.class);if (path != null) {Object obj = ctx.read(path.value());field.setAccessible(true);if (obj != null) {if (obj instanceof String) {String value = (String) obj;if (StrUtil.isBlank(value)) {field.set(dto, null);} else if (field.getType().equals(Long.class)) {field.set(dto, Long.parseLong(value));} else if (field.getType().equals(Integer.class)) {field.set(dto, Integer.parseInt(value));} else if (field.getType().equals(Date.class)) {field.set(dto, parseDate(value));} else {field.set(dto, value);}} else if (obj instanceof Map) {Map value = (Map) obj;Object v = JSONObject.toJavaObject(new JSONObject(value), field.getType());field.set(dto, v);} else if (obj instanceof Integer) {Integer value = (Integer) obj;if (field.getType().equals(Long.class)) {field.set(dto, value.longValue());} else if (field.getType().equals(Date.class)) {if (value.toString().length() == 10) {field.set(dto, new Date(value.longValue() * 1000));} else if (value.toString().length() == 13) {field.set(dto, new Date(value.longValue()));}} else if (field.getType().equals(String.class)) {field.set(dto, value.toString());} else if (field.getType().equals(Float.class)) {field.set(dto, Float.valueOf(value));} else if (field.getType().equals(Double.class)) {field.set(dto, Double.valueOf(value));} else {field.set(dto, value);}} else if (obj instanceof Long) {Long value = (Long) obj;if (field.getType().equals(Integer.class)) {field.set(dto, value.intValue());} else if (field.getType().equals(Date.class)) {if (value.toString().length() == 10) {field.set(dto, new Date(value * 1000));} else if (value.toString().length() == 13) {field.set(dto, new Date(value));}} else if (field.getType().equals(String.class)) {field.set(dto, value.toString());} else {field.set(dto, value);}} else if (obj instanceof Double) {Double value = (Double) obj;if (field.getType().equals(String.class)) {field.set(dto, value.toString());} else if (field.getType().equals(Float.class)) {field.set(dto, value.floatValue());} else {field.set(dto, value);}} else if (obj instanceof Date) {Date value = (Date) obj;field.set(dto, value);} else if (obj instanceof JSONArray) {JSONArray value = (JSONArray) obj;if (field.getType().equals(String.class)) {field.set(dto, value.toJSONString());} else {Type genericType = field.getGenericType();if (genericType instanceof ParameterizedType) {ParameterizedType pt = (ParameterizedType) genericType;// 得到泛型里的class类型对象Class<?> actualTypeArgument = (Class<?>) pt.getActualTypeArguments()[0];List values = com.alibaba.fastjson.JSONArray.parseArray(value.toJSONString(), actualTypeArgument);field.set(dto, values);} else {field.set(dto, value);}}} else if (obj instanceof List) {List value = (List) obj;field.set(dto, value);} else if (obj instanceof JSONObject) {JSONObject value = (JSONObject) obj;if (field.getType().equals(String.class)) {field.set(dto, value.toJSONString());} else {field.set(dto, value);}} else if (obj instanceof Boolean) {Boolean value = (Boolean) obj;if (field.getType().equals(Integer.class)) {field.set(dto, value ? 1 : 0);} else {field.set(dto, value);}} else if (obj instanceof BigDecimal) {BigDecimal value = (BigDecimal) obj;if (field.getType().equals(String.class)) {field.set(dto, value.toString());} else if (field.getType().equals(Double.class)) {field.set(dto, value.doubleValue());} else if (field.getType().equals(BigDecimal.class)) {field.set(dto, value);} else if (field.getType().equals(Float.class)) {field.set(dto, value.floatValue());}}}}}return dto;} catch (IllegalAccessException | InstantiationException iae) {iae.printStackTrace();}return null;}}
@JPath
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface JPath {String value() default "";String format() default "";}
模板代码生成及移交控制权给Spring IOC
关键代码如下,用模板代码生成对应处理逻辑的代码的字符串,包装成java运行中的内存文件,获取编译器,把内存文件表示的数据加载到编译任务队列,执行编译,返回Class对象,到这一步,就是编程线上代码考试的逻辑,你提交自己的代码到远程服务器上编译,用已经准备好的测试数据反射执行你的方法验证代码逻辑符不符合变成要求。
接上一步,获取Spring运行环境上下文,BeanDefinitionBuilder加载Class类,配置初始化设置,设置Bean的名称,注册BeanDefinition,通过ApplicationContext以及Bean的名称调用Bean即可。
@Data
@Component
@ConfigurationProperties("rocket-config")
@Slf4j
public class CodeRunner implements CommandLineRunner {private List<Mq> mq;private final String LISTENER_CODE ="import com.aliyun.openservices.ons.api.Action;\n" +"import com.aliyun.openservices.ons.api.ConsumeContext;\n" +"import com.aliyun.openservices.ons.api.Message;\n" +"import com.aliyun.openservices.ons.api.MessageListener;\n" +"import com.afanticar.transform.util.JsonPathParseUtil;\n" +"import com.afanti.datastreamline.utils.SpringUtils;\n" +"import java.util.ArrayList;\n" +"import java.util.List;\n" +"import org.slf4j.Logger;\n" +"import org.slf4j.LoggerFactory;\n" +"import java.util.Date;\n" +"import java.sql.SQLException;\n" +"import java.lang.reflect.Field;\n" +"import com.afanti.datastreamline.service.AfantiService;\n" +"\n" +"@SuppressWarnings(\"unchecked\")" +"public class AfantiDouyinDataMessageListener implements MessageListener {\n" +"\n" +" private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());\n" +"\n" +" @Override\n" +" public Action consume(Message message, ConsumeContext context) {\n" +" String msgString = new String(message.getBody());\n" +" \n" +" System.out.println(\"接收到消息\" + msgString);\n" +" Object afantiDouyinAwemeInfo = SpringUtils.getBean(\"afantiDouyinAwemeInfo\");\n" +" afantiDouyinAwemeInfo = JsonPathParseUtil.Json2DTO(msgString, afantiDouyinAwemeInfo.getClass());\n" +" try {\n" +" Field field = afantiDouyinAwemeInfo.getClass().getDeclaredField(\"ctime\");\n" +" field.setAccessible(true);\n" +" field.set(afantiDouyinAwemeInfo, new Date());\n" +" } catch (NoSuchFieldException | IllegalAccessException e) {\n" +" e.printStackTrace();\n" +" }" +" List records = new ArrayList();\n" +" records.add(afantiDouyinAwemeInfo);\n" +" AfantiService afantiService = (AfantiService) SpringUtils.getBean(\"afantiService\");\n" +" try {\n" +" afantiService.saveBatchRecordsByInput(\"afanti_aweme_info_all\", records);\n" +" } catch (SQLException exception) {\n" +" exception.printStackTrace();\n" +" }\n" +" return Action.CommitMessage;\n" +" }\n" +" \n" +"}";private final String CONSUMER_CODE ="import com.aliyun.openservices.ons.api.MessageListener;\n" +"import com.aliyun.openservices.ons.api.PropertyKeyConst;\n" +"import com.aliyun.openservices.ons.api.bean.ConsumerBean;\n" +"import com.aliyun.openservices.ons.api.bean.Subscription;\n" +"import com.afanti.datastreamline.utils.SpringUtils;\n" +"import java.util.HashMap;\n" +"import java.util.Map;\n" +"import java.util.Properties;\n" +"import com.afanti.datastreamline.config.MqProperties;\n" +"\n" +"public class AfantiDouyinDataConsumer extends ConsumerBean {\n" +"\n" +" public void initConsumer() {\n" +" //配置文件\n" +" MqProperties mqConfig = (MqProperties) SpringUtils.getBean(\"mqProperties\");\n" +" Properties properties = mqConfig.getMqPropertie();\n" +" // System.out.println(mqConfig.print());\n" +" properties.setProperty(PropertyKeyConst.GROUP_ID, \"GID_AFANTI_CHIN_SURVEY\");\n" +" //将消费者线程数固定为20个 20为默认值\n" +" properties.setProperty(PropertyKeyConst.ConsumeThreadNums, \"15\");\n" +" properties.setProperty(PropertyKeyConst.MaxCachedMessageAmount,\"1000\");\n" +" this.setProperties(properties);\n" +" //订阅关系\n" +" Map<Subscription, MessageListener> subscriptionTable = new HashMap<Subscription, MessageListener>();\n" +" Subscription subscription = new Subscription();\n" +" subscription.setTopic(\"AFANTI_CHIN_SURVEY\");\n" +" MessageListener afantiDouyinDataMessageListener = (MessageListener) SpringUtils.getBean(\"afantiDouyinDataMessageListener\");\n" +" subscriptionTable.put(subscription, afantiDouyinDataMessageListener);\n" +" //订阅多个topic如上面设置\n" +" this.setSubscriptionTable(subscriptionTable);\n" +" this.start();\n" +" }\n" +"}";private final String KAFKA_TEST = "import lombok.extern.slf4j.Slf4j;\n" +"import org.apache.kafka.clients.consumer.ConsumerRecord;\n" +"import org.springframework.beans.factory.annotation.Autowired;\n" +"import org.springframework.kafka.annotation.KafkaListener;\n" +"import org.springframework.stereotype.Component;\n" +"import org.springframework.kafka.support.Acknowledgment;\n\n" +"import java.util.List;\n" +"\n" +"/**\n" +" * @author Data\n" +" */\n" +"@Slf4j\n" +"@Component\n" +"public class AfantiMessageListener {\n" +"\n" +" @KafkaListener(\n" +" topics = \"AFANTI_CHIN_DEV\",\n" +" containerFactory = \"kafkaListenerContainerFactory\",\n" +" groupId = \"chin-test\")\n" +" public void kafkaListener(List<ConsumerRecord<String, String>> messages, Acknowledgment ack) throws Exception {\n" +" System.out.println(messages.get(0));\n" +" ack.acknowledge();\n" +" }\n" +"\n" +"}";private final String COLUMNS = "{\"afanti_douyin_aweme_info\":{\"aweme_id\":{\"type\":\"String\",\"path\":\"item_id\"},\"aweme_title\":{\"type\":\"String\",\"path\":\"title\"},\"cover\":{\"type\":\"String\",\"path\":\"aweme_cover\"},\"ctime\":{\"type\":\"Date\",\"path\":\"c\"}}}";@Overridepublic void run(String... args) {try {compilerAndRegister(DtoFreemarkerUtil.buildCode(COLUMNS), "AfantiDouyinAwemeInfo", null, true);log.info("DTO、Entity代码构建、装载和初始化完成...");compilerAndRegister(LISTENER_CODE, "AfantiDouyinDataMessageListener", null, false);log.info("Listener代码构建、装载完成...");compilerAndRegister(CONSUMER_CODE, "AfantiDouyinDataConsumer", "initConsumer", false);log.info("RocketMq Consumer代码构建、装载完成...");log.info("RocketMq Consumer初始化完成...");compilerAndRegister(KAFKA_TEST, "AfantiMessageListener", null, false);} catch (URISyntaxException | TemplateException | IOException e) {e.printStackTrace();}}@Datastatic public class Mq {private String gid;private String topic;private String platform;}private void compilerAndRegister(String code, String clazzName, String initMethod, boolean needObject) throws URISyntaxException {JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null);ClassJavaFileManager classJavaFileManager = new ClassJavaFileManager(standardFileManager);StringObject stringObject = new StringObject(new URI( clazzName + ".java"), JavaFileObject.Kind.SOURCE, code);// 加入编译任务队列JavaCompiler.CompilationTask task = compiler.getTask(null, classJavaFileManager, null, null, null,Collections.singletonList(stringObject));Class clazz = null;Object entityObj = null;if (task.call()) {ClassJavaFileObject javaFileObject = classJavaFileManager.getClassJavaFileObject();// 获取AppClassloader加载器ClassLoader classLoader = new MyClassLoader(javaFileObject);try {clazz = classLoader.loadClass(clazzName);if (needObject) {entityObj = clazz.newInstance();}} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {e.printStackTrace();}}ApplicationContext ctx = SpringUtils.getApplicationContext();// Spring Ioc Bean工厂DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) ctx.getAutowireCapableBeanFactory();assert clazz != null;// Bean属性等定义器BeanDefinitionBuilder beanDefinitionBuilder;if (needObject) {assert entityObj != null;beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(entityObj.getClass());} else {beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);}// 设置初始化配置 RocketMQ Consumerif (initMethod != null) {beanDefinitionBuilder.setInitMethodName(initMethod);beanDefinitionBuilder.setDestroyMethodName("shutdown");}beanDefinitionBuilder.setLazyInit(false);String beanName = clazzName.substring(0,1).toLowerCase(Locale.ROOT) + clazzName.substring(1);defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());ctx.getBean(beanName);}static class ClassJavaFileManager extends ForwardingJavaFileManager {private ClassJavaFileObject classJavaFileObject;public ClassJavaFileManager(JavaFileManager fileManager) {super(fileManager);}public ClassJavaFileObject getClassJavaFileObject() {return classJavaFileObject;}/**读取Class文件字节流*/@Overridepublic JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className,JavaFileObject.Kind kind, FileObject sibling) {return (classJavaFileObject = new ClassJavaFileObject(className,kind));}}/**存储源文件*/static class StringObject extends SimpleJavaFileObject {private final String content;public StringObject(URI uri, Kind kind, String content) {super(uri, kind);this.content = content;}//使JavaCompiler可以从content获取java源码@Overridepublic CharSequence getCharContent(boolean ignoreEncodingErrors) {return this.content;}}/**class文件(不需要存到文件中)*/static class ClassJavaFileObject extends SimpleJavaFileObject {ByteArrayOutputStream outputStream;public ClassJavaFileObject(String className, Kind kind) {super(URI.create(className + kind.extension), kind);this.outputStream = new ByteArrayOutputStream();}@Overridepublic OutputStream openOutputStream() {return this.outputStream;}//获取输出流为byte[]数组public byte[] getBytes(){return this.outputStream.toByteArray();}}/**自定义classloader*/static class MyClassLoader extends ClassLoader {private final ClassJavaFileObject stringObject;public MyClassLoader(ClassJavaFileObject stringObject){this.stringObject = stringObject;}@Overrideprotected Class<?> findClass(String name) {byte[] bytes = this.stringObject.getBytes();return defineClass(name,bytes,0,bytes.length);}}}
以上代码参数配置以常量显示,线上环境跟Demo有点差别,下次会展示最终的线上代码,正在修修补补中…
PS.参考文档已忘…
相关文章:
Spring boot装载模板代码并自动运行
Spring boot装载模板代码涉及的子模块及准备省心Clickhouse批量写JSON多层级数据自动映射值模板代码生成及移交控制权给Spring IOC涉及的子模块及准备 最近比较有空,之前一直好奇,提交到线上考试的代码是如何执行测试的,在实现了基础的demo后…...
全国领先——液力悬浮仿生型人工心脏上市后在同济医院成功植入
2023年2月22日,华中科技大学同济医学院附属同济医院(同济医院)心脏大血管外科团队举办了一场气氛热烈的小规模庆祝活动,魏翔主任、程才副主任、王星宇副主任医师和李师亮医师到场,为终末期心衰患者黄先生“庆生”&…...
基于蚂蚁优化算法的柔性车间调度研究(Python代码实现)
👨🎓个人主页:研学社的博客💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密…...
云原生周刊:开源漏洞仍然是开发人员面临的挑战 | 2023.2.27
Synopsys 发布了最新一期的开源安全年度报告,开源安全和风险分析 (OSSRA)。这份报告由Synopsys 网络安全研究中心 (CyRC)创建,着眼于 Black Duck 审计服务团队进行的 1,700 多次商业代码库审计的结果。 自 2019 年以来,OSSRA 所有 17 家企业…...
Docker学习总结
1、镜像操作 1.1 拉取、查看镜像 步骤一: 首先去镜像仓库搜索nginx镜像,比如[DockerHub]( Docker Hub Container Image Library | App Containerization ) : 步骤二: 根据查看到的镜像名称,拉取自己需要的镜像 通过命令&…...
Android 9.0系统源码_通知服务(三)应用发送状态栏通知的流程
前言 应用发送一个显示在状态栏上的通知,对于移动设备来说是很常见的一种功能需求,本篇文章我们将会结合Android9.0系统源码具体来分析一下,应用调用notificationManager触发通知栏通知功能的源码流程。 一、应用触发状态栏通知 应用可以通…...
python中的序列——笔记
一、介绍 ABC语言时一个致力于为初学者设计编程环境的长达十年的研究项目。 Python也从ABC那里继承了用统一的风格去处理序列数据这一特点。不管是哪种数据结构,字符串、列表、字节序列、数组、XML元素,抑或是数据库查询结果,它们都共用一套…...
taobao.user.seller.get( 查询卖家用户信息 )
¥开放平台基础API必须用户授权 查询卖家用户信息(只能查询有店铺的用户) 只能卖家类应用调用。 公共参数 请求地址: HTTP地址 http://gw.api.taobao.com/router/rest 公共请求参数: 公共响应参数: 请求参数 点击获取key和secret请求示例…...
WebRTC Qos策略
1.WebRTC 用于提升 QoS 的方法:NACK、FEC、SVC、JitterBuffer、IDR Request、PACER、Sender Side BWE、VFR(动态帧率调整策略)https://blog.csdn.net/CrystalShaw/article/details/80432267丢包重传NACK:一种通知技术,…...
Mysql数据查询
文章目录1 group by子句2 回溯统计3 having子句1 group by子句 group by子句**:分组统计,根据某个字段将所有的结果分类,并进行数据统计分析 分组的目的不是为了显示数据,一定是为了统计数据group by子句一定是出现在where子句之…...
Kafka入门(五)
下面聊聊Kafka常用命令 1、Topic管理命令 以topic:test_1为例 1.1、创建topic ./bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 3 --partitions 3 --topic test_1参数说明: –bootstrap-server:…...
如何快速在windows系统中切换node.js版本
前言 最近在同时维护公司的两个项目,一个是新项目,另一个是老项目,二者所依赖的node版本是不一致的。 这就导致我在切换项目的时候必须重新安装对应版本的 node.js,否则就会报各种神马错误。 但这一卸一装可着实烦死个银…...
设计模式-单例模式(java)
单例是一种常用的设计模式,它的目的是确保一个类只有一个实例,并提供一个全局访问点。在Java编程语言中,实现单例有多种方法,本篇文章将介绍其中的两种实现方式。 方式一:饿汉式单例模式 饿汉式单例模式是最简单的实…...
Revit中复合墙图层的规则和CAD识别翻模墙
一、Revit中用于指定复合墙图层的规则,具体内容? 在编辑复合墙的结构时,请使用“指定图层”工具将“编辑部件”对话框中的行指定给图层或预览窗格中的区域,并遵循这些原则。 在预览窗格中,样本墙的各个行必须保持从左到右的顺序显…...
【DL】Paddle BML Codelab环境使用说明 - 知识点目录
《Paddle BML Codelab环境使用说明》 1. 编辑区 Code Cell 1.1 Code Cell 操作 Magic关键字/魔术命令 Magic命令含义%timeit测试单行语句的执行时间%%timeit测试代码块的执行时间%matplotlib inline显示matplotlib生成的图形%run调用外部python脚本%pdb 调试程序%pwd 查看当…...
python正则表达式处理文本-re模块
python正则表达式处理文本-re模块 1.概述 正则表达式通常用于含有大量文本处理的应用当中。例如,它们经常用作开发者使用的文本编辑程序的搜索模式,包括 vi,emacs 和现代集成开发环境。它们也是 Unix 命令行工具的组成部分,例如…...
换了固态硬盘需要重装系统吗?教你如何实现不重装系统!
电脑大家都用过嘛,如果您的计算机装的还是机械硬盘,想必阁下肯定是修身养性的高手,因为在这个浮躁的社会中,是很少有人能够忍受5分钟甚至更久的开机时间的,不仅开机慢,应用程序的响应速度也很慢,…...
网上医疗预约挂号系统
技术:Java、JSP等摘要:网上医疗预约挂号系统是主要是对居民的保健、护理、疾病预防等健康信息实行有效的预约挂号管理。医疗机构为居民建立完整的健康档案,安排体检以及实施免疫等预防措施。而基于Web的远程保健平台以网上医疗预约挂号系统为…...
专题:一看就会的C++类模板讲解 (1)
目录 一.类模板的作用 二.类模板的定义: 三.类模板的声明格式: 四.类模板对象 五.再举一个例子 一.类模板的作用 面向对象的程序设计编程实践中,我们可能会面临这样的问题:要实现比较两个数的大小。明明比较两个数的方法都一样…...
什么是“奥卡姆剃刀”,如何用“奥卡姆剃刀”解决复杂问题?复杂问题简单化
什么是“奥卡姆剃刀”,如何用“奥卡姆剃刀”解决复杂问题?复杂问题简单化问题什么是“奥卡姆剃刀”?如何使用“奥卡姆剃刀”解决问题复杂问题简单化“汉隆剃刀”小结问题 假设你在夜空中看到一颗闪闪发光的「不明飞行物」,你认为这会是什么呢…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
