网页五子棋——通用模块
目录
项目创建
通用功能模块
错误码
自定义异常类
CommonResult
jackson
加密工具
项目创建
使用 idea 创建 SpringBoot 项目,并引入相关依赖:
配置 MyBatis:
编辑 application.yml:
spring:datasource: # 数据库连接配置url: jdbc:mysql://127.0.0.1:3306/gobang_system?characterEncoding=utf8&useSSL=falseusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver
mybatis: # mybatis 配置configuration:map-underscore-to-camel-case: true #配置驼峰自动转换log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句
通用功能模块
通用功能模块 是在软件开发中,创建的一组通用的功能模块,以便在不同的应用场景中重用,从而提高开发效率、降低重复开发工作量,并确保系统的一致性与可维护性。通用功能模块通常具有高度的复用性,能够服务于多个系统或应用
这部分模块通常存放在项目中的 common 包下
错误码
错误码主要用于标识和处理程序运行中的各种异常情况,能够精确的指出问题所在
错误码的作用有:
明确标识错误:错误码提供了一种明确的方式来表示错误的状态,能够精确的指出问题所在
简化问题排查:通过错误码,我们可以快速的定位问题。在系统日志中会包含大量的信息,而错误码作为一种统一的标识符,可以帮助我们在日志中迅速查找特定的错误类型,提高排查效率
错误处理:客户端可以根据错误码进行特定的错误处理,而不是依赖通用的异常处理
易于维护:集中管理错误码使得它们更容易维护和更新。如,业务逻辑变化,只需要更新错误码的定义,而不需要修改每个使用它们的地方。在接口文档中,错误码也可以清晰的列出所有的错误情况,使开发者更容易立即和使用接口
调试和测试:错误码可用于自动化测试,确保特定的错误情况被正确处理
错误分类:错误码可以将错误分类为不同级别或不同类型,如 客户端错误、服务器错误、业务逻辑错误等
创建 errorcode 包:
定义错误码类型:
@Data
public class ErrorCode {/*** 错误码*/private final Integer code;/*** 错误描述信息*/private final String message;public ErrorCode(Integer code, String message) {this.code = code;this.message = message;}
}
定义全局错误码:
public interface GlobalErrorCodeConstants {// 成功ErrorCode SUCCESS = new ErrorCode(200, "成功");// 服务端错误ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常");ErrorCode NOT_IMPLEMENTED = new ErrorCode(501, "功能未实现/未开启");ErrorCode ERROR_CONFIGURATION = new ErrorCode(502, "配置项错误");ErrorCode UNKNOWN = new ErrorCode(999, "未知错误");
}
定义 controller 层业务错误码:
public interface ControllerErrorCodeConstants {}
其中的错误码信息随着后续业务代码的完成补充
定义 service 层业务错误码:
public interface ServiceErrorCodeConstants {
}
其中的错误码信息随着后续业务代码的完成补充
自定义异常类
自定义异常类是为了在程序中处理特定的错误或异常情境,使得异常处理更加清晰和灵活。通过自定义异常类,可以根据业务需求定义特定的异常类型,方便捕获和处理特定的错误
创建 exception 包:
controller 层异常类:
@Data
@EqualsAndHashCode(callSuper = true)
public class ControllerException extends RuntimeException {/*** controller 层错误码* @see com.example.gobang_system.common.errorcode.ControllerErrorCodeConstants*/private Integer code;/*** 错误描述信息*/private String message;/*** 无参构造方法,方便后续进行序列化*/public ControllerException() {}/*** 全参构造方法,指定 code 和 message* @param code* @param message*/public ControllerException(Integer code, String message) {this.code = code;this.message = message;}/*** 通过 errorCode 指定 code 和 message* @param errorCode*/public ControllerException(ErrorCode errorCode) {this.code = errorCode.getCode();this.message = errorCode.getMessage();}
}
service 层异常类:
@Data
@EqualsAndHashCode(callSuper = true)
public class ServiceException extends RuntimeException{/*** service 层错误码* @see com.example.gobang_system.common.errorcode.ServiceErrorCodeConstants*/private Integer code;/*** 错误描述信息*/private String message;/*** 无参构造方法,方便后续进行序列化*/public ServiceException() {}/*** 全参构造方法,指定 code 和 message* @param code* @param message*/public ServiceException(Integer code, String message) {this.code = code;this.message = message;}/*** 通过 errorCode 指定 code 和 message* @param errorCode*/public ServiceException(ErrorCode errorCode) {this.code = errorCode.getCode();this.message = errorCode.getMessage();}
}
在进行序列化时需要使用无参构造方法,因此需要提供无参构造方法
那么,在进行序列化时为什么要使用无参构造方法呢?
序列化:将对象转化为字节流
反序列化:从字节流中重建对象
在序列化过程中,使用无参构造方法(即不带任何参数的构造方法)是因为序列化和反序列化涉及将对象的状态转换为字节流 并且再 将其从字节流重建回原对象
序列化过程中,java会将对象的状态(字段值)保存在 字节流 中,而反序列化是通过读取这些字节流恢复对象,当反序列化时,JVM 必须首先 创建一个新的对象实例,然后再将字节流中的数据填充到该对象的字段中。为了能够保证顺利创建对象,java需要一个 无参构造方法 来实例化对象
因此,无参构造方法是反序列化时默认的构造方法,java默认调用该构造方法创建对象实例,因为其没有任何参数,创建对象时无需传递任何参数。如果没有无参构造方法,Java 会试图使用其他构造方法来创建对象,但这些构造方法需要相应的参数传递。而反序列化时,并没有提供参数,这就导致反序列化过程失败
总而言之,无参构造方法在序列化和反序列化中的作用主要体现在以下几个方面:
1. 反序列化需要通过无参构造方法来实例化对象,因为反序列化时无法传递参数给构造方法
2. 无参构造方法保证了对象的正确创建,即使类中有其他的构造方法,也不会影响反序列化的成功
3. 无参构造方法不执行任何业务逻辑,保证了反序列化对象的一致性
@Data 注解
@Data 是 Lombok 提供的一个常见注解,在 java 中用于简化类的代码编写。@Data 注解会为类生成一系列的常用功能代码(自动生成 getter 和 setter 方法、toString 方法等),从而减少代码冗余,提升开发效率
若我们此时运行程序,查看 target 中 的 ControllerException.class:
就可以看到对应的 getter、setter 等方法
@EqualsAndHashCode(callSuper = true)
@EqualsAndHashCode 注解也是 Lombok 中的一个注解,用于自动生成 equals() 和 hashcode() 方法。这两个方法是 Java 中非常常见且重要的方法,通常用于对象的比较和存储在基于哈希表的集合(如 HashMap、HashSet)
callSuper = true:调用父类(super)的 equals() 和 hashCode() 方法,不仅会考虑当前类中的字段,还会考虑父类中的字段,确保父类和子类的字段都参与相等性比较和哈希计算
callSuper = false(默认值):不调用父类的 equals() 和 hashCode() 方法,只考虑当前字段,不考虑父类中的字段
此外,在使用 @Data 注解时,可能会出现反编译 target 文件中并未生成对应 getter、setter 等方法的情况
可能是因为 spring 在创建项目添加 lombok 依赖时,会自动引入一个插件,将其删除即可
更多问题可参考:【SpringBug】lombok插件失效,但是没有报错信息,@Data不能生成get和set方法_lombok data get set-CSDN博客
CommonResult<T>
CommonResult<T> 作为控制层方法的返回类型,封装接口调用结果,包括成功数据、错误数据 和 状态码。它可以被 SpringBoot 框架自动转化为 JSON 或其他格式的响应体,发送给客户端
为什么要进行封装呢?
统一的返回格式:确保客户端收到的响应具有一致的结构,避免每个接口都需要自己定义状态码、消息、数据等内容
错误码和消息:提供错误码(code)和错误消息(errorMessage),帮助客户端快速识别和处理错误
泛型数据返回:使用泛型 <T> 允许返回任何类型的数据,增加了返回对象的灵活性
静态方法:提供了 fail() 和 success() 静态方法,方便快速创建错误或成功的响应对象
错误码常量集成:通过 ErrorCode 和 GlobalErrorCodeConstants 使用预定义的错误码,保持错误码的一致性和可维护性
序列化:实现了 Serializable 接口,使得 CommonResult<T> 对象可以被序列化为多种格式,如 JSON 或 XML,方便网络传输
业务逻辑解耦:将业务逻辑与 API 的响应格式分离,使得后端开发人员可以专注业务逻辑实现,而不必关系如何构建响应
客户端友好:客户端开发人员可以通过统一的接口获取数据和错误信息,无需针对每个 API 编写特定的错误处理逻辑
代码实现:
@Data
public class CommonResult<T> implements Serializable {/*** 错误码* @see ErrorCode#getCode()*/private Integer code;/*** 返回数据*/private T data;/*** 错误描述信息*/private String errorMessage;/*** 业务处理成功* @param data* @return* @param <T>*/public static <T> CommonResult<T> success(T data) {CommonResult result = new CommonResult();result.code = GlobalErrorCodeConstants.SUCCESS.getCode();result.data = data;result.errorMessage = "";return result;}/*** 业务处理失败* @param errorCode* @return* @param <T>*/public static <T> CommonResult<T> fail(ErrorCode errorCode) {return fail(errorCode.getCode(), errorCode.getMessage());}/*** 业务处理失败* @param code* @param errorMessage* @return* @param <T>*/public static <T> CommonResult<T> fail(Integer code, String errorMessage) {Assert.isTrue(!GlobalErrorCodeConstants.SUCCESS.getCode().equals(code),"code = 200, 运行成功");CommonResult result = new CommonResult();result.code = code;result.errorMessage = errorMessage;return result;}
}
其中,serializable 接口是 java 提供的一个标记接口(空接口),用于指示一个类的对象可以被序列化,无需实现任何方法,定义在 java.io 包中
此外,若想在 idea 中使用断言,需要先开启断言功能,可参考:
如何开启idea中的断言功能?_idea开启断言-CSDN博客
jackson
在前后端交互的过程中,经常会使用 JSON 格式来传递数据,这也就涉及到 序列化 和 反序列化,此外,我们在进行日志打印时,也会涉及到序列化
因此,我们可以定义一个工具类,来专门处理 序列化
在 java 中,通常使用 ObjectMapper 来处理 Java 对象与 JSON 数据之间的转换
因此,我们首先来学习一下 ObjectMapper 的相关方法和使用
在 test 中创建一个测试类:
@SpringBootTest
public class JacksonTest {@Testvoid jacksonTest() {}
}
首先来看 object 的序列化:
序列化需要使用 ObjectMapper 中的 writeValueAsString 方法:
处理过程中可能会抛出异常,因此需要进行处理
@SpringBootTest
public class JacksonTest {@Testvoid jacksonTest() {// 创建 ObjectMapper 实例ObjectMapper objectMapper = new ObjectMapper();// 序列化CommonResult<String> result = CommonResult.success("成功"); // 创建 java 对象String str = null;try {str = objectMapper.writeValueAsString(result);System.out.println("序列化结果:" + str);} catch (JsonProcessingException e) {throw new RuntimeException(e);}}
}
我们继续看 object 的反序列化:
反序列化需要使用 readValue 方法:
其中,content 是需要读取的字符串,valueType 是将要转化的 java 对象类型
// 反序列化try {CommonResult<String> result1 = objectMapper.readValue(str, CommonResult.class);System.out.println(result1.getCode() + " " + result1.getData());} catch (JsonProcessingException e) {throw new RuntimeException(e);}
运行并观察结果:
此外,除了处理普通的 object,还可能需要处理一些复杂类型,如 集合、Map 等
例如,处理 List 类型的 序列化 和 反序列化:
List 的序列化 与 object 类型的序列化类似:
// List 的序列化List<CommonResult<String>> commonResultList = Arrays.asList(CommonResult.success("test1"),CommonResult.success("test2"),CommonResult.success("test3"));try {str = objectMapper.writeValueAsString(commonResultList);System.out.println(str);} catch (JsonProcessingException e) {throw new RuntimeException(e);}
List 的反序列化:
在对 List 类型进行反序列化时,不能直接将 List 类型传递给 valueType,而是需要构造一个 JavaType 类型
// List 的反序列化JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, CommonResult.class); // 构造参数类型try {commonResultList = objectMapper.readValue(str, javaType);for (CommonResult<String> res : commonResultList) {System.out.println(res.getData());}} catch (JsonProcessingException e) {throw new RuntimeException(e);}
运行并观察结果:
完整测试代码:
@SpringBootTest
public class JacksonTest {@Testvoid jacksonTest() {// 创建 ObjectMapper 实例ObjectMapper objectMapper = new ObjectMapper();// 序列化CommonResult<String> result = CommonResult.success("成功"); // 创建 java 对象String str = null;try {str = objectMapper.writeValueAsString(result);System.out.println("序列化结果:" + str);} catch (JsonProcessingException e) {throw new RuntimeException(e);}// 反序列化try {CommonResult<String> result1 = objectMapper.readValue(str, CommonResult.class);System.out.println(result1.getCode() + " " + result1.getData());} catch (JsonProcessingException e) {throw new RuntimeException(e);}// List 的序列化List<CommonResult<String>> commonResultList = Arrays.asList(CommonResult.success("test1"),CommonResult.success("test2"),CommonResult.success("test3"));try {str = objectMapper.writeValueAsString(commonResultList);System.out.println(str);} catch (JsonProcessingException e) {throw new RuntimeException(e);}// List 的反序列化JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, CommonResult.class); // 构造参数类型try {commonResultList = objectMapper.readValue(str, javaType);for (CommonResult<String> res : commonResultList) {System.out.println(res.getData());}} catch (JsonProcessingException e) {throw new RuntimeException(e);}}
}
可以发现,在使用 objectMapper 中的方式时,每次都要对异常进行处理,十分繁琐
那我们该如何简化呢?
我们来看 SpringBoot 框架中是如何实现的:
不同类型的对象序列化是基本相同的,都是使用 writeValueAsString 方法来进行序列化,因此我们主要来看反序列化:
可以看到,反序列化 Map 和 List 都调用了 tryParse 方法,并传递了两个参数:一个 lambda 表达式,一个 Exception
我们继续看 tryParse 方法:
其中,最主要的方法就是 parse.call(),通过 call() 方法,来执行定义的任务
且 tryParse 方法中对异常进行了处理:
check.isAssignableFrom(var4.getClass()) 判断抛出的异常是否是传入的 check 异常,若是,则抛出 JsonParseException 异常;若不是,则抛出 IllegalStateException 异常
可以看到,框架中通过 tryParse() 方法,巧妙地对异常进行了处理
因此,我们可以借鉴上述方法来进行实现
由于只需要使用一个 ObjectMapper 实例,因此可以创建 单例 ObjectMapper:
public class JacksonUtil {private JacksonUtil() {}private final static ObjectMapper OBJECT_MAPPER;static {OBJECT_MAPPER = new ObjectMapper();}private static ObjectMapper getObjectMapper() {return OBJECT_MAPPER;}
}
实现 tryParse 方法:
private static <T> T tryParse(Callable<T> parser, Class<? extends Exception> check) {try {return parser.call();} catch (Exception e) {if (check.isAssignableFrom(e.getClass())) {throw new JsonParseException(e);}throw new IllegalStateException(e);}}private static <T> T tryParse(Callable<T> parser) {return tryParse(parser, JsonParseException.class);}
实现序列化方法:
/*** 序列化* @param value* @return*/public static String writeValueAsString(Object value) {return tryParse(() -> getObjectMapper().writeValueAsString(value));}
反序列化:
/*** 反序列化* @param content* @param valueType* @return* @param <T>*/public static <T> T readValue(String content, Class<T> valueType) {return tryParse(() -> {return getObjectMapper().readValue(content, valueType);});}/*** 反序列化 List* @param content* @param param List 中元素类型* @return*/public static <T> T readListValue(String content, Class<?> param) {JavaType javaType = getObjectMapper().getTypeFactory().constructParametricType(List.class, param);return tryParse(() -> {return getObjectMapper().readValue(content, javaType);});}
完整代码:
public class JacksonUtil {private JacksonUtil() {}private final static ObjectMapper OBJECT_MAPPER;static {OBJECT_MAPPER = new ObjectMapper();}private static ObjectMapper getObjectMapper() {return OBJECT_MAPPER;}/*** 序列化* @param value* @return*/public static String writeValueAsString(Object value) {return tryParse(() ->getObjectMapper().writeValueAsString(value));}/*** 反序列化* @param content* @param valueType* @return* @param <T>*/public static <T> T readValue(String content, Class<T> valueType) {return tryParse(() -> {return getObjectMapper().readValue(content, valueType);});}/*** 反序列化 List* @param content* @param param List 中元素类型* @return*/public static <T> T readListValue(String content, Class<?> param) {JavaType javaType = getObjectMapper().getTypeFactory().constructParametricType(List.class, param);return tryParse(() -> {return getObjectMapper().readValue(content, javaType);});}private static <T> T tryParse(Callable<T> parser, Class<? extends Exception> check) {try {return parser.call();} catch (Exception e) {if (check.isAssignableFrom(e.getClass())) {throw new JsonParseException(e);}throw new IllegalStateException(e);}}private static <T> T tryParse(Callable<T> parser) {return tryParse(parser, JsonParseException.class);}
}
进行测试:
@SpringBootTest
public class JacksonTest {@Testvoid jacksonTest() {CommonResult<String> failResult = CommonResult.fail(GlobalErrorCodeConstants.ERROR_CONFIGURATION);// 序列化String res = JacksonUtil.writeValueAsString(failResult);System.out.println(res);// 反序列化failResult = JacksonUtil.readValue(res, CommonResult.class);System.out.println(failResult.getCode() + " " + failResult.getErrorMessage());List<CommonResult<String>> commonResults = Arrays.asList(CommonResult.success("test1"),CommonResult.success("test2"),CommonResult.success("test3"));// 序列化 ListString listStr = JacksonUtil.writeValueAsString(commonResults);System.out.println(listStr);// 反序列化commonResults = JacksonUtil.readListValue(listStr, CommonResult.class);for (CommonResult<String> commonResult: commonResults) {System.out.println(commonResult.getData());}}
}
运行结果:
加密工具
在对敏感信息(如密码、手机号等)进行存储时,需要进行加密,从而保证数据的安全性,若直接明文存储,当黑客入侵数据库时,就可以轻松拿到用户的相关信息,从而造成信息泄露或财产损失
在这里,使用 md5 对用户密码进行加密
采用 判断哈希值是否一致 的方法来判断密码是否正确
详细过程可参考:密码加密及验证_加密算法识别-CSDN博客
完整代码:
public class SecurityUtil {// 密钥private static final String AES_KEY = "3416b730f0f244128200c59fd07e6249";/*** 使用 md5 对密码进行加密* @param password 输入的密码* @return 密码 + 盐值*/public static String encipherPassword(String password) {String salt = UUID.randomUUID().toString().replace("-", "");String secretPassword = DigestUtils.md5DigestAsHex((password + salt).getBytes());return secretPassword + salt;}/*** 验证用户输入的密码是否正确* @param inputPassword 用户输入密码* @param sqlPassword 数据库中存储密码* @return*/public static Boolean verifyPassword(String inputPassword, String sqlPassword) {if (!StringUtils.hasLength(inputPassword)) {return false;}if (!StringUtils.hasLength(sqlPassword) || sqlPassword.length() != 64) {return false;}String salt = sqlPassword.substring(32, 64);String secretPassword = DigestUtils.md5DigestAsHex((inputPassword + salt).getBytes());return sqlPassword.substring(0, 32).equals(secretPassword);}
}
相关文章:
网页五子棋——通用模块
目录 项目创建 通用功能模块 错误码 自定义异常类 CommonResult jackson 加密工具 项目创建 使用 idea 创建 SpringBoot 项目,并引入相关依赖: 配置 MyBatis: 编辑 application.yml: spring:datasource: # 数据库连接配…...
FastAPI 高并发与性能优化
FastAPI 高并发与性能优化 目录 🚀 高并发应用设计原则🧑💻 异步 I/O 优化 Web 服务响应速度⏳ 在 FastAPI 中优化异步任务执行顺序🔒 高并发中的共享资源与线程安全问题 1. 🚀 高并发应用设计原则 在构建高并发应…...
阿里云IOT消息处理
文章主要讲述了阿里云IOT平台如何处理设备上报的消息、如何将消息路由到不同的处理逻辑、如何进行消息转发与转换等操作。 一、接收IOT消息 1.创建订阅 2.案列代码 官网案例代码:如何将AMQP JMS客户端接入物联网平台接收消息_物联网平台(IoT)-阿里云帮助中心 代码…...
缓存三大问题及其解决方案
缓存三大问题及其解决方案 1. 前言 在现代系统架构中,缓存与数据库的结合使用是一种经典的设计模式。为了确保缓存中的数据与数据库中的数据保持一致,通常会给缓存数据设置一个过期时间。当系统接收到用户请求时,首先会访问缓存。如果缓…...
如何在VSCode中免费使用DeepSeek R1:本地大模型编程助手全攻略
目录 一、DeepSeek R1为何值得开发者关注? 1.1 开源的推理王者 1.2 性能实测对比 二、三步搭建本地AI编程环境 2.1 硬件准备指南 2.2 三大部署方案详解 方案一:LM Studio(新手友好) 方案二:Ollama(Docker玩家首选) 方案三:Jan(跨平台利器) 2.3 常见报错解决…...
ECCV2022 | LGV | LGV:利用大几何邻域提升对抗样本的可迁移性
LGV: Boosting Adversarial Example Transferability from Large Geometric Vicinity 摘要-Abstract引言-Introduction实验设置-Experimental SettingsLGV: 源于大几何邻域的迁移性-LGV: Transferability from Large Geometric Vicinity研究LGV特性:损失几何的重要性…...
Git 查看修改记录 二
Git 查看修改记录 二 续接 Git 查看一个文件的修改记录 一 一、修改 A.txt 修改 A.txt number6执行命令 git add . git commit -a -m "修改 number6" # git commit -a -m "修改 number6" 执行 输出如下 # $ git commit -a -m "修改 number6"…...
麒麟操作系统-rabbitmq二进制安装
1、通过官网下载https://www.rabbitmq.com/ 官网网址:https://www.rabbitmq.com 首先下载erlang-23.3.4.11-1.el7.x86_64.rpm,其次下载rabbitmq-server-3.10.0-1.el7.noarch.rpm 2、安装erlang yum install -y erlang-23.3.4.11-1.el7.x86_64.rpm 3、…...
说说平衡树的基本实现,与红黑树的区别是什么
说说平衡树的基本实现,与红黑树的区别是什么 平衡树是一种能够在插入、删除和查找操作中保持平衡的二叉搜索树。其目的是确保树的高度在一定范围内,防止出现极端情况(如链表化),以便提高操作效率。常见的平衡树有 AVL …...
uniapp实现首行首列冻结效果
uniapp首行首列冻结 <template><view class"height800 flex-column absolute bgc-withe"><!-- 第一行 --><view class"flex diy-header"><view class"box">时间</view><scroll-view id"1" ena…...
MySQL单表存多大的数据量比较合适
前言 经常使用MySQL数据库的小伙伴都知道,当单表数据量达到一定的规模以后,查询性能就会显著降低。因此,当单表数据量过大时,我们往往要考虑进行分库分表。那么如何计算单表存储多大的数据量合适?当单表数据达到多大的…...
uniapp 使用 鸿蒙开源字体
uniapp vue3 使用 鸿蒙开源字体 我的需求是全局使用鸿蒙字体。 所以: 0. 首先下载鸿蒙字体: 鸿蒙资源 下载后解压,发现里面有几个文件夹: 字体名称说明Sans默认的鸿蒙字体,支持基本的多语言字符(包括字…...
SiliconCloud 支持deepseek,送2000w token
SiliconCloud SiliconCloud 邀请奖励持续进行,2000 万 Tokens 送不停! 邀请好友赚 2000 万 Tokens:每成功邀请一位新用户通过手机号码注册,您将获得 2000 万 Tokens;注册即送 2000 万 Tokens:受邀好友作为…...
从零开始设计一个完整的网站:HTML、CSS、PHP、MySQL 和 JavaScript 实战教程
前言 本文将从实战角度出发,带你一步步设计一个完整的网站。我们将从 静态网页 开始,然后加入 动态功能(使用 PHP),连接 数据库,最后加入 JavaScript 实现交互功能。通过这个教程,你将掌握一个…...
【Python深入浅出㊸】解锁Python3中的TensorFlow:开启深度学习之旅
目录 一、TensorFlow 简介1.1 定义与背景1.2 特点 二、Python 3 与 TensorFlow 的关系2.1 版本对应2.2 为何选择 Python 3 三、安装 TensorFlow3.1 安装步骤3.2 验证安装 四、TensorFlow 基本概念与使用方法4.1 计算图(Graph)4.2 会话(Sessio…...
CMakeLists使用
1.预定义宏 宏 功能 PROJECT_SOURCE_DIR 使用cmake命令后紧跟的目录,一般是工程的根目录 PROJECT_BINARY_DIR 执行cmake命令的目录 CMAKE_CURRENT_SOURCE_DIR 当前处理的CMakeLists.txt所在的路径…...
P7201 [COCI 2019/2020 #1] Džumbus
题目背景 Marin 是一个心地善良的人,因此他将为他的 N 个朋友组织 Q 次宴会。宴会上唯一的饮料被称为 džumbus。 每位朋友对这种饮料的需求量是已知的。在这些朋友中,有 M 组朋友。每一组中的两位在同时满足他们各自的需求量后,将开始互相核对自己对往届 COCI 题目的答案…...
网络性能测试工具ipref
文章目录 一、ipref的介绍二、iperf安装配置三、iperf使用四、iperf常见故障处理 一、ipref的介绍 ipref是一种常用的网络性能测试工具,用于评估网络带宽、延迟和吞吐量等性能指标。它通过在客户端和服务器之间发送数据流来测量网络的性能,可以帮助管理…...
C# Dictionary的实现原理
在 C# 中,Dictionary<TKey, TValue> 是一个基于哈希表(Hash Table)实现的键值对集合。它提供了高效的插入、删除和查找操作,平均时间复杂度接近 O(1)。下面是 Dictionary 的核心实现原理: 1. Dictionary 的核心数…...
在项目中操作 MySQL
在现代Web开发中,Node.js因其非阻塞I/O模型和高效的性能成为了构建后端服务的热门选择之一。与此同时,MySQL作为最流行的关系型数据库管理系统之一,凭借其稳定性、可靠性和易用性,在数据存储方面扮演着重要角色。本文将详细介绍如…...
第6章 6.4 ASP.NET Core Web API各种技术及选择
6.4.1 控制器父类用哪个 6.2小节和6.3小节所演示的ASP.NET Core Web API 的控制器类都继承自ControllerBase,而6.1中MVC的控制器继承自Controller,Controller又继承自ControllerBase。 所以,一般情况下,编写的WebAPI控制器类继承…...
DeepSeek本地化部署【window下安装】【linux下安装】
一、window 本地安装指导 1.1、下载window安装包 https://ollama.com/download/OllamaSetup.exe 1.2、点击下载好的安装包进行安装 检测安装是否成功: C:\Users\admin>ollama -v ollama version is 0.5.7有上面的输出,则证明已经安装成功。 配置…...
字玩FontPlayer开发笔记14 Vue3实现多边形工具
目录 字玩FontPlayer开发笔记14 Vue3实现多边形工具笔记整体流程临时变量多边形组件数据结构初始化多边形工具mousedown事件mousemove事件监听mouseup事件渲染控件将多边形转换为平滑的钢笔路径 字玩FontPlayer开发笔记14 Vue3实现多边形工具 字玩FontPlayer是笔者开源的一款字…...
kkFileView二开之pdf转图片接口
kkFileView二开之Pdf转图片接口 1 kkFileView源码下载及编译2 Pdf转图片接口2.1 背景2.2 分析2.2 接口开发2.2.1 编写Pdf转图片方法2.2.2 编写转换接口 2.3 接口测试2.3.1 Pdf文件准备2.3.2 pdf2Image 3 部署 1 kkFileView源码下载及编译 前文 【kkFileView二开之源码编译及部…...
达梦tpcc压测
造数 在这个日志输出中,主要执行了一系列数据库操作,涵盖了数据库信息检查、表的创建与数据加载、索引的添加、数据验证等步骤。具体分析如下: 数据库信息检查: 查询了数据库的版本、实例名称、日志文件大小、字符集等信息。 删…...
计算机毕业设计PySpark+hive招聘推荐系统 职位用户画像推荐系统 招聘数据分析 招聘爬虫 数据仓库 Django Vue.js Hadoop
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
DeepSeek正重构人形机器人和具身大模型赛道!
中国人工智能公司DeepSeek(深度求索)以“低成本、高效率、强开放”的研发范式横空出世,火遍并震撼全球科技圈;DeepSeek展现出来的核心竞争力,除了低成本及推理能力,更重要的是开源模型能力追赶上了最新的闭…...
第1章 信息化发展(一)
1.1信息与信息化 1.1.1信息基础 1.信息的定义 信息是物质、能量及其属性的标示的集合,是确定性的增加。它以物质介质为载体,传递和反映世界各种事物存在方式、运动状态等的表征。信息不是物质也不是能量,它以一种普遍形式,表达…...
面试经典150题——字典树
文章目录 1、实现 Trie (前缀树)1.1 题目链接1.2 题目描述1.3 解题代码1.4 解题思路 2、添加与搜索单词 - 数据结构设计2.1 题目链接2.2 题目描述2.3 解题代码2.4 解题思路 3、单词搜索 II3.1 题目链接3.2 题目描述3.3 解题代码3.4 解题思路 对于字典树而言,之前做过…...
【前端 DevOps】GitHub Actions 与 GitLab CI 实战:实现前端项目的自动化测试与部署
网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...
SQLMesh系列教程-3:SQLMesh模型属性详解
SQLMesh 的 MODEL 提供了丰富的属性,用于定义模型的行为、存储、调度、依赖关系等。通过合理配置这些属性,可以构建高效、可维护的数据管道。在 SQLMesh 中,MODEL 是定义数据模型的核心结构,初学SQLMesh,定义模型看到属…...
【Maven】多module项目优雅的实现pom依赖管理
【Maven】多module项目优雅的实现pom依赖管理 【一】方案设计原则【二】项目结构示例【三】实现思路【1】可能的问题点:【2】解决方案的思路:【3】需要注意的地方:【4】可能的错误: 【四】实现案例【1】父POM设计(pare…...
【数字】异步FIFO面试的几个小问题与跨时钟域时序约束
入门数字设计的时候,跨时钟域的数据处理是绕不开的课题,特别是多比特数据跨时钟域时,都会采用异步FIFO的方法。 异步FIFO中涉及较多的考点这里记录几个以供大家参考。 1. 异步FIFO的空满判断分别在哪个域? 根据异步FIFO的结构&…...
云原生时代的开发利器
云原生时代的开发工具集之中,至少应有这样一种利器:基于微服务架构的低代码开发平台,同时与业界标准的云原生技术支撑设施能够完全协同和融合。低代码开发平台的构建不仅仅是采用微服务开发框架,更加重要的是符合当前主流的中台和…...
利用IDEA将Java.class文件反编译为Java文件:原理、实践与深度解析
文章目录 引言:当.class文件遇到源代码缺失第一章:反编译技术基础认知1.1 Java编译执行原理1.2 反编译的本质1.3 法律与道德边界 第二章:IDEA内置反编译工具详解2.1 环境准备2.2 三步完成基础反编译2.3 高级反编译技巧2.3.1 调试模式反编译2.…...
C++ Primer 参数传递
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
2.7 静态方法/构造函数Mock
静态方法/构造函数Mock 在单元测试中,静态方法和构造函数的Mock是相对复杂的需求,因为Mockito的核心设计基于对象实例的模拟。然而,通过扩展工具或特定技巧,可以实现对这些场景的处理。本章详解两种主流方案:PowerMoc…...
注册Gmail如何跳过手机验证环节?
很多小伙伴在注册Gmail的时候都会遇到一个难题:手机号码验证,有可能包括了“手机号无法验证” “国内手机号验证失败” “收不到验证码”等等问题,但 根据真实案例,还有部分人则是“幸运地”没有手机号验证环节,那么今…...
【算法专场】哈希表
目录 前言 哈希表 1. 两数之和 - 力扣(LeetCode) 算法分析 算法代码 面试题 01.02. 判定是否互为字符重排 编辑算法分析 算法代码 217. 存在重复元素 算法分析 算法代码 219. 存在重复元素 II 算法分析 算法代码 解法二 算法代码 算法…...
5、pod 详解 (kubernetes)
pod 详解 (kubernetes) Pod 的基础概念pause 容器Pod 的分类与创建自主式 Pod控制器管理的 Pod静态 Pod Pod容器的分类基础容器(infrastructure container)初始化容器(initcontainers)应用容器(…...
二叉树详解:Java实现与应用
在计算机科学中,数据结构是构建高效算法的基石,而二叉树作为一种基础且重要的树形结构,在诸多领域都有着广泛应用,如数据库索引、文件系统、编译器设计等。本文将从基础概念入手,带你逐步深入理解二叉树,并…...
GPT和BERT
笔记来源: Transformer、GPT、BERT,预训练语言模型的前世今生(目录) - B站-水论文的程序猿 - 博客园 ShusenWang的个人空间-ShusenWang个人主页-哔哩哔哩视频(RNN模型与NLP应用) 一、GPT 1.1 GPT 模型的…...
【工业安全】-CVE-2024-30891- Tenda AC18路由器 命令注入漏洞
1.漏洞描述 2.漏洞复现 2.1 qemu-user 模拟: 2.2 qemu-system模拟: 3.漏洞分析 4.poc代码: 1.漏洞描述 漏洞编号:CVE-2024-30891 漏洞名称:Tenda AC18 命令注入 威胁等级:高危 漏洞详情:Ten…...
如何从0开始将vscode源码编译、运行、打包桌面APP
** 网上关于此的内容很少,今天第二次的完整运行了,按照下文的顺序走不会出什么问题。最重要的就是环境的安装,否则极其容易报错,请参考我的依赖版本以及文末附上的vscode官方指南 ** 第一步:克隆 VSCode 源码 首先…...
登录弹窗效果
1,要求 点击登录按钮,弹出登录窗口 提示1:登录窗口 display:none 隐藏状态; 提示2:登录按钮点击后,触发事件,修改 display:block 显示状态 提示3:登录窗口中点击关闭按钮࿰…...
wps或office的word接入豆包API(VBA版本)
直接上代码,由于时间匆忙,以后写个详细的教程 #If VBA7 ThenPrivate Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As…...
深入浅出 Python Logging:从基础到进阶日志管理
在 Python 开发过程中,日志(Logging)是不可或缺的调试和监控工具。合理的日志管理不仅能帮助开发者快速定位问题,还能提供丰富的数据支持,让应用更具可观测性。本文将带你全面了解 Python logging 模块,涵盖…...
系统巡检脚本分享:守护服务器的“健康卫士”
在日常的运维工作中,系统巡检是一项至关重要的任务。它可以帮助我们及时发现服务器的潜在问题,确保系统的稳定运行。今天,我想和大家分享一个实用的系统巡检脚本,它能够帮助我们快速、全面地检查服务器的健康状况。 一、为什么需…...
【Elasticsearch】运行时字段(Runtime Fields)索引时定义运行时字段
在 Elasticsearch 中,运行时字段(Runtime Fields)是一种在查询时动态计算的字段,而不是在索引时预先存储的字段。运行时字段为数据处理提供了极大的灵活性,尤其是在处理结构不固定的日志数据或需要动态生成字段值的场景…...
C++从入门到实战(四)C++引用与inline,nullptr
C从入门到实战(四)C引用与inline,nullptr 前言一、C 引用(一)什么是引用(二)引用的特点(三)引用作为函数参数(四)引用作为函数返回值(…...