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

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涉及的子模块及准备 最近比较有空&#xff0c;之前一直好奇&#xff0c;提交到线上考试的代码是如何执行测试的&#xff0c;在实现了基础的demo后…...

全国领先——液力悬浮仿生型人工心脏上市后在同济医院成功植入

2023年2月22日&#xff0c;华中科技大学同济医学院附属同济医院&#xff08;同济医院&#xff09;心脏大血管外科团队举办了一场气氛热烈的小规模庆祝活动&#xff0c;魏翔主任、程才副主任、王星宇副主任医师和李师亮医师到场&#xff0c;为终末期心衰患者黄先生“庆生”&…...

基于蚂蚁优化算法的柔性车间调度研究(Python代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5;&#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密…...

云原生周刊:开源漏洞仍然是开发人员面临的挑战 | 2023.2.27

Synopsys 发布了最新一期的开源安全年度报告&#xff0c;开源安全和风险分析 (OSSRA)。这份报告由Synopsys 网络安全研究中心 (CyRC)创建&#xff0c;着眼于 Black Duck 审计服务团队进行的 1,700 多次商业代码库审计的结果。 自 2019 年以来&#xff0c;OSSRA 所有 17 家企业…...

Docker学习总结

1、镜像操作 1.1 拉取、查看镜像 步骤一&#xff1a; 首先去镜像仓库搜索nginx镜像&#xff0c;比如[DockerHub]( Docker Hub Container Image Library | App Containerization ) : 步骤二&#xff1a; 根据查看到的镜像名称&#xff0c;拉取自己需要的镜像 通过命令&…...

Android 9.0系统源码_通知服务(三)应用发送状态栏通知的流程

前言 应用发送一个显示在状态栏上的通知&#xff0c;对于移动设备来说是很常见的一种功能需求&#xff0c;本篇文章我们将会结合Android9.0系统源码具体来分析一下&#xff0c;应用调用notificationManager触发通知栏通知功能的源码流程。 一、应用触发状态栏通知 应用可以通…...

python中的序列——笔记

一、介绍 ABC语言时一个致力于为初学者设计编程环境的长达十年的研究项目。 Python也从ABC那里继承了用统一的风格去处理序列数据这一特点。不管是哪种数据结构&#xff0c;字符串、列表、字节序列、数组、XML元素&#xff0c;抑或是数据库查询结果&#xff0c;它们都共用一套…...

taobao.user.seller.get( 查询卖家用户信息 )

&#xffe5;开放平台基础API必须用户授权 查询卖家用户信息&#xff08;只能查询有店铺的用户&#xff09; 只能卖家类应用调用。 公共参数 请求地址: HTTP地址 http://gw.api.taobao.com/router/rest 公共请求参数: 公共响应参数: 请求参数 点击获取key和secret请求示例…...

WebRTC Qos策略

1.WebRTC 用于提升 QoS 的方法&#xff1a;NACK、FEC、SVC、JitterBuffer、IDR Request、PACER、Sender Side BWE、VFR&#xff08;动态帧率调整策略&#xff09;https://blog.csdn.net/CrystalShaw/article/details/80432267丢包重传NACK&#xff1a;一种通知技术&#xff0c;…...

Mysql数据查询

文章目录1 group by子句2 回溯统计3 having子句1 group by子句 group by子句**&#xff1a;分组统计&#xff0c;根据某个字段将所有的结果分类&#xff0c;并进行数据统计分析 分组的目的不是为了显示数据&#xff0c;一定是为了统计数据group by子句一定是出现在where子句之…...

Kafka入门(五)

下面聊聊Kafka常用命令 1、Topic管理命令 以topic&#xff1a;test_1为例 1.1、创建topic ./bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 3 --partitions 3 --topic test_1参数说明&#xff1a; –bootstrap-server&#xff1a;…...

如何快速在windows系统中切换node.js版本

前言 最近在同时维护公司的两个项目&#xff0c;一个是新项目&#xff0c;另一个是老项目&#xff0c;二者所依赖的node版本是不一致的。 这就导致我在切换项目的时候必须重新安装对应版本的 node.js&#xff0c;否则就会报各种神马错误。 但这一卸一装可着实烦死个银&#xf…...

设计模式-单例模式(java)

单例是一种常用的设计模式&#xff0c;它的目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。在Java编程语言中&#xff0c;实现单例有多种方法&#xff0c;本篇文章将介绍其中的两种实现方式。 方式一&#xff1a;饿汉式单例模式 饿汉式单例模式是最简单的实…...

Revit中复合墙图层的规则和CAD识别翻模墙

一、Revit中用于指定复合墙图层的规则&#xff0c;具体内容? 在编辑复合墙的结构时&#xff0c;请使用“指定图层”工具将“编辑部件”对话框中的行指定给图层或预览窗格中的区域&#xff0c;并遵循这些原则。 在预览窗格中&#xff0c;样本墙的各个行必须保持从左到右的顺序显…...

【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.概述 正则表达式通常用于含有大量文本处理的应用当中。例如&#xff0c;它们经常用作开发者使用的文本编辑程序的搜索模式&#xff0c;包括 vi&#xff0c;emacs 和现代集成开发环境。它们也是 Unix 命令行工具的组成部分&#xff0c;例如…...

换了固态硬盘需要重装系统吗?教你如何实现不重装系统!

电脑大家都用过嘛&#xff0c;如果您的计算机装的还是机械硬盘&#xff0c;想必阁下肯定是修身养性的高手&#xff0c;因为在这个浮躁的社会中&#xff0c;是很少有人能够忍受5分钟甚至更久的开机时间的&#xff0c;不仅开机慢&#xff0c;应用程序的响应速度也很慢&#xff0c…...

网上医疗预约挂号系统

技术&#xff1a;Java、JSP等摘要&#xff1a;网上医疗预约挂号系统是主要是对居民的保健、护理、疾病预防等健康信息实行有效的预约挂号管理。医疗机构为居民建立完整的健康档案&#xff0c;安排体检以及实施免疫等预防措施。而基于Web的远程保健平台以网上医疗预约挂号系统为…...

专题:一看就会的C++类模板讲解 (1)

目录 一.类模板的作用 二.类模板的定义&#xff1a; 三.类模板的声明格式&#xff1a; 四.类模板对象 五.再举一个例子 一.类模板的作用 面向对象的程序设计编程实践中&#xff0c;我们可能会面临这样的问题&#xff1a;要实现比较两个数的大小。明明比较两个数的方法都一样…...

什么是“奥卡姆剃刀”,如何用“奥卡姆剃刀”解决复杂问题?复杂问题简单化

什么是“奥卡姆剃刀”&#xff0c;如何用“奥卡姆剃刀”解决复杂问题&#xff1f;复杂问题简单化问题什么是“奥卡姆剃刀”?如何使用“奥卡姆剃刀”解决问题复杂问题简单化“汉隆剃刀”小结问题 假设你在夜空中看到一颗闪闪发光的「不明飞行物」&#xff0c;你认为这会是什么呢…...

角谷定理(递归)

已知有角谷定理&#xff1a; 输入一个自然数&#xff0c;若为偶数&#xff0c;则把它除以2&#xff0c;若为奇数&#xff0c;则把它乘以3加1。经过如此有限次运算后&#xff0c;总可以得到自然数值1。求经过多少次可得到自然数1。如&#xff1a;例如数据22的变化过程&#xff…...

数学小课堂:微积分复盘(高等数学本质上是对趋势的动态描述,是对各种相关性抽象的表述。)

文章目录 引言I 复盘1.1 概念和表述1.2 现实与虚构1.3 有穷和无穷1.4 静态和动态1.5 直觉和逻辑II 通过数学逻辑,理解人生。2.1 精明与聪明2.2 朋友和理性的对手2.3 攒钱和赚钱2.4 荣誉和财富引言 高等数学本质上是对趋势的动态描述,是对各种相关性抽象的表述。 I 复盘 1.…...

JAVA线程池原理详解一

JAVA线程池原理详解一 一. 线程池的优点 线程是稀缺资源&#xff0c;使用线程池可以减少创建和销毁线程的次数&#xff0c;每个工作线程都可以重复使用。可以根据系统的承受能力&#xff0c;调整线程池中工作线程的数量&#xff0c;防止因为消耗过多内存导致服务器崩溃。 二…...

Windows平台Unity Camera场景实现轻量级RTSP服务和RTMP推送

技术背景随着VR技术在医疗、军事、农业、学校、景区、消防、公共安全、研学机构、展厅展馆&#xff0c;商场等场所普及&#xff0c;开发者对Unity平台下的直播体验提出了更高的要求。技术实现Unity平台下的RTMP推流、RTMP、RTSP播放前几年已经覆盖了Windows、Linux、Android、i…...

LSB 题解

今天来刷一道Misc的题目&#xff0c;LSB原理进行图片隐写 LSB原理 LSB是一种利用人类视觉的局限性设计的幻术 PNG和BMP图片中的图像像素一般是由RGB(RED红 GREEN绿 BLUE蓝)三原色组成 记住&#xff0c;JPG图片是不适合使用LSB隐写的&#xff0c;JPG图片对像数进行了有损压缩…...

离线部署docker与镜像

离线部署docker与镜像 1.离线部署docker 1).在docker官网上下载&#xff0c;合适的安装文件 本次使用的是“docker-20.10.9.tgz ” 下载地址&#xff1a;https://download.docker.com/linux/static/stable/x86_64/ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下…...

