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

SpringBoot中动态注册接口

1. 说明

  • 接口注册,使用RequestMappingHandlerMapping来实现
  • mybatis中动态执行sql使用github上的SqlMapper工具类实现

2. 核心代码片段

        以下代码为spring动态注册接口代码示例

@Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping;public boolean register2Spring(String path) {RequestMappingInfo requestMappingInfo = RequestMappingInfo.paths(path).methods(RequestMethod.POST).produces(MediaType.APPLICATION_JSON_VALUE).options(requestMappingHandlerMapping.getBuilderConfiguration()).build();Method method = ReflectionUtils.findMethod(getClass(), "handler",HttpServletRequest.class, HttpServletResponse.class,Map.class, Map.class, Map.class);boolean status = true;try {requestMappingHandlerMapping.registerMapping(requestMappingInfo, this, method);LOGGER.info("【接口注册成功】{}", path);} catch (Exception e) {status = false;LOGGER.error("【注册接口异常】动态映射失败", e.getMessage());}return status;}

3. 源码

3.1 核心代码

3.1.1 ApiServiceHandler

        handler中register职责如下:

  • 注册到数据库中
  • 注册接口到spring容器中
import com.alibaba.fastjson2.JSONObject;
import com.google.common.net.HttpHeaders;
import com.hz.pro.artifact.bean.CommonException;
import com.hz.pro.artifact.bean.Response;
import com.hz.pro.artifact.dynamic.bean.ServiceDto;
import com.hz.pro.artifact.dynamic.mapper.main.ApiServiceMapper;
import com.hz.pro.artifact.utils.SqlMapper;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;/*** @author pp_lan* @date 2024/1/4*/
@Service
public class ApiServiceHandler {private static final Logger LOGGER = LoggerFactory.getLogger(ApiServiceHandler.class);@Autowiredprivate RequestMappingHandlerMapping requestMappingHandlerMapping;@Autowired@Qualifier("sqlSessionFactory")private SqlSessionFactory sqlSessionFactory;@Autowiredprivate ApiServiceMapper apiServiceMapper;public void initialRegister() {List<ServiceDto> apis = findApis();for (ServiceDto api : apis) {try {register2Spring(api.getPath());} catch (Exception e) {LOGGER.error("[接口注册失败]{}", api.getPath(), e.getMessage());}}}/*** 注册到spring,并添加到数据库中** @param path* @param sql* @return*/public boolean register(String path, String sql) {boolean status = this.registerApiOfSql(path, sql);if (status) {status = register2Spring(path);}return status;}/*** 注册到容器** @param path* @return*/public boolean register2Spring(String path) {RequestMappingInfo requestMappingInfo = RequestMappingInfo.paths(path).methods(RequestMethod.POST).produces(MediaType.APPLICATION_JSON_VALUE).options(requestMappingHandlerMapping.getBuilderConfiguration()).build();Method method = ReflectionUtils.findMethod(getClass(), "handler",HttpServletRequest.class, HttpServletResponse.class,Map.class, Map.class, Map.class);boolean status = true;try {requestMappingHandlerMapping.registerMapping(requestMappingInfo, this, method);LOGGER.info("【接口注册成功】{}", path);} catch (Exception e) {status = false;LOGGER.error("【注册接口异常】动态映射失败", e.getMessage());}return status;}@ResponseBodypublic Response handler(HttpServletRequest request, HttpServletResponse response,@PathVariable(required = false) Map<String, Object> pathVariable,@RequestParam(required = false) Map<String, Object> requestParam,@RequestBody(required = false) Map<String, Object> requestBody) {String header = request.getHeader(HttpHeaders.CONTENT_TYPE);// 参数处理JSONObject params;if (header != null && header.contains(MediaType.APPLICATION_JSON_VALUE)) {params = new JSONObject(requestBody);} else {params = new JSONObject(requestParam);}// 执行查询try (SqlMapper sqlMapper = new SqlMapper(sqlSessionFactory)) {String path = request.getRequestURI();String sql = apiServiceMapper.findSqlByPath(path);List<Map<String, Object>> result = sqlMapper.selectList(sql, params);return Response.ok(result);} catch (Exception e) {throw new CommonException("【公共查询异常】", e);}}/*** 查询所有在用接口** @return*/public List<ServiceDto> findApis() {return apiServiceMapper.findApis();}/*** 注册接口** @param path* @param sql* @return*/public boolean registerApiOfSql(String path, String sql) {try {return apiServiceMapper.insertApiSql(path, sql) > 0;} catch (Exception e) {throw new CommonException("【注册接口异常】插入sql配置失败", e);}}}

3.1.2 DynamicController

