Java写项目前的准备工作指南(技术栈选择 环境搭建和工具配置 项目结构设计与模块划分)
前言 📝
在开始编写一个 Java 项目之前,做好充分的准备工作是至关重要的。很多初学者可能在没有清晰规划的情况下就开始编写代码,导致项目开发进度缓慢、结构混乱,甚至最终无法按预期完成。而事实上,项目的成功不仅仅取决于编码能力,还包括项目初期的规划和准备。
准备工作是确保项目顺利进行的基础,它包括技术选型、环境搭建、需求分析、团队协作及项目管理等多个方面。通过这些准备,我们可以确保项目的开发不仅高效而且有可维护性,最终能交付出高质量的代码。
为什么要做准备?
-
避免重复造轮子:明确技术栈和工具,选择最适合的开发方式。
-
提高开发效率:提前确定框架、库和工具,减少开发过程中的反复修改。
-
确保项目结构合理:合理的项目结构和代码规范使得团队协作更加顺畅。
-
确保项目可扩展:良好的设计能够让项目后期更容易扩展和维护。
-
减少后期问题:通过细致的需求分析和预期规划,避免后期返工和不必要的错误。
本指南目标:
本指南旨在为 Java 开发者提供一套完整的项目准备工作流程,帮助大家在开始编写代码之前做好充分的准备,减少不必要的麻烦,提高开发效率。无论是一个个人项目还是团队合作项目,正确的准备工作都能够帮助你顺利完成项目,并且降低开发过程中的风险。
在接下来的章节中,我们将逐步展开以下几个方面的准备工作:
-
明确项目需求:理解需求,设定项目目标。
-
选择技术栈:根据项目的规模和需求,选择适合的开发工具和框架。
-
环境搭建:搭建开发环境、配置版本管理工具。
-
项目结构设计:设计合理的项目结构和模块划分。
-
开发规范和团队协作:确保团队合作高效,代码规范统一。
-
安全与配置管理:设置基本的安全机制,统一配置管理。
准备工作可能看起来繁琐,但一旦做好了充分的准备,项目的开发将变得更加顺畅。通过本指南,你将学会如何系统化地进行项目的规划和准备,为成功开发一个高质量的 Java 项目打下坚实的基础。
让我们从第一个步骤——需求分析与明确目标开始。
1. 明确项目需求 📋
在开始一个项目之前,明确需求是最重要的步骤之一。准确理解业务需求,清楚项目目标,以及如何组织和管理需求变更,都是项目成功的关键因素。在这个阶段,能够为开发团队提供清晰的方向和可交付的目标。
1.1 理解业务需求 🎯
项目目标的明确(做什么,解决什么问题,用户是谁)
在确定项目目标时,需要清楚地回答以下问题:
-
项目的核心目标是什么?
例如,你的项目是构建一个电商平台,还是一个社交媒体应用,或者是一个管理工具?明确目标是设计架构和开发功能的基础。 -
要解决哪些问题?
项目是否是为了解决现有系统的不足?例如,现有的电商平台可能存在性能问题或用户体验不佳,项目的目标可能是优化这些问题。 -
用户是谁?
项目的目标用户是谁?是企业用户还是个人消费者?了解目标用户群体的需求是设计用户界面、功能及技术栈的重要参考。
实际操作建议:
-
创建用户画像:确定项目的目标用户群体,了解他们的需求和痛点。可以根据年龄、职业、兴趣等因素划分不同的用户群体。
-
业务目标与技术目标对齐:确保业务目标和技术目标一致,不偏离项目的核心需求。
业务流程的梳理与分析
业务流程的梳理是理解业务需求的关键步骤。它帮助你清晰地了解项目的工作流程,以及不同角色和操作之间的关系。
实际操作建议:
-
画出流程图:使用工具(如 Visio、Lucidchart 或简单的手绘)画出项目的业务流程图。将用户操作、系统交互、数据流等展示出来。
-
定义用户角色:根据业务流程,定义不同用户的角色和操作权限,例如管理员、普通用户、访客等。
示例: 假设你要开发一个电商系统,业务流程大致如下:
-
用户注册与登录:
-
用户注册 -> 用户信息验证 -> 用户登录
-
-
商品浏览:
-
用户浏览商品 -> 商品信息展示
-
-
购物车与结算:
-
用户添加商品到购物车 -> 提交订单 -> 支付处理
-
-
订单管理:
-
用户查看订单状态 -> 管理员处理订单
-
关键功能模块和功能点的提取
从业务流程中提取出关键的功能模块和功能点是开发的第一步。每个功能模块都应该具有明确的目标和职责,开发时每个模块的功能点需要具体化,便于后续的开发、测试和维护。
实际操作建议:
-
功能模块拆解:将业务流程中的每一个操作拆解成具体的功能模块,形成可执行的任务清单。
-
优先级排序:根据项目的核心需求、用户价值、技术实现的难易度等,优先实现最核心的功能。
示例: 对于电商系统,以下是功能模块拆解:
-
用户模块:
-
用户注册、登录、注销、密码找回、个人信息修改
-
-
商品模块:
-
商品展示、分类、搜索、筛选、推荐
-
-
购物车模块:
-
商品添加到购物车、购物车修改、结算
-
-
订单模块:
-
提交订单、订单支付、订单查询、订单取消
-
-
支付模块:
-
支付方式选择、支付处理、支付结果返回
-
1.2 需求变更管理 🔄
在项目开发过程中,需求变更是不可避免的。客户或产品经理可能会根据市场需求、竞争对手变化或者技术发现提出新的要求。有效管理需求变更,对于保持项目进度和质量至关重要。
如何应对需求变更
-
明确变更管理流程:
-
在项目开始前,明确需求变更的管理流程,例如:变更需求提交 -> 变更需求评审 -> 变更需求实施 -> 验收变更结果。
-
所有需求变更都需要经过评审,确保其必要性和可行性。
-
-
评估影响:
-
每次需求变更时,评估对现有系统、开发进度、资源分配和测试工作的影响。对于较大的变更,可能需要调整项目计划和重新分配资源。
-
-
与客户和团队保持沟通:
-
定期与客户或相关人员沟通,确保需求变更的背景、优先级和实际影响。
-
-
文档化所有变更:
-
所有需求变更都应有明确的文档记录,确保团队所有成员都能及时了解变更内容。
-
实际操作建议:
-
变更需求记录表:使用表格记录每个需求变更的详细信息,包括变更时间、变更原因、变更内容、评审结果等。
-
需求变更会议:定期召开需求变更评审会议,确保所有变更都能被评审并作出合理决策。
需求文档的管理与版本控制
需求文档是项目中最重要的沟通工具之一,它确保开发人员、测试人员、产品经理等各方人员在同一个目标上进行工作。
-
文档管理:
-
使用文档管理工具(如 Confluence、Notion、Google Docs)将需求文档、功能说明、设计文档等集中管理。
-
文档需要定期更新,确保所有团队成员都能访问到最新版本。
-
-
版本控制:
-
使用版本控制工具(如 Git、SVN)管理需求文档的版本。当文档内容变更时,需要记录变更的版本号,确保文档历史清晰。
-
实际操作建议:
-
文档版本管理:每次文档变更后标注版本号,并记录变更内容。
-
文档的审批流程:每次文档更新后,进行审核和批准,确保文档准确性和完整性。
示例:
-
需求文档版本控制:
v1.0:2023-04-01 初步需求文档
v1.1:2023-04-10 更新支付模块需求
v1.2:2023-04-15 修改商品展示功能
小结 📝
-
在项目初期,理解业务需求、梳理业务流程、提取关键功能模块,能帮助开发团队清晰地了解项目目标,制定合理的开发计划。
-
需求变更管理是确保项目稳定进展的关键,需要规范化变更流程、评估变更影响并做好文档管理。
-
项目成功的关键是需求明确,同时能灵活应对需求变更,确保项目按时交付并满足用户的需求。
通过明确需求和高效管理需求变更,项目的开发将更加顺畅,避免后期出现过多不必要的修改和延误。
2. java项目创建的事前准备
2.1 java项目创建讲解
2.1.1 在创建的目录中选择maven
2.1.2 在创建项目中勾选 Lombok Spring Web MySQL Driver 三个依赖
2.1.3 在pom.xml中引入MyBaits-Plus 依赖
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version>
</dependency>
2.1.4 引入参数校验:jakarta.validation
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2.1.5 引⼊JWT令牌的依赖
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.5</version><scope>runtime</scope>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is
preferred --><version>0.11.5</version><scope>runtime</scope>
</dependency>
2.1.6 将application.properties的后缀改为.yml以便我们更好地管理application中的配置
2.1.7 添加后的配置讲解(注意博主上面写的中文哦 不然配制错了就不要怪博主了) 当然如有需要可以添加其他的配置
spring:application:name: demo #自己创建的包名datasource:url: jdbc:mysql://127.0.0.1:3306/需要使用的数据库名字?characterEncoding=utf8&useSSL=false
# 数据库的账号username: root
# 数据库的密码password: rootdriver-class-name: com.mysql.cj.jdbc.Driver
# 配置 MyBatis-Plus 相关属性
mybatis-plus:# 配置 MyBatis-Plus 的配置属性configuration:# 开启下划线到驼峰命名的自动转换map-underscore-to-camel-case: true# 设置日志实现类为标准输出日志log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 配置日志记录的相关属性
logging:# 设置日志文件的名称file:name: spring-blog.log
2.1.8 在 com.example.demo 中创建软件包
解释:
src/main/java 目录
- com.example.demo:项目的根包名。
- common:存放通用工具类、配置类等公共模块。
- advice:可能存放切面相关的通知类 ,用于实现面向切面编程(AOP)。
- config:项目的配置类,如 Spring 相关配置、自定义配置等。
- enums:存放自定义枚举类型。
- exception:自定义异常类,用于处理项目中特定业务异常。
- pojo:存放实体类(Plain Old Java Objects),用于封装业务数据,对应数据库表或业务对象。
- utils:通用工具类,如字符串处理、日期处理等工具类。
- controller:控制层,接收前端请求,调用 Service 层方法,返回响应数据给前端。
- mapper:数据访问层接口,通常与 MyBatis 等持久层框架配合,定义数据库操作方法。
- service:业务逻辑层接口。
- impl:业务逻辑层接口的实现类,UserInfoService 可能是用户信息相关业务逻辑接口。
- Demo3Application:Spring Boot 项目的主启动类,标注有
@SpringBootApplication
等注解,用于启动整个 Spring Boot 应用。
- common:存放通用工具类、配置类等公共模块。
src/main/resources 目录
- static:存放静态资源,如 CSS、JavaScript、图片等,供前端页面使用。
- templates:存放模板文件,如 Thymeleaf、Freemarker 等模板引擎的模板文件,用于生成动态网页。
- application.yml:Spring Boot 项目的配置文件,用于配置数据库连接、服务端口、日志等项目相关参数。
2.2 项⽬公共模块
项⽬分为控制层(Controller),服务层(Service),持久层(Mapper).各层之间的调⽤关系如下:
我们先根据需求完成公共层代码的编写
2.2.1 统⼀返回结果实体类
code:返回的状态码(例如 200、500)
message:返回的消息,描述结果或者错误信息
data:接口返回的具体数据,可能是对象、列表等
定义业务状态枚举
2.2.1.1 在enums上创建ResultCodeEnum
/*** 使用@AllArgsConstructor注解自动生成构造方法* 这个注解是Lombok库的一部分,用于简化Java类的构造方法编写* 它会为类中的所有成员变量生成一个构造方法,使得代码更加简洁** @see lombok.AllArgsConstructor* @see lombok*/
@AllArgsConstructor
public enum ResultCodeEnum {SUCCESS(200 ),FAIL(400),UNAUTHORIZED(401),FORBIDDEN(403),NOT_FOUND(404),INTERNAL_SERVER_ERROR(500);private Integer code;public Integer getCode() {return code;}}
2.2.1.2 在pojo中创建Result<T>泛型
用来构造成功与失败返回的静态方法
/*** 通用的响应结果类,用于封装API请求的响应结果* 该类使用了@Data注解,自动为所有字段生成getter和setter方法* * @param <T> 泛型参数,用于表示响应数据的具体类型*/
@Data
public class Result<T> {/*** 响应状态码*/private Integer code;/*** 响应消息*/private String message;/*** 响应数据*/private T data;/*** 创建一个成功的响应结果* * @param data 响应中携带的数据* @param <T> 泛型参数,表示数据的具体类型* @return 成功的响应结果对象*/public static <T> Result success(T data){Result result = new Result();result.setCode(ResultCodeEnum.SUCCESS.getCode());result.setData(data);return result;}/*** 创建一个失败的响应结果* * @param message 响应消息,描述失败原因* @param <T> 泛型参数,此处无实际用途,为了保持接口一致性* @return 失败的响应结果对象*/public static <T> Result fail(String message){Result result = new Result();result.setCode(ResultCodeEnum.FAIL.getCode());result.setMessage(message);return result;}/*** 创建一个未授权的响应结果* * @param message 响应消息,描述未授权的原因* @param <T> 泛型参数,此处无实际用途,为了保持接口一致性* @return 未授权的响应结果对象*/public static <T> Result unauthorized(String message){Result result = new Result();result.setCode(ResultCodeEnum.UNAUTHORIZED.getCode());result.setMessage(message);return result;}/*** 创建一个禁止访问的响应结果* * @param message 响应消息,描述禁止访问的原因* @param <T> 泛型参数,此处无实际用途,为了保持接口一致性* @return 禁止访问的响应结果对象*/public static <T> Result forbidden(String message){Result result = new Result();result.setCode(ResultCodeEnum.FORBIDDEN.getCode());result.setMessage(message);return result;}/*** 创建一个未找到资源的响应结果* * @param message 响应消息,描述未找到资源的原因* @param <T> 泛型参数,此处无实际用途,为了保持接口一致性* @return 未找到资源的响应结果对象*/public static <T> Result notFound(String message){Result result = new Result();result.setCode(ResultCodeEnum.NOT_FOUND.getCode());result.setMessage(message);return result;}/*** 创建一个内部服务器错误的响应结果* * @param message 响应消息,描述内部服务器错误的原因* @param <T> 泛型参数,此处无实际用途,为了保持接口一致性* @return 内部服务器错误的响应结果对象*/public static <T> Result internalServerError(String message){Result result = new Result();result.setCode(ResultCodeEnum.INTERNAL_SERVER_ERROR.getCode());result.setMessage(message);return result;}
}
success(T data)
:成功返回数据。
fail(String message)
:失败时返回具体的错误消息。
error(String message)
:另一种失败时的消息返回格式。
success(String message)
:成功时只返回消息,data
为 null。这些方法可以简化控制器中返回结果的处理,使得每个接口的返回格式统一。
2.2.2 统一返回结果 🌐
在开发 Java 项目时,特别是在 API 接口设计中,统一的返回结果格式能够极大地提升接口的可维护性和用户体验。通过统一的返回结果格式,前端和后端开发人员可以在约定俗成的格式下进行高效合作,并且能够减少因接口返回不一致而引发的问题。
2.2.2.1 统一返回结果的必要性
1. 标准化接口输出
-
保证所有接口的返回结果都遵循统一的结构,避免前后端数据解析不一致的问题。
-
可以让前端开发人员更加清晰地处理接口响应,简化接口的错误处理逻辑。
2. 增强可维护性
-
通过统一的结构,后期项目中无论是新增接口还是修改接口,都能轻松保持一致性。
-
当项目中需要调整返回结果的结构时,修改一个地方即可避免到处修改。
3. 简化错误处理
-
错误消息、成功消息和数据的格式统一,极大地简化了客户端的错误处理和界面展示逻辑。
4. 便于日志记录与监控
-
统一返回结果格式后,可以方便记录日志,便于调试与监控。无论是成功还是失败,都有明确的返回码和信息。
2.2.2.2 在advice中创建ResponseAdvice 使ResponseAdvice 实现 ResponseBodyAdvice接口(interface) 并重写ResponseBodyAdvice中的两个方法
/*** 全局响应建议类,用于统一处理控制器的响应体* 通过实现ResponseBodyAdvice接口,可以对控制器的响应体进行预处理*/
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {/*** 自动注入ObjectMapper,用于响应体的序列化和反序列化*/@Autowiredprivate ObjectMapper objectMapper;/*** 判断是否支持对响应体进行处理的方法* * @param returnType 控制器方法的返回类型* @param converterType 处理响应体的转换器类型* @return 返回true表示支持对响应体进行处理,false表示不支持*/@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}
/*** 使用SneakyThrows注解的方法示例** 这个方法展示了如何使用SneakyThrows注解来处理可能抛出的异常* 通过这种方式,可以避免在方法签名中显式声明异常,或者在方法内部捕获异常** @param //input 输入参数的说明* @return 返回值的说明*/@SneakyThrows@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {/**if (body instanceof Result<?>):使用 instanceof 关键字来判断 body 对象是否是 Result 类的实例。* Result<?> 中的 <?> 是 Java 中的通配符,表示 Result 类可以是任何泛型类型。也就是说,* 不管 Result 类中泛型的具体类型是什么,只要 body 是 Result 类的实例,这个条件就会成立。return body;:如果 body 是 Result 类的实例,那么直接将 body 返回。* 这意味着不需要对已经是 Result 类型的响应体进行额外的处理,* 保持其原样返回。* *//** 在实际的项目开发中,通常会定义一个统一的响应结果类 Result,* 用于规范接口的返回格式,方便前端开发人员处理接口响应。* 当控制器方法返回的结果已经是 Result 类型时,就不需要再对其进行二次封装,* 直接返回即可,避免重复处理。*/if (body instanceof Result<?>) {return body;}if (body instanceof String) {//objectMapper.writeValueAsString将任何Java对象转换为JSON字符串return objectMapper.writeValueAsString(Result.ok(body));}return Result.ok(body);}
}
3. 定义项目异常 ⚠️
在项目开发过程中,异常处理是非常关键的一部分。合理地定义和处理异常,可以帮助我们提高代码的可维护性、可读性以及用户体验。统一的异常处理不仅能避免重复的代码,还能简化系统错误的管理,方便定位和修复问题。
3.1 为什么需要统一的异常处理?
-
简化异常捕获:避免在每个业务方法中都编写相似的异常处理代码,统一集中管理。
-
提升可维护性:异常处理逻辑集中管理,便于修改和扩展。
-
便于错误追踪和调试:统一的异常格式能够更好地记录日志和定位问题,减少错误定位的时间。
-
用户体验:通过统一的错误提示,向前端返回一致的错误响应格式,避免信息混乱。
3.2 全局异常处理
有了自定义异常类后,接下来可以通过 @ControllerAdvice
注解来处理全局异常。@ControllerAdvice
可以集中捕获 Controller 层的异常,并返回统一格式的错误信息。
在advice中创建ExceptionAdvice
// 使用Slf4j日志框架记录日志信息
@Slf4j
// 定义一个全局异常处理类,用于处理控制器中抛出的异常
@ControllerAdvice
// 使用ResponseBody注解表明返回内容为JSON格式
@ResponseBody
public class ExceptionAdvice {/*** 处理所有的Exception类型的异常* @param e 异常对象* @return 返回包含错误信息的Result对象*/@ExceptionHandler(Exception.class)public Result handler(Exception e) {// 记录异常信息log.error("发生异常 e :{}", e);// 返回错误信息为"登录失败"和异常信息的Result对象return Result.fail("登录失败", e.getMessage());}/*** 处理BlogException类型的异常* @param e 异常对象* @return 返回包含错误信息的Result对象*/@ExceptionHandler(BlogException.class)public Result blogException(Exception e) {// 记录错误信息log.error("发生错误 e :{}", e);// 返回错误信息为"<UNK>"和异常信息的Result对象return Result.fail("<UNK>", e.getMessage());}/*** 处理NoResourceFoundException类型的异常* @param e 异常对象* @return 返回包含错误信息的Result对象*/@ResponseStatus(HttpStatus.NOT_FOUND)@ExceptionHandler(NoResourceFoundException.class)public Result blogException(NoResourceFoundException e) {// 记录文件不存在的错误信息log.error("文件不存在 e :{}", e.getResourcePath());// 返回错误信息为"<UNK>"和资源路径信息的Result对象return Result.fail("<UNK>", e.getResourcePath());}
}
3.3 定义项⽬异常
在exception包中创建BlogException 并继承 RuntimeException
/*
BlogException 是一个自定义的业务异常类,用于在博客系统中抛出特定的业务异常。
当业务逻辑执行过程中遇到不符合预期的情况时,可以通过 throw new BlogException(...)的方式抛出该异常,然后由统一的异常处理器捕获并返回友好的错误信息给客户端。
* */
public class BlogException extends RuntimeException {private int code;private String msg;public BlogException() {}public BlogException(int code, String msg) {this.code = code;this.msg = msg;}public BlogException(int code) {this.code = code;}public BlogException(String msg) {this.msg = msg;}}
4.在mapper中创建要实现数据库中的自定义的自造字段
例如 一个用户登录的字段 在pojo中写的 UserInfo
@Data
public class UserInfo {@TableId(value ="id",type = IdType.AUTO)private Integer id;private String userName;private String password;private String githubUrl;private Integer deletaFlag;private LocalDate createTime;private LocalDate updateTime;
}
在mapper中构造UserInfoMapper 来继承MyBatis Plus的映射接口 专注于UserInfo实体类的CRUD操作 不用我们在再写数据库的增删改查的操作了
MyBatis-Plus官方查询文档 :
持久层接口 | MyBatis-Plus
/*** UserInfoMapper接口是MyBatis Plus的映射接口,用于定义对BlogInfo表的操作* 它继承自BaseMapper,专注于UserInfo实体类的CRUD操作*/
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {// 此处无需添加额外方法,因为BaseMapper已经提供了基本的数据操作方法
}
结语 🎉
在任何成功的项目背后,细致的规划与充分的准备工作都是必不可少的。通过明确项目需求、选择合适的技术栈、搭建开发环境、设计合理的项目结构、制定代码规范、管理需求变更等准备工作,我们为开发阶段的高效推进打下了坚实的基础。
本指南为 Java 项目的开发准备工作提供了清晰的框架和步骤,帮助你在启动开发前做出明智的决策,并减少开发过程中可能遇到的问题。
未来的挑战与扩展
随着项目的逐步推进,你将会遇到许多新的挑战,例如性能优化、分布式系统架构设计、容器化部署等。幸运的是,随着你对项目的深入了解和经验积累,你会逐渐掌握解决这些问题的方法。
本指南帮助你打下了坚实的项目基础,但在实际开发过程中,技术不断发展,需求不断变化,我们需要保持学习的态度,灵活应对各种问题。
最后:
“精心准备,才能迎接挑战。”
项目的成功不在于代码的多少,而在于准备的充分与执行的高效。希望本指南能帮助你在开发过程中少走弯路,顺利交付高质量的产品。
无论是个人项目还是团队协作,做好前期准备工作,确保项目的高效推进,将是你成功的关键!🎯
如果你有任何问题,或是在实际开发中遇到挑战,随时可以与我联系,祝你项目开发顺利,代码如行云流水!🚀
博主还会对项目中的不同模块进行详细的讲解 请大家尽情的等待吧 🎉
相关文章:
Java写项目前的准备工作指南(技术栈选择 环境搭建和工具配置 项目结构设计与模块划分)
前言 📝 在开始编写一个 Java 项目之前,做好充分的准备工作是至关重要的。很多初学者可能在没有清晰规划的情况下就开始编写代码,导致项目开发进度缓慢、结构混乱,甚至最终无法按预期完成。而事实上,项目的成功不仅仅…...
如何使用 Redis 缓存验证码
目录 🧠 Redis 缓存验证码的工作原理 🧰 实现流程 1. 安装 Redis 和 Python 客户端 2. 生成并缓存验证码 示例代码:生成并存储验证码 3. 发送验证码(以短信为例) 4. 校验验证码 示例代码:校验验证码…...
(八)RestAPI 毛子(Unit Testing)
文章目录 项目地址一、Unit Testing1.1 创建X unit 测试项目1. 创建项目目录2. 管理包 1.2 创建CreateEntryDtoValidator测试1.3 创建CreateEntryDtoValidator测试 二、Integration test2.1 创建Integration test环境1. 安装所需要的包 2.2 配置基础设置1. 数据库链接DevHabitW…...
德州仪器(TI)—TDA4VM芯片详解(2)—产品应用和介绍
写在前面 本系列文章主要讲解德州仪器(TI)TDA4VM芯片的相关知识,希望能帮助更多的同学认识和了解德州仪器(TI)TDA4VM芯片。 若有相关问题,欢迎评论沟通,共同进步。(*^▽^*) 错过其他章节的同学…...
vue2,3:v-model的语法糖
Vue2的v-model 语法糖 **1. **v-model 的作用 v-model 是 Vue 中用于实现双向数据绑定的指令,主要用于表单元素(如 、、)和自定义组件。它简化了数据与视图之间的同步,使得开发者可以方便地处理用户输入。 **2. **v-model 的语…...
【深度学习】#10 注意力机制
主要参考学习资料: 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 目录 注意力提示生物学中的注意力提示查询、键和值 注意力汇聚注意力评分函数掩蔽softmax操作加性注意力缩放点积注意力 Bahdanau注意力多头注意力自注意力和位…...
Modbus总线协议智能网关协议转换案例解析:提升系统兼容性
Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气,Schneider Electic)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(Defacto),并日现在是工业电子设备之间常用的连接方式 Modbus是一种串行通信协…...
echarts自定义图表--仪表盘
基于仪表盘类型的自定义表盘 上图为3层结构组成 正常一个仪表盘配置要在外圈和内圈之间制造一条缝隙间隔 再创建一个仪表盘配置 背景透明 进度条拉满 进度条颜色和数据的背景相同开始处的线 又一个仪表盘配置 数值固定一个比较小的值 <!DOCTYPE html> <html><h…...
第五章:Execution Flow Framework
Chapter 5: Execution Flow Framework 从消息记忆到执行流程:如何让多个AI“同事”协同完成复杂任务? 在上一章的消息与记忆系统中,我们已经能让AI记住之前的对话内容。但你是否想过:如果用户要求“预订从北京到上海的高铁&#…...
01 C++概述
一、C语言发展史 起源与演进 • 1960s:剑桥大学Martin Richards开发BCPL语言,用于系统软件开发。 • 1970年:贝尔实验室Ken Thompson在BCPL基础上发明B语言。 • 1972年:Dennis Ritchie和Brian Kernighan设计出C语言,兼…...
Kotlin DSL 深度解析:从 Groovy 迁移的困惑与突破
引言 Gradle 作为现代构建工具,支持 Groovy 和 Kotlin 两种 DSL(领域特定语言)。Kotlin DSL 因其类型安全和更好的 IDE 支持逐渐流行,但它的语法设计却让许多开发者感到困惑,尤其是从 Groovy 迁移时。 本文将从 Kotl…...
2025年二级造价师考点总结
二级造价师考点总结 一、建设工程造价管理 工程造价构成:重点掌握建筑安装工程费(人工费、材料费、机械费、企业管理费、利润、规费、税金)的组成及计算。 计价依据:熟悉工程量清单计价规范,掌握定额计价与清单计价的…...
Typecho博客使用阿里云cdn和oss:handsome主题进阶版
Typecho使用阿里云cdn和oss 设置前需要保证阿里云cdn和oss已配置好且可以正常使用一、准备工作二、修改 Handsome 主题的静态资源链接方法 1:直接修改主题文件(推荐)方法 2:通过主题设置自定义(方便) 三、处…...
知识体系_用户研究_用户体验度量模型
1 用户体验度量常见模型 1.1 满意度(CSAT/PSAT) CSAT(Customer Satisfaction)指客户满意度,PAST(Product Satisfaction)指产品满意度。顾名思义,其用于衡量客户对产品或服务的体验度量指标。在用户完成某个产品或某项服务的体验后,对其进行…...
邮件分类特征维度实验分析
活动发起人小虚竹 想对你说: 这是一个以写作博客为目的的创作活动,旨在鼓励大学生博主们挖掘自己的创作潜能,展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴,那么,快来参加吧!…...
Linux服务之Nginx服务部署及基础配置
目录 一.Nginx介绍 1.Nginx功能介绍 2.基础特性 3.Web服务相关的功能 4.I/O模型相关概念 5.nginx模块 6.Nginx文件存放位置 7.Nginx事件驱动模型 二.平滑升级及信号使用 1.Nginx 程序当作命令使用 2.信号类型 3.平滑升级nginx 4.回滚 三.Nginx调优 1.隐藏版本号或…...
Centos小白之在CentOS8.5中安装Rabbitmq 3.10.8
注意事项 安装以及运行等其他操作,要使用root账号进行,否则会遇到很多麻烦的事情。 使用命令行进行远程登录 ssh root192.168.0.167 安装make 执行安装命令 yum -y install make gcc gcc-c kernel-devel m4 ncurses-devel openssl-devel这里有可能会…...
基于单片机的游泳馆智能管理系统设计与实现
标题:基于单片机的游泳馆智能管理系统设计与实现 内容:1.摘要 随着游泳馆规模的不断扩大和管理需求的日益提高,传统的管理方式已难以满足高效、精准的管理要求。本文旨在设计并实现一种基于单片机的游泳馆智能管理系统。采用单片机作为核心控制单元,结合…...
深度相机(一)——深度相机模型及用途介绍
一、深度相机概述 深度相机,又称 3D 相机,是一种能够获取场景中物体深度信息(即物体到相机的距离)的设备。与传统相机只能拍摄二维平面图像不同,深度相机不仅能记录物体的颜色和纹理,还能通过特定技术手段测…...
【Torch】nn.Conv1d、nn.Conv2d、nn.Conv3d算法详解
1. nn.Conv1d 1.1 输入(Input)和输出(Output) 输入张量 形状:(batch_size, in_channels, length) batch_size:一次过网络的样本数in_channels:每个样本的通道数(特征维度࿰…...
Android WebRTC回声消除
文章目录 安卓可用的回声消除手段各种回声消除技术优缺点WebRTC回声消除WebRTC回声消除回声消除处理流程WebRTC AECM APP 安卓可用的回声消除手段 硬件回声消除 使用 AudioRecord 的 VOICE_COMMUNICATION 模式:通过 AudioRecord 的 VOICE_COMMUNICATION 音频源可以…...
[Linux运维] [Ubuntu/Debian]在Lightsail Ubuntu服务器上安装Python环境的完整指南
在之前的教程中,我们已经讲过如何开通亚马逊Lightsail服务器并安装宝塔面板。今天,我们来进一步补充:如何在Lightsail上的Ubuntu/Debian系统中安装和配置Python开发环境。 本教程不仅适用于Lightsail服务器,也适用于所有使用Ubunt…...
2025医疗领域AI发展五大核心趋势与路线研究
引言 人工智能技术正在全球范围内深刻改变医疗服务的提供方式,推动全球医疗的普惠化、技术合作、产业升级以及公共卫生防控发生巨变[0]。医疗AI的浪潮奔涌向前,从2024年开始,生成式AI的爆发式发展更是将医疗AI推到了新的十字路口[1]。在这一背景下,本报告将深入探讨医疗领…...
【学习笔记】机器学习(Machine Learning) | 第六周|过拟合问题
机器学习(Machine Learning) 简要声明 基于吴恩达教授(Andrew Ng)课程视频 BiliBili课程资源 文章目录 机器学习(Machine Learning)简要声明 摘要过拟合与欠拟合问题一、回归问题中的过拟合1. 欠拟合(Underfit&#x…...
【MQ篇】RabbitMQ之惰性队列!
目录 引言:当“生产”大于“消费”,队列就“胖”了!肥宅快乐队列?🤔队列界的“躺平”大师:惰性队列(Lazy Queues)驾到!😴如何“激活”你的队列的“惰性”属性…...
计算机视觉——通过 OWL-ViT 实现开放词汇对象检测
介绍 传统的对象检测模型大多是封闭词汇类型,只能识别有限的固定类别。增加新的类别需要大量的注释数据。然而,现实世界中的物体类别几乎无穷无尽,这就需要能够检测未知类别的开放式词汇类型。对比学习(Contrastive Learning&…...
第二部分:网页的妆容 —— CSS(下)
目录 6 布局基础:Display 与 Position - 元素如何排列和定位6.1 小例子6.2 练习 7 Flexbox 弹性布局:一维布局利器7.1 小例子7.2 练习 8 Grid 网格布局:强大的二维布局系统8.1 小例子8.2 练习 9 响应式设计与媒体查询:适应不同设备…...
vite项目tailwindcss4的使用
1、安装taillandcss 前几天接手了一个项目,看到别人用tailwindcss节省了很多css代码的编写,所以自己也想在公司项目中接入tailwindcss。 官网教程如下: Installing Tailwind CSS with Vite - Tailwind CSS 然而,我在vite中按…...
css中:is和:where 伪函数
在 CSS 里,:is() 属于伪类函数,其作用是对一组选择器进行匹配,只要元素与其中任何一个选择器相匹配,就可以应用对应的样式规则。以下是详细介绍: 基本语法 :is() 函数的参数是一个或多个选择器,各个选择器之…...
线下零售数据采集:在精度与效率之间寻找平衡点
线下零售数据采集:在精度与效率之间寻找平衡点 为什么线下零售必须重视数据采集? 随着零售行业竞争加剧,门店执行的标准化与透明化成为供应链协作、销售提升的基础工作。 POG(陈列执行规范)的落地效果、陈列策略的调整…...
【Robocorp实战指南】Python驱动的开源RPA框架
目录 前言技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块说明技术选型对比 二、实战演示环境配置要求核心代码实现案例1:网页数据抓取案例2:Excel报表生成 运行结果验证 三、性能对比测试方…...
新ubuntu物理机开启ipv6让外网访问
Ubuntu 物理机 SSH 远程连接与 IPv6 外网访问测试指南 1. 通过 SSH 远程连接 Ubuntu 物理机 1.1 安装 SSH 服务 sudo apt update sudo apt install openssh-server1.2 检查 SSH 服务状态 sudo systemctl status ssh确认出现 active (running)。 1.3 获取物理机 IP 地址 i…...
驱动开发硬核特训 │ Regulator 子系统全解
一、Regulator子系统概述 在 Linux 内核中,Regulator 子系统是专门用于管理电源开关、电压调整、电流控制的一套完整框架。 它主要解决以下问题: 设备需要的电压通常不一样,如何动态调整?有些设备休眠时需要关闭供电࿰…...
入门版 鸿蒙 组件导航 (Navigation)
入门版 鸿蒙 组件导航 (Navigation) 注意:使用 DevEco Studio 运行本案例,要使用模拟器,千万不要用预览器,预览器看看 Navigation 布局还是可以的 效果:点击首页(Index)跳转到页面(…...
怎样将visual studio 2015开发的项目 保存为2010版本使用
用的老旧电脑跑vs2015太慢了,实在忍不了了! 想把用 Visual Studio 2015 的做的项目保存为 Visual Studio 2010 兼容的格式,以后都使用2010写了。自己在网上搜了一下,亲测以下步骤可以的 手动修改解决方案和项目文件 修改解决方案…...
【学习笔记】软件测试流程-测试设计阶段
软件测试设计阶段这个阶段主要工作是编写测试用例。 什么是测试用例? 测试用例(TestCase)是为项目需求而编制的一组测试输入、执行条件以及预期结果,以便测试某个程序是否满足客户需求。简而言之,测试用例是每一个测…...
Rust 学习笔记:关于切片的两个练习题
Rust 学习笔记:关于切片的两个练习题 Rust 学习笔记:关于切片的两个练习题引用和切片引用的大小以下程序能否通过编译? Rust 学习笔记:关于切片的两个练习题 参考视频: https://www.bilibili.com/video/BV1GrDQYeEzS…...
BeeWorks企业内部即时通讯软件支持国产化,已在鸿蒙系统上稳定运行
一、企业用户面临的困境与痛点 一些企业用的即时通讯软件比较旧,存在的问题不仅影响了日常工作的正常开展,也阻碍了企业信息化建设的进程: ● 国产系统与移动端不兼容:仅支持Windows和MAC系统,无法在银河麒麟、统信U…...
java对文字按照语义切分
实现目标 把一段文本按照一个完整的一句话为单元进行切分。如:以逗号,感叹号结尾看作是一个句子。 实现方案 StanfordCoreNLP切分 引入依赖 <dependency><groupId>edu.stanford.nlp</groupId><artifactId>stanford-corenlp<…...
华纳云:centos如何实现JSP页面的动态加载
JSP(JavaServer Pages)作为Java生态中常用的服务器端网页技术,具有动态内容生成、可扩展性强、与Java无缝结合等优势。 而CentOS作为一款稳定、高效、安全的Linux服务器操作系统,非常适合部署JSP应用。 想要让JSP页面实现动态更新加载,避免…...
Android 消息队列之MQTT的使用(二):会话+消息过期机制,设备远程控制,批量控制实现
目录 一、实际应用场景 室内温湿度数据上传设备远程控制批量控制实现 二、会话管理、消息过期设置 4.1 会话管理 Clean Session参数 新旧会话模式对比典型应用场景 4.2 消息过期设置 MQTT 5.0消息过期机制 Message Expiry Interval属性QoS级别影响 三、实际应用场景 …...
一、JVM基础概念
一、JVM的设计目标 一次编译,到处运行(跨平台) ➔ Java编译成字节码,由JVM在不同平台解释/编译执行,实现跨平台。 内存管理与垃圾回收 ➔ JVM统一负责内存分配和回收,降低内存泄漏的风险。 性能优化 ➔ JIT(即时编译…...
深度学习---Pytorch概览
一、PyTorch 是什么? 1. 定义与定位 开源深度学习框架:由 Facebook(Meta)AI 实验室开发,基于 Lua 语言的 Torch 框架重构,2017 年正式开源,主打动态计算图和易用性。核心优势:灵活…...
第33周JavaSpringCloud微服务 分布式综合应用
第33周JavaSpringCloud微服务 分布式综合应用 一、分布式综合应用概述 分布式知识体系内容广泛,主要包括分布式事务、分布式锁、RabbitMQ等消息中间件的应用以及跨域问题的解决。 1.1 课程重点内容介绍 分布式事务 :在大型项目中普遍存在,…...
Paramiko 完全指南
目录 Paramiko 概述核心功能与模块框架安装与依赖基础用法与案例详解 SSH 连接与命令执行密钥认证SFTP 文件传输交互式会话端口转发 高级功能与实战技巧常见问题与解决方案总结与资源推荐 1. Paramiko 概述 是什么? Paramiko 是一个纯 Python 实现的 SSHv2 协议库…...
夜莺监控V8(Nightingale)二进制部署教程(保姆级)
夜莺监控部署 前置工作 1. 部署好mysql 2. 部署好redis 3. 部署好prometheus夜莺压缩包下载 本教程基于Centos7系统下的二进制方式部署,先去官网进行压缩包下载 在系统创建/opt/n9etest目录,并将压缩包拖进目录 mkdir /opt/n9etest进入/opt/n9etest࿰…...
鸿蒙应用开发 知识点 官网快速定位表
ArkTS 语言介绍 ArkTS 语言介绍 基础入门 资源分类与访问 添加组件(基础组件) 显示图片 (Image) 按钮 (Button) 单选框 (Radio) 切换按钮 (Toggle) 进度条 (Progress) 视频播放 (Video) 使用文本 文本显示 (Text/Span) 文本输入 (TextInput/TextArea) 使用弹窗 使用弹…...
【神经网络与深度学习】两种加载 pickle 文件方式(joblib、pickle)的差异
引言 从深度学习应用到数据分析的多元化需求出发,Python 提供了丰富的工具和模块,其中 pickle 和 joblib 两种方式在加载数据文件方面表现尤为突出。不同场景对性能、兼容性以及后续处理的要求不尽相同,使得这两种方式各显优势。本文将通过深…...
quickbi finebi 测评(案例讲解)
quickbi & finebi 测评 国产BI中入门门槛比较低的有两个,分别是quickbi和finebi。根据我的经验通过这篇文章做一个关于这两款BI的测评文章。 quickbi分为个人版、高级版、专业版、私有化部署四种。这篇文章以quickbi高级版为例,对quickbi进行分享。…...
vue的生命周期 以及钩子
最早可以在created 时调用后端接口获取数据,因为beforecreated的时候 那个data 都还还是初始化出来 修改数据的时候触发 update 案例1:create 案例2:一进来页面获取搜索框焦点 echarts 饼图渲染 初始化dom后才去准备实例,所以必须要在dom之后…...