Linux文件系统介绍(上)

使用 Linux 系统时&#xff0c;需要作出的决策之一就是为存储设备选用什么文件系统。大多数 Linux 发行版在安装时会非常贴心地提供默认的文件系统&#xff0c;大多数入门级用户想都不想就用了默认的那个。 使用默认文件系统未必就不好&#xff0c;但了解一下可用的选择有时也会…...

创建SpringBoot注意事项

作为一个java小白&#xff0c;你是否因为创建SpringBoot项目那些莫名其妙的错误搞得头皮发麻。不要慌张&#xff0c;这篇文章能帮你解决90%的问题【持续更新…】 本文结合创建SpringBoot项目的完整过程来讲 在idea中新建项目 虽然SpringBoot项目是由maven内核组成的&#xff0…...

2023年全国最新二级建造师精选真题及答案9

百分百题库提供二级建造师考试试题、二建考试预测题、二级建造师考试真题、二建证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 11.关于施工合同违约赔偿损失范围的说法&#xff0c;正确的是&#xff08;&#xff09;。 A.…...

解决MySQL的 Row size too large (> 8126).

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;无尽的折腾后&#xff0c;终于又回到…...

网站建设交接清单/怎么制作网页教程

Eureka&#xff1a;就是服务注册中心&#xff08;可以是一个集群&#xff09;&#xff0c;对外暴露自己的地址 提供者&#xff1a;启动后向Eureka注册自己信息&#xff08;地址&#xff0c;提供什么服务&#xff09; 消费者&#xff1a;向Eureka订阅服务&#xff0c;Eureka会将…...

