《苍穹外卖》SpringBoot后端开发项目核心知识点与常见问题整理(DAY1 to DAY3)
目录
- 一、在本地部署并启动Nginx服务
- 1. 解压Nginx压缩包
- 2. 启动Nginx服务
- 3. 验证Nginx是否启动成功:
- 二、导入接口文档
- 1. 黑马程序员提供的YApi平台
- 2. YApi Pro平台
- 3. 推荐工具:Apifox
- 三、Swagger
- 1. 常用注解
- 1.1 @Api与@ApiModel
- 1.2 @ApiModelProperty与@ApiOperation
- 四、基于JWT和ThreadLocal动态获取员工ID
- 1. 在pom.xml中引入JWT依赖
- 2. 在application.yaml中配置JWT参数
- 3. 使用JWT获取当前登录员工ID
- 4. 通过拦截器解析JWT
- 5. 使用ThreadLocal传递员工ID
- 6. 在Service中获取员工ID
- 五、DTO的使用原因
- 1. 实体类 Employee
- 2. DTO EmployeeDTO
- 3. 使用 DTO 的场景
- 3.1 查询员工信息
- 3.2 更新员工信息
- 3.3 新增员工
- 4. DTO、VO和实体类的区别
- 六、为什么使用 XML 注解而不是 MyBatis 注解
- 1. 使用 XML 注解的原因
- 1.1 动态 SQL 支持
- 1.2 SQL 与代码分离
- 1.3 复用性
- 1.4 工具支持
- 2. MyBatis 注解的局限性
- 2.1 动态 SQL 支持有限
- 2.2 可读性差
- 2.3 维护困难
- 七、Spring Boot 的请求映射规则
- 1. 类级别路径
- 2. 方法级别路径
- 2.1 分页查询
- 2.2 根据 ID 查询菜品
- 2.3 修改菜品
- 2.4 新增菜品
- 2.5 批量删除菜品
- 3. 如何区分不同的功能
- 4. 示例请求
- 4.1 新增菜品
- 4.2 修改菜品
- 4.3 批量删除菜品
- 4.4 分页查询菜品
- 4.5 根据 ID 查询菜品
- 八、接口设计中的是否必需原则
- 1. 请求参数说明
- 1.1 Java代码分析
- 1.1.1 必需参数
- 1.2 XML映射文件分析
- 1.2.1 可选参数
- 2. 返回响应说明
- 2.1 Java代码分析
- 2.1.1 必需参数
- 2.1.2 可选参数
- 2.2 返回响应示例
- 2.2.1 成功响应(带数据)
- 2.2.2 成功响应(不带数据)
- 2.2.3 失败响应
- 九、阿里云OSS配置指南
- 1. 注册阿里云OSS账号
- 2. 获取关键信息
- 3. 更新配置文件
- 4, 重新运行服务
- 十、SpringBoot配置类详解
- 1. 生产环境与开发环境配置
- 1.1 配置文件命名规则
- 1.2 激活环境配置
- 1.3 占位符替换
- 示例
- 2. Spring 前缀与自定义前缀配置
- 2.1 Spring 内置配置
- 2.2 自定义配置
- 3. 自定义配置类的注册与使用
- 3.1 创建配置类
- 3.1.1 JWT 配置类
- 3.1.2 阿里云 OSS 配置类
- 3.2 使用配置类
- 3.2.1 在 Service 中使用配置类
- 3.3 配置类的注册
- 十一、SpringBoot注解汇总
- 1. Spring MVC 相关注解
- 2. Swagger 相关注解
- 3. Spring 核心注解
- 4. AOP 相关注解
- 5. Lombok 相关注解
- 6. MyBatis 相关注解
- 7. 配置相关注解
本文旨在为刚完成《苍穹外卖》项目DAY1至DAY3章节学习的学员提供难点解析与核心知识点梳理。鉴于该项目由黑马程序员于2023年推出,在实际构建过程中可能会遇到诸如网站链接失效、阿里OSS服务不可用等问题。本文将针对这些常见问题提供解决方案,并帮助学员更好地掌握项目关键内容。
视频链接:黑马程序员Java项目实战《苍穹外卖》,最适合新手的SpringBoot+SSM的企业级Java项目实战
网盘资料:苍穹外卖讲义&前后端源码
一、在本地部署并启动Nginx服务
在开发过程中,我们经常需要使用Nginx来部署前端项目或作为反向代理服务器。
1. 解压Nginx压缩包
首先,确保你已经从黑马程序员资料中下载了Nginx的压缩包。接下来,按照以下步骤解压:
选择解压路径:
- 将Nginx压缩包解压到一个全英文路径中。例如:
D:\nginx
- 注意:路径中不要包含中文或特殊字符,否则可能会导致Nginx无法正常运行。
2. 启动Nginx服务
解压完成后,按照以下步骤启动Nginx:
进入Nginx目录:
- 打开解压后的Nginx文件夹,找到
nginx.exe
文件。路径通常为:C:\nginx\nginx.exe
启动Nginx:
- 双击
nginx.exe
文件,启动Nginx服务。 - 启动后,Nginx会在后台运行,你可以在任务管理器中看到
nginx.exe
进程。
3. 验证Nginx是否启动成功:
- 打开浏览器,访问以下地址(其中80是默认端口可省略不写):
http://localhost:80
- 如果看到此页面,说明Nginx已成功启动。
- 注意:Nginx默认不会随系统自动启动,因此每次重启电脑后,都需要手动启动Nginx
二、导入接口文档
在开发过程中,接口管理平台是团队协作和项目管理的重要工具。以下是几个常用平台的对比:
1. 黑马程序员提供的YApi平台
- 地址:http://yapi.smart-xwork.cn/
- 状态:已弃用
- 功能:适合用于接口管理和文档生成。
2. YApi Pro平台
- 地址:https://yapi.pro/
- 问题:需要挂梯子才能访问,且极易卡顿,使用体验不佳。
3. 推荐工具:Apifox
- 地址:https://apifox.com/
- 优势:
- 无需梯子即可访问。
- 性能流畅,支持接口文档、Mock数据、自动化测试等功能。
- 支持导入YApi数据格式的接口文档,方便无缝迁移现有项目。
三、Swagger
Swagger 是一种用于设计、构建、记录和使用 RESTful Web 服务的开源框架。它提供了一套工具,帮助开发者设计、构建、文档化和测试 API。
启动服务:访问 http://localhost:8080/doc.html
1. 常用注解
通过注解可以控制生成的接口文档,使接口文档拥有更好的可读性,常用注解如下:
注解 | 说明 |
---|---|
@Api | 用在类上,例如Controller,表示对类的说明 |
@ApiModel | 用在类上,例如entity、DTO、VO |
@ApiModelProperty | 用在属性上,描述属性信息 |
@ApiOperation | 用在方法上,例如Controller的方法,说明方法的用途、作用 |
1.1 @Api与@ApiModel
1.2 @ApiModelProperty与@ApiOperation
四、基于JWT和ThreadLocal动态获取员工ID
在开发员工管理系统时,新增员工时需要记录创建人和修改人的ID。如果直接使用固定值,会导致数据不准确,无法真实反映操作者。
public void save(EmployeeDTO employeeDTO) {Employee employee = new Employee();employee.setCreateUser(10L); // 固定值employee.setUpdateUser(10L); // 固定值employeeMapper.insert(employee);
}
因此我们要通过JWT和ThreadLocal动态获取当前登录员工的ID,并实现数据的准确记录。在使用 JWT(JSON Web Token)进行身份验证时,通常需要在项目中引入相关的依赖库,并在配置文件中设置 JWT 的参数。以下是如何在 Spring Boot 项目中引入 JWT 并进行配置的简单说明:
1. 在pom.xml中引入JWT依赖
为了使用 JWT,我们需要引入一个 JWT 库,比如 java-jwt
(由 Auth0 提供)。
<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version> <!-- 使用最新版本 -->
</dependency>
2. 在application.yaml中配置JWT参数
在 application.yaml
文件中定义 JWT 的相关配置,例如密钥、过期时间和令牌名称。
sky:jwt:# 设置 JWT 签名加密时使用的秘钥admin-secret-key: itcast# 设置 JWT 过期时间(单位:毫秒)admin-ttl: 7200000 # 2小时# 设置前端传递过来的令牌名称admin-token-name: token
admin-secret-key
:用于签名和验证 JWT 的密钥。必须保密,且长度足够复杂以确保安全性。admin-ttl
:JWT 的有效期(以毫秒为单位)。例如,7200000
表示 2 小时。admin-token-name
:前端传递 JWT 时使用的参数名称。例如,前端可能会在请求头或请求参数中传递token=xxx
。
3. 使用JWT获取当前登录员工ID
员工登录成功后,系统会生成JWT令牌并返回给前端。JWT中包含了当前登录员工的ID信息。
/*** 员工管理*/
@RestController
@RequestMapping("/admin/employee")
@Api(tags = "员工相关接口")
@Slf4j
public class EmployeeController {@Autowiredprivate EmployeeService employeeService;@Autowiredprivate JwtProperties jwtProperties;/*** 登录** @param employeeLoginDTO* @return*/@PostMapping("/login")public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {log.info("员工登录:{}", employeeLoginDTO);Employee employee = employeeService.login(employeeLoginDTO);//登录成功后,生成jwt令牌Map<String, Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.EMP_ID, employee.getId());String token = JwtUtil.createJWT(jwtProperties.getAdminSecretKey(),jwtProperties.getAdminTtl(),claims);EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder().id(employee.getId()).userName(employee.getUsername()).name(employee.getName()).token(token).build();return Result.success(employeeLoginVO);}...
}
4. 通过拦截器解析JWT
在每次请求时,前端会携带JWT令牌。通过拦截器解析JWT,获取当前登录员工的ID。
/*** jwt令牌校验的拦截器*/
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {@Autowiredprivate JwtProperties jwtProperties;/*** 校验jwt** @param request* @param response* @param handler* @return* @throws Exception*/public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//判断当前拦截到的是Controller的方法还是其他资源if (!(handler instanceof HandlerMethod)) {//当前拦截到的不是动态方法,直接放行return true;}//1、从请求头中获取令牌String token = request.getHeader(jwtProperties.getAdminTokenName());//2、校验令牌try {log.info("jwt校验:{}", token);Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());log.info("当前员工id:", empId);BaseContext.setCurrentId(empId);//3、通过,放行return true;} catch (Exception ex) {//4、不通过,响应401状态码response.setStatus(401);return false;}}
}
5. 使用ThreadLocal传递员工ID
通过ThreadLocal实现线程隔离,将当前登录员工的ID传递给Service层。
public class BaseContext {public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();public static void setCurrentId(Long id) {threadLocal.set(id);}public static Long getCurrentId() {return threadLocal.get();}public static void removeCurrentId() {threadLocal.remove();}
}
6. 在Service中获取员工ID
在Service层中,从ThreadLocal中获取当前登录员工的ID,并设置为创建人和修改人。
public void save(EmployeeDTO employeeDTO) {Employee employee = new Employee();employee.setCreateUser(BaseContext.getCurrentId()); // 动态获取当前登录员工IDemployee.setUpdateUser(BaseContext.getCurrentId()); // 动态获取当前登录员工IDemployeeMapper.insert(employee);
}
五、DTO的使用原因
在项目中,Employee
是实体类(Entity),用于表示数据库中的员工记录,而 EmployeeDTO
是数据传输对象(DTO),用于在不同层之间传递数据。以下是使用 DTO 的主要原因和优势:
1. 实体类 Employee
package com.sky.entity;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.time.LocalDateTime;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {private static final long serialVersionUID = 1L;private Long id; // 员工IDprivate String username; // 用户名private String name; // 姓名private String password; // 密码(敏感字段)private String phone; // 手机号private String sex; // 性别private String idNumber; // 身份证号private Integer status; // 状态private LocalDateTime createTime; // 创建时间(内部字段)private LocalDateTime updateTime; // 更新时间(内部字段)private Long createUser; // 创建人(内部字段)private Long updateUser; // 更新人(内部字段)
}
2. DTO EmployeeDTO
package com.sky.dto;import lombok.Data;
import java.io.Serializable;@Data
public class EmployeeDTO implements Serializable {private Long id; // 员工IDprivate String username; // 用户名private String name; // 姓名private String phone; // 手机号private String sex; // 性别private String idNumber; // 身份证号
}
3. 使用 DTO 的场景
3.1 查询员工信息
- 前端只需要员工的基本信息(如
id
、username
、name
、phone
、sex
、idNumber
)。 - 后端返回
EmployeeDTO
,过滤掉敏感字段(如password
)和内部字段(如createTime
)。
3.2 更新员工信息
- 前端传递
EmployeeDTO
作为请求体,后端根据 DTO 更新员工信息。 - 避免前端传递不必要的字段(如
password
、createTime
)。
3.3 新增员工
- 前端传递
EmployeeDTO
作为请求体,后端将 DTO 转换为实体类并保存到数据库。 - 避免前端传递内部字段(如
createTime
、updateTime
)。
4. DTO、VO和实体类的区别
特性 | DTO | VO | Entity |
---|---|---|---|
目的 | 数据传输 | 数据展示或封装值 | 表示数据库中的数据结构 |
使用场景 | 跨层数据传输(如Controller-Service) | 展示层或领域模型 | 数据库操作、业务逻辑 |
可变性 | 可变(通常有setter) | 通常不可变(无setter) | 可变(用于持久化和业务逻辑) |
字段 | 与传输需求相关 | 与展示或业务逻辑相关 | 与数据库表字段严格对应 |
行为 | 通常无行为 | 可能包含简单行为(如格式化) | 包含业务逻辑和验证规则 |
示例 | UserDTO | UserVO | UserEntity |
六、为什么使用 XML 注解而不是 MyBatis 注解
1. 使用 XML 注解的原因
1.1 动态 SQL 支持
- XML 提供了强大的动态 SQL 支持,例如
<if>
、<foreach>
、<choose>
等标签。 - 在复杂的查询场景中,动态 SQL 可以更灵活地构建 SQL 语句。
1.2 SQL 与代码分离
- 将 SQL 语句写在 XML 文件中,可以使 SQL 与 Java 代码分离,便于维护和管理。
- 对于复杂的 SQL 语句,XML 文件的可读性更高。
1.3 复用性
- XML 文件中的 SQL 语句可以在多个 Mapper 接口中复用。
- 例如,可以在不同的 Mapper 接口中引用同一个 SQL 片段。
1.4 工具支持
- MyBatis 提供了丰富的工具支持 XML 文件的编写和调试。
- 例如,MyBatis Generator 可以自动生成 XML 映射文件。
2. MyBatis 注解的局限性
2.1 动态 SQL 支持有限
- MyBatis 注解对动态 SQL 的支持较弱,复杂的 SQL 语句难以用注解实现。
- 例如,
@Select
注解无法直接实现<foreach>
这样的动态 SQL。
<select id="getSetmealIdsByDishIds" resultType="java.lang.Long">select setmeal_id from setmeal_dish where dish_id in<foreach collection="dishIds" item="dishId" separator="," open="(" close=")">#{dishId}</foreach>
</select>
2.2 可读性差
- 复杂的 SQL 语句写在注解中会导致代码冗长,可读性差。
- 例如,一个包含多个条件的查询语句会显得非常混乱。
2.3 维护困难
- SQL 语句与 Java 代码混合在一起,维护起来不如 XML 文件方便。
- 修改 SQL 语句时需要重新编译 Java 代码。
七、Spring Boot 的请求映射规则
在 Spring Boot 中,请求的映射是通过 类级别的 @RequestMapping
和 方法级别的 @PutMapping
、@GetMapping
等注解 共同决定的。
- 类级别的
@RequestMapping
:- 定义了该类中所有方法的公共路径前缀。
- 例如,
@RequestMapping("/admin/dish")
表示该类中的所有方法都映射到/admin/dish
路径下。 - 管理端发出的请求,统一使用
/admin
作为前缀。 - 用户端发出的请求,统一使用
/user
作为前缀。
- 方法级别的
@PutMapping
、@GetMapping
等:- 定义了具体的 HTTP 方法和路径。
- 如果方法级别的注解没有指定路径,则默认使用类级别的路径。
1. 类级别路径
@RestController
@RequestMapping("/admin/dish")
public class DishController {// 方法定义...
}
- 所有方法的公共路径前缀是
/admin/dish
。
2. 方法级别路径
2.1 分页查询
@GetMapping("/page")
public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO) {// 方法实现...
}
- 完整路径是
/admin/dish/page
。
2.2 根据 ID 查询菜品
@GetMapping("/{id}")
public Result<DishVO> getById(@PathVariable Long id) {// 方法实现...
}
- 完整路径是
/admin/dish/{id}
。
2.3 修改菜品
@PutMapping
public Result update(@RequestBody DishDTO dishDTO) {// 方法实现...
}
- 由于
@PutMapping
没有指定路径,默认使用类级别的路径/admin/dish
。
2.4 新增菜品
@PostMapping
public Result save(@RequestBody DishDTO dishDTO) {// 方法实现...
}
- 由于
@PostMapping
没有指定路径,默认使用类级别的路径/admin/dish
。
2.5 批量删除菜品
@DeleteMapping
public Result delete(@RequestParam List<Long> ids) {// 方法实现...
}
- 由于
@DeleteMapping
没有指定路径,默认使用类级别的路径/admin/dish
。
3. 如何区分不同的功能
Spring Boot 通过 HTTP 方法 来区分不同的功能。例如:
HTTP 方法 | 路径 | 功能 |
---|---|---|
POST | /admin/dish | 新增菜品 |
PUT | /admin/dish | 修改菜品 |
DELETE | /admin/dish | 批量删除菜品 |
GET | /admin/dish/page | 分页查询菜品 |
GET | /admin/dish/{id} | 根据 ID 查询菜品 |
4. 示例请求
4.1 新增菜品
- HTTP 方法:
POST
- URL:
/admin/dish
- 请求体:
{"name": "宫保鸡丁","price": 38.0,"flavors": [{"name": "微辣","value": "少辣"}] }
4.2 修改菜品
- HTTP 方法:
PUT
- URL:
/admin/dish
- 请求体:
{"id": 1,"name": "宫保鸡丁","price": 40.0,"flavors": [{"name": "微辣","value": "少辣"}] }
4.3 批量删除菜品
- HTTP 方法:
DELETE
- URL:
/admin/dish?ids=1,2,3
- 请求参数:
ids=1,2,3
4.4 分页查询菜品
- HTTP 方法:
GET
- URL:
/admin/dish/page?page=1&pageSize=10
- 请求参数:
page=1&pageSize=10
4.5 根据 ID 查询菜品
- HTTP 方法:
GET
- URL:
/admin/dish/1
- 路径参数:
id=1
八、接口设计中的是否必需原则
参数的必需与非必需性是通过不同的方式来体现的,以下是具体案例
1. 请求参数说明
从接口文档中可以看到,请求参数包括以下几项:
参数名 | 类型 | 说明 | 必需性 | 示例值 |
---|---|---|---|---|
categoryId | string | 分类id | 可选 | 101 |
name | string | 菜品名称 | 可选 | 官保鸡丁 |
page | string | 页码 | 必需 | 1 |
pageSize | string | 每页记录数 | 必需 | 10 |
status | string | 分类状态 | 可选 | 1 |
-
必需参数:
page
和pageSize
是分页查询的必需参数,用于指定查询的页码和每页的记录数。
-
可选参数:
categoryId
、name
和status
是可选参数,用于过滤查询结果。
1.1 Java代码分析
在此 Java 代码中,DishPageQueryDTO
是一个数据传输对象(DTO),用于封装分页查询的参数。以下是代码的详细分析:
public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {// 1. 使用 PageHelper 进行分页PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());// 2. 调用 Mapper 进行查询Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);// 3. 返回分页结果return new PageResult(page.getTotal(), page.getResult());
}
1.1.1 必需参数
dishPageQueryDTO.getPage()
和dishPageQueryDTO.getPageSize()
是分页查询的必需参数。- 如果这两个参数为空或未提供,分页功能将无法正常工作。
1.2 XML映射文件分析
在 SQL 代码中,动态 SQL 语句根据传入的参数生成查询条件。以下是代码的详细分析:
<select id="pageQuery" resultType="com.sky.vo.DishVO">select d.* , c.name as categoryName from dish d left outer join category c on d.category_id = c.id<where><if test="name != null">and d.name like concat('%',#{name},'%')</if><if test="categoryId != null">and d.category_id = #{categoryId}</if><if test="status != null">and d.status = #{status}</if></where>order by d.create_time desc
</select>
1.2.1 可选参数
name
、categoryId
和status
是可选参数,通过<if>
标签动态生成查询条件。- 如果某个参数为
null
,则对应的条件不会添加到 SQL 查询中。
通过这种设计,分页查询接口既满足了基本的查询需求,又提供了灵活的过滤选项,适用于不同的业务场景。
2. 返回响应说明
在 API 设计中,返回响应的数据结构通常需要遵循一定的规范,以确保客户端能够准确处理和理解服务器的响应。Result<T>
类是一个典型的统一响应格式,根据不同的设计需求,我们发现 code
一定是必需的,而 msg
和 data
在某些情况下是可选的,而在某些情况可能是必需的。接下来,我们将详细探讨这种设计背后的原因。
2.1 Java代码分析
package com.sky.result;import lombok.Data;import java.io.Serializable;`/*** 后端统一返回结果* @param <T>*/
@Data
public class Result<T> implements Serializable {private Integer code; //编码:1成功,0和其它数字为失败private String msg; //错误信息private T data; //数据public static <T> Result<T> success() {Result<T> result = new Result<T>();result.code = 1;return result;}public static <T> Result<T> success(T object) {Result<T> result = new Result<T>();result.data = object;result.code = 1;return result;}public static <T> Result<T> error(String msg) {Result result = new Result();result.msg = msg;result.code = 0;return result;}}
2.1.1 必需参数
code
是必需的
- 作用:
code
用于表示请求的处理结果状态,通常是一个数字。- 例如:
1
表示成功,0
或其他数字表示失败。
- 例如:
- 为什么必需:
- 明确状态:客户端需要知道请求是否成功。
code
提供了一个明确的状态标识,客户端可以根据它决定后续操作。 - 标准化:统一的
code
值可以让客户端以一致的方式处理所有 API 的响应。 - 错误处理:当请求失败时,
code
可以帮助客户端快速定位问题类型(如权限不足、资源不存在等)。
- 明确状态:客户端需要知道请求是否成功。
2.1.2 可选参数
msg
是可选的
- 作用:
msg
用于提供额外的错误信息或成功提示。- 例如:成功时:
msg
可以为空或包含提示信息(如“操作成功”),失败时:msg
可以包含具体的错误描述(如“用户未找到”)。
- 例如:成功时:
- 为什么可选:
- 成功时可能不需要:在请求成功的情况下,客户端可能只需要
data
,而不需要额外的提示信息。 - 减少冗余:如果
msg
是必需的,即使没有实际意义的信息(如成功时的默认提示),也需要返回,这会增加响应的冗余。 - 灵活性:在某些场景下,错误信息可能由其他方式提供(如日志或专门的错误处理机制),因此
msg
可以省略。
- 成功时可能不需要:在请求成功的情况下,客户端可能只需要
data
是可选的
- 作用:
data
用于承载实际的响应数据。- 例如:查询接口返回的列表或对象,创建接口返回的新创建的资源。
- 为什么可选:
- 某些操作不需要返回数据:例如,删除操作或简单的状态更新操作可能不需要返回任何数据。
- 减少冗余:如果
data
是必需的,即使没有数据也需要返回一个空对象或null
,这会增加响应的冗余。 - 灵活性:某些接口可能只需要返回状态信息(如
code
和msg
),而不需要额外的数据。
2.2 返回响应示例
2.2.1 成功响应(带数据)
{"code": 1,"msg": "操作成功","data": {"id": 123,"name": "John Doe"}
}
2.2.2 成功响应(不带数据)
{"code": 1
}
2.2.3 失败响应
{"code": 0,"msg": "用户未找到"
}
这种设计符合 API 设计的最佳实践,能够满足大多数场景的需求,同时保持简洁和一致性。
九、阿里云OSS配置指南
在使用对象存储服务时,可能会遇到Bucket失效的情况,从而导致服务无法正常运行。为了解决这个问题,我们需要重新配置一个新的Bucket,并更新相关配置文件。参考教程:Java利用阿里云OSS/本地存储实现文件上传功能
1. 注册阿里云OSS账号
首先,访问阿里云-对象存储OSS官网注册账号。新用户可免费试用20GB存储空间,有效期为3个月。
2. 获取关键信息
注册完成后,开通对象存储服务OSS,创建第一个Bucket,并获取以下四个关键信息:
Endpoint
:OSS服务的访问地址。Access Key ID
:用于身份验证的访问密钥ID。Access Key Secret
:用于身份验证的访问密钥。Bucket Name
:新创建的Bucket名称。
3. 更新配置文件
将上述获取的信息填写到对应的YAML配置文件sky-server/src/main/resources/application-dev.yml
目录下
sky:datasource:driver-class-name: com.mysql.cj.jdbc.Driverhost: localhostport: 3306database: sky_take_outusername: your_usernamepassword: your_passwordalioss:endpoint: your_endpointaccess-key-id: your_accessKeyIdaccess-key-secret: your_keySecretbucket-name: your_bucketName# endpoint: oss-cn-hangzhou.aliyuncs.com
# access-key-id: LTAI5tPeFLzsPPT8gG3LPW64
# access-key-secret: U6k1brOZ8gaOIXv3nXbulGTUzy6Pd7
# bucket-name: sky-take-out
4, 重新运行服务
保存配置文件后,重新运行服务并打开前端页面,发现图片能够正常上传了!
并且我们可以在自己的对象存储OSS文件管理中监控到从前端页面上传的图片文件
十、SpringBoot配置类详解
在 Spring Boot 项目中,配置文件是管理应用程序行为的关键部分。通过合理使用配置类,我们可以轻松实现多环境配置、自定义配置以及配置的动态注入。
1. 生产环境与开发环境配置
Spring Boot 支持多环境配置,通常我们会为不同环境(如开发、测试、生产)创建不同的配置文件。通过 spring.profiles.active
属性,可以动态切换环境。
1.1 配置文件命名规则
- 默认配置文件:
application.yaml
(或application.properties
)。 - 环境特定配置文件:
application-{profile}.yaml
,其中{profile}
是环境标识,如dev
、prod
。
1.2 激活环境配置
在 application.yaml
中,通过 spring.profiles.active
指定激活的环境:
spring:profiles:active: dev # 激活开发环境
dev
的含义:表示加载application-dev.yaml
文件。prod
的含义:表示加载application-prod.yaml
文件。
1.3 占位符替换
在配置文件中,可以使用 ${}
占位符引用其他配置项的值。Spring Boot 会在启动时自动替换这些占位符。
示例
-
application.yaml
:spring:datasource:url: jdbc:mysql://${sky.datasource.host}:${sky.datasource.port}/${sky.datasource.database}
-
application-dev.yaml
:sky:datasource:host: localhostport: 3306database: devdb
-
最终替换结果:
spring:datasource:url: jdbc:mysql://localhost:3306/devdb
2. Spring 前缀与自定义前缀配置
Spring Boot 的配置文件支持两种类型的配置:Spring 内置配置和自定义配置。
2.1 Spring 内置配置
Spring Boot 使用 spring
作为内置配置的命名空间,用于配置框架本身的行为,例如:
- 数据源配置:
spring.datasource
- Redis 配置:
spring.redis
- Profile 激活:
spring.profiles.active
spring:datasource:url: jdbc:mysql://localhost:3306/mydbusername: rootpassword: rootredis:host: localhostport: 6379
2.2 自定义配置
自定义配置通常用于业务相关的配置项。我们可以使用自定义前缀(如 sky
)来组织这些配置。
sky:jwt:admin-secret-key: itcastadmin-ttl: 7200000alioss:endpoint: oss-cn-shenzhen.aliyuncs.comaccess-key-id: LTAI5tRK6gZ9f6CyHCaWh7e8
3. 自定义配置类的注册与使用
Spring Boot 提供了 @ConfigurationProperties
注解,用于将配置文件中的值绑定到 Java 对象中。
3.1 创建配置类
通过 @ConfigurationProperties
注解,指定配置的前缀,并定义与配置项对应的字段。
3.1.1 JWT 配置类
package com.sky.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "sky.jwt")
@Data
public class JwtProperties {private String adminSecretKey;private long adminTtl;private String adminTokenName;
}
3.1.2 阿里云 OSS 配置类
package com.sky.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "sky.alioss")
@Data
public class AliOssProperties {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;
}
3.2 使用配置类
在其他组件(如 Service、Controller)中,可以通过 @Autowired
注入配置类,直接使用配置值。
3.2.1 在 Service 中使用配置类
package com.sky.service;import com.sky.properties.AliOssProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class OssService {@Autowiredprivate AliOssProperties aliOssProperties;public void printOssConfig() {System.out.println("Endpoint: " + aliOssProperties.getEndpoint());System.out.println("AccessKeyId: " + aliOssProperties.getAccessKeyId());}
}
3.3 配置类的注册
@Component
:将配置类注册为 Spring 的 Bean。@ConfigurationProperties
:指定配置的前缀,并绑定配置项。
十一、SpringBoot注解汇总
1. Spring MVC 相关注解
-
@RestController
:
标记一个类为 RESTful 控制器,返回值直接作为响应体(通常是 JSON 格式),它结合了@Controller
和@ResponseBody
的功能,适用于开发 RESTful API。 -
@RequestMapping
:
映射 HTTP 请求到控制器方法,可以指定请求路径、请求方法(如 GET、POST)等。 -
@PostMapping
:
专门处理 HTTP POST 请求,是@RequestMapping(method = RequestMethod.POST)
的简写。 -
@GetMapping
:
专门处理 HTTP GET 请求,是@RequestMapping(method = RequestMethod.GET)
的简写。 -
@DeleteMapping
:
专门处理 HTTP DELETE 请求,是@RequestMapping(method = RequestMethod.DELETE)
的简写。 -
@PutMapping
:
专门处理 HTTP PUT 请求,是@RequestMapping(method = RequestMethod.PUT)
的简写。 -
@RequestBody
:
将 HTTP 请求体(通常是 JSON 格式)绑定到方法参数,适用于接收客户端传递的复杂数据。 -
@ResponseBody
:
将方法的返回值直接作为 HTTP 响应体(通常是 JSON 格式),而不是跳转到视图页面。 -
@PathVariable
:
将 URL 路径中的变量绑定到方法参数,适用于 RESTful 风格的 URL。
2. Swagger 相关注解
-
@Api
:
标记一个类为 Swagger 资源,用于生成 API 文档。 -
@ApiModel
:
描述 Swagger 模型类,通常用于实体类,生成文档中的模型信息。 -
@ApiModelProperty
:
描述 Swagger 模型类的属性,用于生成文档中属性的详细信息。 -
@ApiOperation
:
描述 API 接口的操作,用于生成文档中接口的详细信息。
3. Spring 核心注解
-
@Autowired
:
自动注入 Spring Bean,用于依赖注入。 -
@Bean
:
声明一个方法返回的对象为 Spring Bean,通常用于配置类中。 -
@Configuration
:
标记一个类为配置类,用于定义 Bean 或其他配置。 -
@Service
:
标记一个类为服务层组件,通常用于业务逻辑层。 -
@Component
:
标记一个类为 Spring 组件,泛指任何 Spring 管理的 Bean。 -
@SpringBootApplication
:
标记主启动类,包含@Configuration
、@EnableAutoConfiguration
和@ComponentScan
,用于启动 Spring Boot 应用。 -
@EnableTransactionManagement
:
启用 Spring 的事务管理,通常用于配置类中。
4. AOP 相关注解
-
@Aspect
:
标记一个类为切面,用于定义横切关注点(如日志、事务)。 -
@Before
:
在目标方法执行前执行切面逻辑。 -
@Pointcut
:
定义切点表达式,用于指定哪些方法需要被切面处理。
5. Lombok 相关注解
-
@Slf4j
:
自动生成日志对象log
,简化日志记录代码。 -
@Data
:
自动生成getter
、setter
、toString
、equals
和hashCode
等方法。 -
@Builder
:
为类生成 Builder 模式支持,简化对象的创建。 -
@NoArgsConstructor
:
生成无参构造方法。 -
@AllArgsConstructor
:
生成全参构造方法。
6. MyBatis 相关注解
-
@Mapper
:
标记一个接口为 MyBatis 的 Mapper 接口,用于定义数据库操作。 -
@Delete
:
映射 SQL 删除操作。 -
@Select
:
映射 SQL 查询操作。 -
@Insert
:
映射 SQL 插入操作。 -
@AutoFill
:
自定义注解,用于自动填充字段(如创建时间、更新时间)。
7. 配置相关注解
@ConfigurationProperties
:
将配置文件中的值绑定到 Java 对象中,通常用于加载自定义配置,其中prefix
:指定配置项的前缀,从配置文件中加载特定部分的配置。
相关文章:
《苍穹外卖》SpringBoot后端开发项目核心知识点与常见问题整理(DAY1 to DAY3)
目录 一、在本地部署并启动Nginx服务1. 解压Nginx压缩包2. 启动Nginx服务3. 验证Nginx是否启动成功: 二、导入接口文档1. 黑马程序员提供的YApi平台2. YApi Pro平台3. 推荐工具:Apifox 三、Swagger1. 常用注解1.1 Api与ApiModel1.2 ApiModelProperty与Ap…...
【从零开始学习计算机科学】数据库系统(十一)云数据库、NoSQL 与 NewSQL
【从零开始学习计算机科学】数据库系统(十一)云数据库、NoSQL 与 NewSQL 云数据库云服务器的服务云数据库和传统的分布式数据库的异同NoSQLNoSQL数据库的特点CAP定理NoSQL的特性NoSQL数据库的分类NoSQL的适用场景Nosql数据库实例-RedisRedis的优势MongoDBMongoDB的特点NewSQL…...
Linux入门 全面整理终端 Bash、Vim 基础命令速记
Linux入门 2025 超详细全面整理 Bash、Vim 基础命令速记 刚面对高级感满满的 终端窗口是不是有点懵?于是乎,这份手册就是为你准备的高效学习指南!我把那些让人头大的系统设置、记不住的命令都整理成了对你更友好的格式,让你快速学…...
LInux基础--apache部署网站
httpd的安装 yum -y install httpdhttpd的使用 启动httpd systemctl enable --now httpd使用enable --now 进行系统设置时,会将该服务设置为开机自启并且同时开启服务 访问httpd 创建虚拟主机 基于域名 在一台主机上配置两个服务server1和server2,其…...
重生之我在学Vue--第12天 Vue 3 性能优化实战指南
重生之我在学Vue–第12天 Vue 3 TypeScript 类型系统深度整合 文章目录 重生之我在学Vue--第12天 Vue 3 TypeScript 类型系统深度整合前言一、TypeScript与Vue3的集成1.1 项目初始化配置1.2 类型配置文件解析 二、类型声明实战2.1 Props类型约束2.2 Emit事件类型2.3 组合式AP…...
Go 语言封装 HTTP 请求的 Curl 工具包
文章目录 Go 语言封装 HTTP 请求的 Curl 工具包🏗️ 工具包结构简介核心结构体定义初始化函数 🌟 功能实现1. 设置请求头2. 构建请求3. 发送请求4. 发送 GET 请求5. 发送 POST 请求6. 发送 PUT 请求7. 发送 DELETE 请求8. 读取响应体 💡 实现…...
【Go】Go MongoDB 快速入门
1. MongoDB 简介 1.1 MongoDB 介绍 由于我们时常需要存储一些大文本数据(比如文章内容),存储到一些关系型数据库可能不是最好的选择,这个时候就需要引入一些 NoSQL(Not Only SQL),比如 MongoD…...
Java --- 根据身份证号计算年龄
介绍 根据身份证号计算年龄 Java代码 /*** 根据身份证号计算年龄* param birthDateStr* return*/public static int calculateAge(String birthDateStr) {try {birthDateStrbirthDateStr.substring(6,68);// 定义日期格式SimpleDateFormat sdf new SimpleDateFormat("…...
[LeetCode热门100题]|137,260,268,面试17.19
1、137 只出现一次数字|| 1、题目描述 137 只出现一次数字||https://leetcode.cn/problems/single-number-ii/description/ 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你…...
WPF未来展望:紧跟技术发展趋势,探索新的可能性
WPF未来展望:紧跟技术发展趋势,探索新的可能性 一、前言二、WPF 与.NET 技术的融合发展2.1 拥抱.NET Core2.2 利用.NET 5 及后续版本的新特性 三、WPF 在新兴技术领域的应用拓展3.1 与云计算的结合3.2 融入物联网生态 四、WPF 在用户体验和设计方面的创新…...
maxwell
一、maxwell简介 它是一款轻量级工具,主要用于实现 MySQL 到 Kafka 的数据实时同步,尤其适合对实时性要求较高的场景。 1.核心功能 借助解析 MySQL 的 Binlog,能够实时捕获数据变更,并将这些变更数据发送至 Kafka。 2.缺点 仅…...
Qt 6.6.1 中 QPixmap::grabWindow() 的用法与替代方案
一、Qt 6 中的 API 变化 弃用 QPixmap::grabWindow() 在 Qt 6 中,QPixmap::grabWindow() 已被迁移至 QScreen 类,需通过 QScreen::grabWindow() 实现窗口截取。 原因: Qt 6 重构了图形模块,QPixmap 的截屏功能被整合到 QSc…...
【软件】免费的PDF全文翻译软件,能保留公式图表的样式
转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 很多PDF全文翻译软件都是收费的,而划线翻译看着又很累。这个开源的PDF全文翻译软件非常好用,并且能够保留公式、图表、目录和注…...
LeetCode 112. 路径总和 II java题解
https://leetcode.cn/problems/path-sum/description/ class Solution {boolean resfalse;//记录结果public boolean hasPathSum(TreeNode root, int targetSum) {if(rootnull) return res;int sum0;find(root,sum,targetSum);return res;}public void find(TreeNode root,int…...
如何快速定位导致服务器卡顿的进程
在 Linux 系统中,可以通过多种方式快速定位导致服务器卡顿的进程。以下是一些常用的方法: 1. 使用 top 和 htop 命令: 使用 top 或 htop 命令可以实时监视系统资源利用情况,包括 CPU 和内存占用情况,以及运行的进程列…...
【计算机网络】第八版和第七版的主要区别,附PDF
「《计算机网络》(... 谢希仁」,https://pan.quark.cn/s/7c2147cb48f7 1. 新增内容 - 软件定义网络(SDN):第八版在网络层章节中新增了对SDN的简介(第4章),介绍了其基本原理和应用。 - Wi-Fi代…...
ubuntu20.04_vscode_snap安装方式
停止 Snap 服务 运行以下命令: sudo systemctl stop snapd 彻底停止 Snap 服务 停止 snapd.service 和 snapd.socket: sudo systemctl stop snapd.socket sudo systemctl stop snapd.service 禁用 Snap 服务的自动启动(可选)&…...
基于SpringBoot实现旅游酒店平台功能十一
一、前言介绍: 1.1 项目摘要 随着社会的快速发展和人民生活水平的不断提高,旅游已经成为人们休闲娱乐的重要方式之一。人们越来越注重生活的品质和精神文化的追求,旅游需求呈现出爆发式增长。这种增长不仅体现在旅游人数的增加上࿰…...
coze ai assistant Task 2
创建一个智能体:夸夸机器人 https://www.coze.cn/store/agent/7480939060010713138?bot_idtrue 改为豆包系列-豆包角色扮演 添加bingWebSearch搜索 添加前: 添加后: 改为工具调用: 添加知识库 使用长期记忆 结合自己的需求&…...
Qt/C++音视频开发82-系统音量值获取和设置/音量大小/静音
一、前言 在音视频开发中,音量的控制分两块,一个是控制播放器本身的音量,绝大部分场景都是需要控制这个,这个不会影响系统音量的设置。还有一种场景是需要控制系统的音量,因为播放器本身的音量是在系统音量的基础上控…...
C盘清理终极方案——基于Windows软连接的目录迁移实战
C盘清理终极方案——基于Windows软连接的目录迁移实战 (案例实现:.cache、.conda、AppData\docker等目录移动至D盘) 核心 # 创建目录软连接 mklink /J "C:\Users\<用户名>\AppData\Local\Docker" "D:\SoftwareCa…...
医疗AI测试实战:如何确保人工智能安全赋能医疗行业?
一、医疗AI测试的重要性 人工智能(AI)正广泛应用于医疗行业,如疾病诊断、医学影像分析、药物研发、手术机器人和智能健康管理等领域。医疗AI技术的应用不仅提高了诊断效率,还能降低误诊率,改善患者治疗效果。然而&…...
在资源有限中逆势突围:从抗战智谋到寒门高考的破局智慧
目录 引言 一、历史中的非对称作战:从李牧到八路军的智谋传承 李牧戍边:古代军事博弈中的资源重构 八路军的游击战:现代战争中的智慧延续 二、创业界的逆袭之道:小米与拼多多的资源重构 从MVP到杠杆解 社交裂变与资源错配 …...
在使用element-ui时表单的表头在切换页面时第一次进入页面容易是白色字体解决方法
在里面添加:header-cell-style"{ color: black }" <el-table :data"tableData" style"width: 100%" height"250" :header-cell-style"{ color: black }" ></el-table> 正确代码是 <templat…...
与指定数字相同的数的个数(信息学奥赛一本通-1102)
【题目描述】 输出一个整数序列中与指定数字相同的数的个数。 【输入】 输入包含三行: 第一行为n,表示整数序列的长度(n≤100); 第二行为n个整数,整数之间以一个空格分开; 第三行包含一个整数,为指定的数字…...
13. Pandas :使用 to_excel 方法写入 Excel文件
一 to_excel 方法的相关参数 用它来指定要将 DataFrame 写入哪些工作表的哪些单元格,以及是否需要包含列标题和 DataFrame 索引。如何处理特殊值(如 np.nan 和 np.inf)。 1.指定工作表和单元格 sheet_name:指定将 DataFrame 写入的…...
python画图文字显示不全+VScode新建jupyter文件
之前有两个jupyter文件,一个显示正确一个显示错误。已经尝试过的方法包括: 1、更改下载好的SimHei字体,或者其他支持中文的字体 2、重新创建虚拟环境 3、清楚matplotlib缓存目录 4、从anaconda的jupyter换至vscode 目前部分中文不能正常…...
C#中继承的核心定义
1. 继承的核心定义 继承 是面向对象编程(OOP)的核心特性之一,允许一个类(称为子类/派生类)基于另一个类(称为父类/基类)构建,自动获得父类的成员(字段、属…...
MOEFeedForward 模块
代码 class FeedForward(nn.Module):def __init__(self, config: LMConfig):super().__init__()if config.hidden_dim is None:hidden_dim 4 * config.dimhidden_dim int(2 * hidden_dim / 3)config.hidden_dim config.multiple_of * ((hidden_dim config.multiple_of - 1…...
TypeScript变量声明详解:与JavaScript的对比与工程化价值
TypeScript的变量声明机制在保留JavaScript灵活性的同时,通过类型注解和作用域强化显著提升了代码可靠性。本文将深入解析TypeScript的变量声明特性,并与JavaScript/ES标准进行对比,揭示其工程实践价值。 一、变量声明方式对比 1. 基础声明语…...
在 Axios 中设置代理
在 Axios 中设置代理 Axios 与代理 Axios 是 JavaScript 生态中最广泛使用的 HTTP 客户端之一。它基于 Promise,提供了易用、直观的 API,用于执行 HTTP 请求并处理自定义请求头、配置和 Cookie 等。 通过为 Axios 请求设置代理,您可以隐藏自…...
WebSocket 使用教程
WebSocket 使用教程 WebSocket 是一种在现代网络应用中广泛使用的网络通信协议,旨在实现服务器与客户端之间高效、实时的双向通信。与传统的 HTTP 协议相比,WebSocket 提供了更低的延迟和更高的互动性,使其成为构建实时应用的理想选择。无论…...
【RabbitMQ】rabbitmq在spring boot中的使用
rabbitmq官网地址:https://www.rabbitmq.com/tutorials 下面介绍rabbitmq官网中七种使用方式在spring boot中如何使用 下面是基于 Spring Boot 使用 RabbitMQ 实现这七种模式的示例代码。假设已经引入了以下依赖: Maven 依赖 <dependency><g…...
独立开发记录:使用Trae和Cloudflare快速搭建了自己的个人博客
前段时间我计划搭建个人博客,用于记录自己写的文章、录制的课程和开发的项目,于是结合 Trae AI IDE 与 Cloudflare 快速搭建并上线了人生第一个网站,在这个过程中,我整合了两种工具的优势(AI辅助开发 免费托管加速&a…...
文件解析漏洞详解
IIS解析漏洞 环境安装 windows2003iis6 IIS6.X ⽬录解析 在iis6.x中,.asp⽂件夹中的任意⽂件都会被当做asp⽂件去执⾏。 在iis的⽹站根⽬录新建⼀个名为x.asp的⽂件 在x.asp中新建⼀个png⽂件。内容为<%now()%> asp代码。 外部浏览器中访问windows2003的i…...
自然语言处理:文本聚类
介绍 大家好,博主又来和大家分享自然语言处理领域的知识了。今天给大家分享的内容是自然语言处理中的文本聚类。 文本聚类在自然语言处理领域占据着重要地位,它能将大量无序的文本按照内容的相似性自动划分成不同的类别,极大地提高了文本处…...
【MySQL】基本操作 —— DDL
目录 DDLDDL 常用操作对数据库的常用操作查看所有数据库创建数据库切换、显示当前数据库删除数据库修改数据库编码 对表的常用操作创建表数据类型数值类型日期和时间类型字符串类型 查看当前数据库所有表查看指定表的创建语句查看指定表结构删除表 对表结构的常用操作给表添加字…...
玩转python:通俗易懂掌握高级数据结构:collections模块之namedtuple
引言 namedtuple是Python中collections模块提供的一个强大工具,用于创建具有字段名的元组。它不仅具备元组的不可变性,还能通过字段名访问元素,极大地提高了代码的可读性和可维护性。本文将详细介绍namedtuple的关键用法和特性,并…...
[GHCTF 2025]SQL??? 【sqlite注入】
梳理一下SQLite注入 常见指令 查看版本:sqlite_version() 列出附加数据库中的所有表:.tables 注入步骤 先查字段: 1 order by 5 # 三板斧: 0 union select 1,2,sql from sqlite_master; sql字段存储创建该数据库对象时所使…...
spring boot 发送邮件验证码
一、前置需求 1、准备邮箱 2、登录授权码 qq邮箱在–>设置–>账号POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 开启服务 二、发送邮件 1、简单邮件 包含邮件标题、邮件正文 2、引入mail启动器 <dependency><groupId>org.springframework.boot</groupI…...
[项目]基于FreeRTOS的STM32四轴飞行器: 二.项目搭建及移植FreeRTOS
基于FreeRTOS的STM32四轴飞行器: 二.项目搭建及debug模块 一.项目搭建二.移植FreeRTOS 一.项目搭建 先配置SYS系统滴答定时器来源为默认,因为其他定时器用来驱动电机了只能与FreeRTOS共用: 之后选择RCC配置芯片的时钟来源: 配置时钟树&am…...
Amazon RDS ProxySQL 探索(一)
:::info 💡 在日常开发中,开发者们会涉及到数据库的连接,在使用Amazon RDS数据库时,若使用集群模式或者多数据库时,会出现一写多读多个Endpoint,在实际开发中, 开发者们配置数据库连接通常希望走…...
高速PCB设计(布线设计)
以下是针对高速PCB布线设计的综合笔记,结合用户提供的设计规范及行业通用原则整理而成: 一、关键信号布线原则 布线优先级 顺序:射频信号>中/低频信号>时钟信号>高速信号射频信号需包地处理,线…...
《探秘人工智能与鸿蒙系统集成开发的硬件基石》
在科技飞速发展的当下,人工智能与鸿蒙系统的集成开发开辟了创新的前沿领域。这一融合不仅代表着技术的演进,更预示着智能设备生态的全新变革。而在这场技术盛宴的背后,坚实的硬件配置是确保开发顺利进行的关键,它就像一座大厦的基…...
使用Langflow和AstraDB构建AI助手:从架构设计到与NocoBase的集成
本文由 Leandro Martins 编写,最初发布于 Building an AI Assistant with Langflow and AstraDB: From Architecture to Integration with NocoBase。 引言 本文的目标是演示如何创建一个集成了 NocoBase、LangFlow 和 VectorDB 工具的 AI 助手。作为基础…...
【零基础入门unity游戏开发——unity3D篇】3D物理系统之 —— 3D刚体组件Rigidbody
考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、流程控制、面向对象等,适合没有编程基础的…...
工程化与框架系列(30)--前端日志系统实现
前端日志系统实现 📝 引言 前端日志系统是应用监控和问题诊断的重要工具。本文将深入探讨前端日志系统的设计与实现,包括日志收集、处理、存储和分析等方面,帮助开发者构建完整的前端日志解决方案。 日志系统概述 前端日志系统主要包括以…...
小爱音箱控制家里的NAS将影片在电视上播放-deepseek帮助下实现-慎入openmanux
天始规划 我给ai一个任务,不过我没那么多能力,听说AI代理很行,这个任务我打算交给它.就用现在火的,openmanu,功能简单,我来安装openmanus,并规划任务. 进入openmanu首页 https://github.com/wjcroom/OpenManus openusa推荐使用uv管理,打算安装在家里的nas虚拟机.uv和python环…...
jQuery EasyUI 扩展
jQuery EasyUI 扩展 引言 jQuery EasyUI 是一个基于 jQuery 的易于使用的界面扩展库,它简化了网页界面的开发过程。随着 Web 技术的不断发展,越来越多的开发者开始寻求对 jQuery EasyUI 的扩展,以满足不同场景下的需求。本文将详细介绍 jQuery EasyUI 的扩展方法、技巧以及…...
笔试刷题专题(一)
文章目录 最小花费爬楼梯(动态规划)题解代码 数组中两个字符串的最小距离(贪心(dp))题解代码 点击消除题解代码 最小花费爬楼梯(动态规划) 题目链接 题解 1. 状态表示࿱…...