网页五子棋——通用模块

目录

项目创建

通用功能模块

错误码

自定义异常类

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);}
}

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

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

相关文章

【工具】在idea运行go后端

场景&#xff1a;从gitee仓库下载一个go语言前后端分离项目&#xff0c;想跑通前后端 ---------------------------------------------------------------------------------------------------------------------- 后端 1.下载插件 在idea的setting里面输入go&#xff0c;…

通达信如何导出以往的分时数据

1当天分时数据的导出 以梦网科技为例&#xff0c;在分笔交易上面右键&#xff0c;选择“放大”&#xff0c;放大后选择“选项”&#xff0c;选择“数据导出”&#xff0c;弹出界面中修改路径与文件名即可。 2以往数据的导出 以梦网科技为例&#xff0c;今天是2025年2月14号…

【面试题系列】Java 多线程面试题深度解析

本文涉及Java 多线程面试题&#xff0c;从基础到高级&#xff0c;希望对你有所帮助&#xff01; 一、基础概念类 1. 请简述 Java 中线程的几种状态及其转换条件 题目分析&#xff1a;这是多线程基础中的基础&#xff0c;考查对线程生命周期的理解&#xff0c;在多线程编程中&…

Java Virtual Machine(JVM)

JVM跨平台原理 跨平台&#xff1a;一次编译&#xff0c;到处运行 本质&#xff1a;不同操作系统上运行的JVM不一样&#xff0c;只需要把java程序编译成一份字节码文件&#xff0c;JVM执行不同的字节码文件。 Java是高级语言&#xff0c;提前编译一下&#xff08;变成字节码文件…

duckdb导出Excel和导出CSV速度测试

运行duckdb数据库 D:>duckdb v1.2.0 5f5512b827 Enter “.help” for usage hints. Connected to a transient in-memory database. Use “.open FILENAME” to reopen on a persistent database. 生成模拟数据&#xff0c;10个列&#xff0c;100万行数据&#xff1b; --…

TCP/IP参考模型和网络协议

由于国防部担心他们一些重要的主机、路由器和互联网关可能会突然崩溃&#xff0c;所以网络必须实现的另一目标是网络不受子网硬件损失的影响&#xff0c;已经建立的会话不会被取消&#xff0c;而且整个体系结构必须相当灵活。 TCP/IP是一组用于实现网络互连的通信协议。Interne…

uniapp商场之订单模块【订单列表】

文章目录 前言一、准备静态结构(分包)二、Tabs滑动切换1.Tabs文字渲染2.点文字高亮切换3.swiper滑动切换三、Tabs页面跳转高亮四、订单列表渲染1.封装列表组件2.订单状态父传子3.封装请求API4.准备请求参数5.初始化调用6.页面渲染五、订单支付1.页面条件渲染2.事件绑定前言 …

【教程】MySQL数据库学习笔记(七)——多表操作(持续更新)

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【MySQL数据库学习】系列文章 第一章 《认识与环境搭建》 第二章 《数据类型》 第三章 《数据定义语言DDL》 第四章 《数据操…

Mysql数据库

一.数据定义语言DDL 一.概述 DDL用于定义和管理数据库的结构 DDL关键字&#xff1a;1.CREATE; 2.ALTER; 3.DROP 二.SQL命名规定和规范 1.标识符命名规则 2.标识符命名规范 三.库管理 1. CREATE DATABASE 数据库名; 2. CREATE DATABASE IF NOT EXISTS 数据库名; 3. CREATE…

C++,STL容器适配器,priority_queue:优先队列深入解析

文章目录 一、容器概览与核心特性核心特性速览二、底层实现原理1. 二叉堆结构2. 容器适配器架构三、核心操作详解1. 容器初始化2. 元素操作接口3. 自定义优先队列四、实战应用场景1. 任务调度系统2. 合并K个有序链表五、性能优化策略1. 底层容器选择2. 批量建堆优化六、注意事项…

django上传文件

1、settings.py配置 # 静态文件配置 STATIC_URL /static/ STATICFILES_DIRS [BASE_DIR /static, ]上传文件 # 定义一个视图函数&#xff0c;该函数接收一个 request 参数 from django.shortcuts import render # 必备引入 import json from django.views.decorators.http i…

mapbox 从入门到精通 - 目录

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;mapbox 从入门到精通 文章目录 一、&#x1f340;总目录1.1 ☘️ mapbox基础1.2 ☘️…

【Qt】:概述(下载安装、认识 QT Creator)

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Qt 目录 一&#xff1a;&#x1f525; 介绍 &#x1f98b; 什么是 QT&#x1f98b; QT 发展史&#x1f98b; Qt版本&#x1f98b; QT 优点 一&#xff1a;&#x1f525; 搭建Qt开发环境 &#x1f9…

设置mysql的主从复制模式

mysql设置主从复制模式似乎很容易&#xff0c;关键在于1&#xff09;主库启用二进制日志&#xff0c;2&#xff09;从库将主库设为主库。另外&#xff0c;主从复制&#xff0c;复制些什么&#xff1f;从我现在获得的还很少的经验来看&#xff0c;复制的内容有表&#xff0c;用户…

halo发布文章的插件问题分析

前言 在准备发文到 halo 系统的时候提示错误如下&#xff0c;全是乱码 尝试将 halo 插件卸载后&#xff0c;再将插件目录下的文件全部删除 插件目录在 C:\Users\Administrator\.vscode\extensions\halo-dev.halo-1.3.0 然后再重新安装插件&#xff0c;在进行初始化的时候依然…

Spring Data Neo4j

文章目录 Spring Data Neo4j简介Neo4j-OGM与SDN的区别 开发体验版本说明项目地址项目结构创建项目配置连接信息激活事务管理器创建实体类Movie类Person类ActedIn关系类 创建Dao层service层测试案例CRUD TestPersonService TestActedIn Test 执行结果查询 Spring Data Neo4j简介…

Java发展史

JavaEE的由来 语言的诞生 Java的前身是Oak语言&#xff0c;其目的是搞嵌入式开发开发智能面包机 叮~~~&#x1f35e;&#x1f35e;&#x1f35e; 产品以失败告终 巅峰 网景公司需要网景浏览器打开网页&#xff0c;Oak->Java&#xff0c;进行前端开发&#xff08;相关技…

怎么让DeepSeek自动化写作文案

在数字化时代&#xff0c;内容创作已成为企业争夺用户注意力的核心竞争力。面对海量信息需求&#xff0c;企业往往面临内容创作效率低下、质量参差不齐、周期长等问题。如何用技术手段解决这些痛点&#xff0c;成为企业迫切需要破解的难题。今天&#xff0c;我们将以DeepSeek为…

Mysql之主从复制

目录 1.概述 2.工作原理 3.综合案例 3.1前期准备 3.2主库配置 3.3从库配置 3.4常见问题 3.4.1主从同步出现一下错误&#xff1a;Slave_IO_Running: No 3.4.1主从同步出现一下错误&#xff1a;Slave_IO_Running: Connecting? 3.5数据测试 1.概述 MySQL的主从复制&am…

从无序到有序:上北智信通过深度数据分析改善会议室资源配置

当前企业普遍面临会议室资源管理难题&#xff0c;预约机制不完善和临时会议多导致资源调度不合理&#xff0c;既有空置又有过度拥挤现象。 针对上述问题&#xff0c;上北智信采用了专业数据分析手段&#xff0c;巧妙融合楼层平面图、环形图、折线图和柱形图等多种可视化工具&a…