        手动注册接口执行/dynamic/register方法,便可以完成接口注册。

import com.hz.pro.artifact.bean.Response;
import com.hz.pro.artifact.dynamic.bean.ApiReq;
import com.hz.pro.artifact.dynamic.service.ApiServiceHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author pp_lan* @date 2024/1/2*/
@RestController
@RequestMapping("/dynamic")
public class DynamicController {@Autowiredprivate ApiServiceHandler apiServiceHandler;/*** 注册接口** @param apiReq* @return*/@PostMapping("register")public Response register(@RequestBody @Validated ApiReq apiReq) {boolean registerStatus = apiServiceHandler.register(apiReq.getPath(), apiReq.getSql());return registerStatus ? Response.ok("接口注册成功") : Response.error("接口注册失败");}
}

3.2 依赖类

3.2.1 SqlMapper

        此为github上有开源工具类,最新代码请移步github。以下为其源码:

import org.apache.ibatis.builder.StaticSqlSource;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;import java.util.ArrayList;
import java.util.List;
import java.util.Map;/*** MyBatis执行sql工具,在写SQL的时候建议使用参数形式的可以是${}或#{}** 不建议将参数直接拼到字符串中,当大量这么使用的时候由于缓存MappedStatement而占用更多的内存** @author liuzh* @since 2015-03-10*/
public class SqlMapper implements AutoCloseable {private final MSUtils msUtils;private final SqlSession sqlSession;/*** 构造方法,默认缓存MappedStatement** @param sqlSession*/public SqlMapper(SqlSession sqlSession) {this.sqlSession = sqlSession;this.msUtils = new MSUtils(sqlSession.getConfiguration());}public SqlMapper(SqlSessionFactory sqlSessionFactory) {this.sqlSession = sqlSessionFactory.openSession();this.msUtils = new MSUtils(sqlSession.getConfiguration());}/*** 获取List中最多只有一个的数据** @param list List结果* @param <T>  泛型类型* @return*/private <T> T getOne(List<T> list) {if (list.size() == 1) {return list.get(0);} else if (list.size() > 1) {throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());} else {return null;}}/*** 查询返回一个结果,多个结果时抛出异常** @param sql 执行的sql* @return*/public Map<String, Object> selectOne(String sql) {List<Map<String, Object>> list = selectList(sql);return getOne(list);}/*** 查询返回一个结果,多个结果时抛出异常** @param sql   执行的sql* @param value 参数* @return*/public Map<String, Object> selectOne(String sql, Object value) {List<Map<String, Object>> list = selectList(sql, value);return getOne(list);}/*** 查询返回一个结果,多个结果时抛出异常** @param sql        执行的sql* @param resultType 返回的结果类型* @param <T>        泛型类型* @return*/public <T> T selectOne(String sql, Class<T> resultType) {List<T> list = selectList(sql, resultType);return getOne(list);}/*** 查询返回一个结果,多个结果时抛出异常** @param sql        执行的sql* @param value      参数* @param resultType 返回的结果类型* @param <T>        泛型类型* @return*/public <T> T selectOne(String sql, Object value, Class<T> resultType) {List<T> list = selectList(sql, value, resultType);return getOne(list);}/*** 查询返回List<Map<String, Object>>** @param sql 执行的sql* @return*/public List<Map<String, Object>> selectList(String sql) {String msId = msUtils.select(sql);return sqlSession.selectList(msId);}/*** 查询返回List<Map<String, Object>>** @param sql   执行的sql* @param value 参数* @return*/public List<Map<String, Object>> selectList(String sql, Object value) {Class<?> parameterType = value != null ? value.getClass() : null;String msId = msUtils.selectDynamic(sql, parameterType);return sqlSession.selectList(msId, value);}/*** 查询返回指定的结果类型** @param sql        执行的sql* @param resultType 返回的结果类型* @param <T>        泛型类型* @return*/public <T> List<T> selectList(String sql, Class<T> resultType) {String msId;if (resultType == null) {msId = msUtils.select(sql);} else {msId = msUtils.select(sql, resultType);}return sqlSession.selectList(msId);}/*** 查询返回指定的结果类型** @param sql        执行的sql* @param value      参数* @param resultType 返回的结果类型* @param <T>        泛型类型* @return*/public <T> List<T> selectList(String sql, Object value, Class<T> resultType) {String msId;Class<?> parameterType = value != null ? value.getClass() : null;if (resultType == null) {msId = msUtils.selectDynamic(sql, parameterType);} else {msId = msUtils.selectDynamic(sql, parameterType, resultType);}return sqlSession.selectList(msId, value);}/*** 插入数据** @param sql 执行的sql* @return*/public int insert(String sql) {String msId = msUtils.insert(sql);return sqlSession.insert(msId);}/*** 插入数据** @param sql   执行的sql* @param value 参数* @return*/public int insert(String sql, Object value) {Class<?> parameterType = value != null ? value.getClass() : null;String msId = msUtils.insertDynamic(sql, parameterType);return sqlSession.insert(msId, value);}/*** 更新数据** @param sql 执行的sql* @return*/public int update(String sql) {String msId = msUtils.update(sql);return sqlSession.update(msId);}/*** 更新数据** @param sql   执行的sql* @param value 参数* @return*/public int update(String sql, Object value) {Class<?> parameterType = value != null ? value.getClass() : null;String msId = msUtils.updateDynamic(sql, parameterType);return sqlSession.update(msId, value);}/*** 删除数据** @param sql 执行的sql* @return*/public int delete(String sql) {String msId = msUtils.delete(sql);return sqlSession.delete(msId);}/*** 删除数据** @param sql   执行的sql* @param value 参数* @return*/public int delete(String sql, Object value) {Class<?> parameterType = value != null ? value.getClass() : null;String msId = msUtils.deleteDynamic(sql, parameterType);return sqlSession.delete(msId, value);}@Overridepublic void close() throws Exception {this.sqlSession.close();}private class MSUtils {private Configuration configuration;private LanguageDriver languageDriver;private MSUtils(Configuration configuration) {this.configuration = configuration;languageDriver = configuration.getDefaultScriptingLanuageInstance();}/*** 创建MSID** @param sql 执行的sql* @param sql 执行的sqlCommandType* @return*/private String newMsId(String sql, SqlCommandType sqlCommandType) {StringBuilder msIdBuilder = new StringBuilder(sqlCommandType.toString());msIdBuilder.append(".").append(sql.hashCode());return msIdBuilder.toString();}/*** 是否已经存在该ID** @param msId* @return*/private boolean hasMappedStatement(String msId) {return configuration.hasStatement(msId, false);}/*** 创建一个查询的MS** @param msId* @param sqlSource  执行的sqlSource* @param resultType 返回的结果类型*/private void newSelectMappedStatement(String msId, SqlSource sqlSource, final Class<?> resultType) {MappedStatement ms = new MappedStatement.Builder(configuration, msId, sqlSource, SqlCommandType.SELECT).resultMaps(new ArrayList<ResultMap>() {{add(new ResultMap.Builder(configuration, "defaultResultMap", resultType, new ArrayList<ResultMapping>(0)).build());}}).build();//缓存configuration.addMappedStatement(ms);}/*** 创建一个简单的MS** @param msId* @param sqlSource      执行的sqlSource* @param sqlCommandType 执行的sqlCommandType*/private void newUpdateMappedStatement(String msId, SqlSource sqlSource, SqlCommandType sqlCommandType) {MappedStatement ms = new MappedStatement.Builder(configuration, msId, sqlSource, sqlCommandType).resultMaps(new ArrayList<ResultMap>() {{add(new ResultMap.Builder(configuration, "defaultResultMap", int.class, new ArrayList<ResultMapping>(0)).build());}}).build();//缓存configuration.addMappedStatement(ms);}private String select(String sql) {String msId = newMsId(sql, SqlCommandType.SELECT);if (hasMappedStatement(msId)) {return msId;}StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);newSelectMappedStatement(msId, sqlSource, Map.class);return msId;}private String selectDynamic(String sql, Class<?> parameterType) {String msId = newMsId(sql + parameterType, SqlCommandType.SELECT);if (hasMappedStatement(msId)) {return msId;}SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);newSelectMappedStatement(msId, sqlSource, Map.class);return msId;}private String select(String sql, Class<?> resultType) {String msId = newMsId(resultType + sql, SqlCommandType.SELECT);if (hasMappedStatement(msId)) {return msId;}StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);newSelectMappedStatement(msId, sqlSource, resultType);return msId;}private String selectDynamic(String sql, Class<?> parameterType, Class<?> resultType) {String msId = newMsId(resultType + sql + parameterType, SqlCommandType.SELECT);if (hasMappedStatement(msId)) {return msId;}SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);newSelectMappedStatement(msId, sqlSource, resultType);return msId;}private String insert(String sql) {String msId = newMsId(sql, SqlCommandType.INSERT);if (hasMappedStatement(msId)) {return msId;}StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);newUpdateMappedStatement(msId, sqlSource, SqlCommandType.INSERT);return msId;}private String insertDynamic(String sql, Class<?> parameterType) {String msId = newMsId(sql + parameterType, SqlCommandType.INSERT);if (hasMappedStatement(msId)) {return msId;}SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);newUpdateMappedStatement(msId, sqlSource, SqlCommandType.INSERT);return msId;}private String update(String sql) {String msId = newMsId(sql, SqlCommandType.UPDATE);if (hasMappedStatement(msId)) {return msId;}StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);newUpdateMappedStatement(msId, sqlSource, SqlCommandType.UPDATE);return msId;}private String updateDynamic(String sql, Class<?> parameterType) {String msId = newMsId(sql + parameterType, SqlCommandType.UPDATE);if (hasMappedStatement(msId)) {return msId;}SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);newUpdateMappedStatement(msId, sqlSource, SqlCommandType.UPDATE);return msId;}private String delete(String sql) {String msId = newMsId(sql, SqlCommandType.DELETE);if (hasMappedStatement(msId)) {return msId;}StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);newUpdateMappedStatement(msId, sqlSource, SqlCommandType.DELETE);return msId;}private String deleteDynamic(String sql, Class<?> parameterType) {String msId = newMsId(sql + parameterType, SqlCommandType.DELETE);if (hasMappedStatement(msId)) {return msId;}SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);newUpdateMappedStatement(msId, sqlSource, SqlCommandType.DELETE);return msId;}}
}

3.2.2 ApiServiceMapper

import com.hz.pro.artifact.dynamic.bean.ServiceDto;
import org.apache.ibatis.annotations.Param;import java.util.List;/*** @author pp_lan* @date 2024/1/5*/
public interface ApiServiceMapper {List<ServiceDto> findApis();String findSqlByPath(@Param("path") String path);int insertApiSql(@Param("path") String path, @Param("sqlContent") String sqlContent);
}

3.2.3 ApiServiceMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hz.pro.artifact.dynamic.mapper.main.ApiServiceMapper"><select id="findApis" resultType="com.hz.pro.artifact.dynamic.bean.ServiceDto">select path, sql_content from t_api_sql where in_use = 1</select><select id="findSqlByPath" resultType="java.lang.String">select sql_content from t_api_sql where path = #{path} and in_use = 1</select><insert id="insertApiSql">INSERT INTO t_api_sql VALUES(#{path}, #{sqlContent}, 1)</insert></mapper>

4 效果

4.1 注册

4.2 查询

5. 其他

