Spring boot装载模板代码并自动运行

news/2024/4/26 17:53:37/文章来源:https://blog.csdn.net/ch123456hy/article/details/129066959

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.参考文档已忘…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_75474.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库多主键in查询组合篇(sqlserver特殊)

此篇介绍的是oracle、mysql、sqlserver、达梦、人大金仓、南大通用数据库的单主键和复合主键select in的查询总结。 Mysql Select id,name from t_db_task where (id,name) in((915,Oracle内到外全表同步),(916,Oracle外到内全表同步),(921,Oracle外到内的触发同步)); selec…

ElasticSearch 学习笔记总结(三)

文章目录一、ES 相关名词 专业介绍二、ES 系统架构三、ES 创建分片副本 和 elasticsearch-head插件四、ES 故障转移五、ES 应对故障六、ES 路由计算 和 分片控制七、ES集群 数据写流程八、ES集群 数据读流程九、ES集群 更新流程 和 批量操作十、ES 相关重要 概念 和 名词十一、…

Java9之HttpClientAPI实战详解

Java9 之 HttpClientAPI 实战详解 前言 相信关注 java9 的小伙伴们都知道 java9 版本内置模块提供了 Http 功能&#xff0c;当然并不是说之前 jdk 之前并不支持&#xff0c;那么这次更新又多了什么呢&#xff1f;或者是解决了什么问题&#xff1f; 说明 自 JDK 1.0 以来&…

mac安装 Termius

1.下载安装包 链接: https://pan.baidu.com/s/1f5xmvYnVehCkMUD291SbsA?pwdy43k 提取码: y43k 2.打开系统偏好设置 -> 安全性与隐私 -> 通用&#xff0c;勾选“任何来源” 显示文件损坏的情况下执行下面操作 3.打开terminal终端 3.1 输入&#xff1a;sudo spctl --m…

“来源可靠、程序规范、要素合规”与“四性”

《从技术可行性的视角看电子档案的“四性”》一文中已经明确&#xff0c;笔者认为的电子档案“四性”是指“真实性、完整性、可用性和安全性”。而《从特斯拉“刹车失灵”事件看电子档案的法定要求》一文中&#xff0c;笔者对于“来源可靠、程序规范、要素合规”的解读如下&…

解决windows安装wxPython安装失败、速度过慢及PyCharm上wx包爆红问题

网上关于wxPython安装失败&#xff0c;安装速度过慢&#xff0c;以及安装成功后PyCharm中import wx仍然爆红的文章有很多&#xff0c;也特别杂&#xff0c;解决起来特别困难&#xff0c;今天在这里对问题的处理进行一个整合&#xff0c;希望能帮助到大家。 安装wxPython这里运用…

MySQL表的增删查改(基础)

gitee:博客中的所有操作整合新增语法:insert [into] table_name values(value_list)[案例] 创建一个学生表进行数据插入1.1单行数据全列插入[提示]我们可以想在记事本上写下命令,让后复制到数据库客户端,这样可以在出错的时候进行快速修改.同时为了美观和明了,我们可以进行适当…

计算机的发展

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。个人爱好: 编程&#xff0c;打篮球&#xff0c;计算机知识个人名言&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石…

低代码开发平台选型必看指南

低代码开发是近年来逐渐兴起的一种新型软件开发方式。它通过封装常见的软件开发流程和代码&#xff0c;使得非专业的开发者也能够轻松创建复杂的应用程序。这种开发方式已经受到了许多企业的青睐&#xff0c;成为提高生产效率、降低开发成本的一种有效途径。 低代码开发的核心…

docker部署zabbix6.2.7+grafana

目录 1、下载docker 2、下载相关镜像文件 3、创建一个供zabbix系统使用的网络环境 4、创建一个供mysql数据库存放文件的目录 5、启动mysql容器 6、为zabbix-server创建一个持久卷 7、启动zabbix-server容器 8、创建语言存放目录 9、启动zabbix-web容器 10、启动zabbix…

【解锁技能】学会Python条件语句的终极指南!

