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

springboot项目中整合高德地图

一:高德开放平台的使用

        高德开放平台 | 高德地图API 

       注册高德地图账号

        认证填写个人信息: 

        认证方式选择“个人认证开发者”即可,然后完善信息

         认证成功之后,再次进入控制台,创建关于地图的应用

        

        创建Key(yml文件需要使用):

        

        

        以上步骤便可以完成高德地图的申请和key的创建。


开始Springboot的创建(就不从0到一的创建了)


二:创建数据库(我是用的是MySQL)

        建表语句:

CREATE TABLE `location_record` (`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',`ip` VARCHAR(50) DEFAULT NULL COMMENT '客户端IP地址',`longitude` DOUBLE(10,6) NOT NULL COMMENT '经度坐标,精确到小数点后6位',`latitude` DOUBLE(10,6) NOT NULL COMMENT '纬度坐标,精确到小数点后6位',`address` VARCHAR(255) DEFAULT NULL COMMENT '详细地址信息',`formatted_address` VARCHAR(255) DEFAULT NULL COMMENT '格式化后的完整地址',`city` VARCHAR(100) DEFAULT NULL COMMENT '所在城市名称',`province` VARCHAR(100) DEFAULT NULL COMMENT '所在省份名称',`district` VARCHAR(100) DEFAULT NULL COMMENT '新增:所在区县名称',`street` VARCHAR(100) DEFAULT NULL COMMENT '新增:街道信息',`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',`update_time` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间',PRIMARY KEY (`id`),KEY `idx_location` (`longitude`,`latitude`),KEY `idx_create_time` (`create_time`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='地理位置信息记录表';

        表中样式:


三:Springboot所需的依赖(根据你的需求再去增加删除依赖)

dependencies><!-- FastJSON --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><!-- OkHttp --><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.12.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version> 1.2.23</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.6</version></dependency><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.6.13</version></dependency><!-- Apache HttpClient --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version></dependency><!-- Spring Boot Configuration Processor --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><version>2.6.13</version><optional>true</optional></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.26</version></dependency>
</dependencies>

四:yml文件的配置

server:port: 8096spring:amap:key: "你的高德地图key值"version: 2.0geocode-url: https://restapi.amap.com/v3/geocode/geoip-url: https://restapi.amap.com/v3/ipregeo-url: https://restapi.amap.com/v3/geocode/regeodatasource: # 数据源配置driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/你所建表对应的数据库?serverTimezone=Asia/Shanghai&useSSL=falseusername: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSource# mybatis-plus配置,也可以不加,只是为了显示SQL,Springboot都自动配置好了
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

五:所需要的类

        

 AmapConfig:

package com.qfedu.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;@Data
@Configuration
@ConfigurationProperties(prefix = "spring.amap")
public class AmapConfig {private String key;                   // 对应配置中的 keyprivate String securityJsCode;        // 对应 security-js-codeprivate String version = "2.0";       // 默认版本号private String geocodeUrl;            // 对应 geocode.urlprivate String ipUrl;                 // 对应 ip.urlprivate String regeoUrl;              // 对应 regeo.url
}

WebMvcConfig(因为我的项目中配置了拦截器,所以需要这样一个类):

package com.qfedu.config;import com.qfedu.common.core.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Beanpublic LoginInterceptor loginInterceptor() {return new LoginInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/api/amap/**","/api/location/**"  // 新增排除location相关路径);}
}

HttpUtils:

package com.qfedu.utils;import com.sun.deploy.net.URLEncoder;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;import java.io.IOException;
import java.nio.charset.StandardCharsets;public class HttpUtil {public static String doGet(String url) throws IOException {if (url == null || url.trim().isEmpty()) {throw new IllegalArgumentException("URL不能为空");}CloseableHttpClient httpClient = HttpClients.createDefault();HttpGet httpGet = new HttpGet(url);// 设置请求头httpGet.setHeader("Accept", "application/json");httpGet.setHeader("Content-Type", "application/json");try (CloseableHttpResponse response = httpClient.execute(httpGet)) {int statusCode = response.getStatusLine().getStatusCode();if (statusCode != 200) {throw new IOException("HTTP请求失败,状态码: " + statusCode + ", URL: " + url);}HttpEntity entity = response.getEntity();if (entity == null) {throw new IOException("响应体为空");}return EntityUtils.toString(entity, StandardCharsets.UTF_8);} finally {httpClient.close();}}public static String encodeUrlParam(String param) {try {return URLEncoder.encode(param, StandardCharsets.UTF_8.name());} catch (Exception e) {return param;}}
}

返回值R类:(我的R类没有使用泛型)

package com.qfedu.common.core.common;public class R {/*** code,指状态码,* 随意定,20000 是正确,40000 错误* 50000 请求超时* 60000 没有权限* msg,指信息描述* data,返回的数据*/private int code;private String msg;private Object data;public static R ok() {R r = new R();r.setCode(200);r.setMsg("成功");return r;}public static R ok(Object data) {R r = new R();r.setCode(200);r.setMsg("成功");r.setData(data);return r;}public static R fail() {R r = new R();r.setCode(500);r.setMsg("失败");return r;}public static R fail(String msg) {R r = new R();r.setCode(500);r.setMsg(msg);return r;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}}

免登录自定义注解:

package com.qfedu.common.core.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 以梦为马,以汗为泉,不忘初心,不负韶华** @author ${上官箫宇}* @version 1.0* @data 2025/6/3 16:08*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)//注解运行时生效
public @interface NoLogin {
}

拦截器:

package com.qfedu.common.core.interceptor;import com.qfedu.common.core.annotation.NoLogin;
import com.qfedu.common.core.constants.CommonConstants;
import com.qfedu.common.core.utils.JwtUtils;
import com.qfedu.common.core.utils.UserUtils;
import io.jsonwebtoken.Claims;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;/*** ---Do First---** @author:wellseasun* @date:2025/5/22 下午 8:30* @desc:*/
public class LoginInterceptor implements HandlerInterceptor {// preHandle:执行时机:访问接口前@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {// handler表示处理某个请求的处理器对象,// 如果是类级别的拦截器,则handler为类对象,如果是方法级别的拦截器,则handler为方法对象if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();boolean annotationPresent = method.isAnnotationPresent(NoLogin.class);if (annotationPresent) {// 如果使用了注解,直接放行return true;} else {// 没有使用注解,需要从请求头中获取名为LOGIN_TOKEN的tokenString token = request.getHeader(CommonConstants.LOGIN_TOKEN);if (token == null || token.isEmpty()) {throw new RuntimeException("请重新登录");}try {JwtUtils jwtUtils = new JwtUtils();Claims claims = jwtUtils.parseJWT(token);UserUtils.setUid((Integer) claims.get("uid"));} catch (Exception e) {throw e;}}}return true;}}

没错,下面就是层级关系:

mapper:

package com.qfedu.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qfedu.common.core.entity.LocationRecord;public interface LocationRecordMapper extends BaseMapper<LocationRecord> {
}

service:

package com.qfedu.service;import com.alibaba.fastjson.JSONObject;
import com.qfedu.common.core.entity.LocationRecord;public interface AmapService {/*** IP定位* @param ip IP地址* @return 定位结果*/JSONObject ipLocation(String ip);/*** 逆地理编码* @param longitude 经度* @param latitude 纬度* @return 地址信息*/JSONObject regeoLocation(Double longitude, Double latitude);/*** 地理编码* @param address 地址* @return 经纬度信息*/JSONObject geoLocation(String address);/*** 保存定位记录* @param record 定位记录* @return 是否成功*/boolean saveLocationRecord(LocationRecord record);
}

service实现类:

package com.qfedu.service.impl;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qfedu.common.core.entity.LocationRecord;
import com.qfedu.config.AmapConfig;
import com.qfedu.mapper.LocationRecordMapper;
import com.qfedu.service.AmapService;
import com.qfedu.utils.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import javax.annotation.PostConstruct;/*** 高德地图服务实现类* 提供IP定位、地理编码、逆地理编码等核心功能*/
@Service
public class AmapServiceImpl extends ServiceImpl<LocationRecordMapper, LocationRecord>implements AmapService {private static final Logger logger = LoggerFactory.getLogger(AmapServiceImpl.class);@Autowiredprivate AmapConfig amapConfig; // 高德配置参数(key/url等)/*** 初始化时打印配置信息(调试用)*/@PostConstructpublic void init() {logger.info("高德地图配置加载: key={}, ipUrl={}, geoUrl={}, regeoUrl={}",amapConfig.getKey(),amapConfig.getIpUrl(),amapConfig.getGeocodeUrl(),amapConfig.getRegeoUrl());}// ==================== 核心服务方法 ====================/*** IP定位服务* @param ip 需要查询的IP地址* @return 包含定位结果的JSON对象(status=1成功,0失败)*/@Overridepublic JSONObject ipLocation(String ip) {// 参数校验if (!StringUtils.hasText(ip)) {return createErrorResponse("IP地址不能为空");}try {// 配置校验validateConfig(amapConfig.getKey(), amapConfig.getIpUrl());// 构建请求URL(示例:https://restapi.amap.com/v3/ip?key=xxx&ip=8.8.8.8)String url = String.format("%s?key=%s&ip=%s",amapConfig.getIpUrl().trim(),amapConfig.getKey().trim(),HttpUtil.encodeUrlParam(ip));validateUrl(url); // URL格式校验logger.info("请求高德IP定位API: {}", url);// 发送HTTP请求并解析响应String response = HttpUtil.doGet(url);logger.debug("高德IP定位API响应: {}", response);return parseResponse(response);} catch (Exception e) {logger.error("IP定位失败, IP: " + ip, e);return createErrorResponse("IP定位失败: " + e.getMessage());}}/*** 逆地理编码服务(坐标→地址)* @param longitude 经度* @param latitude 纬度* @return 包含地址信息的JSON响应*/@Overridepublic JSONObject regeoLocation(Double longitude, Double latitude) {if (longitude == null || latitude == null) {return createErrorResponse("经纬度不能为空");}try {validateConfig(amapConfig.getKey(), null); // 仅校验Key// 构建请求URL(示例:https://restapi.amap.com/v3/geocode/regeo?key=xxx&location=116.4,39.9)String location = longitude + "," + latitude;String url = String.format("%s?key=%s&location=%s",amapConfig.getRegeoUrl(),amapConfig.getKey(),HttpUtil.encodeUrlParam(location));logger.debug("请求高德逆地理编码API: {}", url);String response = HttpUtil.doGet(url);logger.debug("高德逆地理编码API响应: {}", response);return parseResponse(response);} catch (Exception e) {logger.error("逆地理编码失败, 位置: " + longitude + "," + latitude, e);return createErrorResponse("逆地理编码失败: " + getErrorMessage(e));}}/*** 地理编码服务(地址→坐标)* @param address 结构化地址(如"北京市海淀区中关村大街1号")* @return 包含经纬度的JSON响应*/@Overridepublic JSONObject geoLocation(String address) {if (!StringUtils.hasText(address)) {return createErrorResponse("地址不能为空");}try {validateConfig(amapConfig.getKey(), null); // 仅校验Key// 构建请求URL(示例:https://restapi.amap.com/v3/geocode/geo?key=xxx&address=北京)String url = String.format("%s?key=%s&address=%s",amapConfig.getGeocodeUrl(),amapConfig.getKey(),HttpUtil.encodeUrlParam(address));logger.debug("请求高德地理编码API: {}", url);String response = HttpUtil.doGet(url);logger.debug("高德地理编码API响应: {}", response);return parseResponse(response);} catch (Exception e) {logger.error("地理编码失败, 地址: " + address, e);return createErrorResponse("地理编码失败: " + getErrorMessage(e));}}/*** 保存定位记录到数据库* @param record 定位记录实体* @return 是否保存成功*/@Overridepublic boolean saveLocationRecord(LocationRecord record) {try {return this.save(record); // 调用MyBatis-Plus的save方法} catch (Exception e) {logger.error("保存定位记录失败", e);return false;}}// ==================== 内部工具方法 ====================/*** 校验高德配置参数* @param key 高德API Key* @param url 需要校验的API地址(可选)* @throws IllegalStateException 当配置不合法时抛出*/private void validateConfig(String key, String url) {if (amapConfig == null || !StringUtils.hasText(key)) {throw new IllegalStateException("高德地图配置未正确初始化");}if (url != null && !StringUtils.hasText(url)) {throw new IllegalStateException("高德API地址未配置");}}/*** 校验URL合法性* @param url 待校验的URL* @throws IllegalArgumentException 当URL非法时抛出*/private void validateUrl(String url) {if (!url.startsWith("http")) {throw new IllegalArgumentException("无效的API URL: " + url);}}/*** 解析高德API响应* @param response 原始JSON字符串* @return 解析后的JSONObject*/private JSONObject parseResponse(String response) {if (!StringUtils.hasText(response)) {return createErrorResponse("空响应");}try {JSONObject result = JSON.parseObject(response);return result != null ? result : createErrorResponse("响应解析失败");} catch (Exception e) {logger.error("解析高德API响应失败", e);return createErrorResponse("响应解析失败: " + e.getMessage());}}/*** 创建错误响应* @param message 错误信息* @return 标准化错误JSON(status=0)*/private JSONObject createErrorResponse(String message) {JSONObject result = new JSONObject();result.put("status", "0"); // 高德标准错误码result.put("info", message);return result;}/*** 提取异常信息(避免null)*/private String getErrorMessage(Exception e) {return e.getMessage() != null ? e.getMessage() : "未知错误";}
}

controller:

package com.qfedu.controller;import com.alibaba.fastjson.JSONObject;
import com.qfedu.common.core.annotation.NoLogin;
import com.qfedu.common.core.common.R;
import com.qfedu.common.core.entity.LocationRecord;
import com.qfedu.service.AmapService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.Date;/*** 高德地图定位服务控制器* 提供IP定位、逆地理编码、地理编码三大核心功能*/
@RestController
@RequestMapping("/api/location")
public class LocationController {@Autowiredprivate AmapService amapService; // 高德地图服务接口/*** IP定位接口* @param ip 需要定位的IP地址(如8.8.8.8)* @return 标准化响应R<JSONObject>,包含定位结果或错误信息*/@GetMapping("/ip")@NoLoginpublic R locateByIp(@RequestParam String ip) {// 调用高德IP定位服务JSONObject result = amapService.ipLocation(ip);// 校验高德API返回状态码(1=成功)if (result != null && "1".equals(result.getString("status"))) {saveLocationRecord(ip, result); // 持久化定位记录return R.ok(result); // 返回成功响应}// 失败时返回错误信息(优先使用高德返回的info字段)return R.fail(result != null ? result.getString("info") : "IP定位服务不可用");}/*** 逆地理编码接口(坐标→地址)* @param longitude 经度(如116.404)* @param latitude 纬度(如39.915)* @return 包含地址信息的标准化响应*/@GetMapping("/regeo")@NoLoginpublic R regeo(@RequestParam Double longitude,@RequestParam Double latitude) {JSONObject result = amapService.regeoLocation(longitude, latitude);if (result != null && "1".equals(result.getString("status"))) {saveLocationRecord(null, longitude, latitude, result); // IP传nullreturn R.ok(result);}return R.fail(result != null ? result.getString("info") : "逆地理编码服务不可用");}/*** 地理编码接口(地址→坐标)* @param address 结构化地址(如"北京市海淀区中关村大街1号")* @return 包含经纬度的标准化响应*/@GetMapping("/geo")@NoLoginpublic R geo(@RequestParam String address) {JSONObject result = amapService.geoLocation(address);if (result != null && "1".equals(result.getString("status"))) {return R.ok(result); // 地理编码不保存记录}return R.fail(result != null ? result.getString("info") : "地理编码服务不可用");}// 内部工具方法/*** 从IP定位结果提取经纬度并保存记录* @param ip IP地址* @param result 高德API返回的完整结果*/private void saveLocationRecord(String ip, JSONObject result) {JSONObject locationObj = result.getJSONObject("location");if (locationObj != null) {saveLocationRecord(ip,locationObj.getDouble("lng"), // 经度字段locationObj.getDouble("lat"), // 纬度字段result);}}/*** 保存定位记录到数据库(核心方法)* @param ip 可能为null(当来源是逆地理编码时)* @param longitude 经度(必填)* @param latitude 纬度(必填)* @param result 高德API原始结果(用于提取地址信息)*/private void saveLocationRecord(String ip,Double longitude,Double latitude,JSONObject result) {if (result == null) return;// 1. 构建定位记录实体LocationRecord record = new LocationRecord();record.setIp(ip); // IP可能为nullrecord.setLongitude(longitude);record.setLatitude(latitude);// 2. 提取格式化地址(如"北京市海淀区中关村大街1号")String formattedAddress = result.getString("formatted_address");record.setAddress(formattedAddress);record.setFormattedAddress(formattedAddress);// 3. 提取结构化地址组件(省、市、区等)JSONObject addressComponent = result.getJSONObject("addressComponent");if (addressComponent != null) {record.setProvince(addressComponent.getString("province"));record.setCity(addressComponent.getString("city"));// 可扩展:district(区)、street(街道)等字段}// 4. 设置时间戳并保存record.setCreateTime(new Date());amapService.saveLocationRecord(record); // 调用MyBatis-Plus持久化}
}

下面就是启动类:(首先不要忘记启动类的扫描注解,还有就是本次用到的注解

@EnableConfigurationProperties({AmapConfig.class})// 启用AmapConfig配置类)
package com.qfedu;import com.qfedu.config.AmapConfig;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;@SpringBootApplication
@MapperScan("com.qfedu.mapper")
@EnableConfigurationProperties({AmapConfig.class})// 启用AmapConfig配置类public class MicroServeAmapApplication {public static void main(String[] args) {SpringApplication.run(MicroServeAmapApplication.class, args);}}

写一个简单的页面展示吧,位置你们知道吧,我就不说详细了

展示台湾省地图吧(中国一点都不能少)

下面就是展示的代码,我只不过吧经纬度写成死值了,

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>高德地图展示测试:台湾省台北市地图 - 台北101</title><!-- 引入高德地图JS API --><script src="https://webapi.amap.com/maps?v=2.0&key=你的高德地图key"></script><style>#container {width: 100%;height: 600px;}</style>
</head>
<body>
<!-- 地图容器 -->
<div id="container"></div><script>// 初始化地图,中心点设为台北市var map = new AMap.Map('container', {zoom: 14,          // 缩放级别center: [121.5654, 25.0330], // 台北市坐标viewMode: '2D'     // 2D地图});// 添加标记点(台北101大楼)var marker = new AMap.Marker({position: [121.5654, 25.0330], // 台北101坐标map: map});// 信息窗口内容var infoWindow = new AMap.InfoWindow({content: '<div style="padding:5px;">台北101大楼</div>',offset: new AMap.Pixel(0, -30)});infoWindow.open(map, marker.getPosition());
</script>
</body>
</html>

http://www.xdnf.cn/news/1013905.html

相关文章:

  • leetcode题解538:把二叉搜索树转换为累加树
  • 微型导轨在实验室场景中的多元应用
  • 个人支出智能分析系统
  • 【HarmonyOS Next之旅】DevEco Studio使用指南(三十三) -> 构建任务
  • finereport普通报表根据用户权限限制数据查询
  • 动态规划算法的欢乐密码(二):路径问题
  • 【软件开发】什么是DSL
  • Excel大厂自动化报表实战(互联网金融-数据分析周报制作中)
  • 如何使用Postman做接口自动化测试
  • GitHub Actions 深度实践:零运维搭建 CI/CD 流水线
  • OCP 认证培训:踏入 Oracle 数据库专家的殿堂
  • 基于MATLAB的车牌检测系统:传统图像处理与深度学习的创新融合
  • 将MySQL数据库中所有表和字段编码统一改为utf8mb4_unicode_ci
  • 数据库学习(五)——MySQL索引
  • 2025年ASOC SCI2区TOP,强化学习驱动双邻域结构人工蜂群算法RL_DNSABC,深度解析+性能实测
  • React Native 构建与打包发布(iOS + Android)
  • Java EE 导读
  • 从信息孤岛到智能星云:学习助手编织高校学习生活的全维度互联网络
  • “第三届全国技能大赛”倒计时100天—千眼狼高速摄像机为焊接与增材制造项目提供可视化评判依据
  • electron实现加载页(启动页)
  • 优秀的大语言模型
  • 物联网嵌入式硬件开发管理指南(超详细版):基于三种外包方式的三阶段策略
  • 【经验总结】ECU休眠后连续发送NM报文3S后ECU网络才被唤醒问题分析
  • Android13 新增 Stable AIDL接口
  • 猎板PCB:手机主板pcb需要做哪些可靠性测试
  • 笔记本电脑安装win10哪个版本好_笔记本装win10专业版图文教程
  • 智驱未来:迁移科技3D视觉系统重塑复合机器人产业生态
  • 【Create my OS】1 最小内核
  • 上传一个菜谱-最后部分(项目完结)
  • Python爬虫实战:研究WebSocket-for-Python相关技术