       上述实现步骤已完成接口的注册、查询功能。但是存在一个问题,重启后接口便不存在了,需要重新初始化。后续可以使用监听读取数据库中接口配置进行接口的初始化。

相关文章:

SpringBoot中动态注册接口

1. 说明 接口注册&#xff0c;使用RequestMappingHandlerMapping来实现mybatis中动态执行sql使用github上的SqlMapper工具类实现 2. 核心代码片段 以下代码为spring动态注册接口代码示例 Autowired private RequestMappingHandlerMapping requestMappingHandlerMapping;publ…...

CSS 实现两个圆圈重叠部分颜色不同

这是期望实现的效果&#xff0c;由图可知&#xff0c;圆圈底图透明度是0.4&#xff0c;左侧要求重叠部分透明度是0.7&#xff0c;所以不能通过简单的透明度叠加来实现最右侧的效果。 这就需要另外新建一个图层来叠加在两个圆圈重叠上方。 直接看代码 .circle_hight {width: 1…...

【数据库系统概念】第7-14章集合

文章目录 第七章 数据库设计和E-R模型&#xff08;重点&#xff01;&#xff01;&#xff01;&#xff09;~~7.1 设计过程概览&#xff08;了解&#xff09;~~7.1.1 设计阶段7.1.2 设计选择 7.2 实体-联系模型&#xff08;重点掌握&#xff09;7.2.1 实体集7.2.2 联系集联系集的…...

Kibana

Kibana是一个针对Elastic Search的开源分析及可视化的平台&#xff0c;使用kibana可以查询、查看并与存储在ES索引的数据进行交互操作&#xff0c;可以理解为一个客户端的工具&#xff0c;比如mysql和navicat。 使用kibana能执行高级的数据分析&#xff0c;并能以图表、表格和地…...

C#使用 OpenHardwareMonitor获取CPU或显卡温度、使用率、时钟频率相关方式

C# 去获取电脑相关的基础信息&#xff0c;还是需要借助 外部的库&#xff0c;我这边尝试了自己去实现它 网上有一些信息&#xff0c;但不太完整&#xff0c;都比较零碎&#xff0c;这边尽量将代码完整的去展示出来 OpenHardwareMonitor获取CPU的温度和频率需要管理员权限 在没…...

K8S--- volumesvolumeMount

一、Volume 简介 在容器当中的磁盘文件(on-disk file )是短暂的(ephemeral),这会对重要的应用程序或者数据产生一些问题。当容器崩溃或停止时,会出现一个问题,即容器状态不会被保存,因此在容器生命周期内被创建或者修改的文件都将丢失。在容器崩溃期间,kubelet会以干净状…...

AntV-G6 -- 将G6图表应用到项目中

1. 效果图 2. 安装依赖 npm install --save antv/g6 3. 代码 import { useEffect } from alipay/bigfish/react; import G6 from antv/g6;const data {id: root,label: 利息收入,subLabel: 3,283.456,ratio: 3,children: [{id: child-a,label: 平均利息,subLabel: 9%,ratio:…...

第二百五十回

文章目录 1. 概念介绍2. 使用方法2.1 简单用法2.2 自定义用法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"三方包open_settings"相关的内容&#xff0c;本章回中将介绍另外一个三方包&#xff1a;bluetooth_enable_fork.闲话休提&#xff0c;让我们一起Talk Flu…...

如何把硬盘(分区)一分为二?重装系统的小伙伴不可不看

注意事项&#xff1a;本教程操作不当会导致数据丢失 请谨慎操作 请谨慎操作 请谨慎操作 前言 相信各位小伙伴都会切土豆吧&#xff0c;本教程就是教大家如何切土豆切得好的教程。 啊哈哈哈&#xff0c;开玩笑的。 比如你有一个D盘是200GB&#xff0c;想要把它变成两个100G…...

【AI视野·今日NLP 自然语言处理论文速览 第六十六期】Tue, 31 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Tue, 31 Oct 2023 (showing first 100 of 141 entries) Totally 100 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers The Eval4NLP 2023 Shared Task on Prompting Large Language Models a…...

解决Canvas画图清晰度问题

最近在开发Web端远程桌面的时候遇到的一个问题&#xff0c;解决记录一下&#xff0c;分享给各位有需要用到的朋友。 先吹下水&#xff1a;远程桌面的连接我们是通过Websocket连接后&#xff0c;后端不断返回远程端的界面二进制数据流&#xff0c;我接收到之后转为图像&#xf…...

zookeeper经典应用场景之分布式锁

1. 什么是分布式锁 在单体的应用开发场景中涉及并发同步的时候&#xff0c;大家往往采用Synchronized&#xff08;同步&#xff09;或者其他同一个JVM内Lock机制来解决多线程间的同步问题。在分布式集群工作的开发场景中&#xff0c;就需要一种更加高级的锁机制来处理跨机器的进…...

红队专题-Web安全/渗透测试-文件上传/下载/包含

文件上传/下载/包含 招募六边形战士队员利用目录穿越反弹SHELL实战测试2.2 提交报文修改检测3.2 文件内容检测绕过完整文件结构 检测 第四章&#xff1a;解析漏洞第一节 常见解析漏洞iis/nginx php fastcgi 取值错误 解析漏洞 &#xff08;配置错误&#xff09;nginx 文件名逻…...

安装阿里云CLI之配置阿里云凭证信息

有时候需要再主机上通过 OpenAPI 的调用访问阿里云&#xff0c;并完成控制&#xff0c;此时就需要在服务器上安装阿里云CLI&#xff0c;并完成账号的设置。 1. 登录阿里云创建账号 1.1 点击阿里云头像 ——》 控制访问 ——》创建一个拥有DNS权限的用户 这个用户不用太多权限…...

阿里云和腾讯云2核2G3M服务器上传速度多少?

2核2G3M服务器上传速度多少&#xff1f;上传是按10M带宽算&#xff0c;上传速度是1280KB/秒&#xff0c;即1.25M/秒&#xff1b;下载速度按3M带宽计算&#xff0c;下载速度是384KB/秒。本文阿腾云atengyun.com是以阿里云为例的&#xff0c;阿里云服务器当公网带宽小于10M及10M以…...

Python中的cls语法

在Python中&#xff0c;cls 是一个用于指代类本身的约定性名称&#xff0c;通常用作类方法&#xff08;class method&#xff09;中的第一个参数。cls 类似于 self&#xff0c;它是对类的引用&#xff0c;而不是对实例的引用。cls 通常在类方法中用于访问类级别的属性和方法。举…...

【Java】java -jar 读取jar包之外的yml

需求描述 springboot项目接入nacos配置&#xff0c;代码中使用bootstrap.yml来指定nacos信息&#xff0c;为了防止不同环境的来回切换&#xff0c;服务器中都单独在放一个bootstrap.yml&#xff0c;来指定具体环境的nacos配置&#xff0c;如sit服务器使用sit的nacos配置&#…...

遥感影像-语义分割数据集:山体滑坡数据集详细介绍及训练样本处理流程

原始数据集详情 简介&#xff1a;该遥感滑坡数据集由卫星光学图像、滑坡边界的形状文件和数字高程模型组成。该数据集中的所有图像&#xff0c;即770张滑坡图像&#xff08;红点&#xff09;和2003张非滑坡图像&#xff0c;都是从2018年5月至8月拍摄的TripleSat卫星图像中截取…...

ubuntu 22.04 安装r-base时缺少r-recommended

sudo apt-get install r-base时报错&#xff1a; 下列软件包有未满足的依赖关系&#xff1a; r-base : 依赖: r-recommended ( 4.3.2-1.2004.0) 但无法安装它 E: 无法修正错误&#xff0c;因为您要求某些软件包保持现状&#xff0c;就是它们破坏了软件包间的依赖关系。 解决方…...

HarmonOS 通用组件(Button)

本文 我们来看看基础组件中的 Button 这是 ArkTS ui 原生支持的一个组件 用来创建不同样式的按钮 首先 我们还是创建一个最基本的组件结构 Entry Component struct Index {build() {Row() {Column() {}.width(100%)}.height(100%)} }我们可以在 Column 组件中 加入一个button…...

代码随想录算法训练DAY22|二叉树8

算法训练DAY22|二叉树8 235. 二叉搜索树的最近公共祖先 力扣题目链接(opens new window) 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点…...

如何解决跨域问题

跨域是什么 跨域是指在浏览器中运行的前端程序试图通过XMLHttpRequest等方式向不同域的后端服务器发送请求时&#xff0c;会遭遇浏览器同源策略限制的情况默认情况下&#xff0c;浏览器只允许在同一来源&#xff08;协议、域名、端口&#xff09;下进行请求&#xff0c;而跨域…...

Typora 编辑器 讲解 包括使用方式 快捷键 附带下载地址 (免费破解)

CSDN 成就一亿技术人&#xff01; 今天来讲一下很好用的编辑器 Typora CSDN 成就一亿技术人&#xff01; 什么是Typora&#xff1f; 它是一个 Markdown 编辑器和阅读器&#xff0c;这意味着您可以使用简单的格式代码 &#xff08;Markdown&#xff09;是一种轻量级标记语言&…...

16-Echarts简化系列之:平行坐标系 parallel 和 parallelAxis 坐标轴

parallel&#xff1a; 可视化高维数据的图表&#xff0c;特点在于可同时展示多个变量之间的关系&#xff0c;并且可以通过调整轴的顺序和缩放来探索不同的数据视角。帮助探索数据之间的关系和趋势 parallelAxis&#xff1a; 平行坐标系中的坐标轴。 parallel 和 parallelAx…...

SqlServer内存使用情况

-- 查询执行中sql语句 SELECT TOP 500 [session_id], [request_id], [start_time] AS 开始时间, getdate() as 当前时间, [status] AS 状态, [command] AS 命令, dest.[text] AS sql语句, DB_NAME([database_id]) AS 数据库名, [blocking_session_id] AS 正在阻塞其他会话的会话…...

谈谈我的三次考研经历

阿七经历过三次考研。 第一次&#xff0c;大四毕业那年&#xff0c;大三开始有紧迫感&#xff0c;因为大学几年什么也没学会&#xff0c;毕业考试成绩从第二个学期开始就一路下滑&#xff0c;每次都是考前一周突击&#xff0c;最后擦着及格线通过。 大三就开始和几个同学组队…...

红队打靶练习:SAR: 1

目录 信息收集 1、arp 2、netdiscover 3、nmap 4、nikto 5、whatweb 小结 目录探测 1、gobuster 2、dirsearch WEB CMS 1、cms漏洞探索 2、RCE漏洞利用 提权 get user.txt 本地提权 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface:…...

WSL 与真实 linux 环境区别有多大?

随着 Windows 系统的不断发展和完善&#xff0c;WSL&#xff08;Windows Subsystem for Linux&#xff09;作为 Windows 10 的一个功能&#xff0c;为 Windows 用户提供了一个可以在 Windows 环境下运行 Linux 二进制可执行文件的环境。然而&#xff0c;尽管 WSL 为用户提供了一…...

Springboot和Spring有什么区别

SpringBoot和Spring的关系 不是&#xff1a;从马车到汽车那种交通出行的颠覆&#xff0c;从燃油车到纯电动车那种能源利用的变革&#xff0c;从人工驾驶到AI智能那种驾驶方式的升级。总之&#xff0c;不是产品的升级换代&#xff0c;不是谁要替换谁。而是&#xff1a;汽车从手…...

创建Qt项目

项目工程名称一般不要有特殊符号&#xff0c;不要有中文 项目工程保存路径可修改的&#xff0c;但路径不要带中文 构建系统&#xff0c;有3种&#xff0c;这里使用qmake qmake和cmake区别 构建过程不同&#xff0c;项目管理不同。 1、构建过程&#xff0c;qmake是Qt框架自带的…...

衡水网站建设最新报价/百度网站优化排名

enter code here相当新颖&#xff0c;做我的第一个HTML项目。其中我必须创建一个表格&#xff0c;我已经设法做好了。但是&#xff0c;这不完全相同。下面是我有&#xff1a;HTML - 表格单元尺寸1Thunder Road4:47210th Avenue Freeze Out3:103Night3:004Backstreet6:295Born T…...

asp.net 建立网站/东莞寮步最新通知

--------------------------------------------------------------------------------------------- [版权申明&#xff1a;本文系作者原创&#xff0c;转载请注明出处] 文章出处&#xff1a; http://blog.csdn.net/sdksdk0/article/details/53639792 作者&#xff1a;朱培 …...

环球国际网站建设/网站信息

测试用例可以用来衡量一个项目测试质量&#xff0c;因此在平时的测试流程中&#xff0c;编写测试用例就是测试过程中很重要的一步&#xff0c;每一个测试工程师都需要并且非常熟练的编写测试用例&#xff0c;能在编写测试用例中尽可能的覆盖任何异常的测试点&#xff1b;如何能…...

php网站开发过程考试/免费广告网

许多人以为&#xff0c;使用了Zend Framework&#xff0c;使用了Smarty&#xff0c;网站就是企业级的了。Zend Framework是一个企业级的框架&#xff0c;Smarty也是一个企业级的模板引擎&#xff0c;但是一个厨师级的锅和一把厨师级的刀并不一定就能炒出厨师级的菜来。 Zend Fr…...

专门做调查的网站/引流推广怎么做

这几天没事&#xff0c;在网上看了一下NET6的开源框架&#xff0c;有几个比较完整切好用的框架&#xff0c;分享一下 1、Admin.NET通用管理平台 这个框架用了几次&#xff0c;还不错&#xff0c;写法也感觉满好的 gitee地址&#xff1a;https://gitee.com/zuohuaijun/Admin.NET…...

企业网站模板html下载/网站优化靠谱seo

[VM-虚拟机]重新导入虚拟环境启动报错 Writed by semiter 版权所有&#xff0c;文章允许转载&#xff0c;但必须以链接方式注明源地址&#xff0c;否则追究法律责任! OS:win7 32bit vmware server:2.0.2 情形一&#xff1a; 重装系统后&#xff0c;机器名称改变了&#xff0…...