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. 其他

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

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

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

相关文章

进程控制-操作系统

1. 进程概述 进程和程序的区别:程序和进程是两个不同的概念&#xff0c;他们的状态&#xff0c;占用的系统资源都是不同的。 程序&#xff1a;就是磁盘上的可执行文件文件, 并且只占用磁盘上的空间&#xff0c;是一个静态的概念。进程&#xff1a;被执行之后的程序叫做进程&a…

Maven之依赖的传递

问题导入 1. 依赖传递 A依赖B&#xff0c;B依赖C&#xff0c;A是否依赖于C呢&#xff1f;–A依赖于C 依赖具有传递性 路径优先&#xff1a;当依赖中出现相同的的资源时&#xff0c;层级越深&#xff0c;优先级越低&#xff0c;层级越浅&#xff0c;优先级越高 声明优先&…

nacos 2.* 部署在linux服务器无法注册问题

通过sdk注册代码 报错 Exception in thread "main" ErrCode:-401, ErrMsg:Client not connected, current status:STARTING at com.alibaba.nacos.common.remote.client.RpcClient.request(RpcClient.java:639) at com.alibaba.nacos.common.remote.client…

【网络编程】——基于TCP协议实现回显服务器及客户端

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、TCP实…

AI无人直播系统怎么样?三点说明

近年来&#xff0c;因为科技的高速进步&#xff0c;不断涌现出了越来越多的新技术和创新事物&#xff0c;它们以其独特的方式取代了我们的许多传统做法&#xff0c;从而彻底解放了我们的双手。在这股潮流中&#xff0c;无人直播作为一种创新形式&#xff0c;使得直播变得更加简…

【容器】K8s RBAC介绍

认识RBAC RBAC&#xff08;基于角色的访问控制&#xff09;是一种将权限分配给用户和服务的方法&#xff0c;基于他们的角色来确定他们可以访问和修改的资源。K8s使用RBAC作为来访请求鉴权的机制之一。 场景&#xff1a;访问K8s接口时的认证和鉴权 某些场景下&#xff0c;我…

面试算法98:路径的数目

题目 一个机器人从mn的格子的左上角出发&#xff0c;它每步要么向下要么向右&#xff0c;直到抵达格子的右下角。请计算机器人从左上角到达右下角的路径的数目。例如&#xff0c;如果格子的大小是33&#xff0c;那么机器人从左上角到达右下角有6条符合条件的不同路径。 分析…

rabbitmq延时队列相关配置

确保 RabbitMQ 的延时消息插件已经安装和启用。你可以通过执行以下命令来安装该插件&#xff1a; rabbitmq-plugins enable rabbitmq_delayed_message_exchange 如果提示未安装&#xff0c;以下是安装流程&#xff1a; 查看mq版本&#xff1a; 查看自己使用的 MQ&#xff08;…

全网最全丨傻瓜式Fiddler教程大全丨从安装到抓包

前言 在我们做接口测试的时候&#xff0c;经常需要验证发送的消息是否正确&#xff0c;或者在出现问题的时候&#xff0c;查看手机客户端发送给server端的包内容是否正确&#xff0c;就需要用到抓包工具。 今天&#xff0c;给大家带来最常用的Fiddler的傻瓜式教程大全——从安…

九、综合实例:修改用户资料(Qt5 GUI系列)

目录 一、设计需求 二、实现代码 三、代码解析 四、总结 一、设计需求 设计一个修改用户资料功能的对话框&#xff0c;要求包含基本信息、联系方式、详细资料的编辑和修改。本实例只实现界面。 二、实现代码 导航页面&#xff1a; //添加的头文件 #include <QStacked…

深入理解Python中的二分查找与bisect模块

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

安装Cygwin的包管理器apt-cyg并安装tree命令

文章目录 一、从官网添加必要软件包1. 安装2. 检查 二、安装apt-cyg1. 下载安装2.修复 三、安装tree命令1. 安装2.检验 一、从官网添加必要软件包 1. 安装 因为第一次安装cygwin时走的都是默认选项&#xff0c;所以这里是二次添加额外包。 打开官网&#xff0c;下载安装程序。…

【导出与导入Virtualbox虚拟机和启动连接openGauss数据库】

【导出与导入Virtualbox虚拟机和启动连接openGauss数据库】 一、导出虚拟机二、导入虚拟机三、启动数据库四、使用Data Studio连接数据库 一、导出虚拟机 选择关机状态的虚拟机 -> 管理菜单 -> 导出虚拟电脑 点击完成后&#xff0c;需要等待一小段时间&#xff0c;如…

每日一道算法题day-three(备战蓝桥杯)

哈喽大家好&#xff0c;今天来给大家带来每日一道算法题系列第三天&#xff0c;让我们来看看今天的题目&#xff0c;一起备战蓝桥杯 题目&#xff1a; 小 Y的桌子上放着 n 个苹果从左到右排成一列&#xff0c;编号为从 11 到 n。 小苞是小 Y 的好朋友&#xff0c;每天她都会…

Java JDK8到21演升特性汇总

Java JDK 8 到 19 演升特性汇总 文章目录 Java JDK 8 到 19 演升特性汇总一、版本roadmap图二、版本与特性JDK8 [2014-03-18]JDK11[2018-09-25]JDK17【2021-09-14】JDK21 [2023-09-19] 一、版本roadmap图 官方地址 JDK8,JDK11,JDK17,JDK21是长期维护的版本。spring boot3最低支…

D-Link DES-108 交换机

D-Link DES-108 交换机 1. 百兆交换机 8 口References ​ D-Link Corporation is a Taiwanese multinational networking equipment manufacturing corporation headquartered in Taipei, Taiwan. Taiwanese&#xff1a;adj. 台湾的 n. 台湾人 headquarter [hedkwɔ:tə]&#…

汽车电子学习总结

国内的主要有比亚迪、联合汽车电子&#xff08;联电&#xff09;、麦格米特、上海电驱动&#xff1b;国外的主要有欧美系的博世、麦格纳、大陆、博格华纳&#xff1b;日系的电装、电产等公司。

AIOps探索 | 基于大模型构建高效的运维知识及智能问答平台(2)案例分享

原作者&#xff1a;擎创科技产品专家 布博士 案例分享 所需要的软件列表 本次案例的实现&#xff0c;全部采用开源或SAAS的产品来提供&#xff0c;并不涉及到私有化部署的软件产品。软件列表如下所示&#xff0c;如何申请apikey请自行研究&#xff0c;在这里不再详细说明&…

VIT用于图像分类 学习笔记(附代码)

论文地址&#xff1a;https://arxiv.org/abs/2010.11929 代码地址&#xff1a;https://github.com/bubbliiiing/classification-pytorch 1.是什么&#xff1f; Vision Transformer&#xff08;VIT&#xff09;是一种基于Transformer架构的图像分类模型。它将图像分割成一系列…

如何实现安卓端与苹果端互通

在移动应用开发中&#xff0c;如何实现安卓端和苹果端的互通是一个重要的问题。二者缺少一个都会有损失&#xff0c;那如何实现安卓端跟苹果端互通&#xff0c;下面简单的介绍几点方法来帮助你再不同的平台上实现数据交互和功能互通。 基于Web技术 使用Web技术是一种常见并且…