wordpress微博分享插件/中国站长网站

在网络中 ping 是一个十分强大的 TCP/IP 工具。它的作用主要为&#xff1a; 1、用来检测网络的连通情况和分析网络速度 2、根据域名得到服务器 IP 3、根据 ping 返回的 TTL 值来判断对方所使用的操作系统及数据包经过路由器数量。 一般情况下&#xff0c;我们只会使用ping…...

范文写作网站/百度统计流量研究院

遇坑整理 遇到了就记下 2021-07-06 14:42 bj spirng boot运行application报错&#xff1a; 找不到或无法加载主类 解决措施&#xff1a; >点击IDEA最右边的Maven我们可以看到我们的项目, >Lifecycle >clean(情况加载及配置文件)>install(重新加载配置) 解决. idea …...

网站做任务佣金/网站seo在线诊断

由于这个游戏比较简单&#xff0c;具体实现不做详细的解释&#xff0c;只是说说框架吧&#xff0c;我今天花了一个下午敲好代码&#xff0c;需要代码的可以到 https://github.com/hanxi/Snake 下载源代码。 写代码前&#xff0c;没有设计类图&#xff0c;下面是用starUML生成的…...

安徽省城乡建设网站/跨境电商怎么开店铺

为什么80%的码农都做不了架构师&#xff1f;>>> 添加环境变量&#xff0c;中增加一项&#xff0c;其中变量为为NLS_LANG&#xff0c;变量值为"AMERICAN_AMERICA.ZHS16GBK"(不包括双引号)。 重启toad后&#xff0c;即可看到原为乱码的内容&#xff0c;显示…...

电子商务网站界面设计实验报告/温州seo服务

谷歌人工智能部门DeepMind在预测蛋白质结构方面迈出了一大步。公司表示&#xff0c;DeepMind开发的AlphaFold系统已经解决了关键的“蛋白质折叠问题”&#xff0c;并将解决问题的运算时间从数月缩短至数小时&#xff0c;这有助于加快药物发现速度&#xff0c;有可能破解一个类似…...