文章目录前言一. python条件语句的介绍1.1 什么是条件语句1.2 条件语句的语法1.3 关于内置函数bool()二. 分支语句之单分支三. 多分支语句3.1 二分支语句3.2 多分支语句3.3 嵌套循环总结前言 &#x1f3e0;个人主页&#xff1a;欢迎访问 沐风晓月的博客 &#x1f9d1;个人简介&…

EPICS synApps介绍

一、synApps是什么&#xff1f; 1&#xff09; 一个用于同步束线用户的EPICS模块集合。 2&#xff09; EPICS模块 alive, autosave, busy, calc, camac, caputRecorder, dac128V, delaygen, dxp, ip, ip330, ipUnidig, love, mca, measComp, modbus, motor, optics, quadEM,…

【蓝桥杯选拔赛真题38】python目标值判断 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析

目录 python目标值判断 一、题目要求 1、编程实现 2、输入输出 二、解题思路

【牛客刷题专栏】0x0E:JZ6 从尾到头打印链表(C语言编程题)

前言 个人推荐在牛客网刷题(点击可以跳转)&#xff0c;它登陆后会保存刷题记录进度&#xff0c;重新登录时写过的题目代码不会丢失。个人刷题练习系列专栏&#xff1a;个人CSDN牛客刷题专栏。 题目来自&#xff1a;牛客/题库 / 在线编程 / 剑指offer&#xff1a; 目录前言问题…

CVE-2022-42889 Apache Commons Text 漏洞

0x00 前言 所幸遇到&#xff0c;就简单看看&#xff0c;其中没有啥比较难的地方&#xff0c;仅做记录。10月13日的漏洞。 cve链接可以看下面这个&#xff1a; https://cve.mitre.org/cgi-bin/cvename.cgi?nameCVE-2022-42889 git地址&#xff1a; https://github.com/apache…

前端进阶JS运行原理

JS运行原理 深入了解V8引擎原理 浏览器内核是由两部分组成的&#xff0c;以webkit为例&#xff1a; WebCore&#xff1a;负责HTML解析、布局、渲染等等相关的工作&#xff1b;JavaScriptCore&#xff1a;解析、执行JavaScript代码&#xff1b; 官方对V8引擎的定义&#xff1…

汇编指令学习(MOV,MOVSX,MOVZX,LEA,XCHG)

一、MOV指令1、将十六进制0x1234数值&#xff0c;赋值给eax寄存器mov eax,0x12342、将十六进制0x123数值&#xff0c;赋值给内存地址为ebxmov dword [ebx],0x1233、将edx的高八位赋值给eax的低八位ax&#xff0c;eax的低16位&#xff0c;al&#xff0c;eax的低8位&#xff0c;a…

(三)随处可见的LED广告屏是怎么工作的呢?接入GUI

续上文&#xff0c;本篇我们将尝试接入一个GUI来控制点阵屏。在前两篇中&#xff0c;我们相继介绍了点阵屏的控制原理&#xff0c;以及如何让点阵屏按照我们所想的进行显示。本篇将在此基础上接入一个GUI&#xff0c;使点阵屏的控制更加优雅。限于阅读体验和展示效果&#xff0…

深入理解border以及应用

深入border属性以及应用&#x1f44f;&#x1f44f; border这个属性在开发过程中很常用&#xff0c;常常用它来作为边界的。但是大家真的了解border吗&#xff1f;以及它的形状是什么样子的。 我们先来看这样一段代码&#xff1a;&#x1f44f; <!--* Author: syk 185901…

k8s环境jenkins发布vue项目指定nodejs版本

k8s环境jenkins发布vue项目指定nodejs版本1、背景2、分析3、解决方法3.1、 找到配置镜像位置3.2、 制作新镜像3.3、 推送镜像到私有仓库3.4、 修改配置文件1、背景 发布一个前端项目&#xff0c;它需要nodejs 16.9.0版本支持&#xff0c;而kubesphere 3.2.0集成的jenkins 的镜…