卓越之旅:在优秀案例中精进,编织技术梦想

本文最后更新于:5 小时前

不知道少了什么感觉,没有以前快乐。

写在前面

2024 年 7 月 12 日

为什么会突然想到写这样一篇博客呢?我简单反省过这半年来的学习规划,确实很长时间没有更新过专精编程技术的博客了。

在今年这个最关键的时间节点,我很清楚自己最需要做什么。

在今年上半年有过的唯一一段工作经历,让我越发清醒地意识到:在持续备战秋招的忙碌生活中,我必须要找到自己真正喜欢并愿意长期付之以时间的爱好。

最近很喜欢研究象棋,也在尝试了解学习视频剪辑的艺术,更多的是通过读书,写作来记录生活,陶冶情操。

那段工作经历让我真正意识到,工作只是生存的一部分,上班之余的时间才算是真正的生活。

所以我更希望能够在工作之余的闲暇时间,做点什么来充实自己的业余生活。

我发觉到长期处于烦闷无聊的工作中,我对编程学习的兴趣在逐渐消退了,我需要重新汲取外部优质资源。

站在巨人的肩膀上,开启我的编程精进之路。

项目

仿网易云音乐

🍖 推荐阅读:

网易云音乐 (163.com)

Node.js — Node.js, the difference between development and production (nodejs.org)

项目启动

2024 年 7 月 12 日

前端项目跑起来:

当在命令行中遇到 'vue-cli-service' 不是内部或外部命令,也不是可运行的程序或批处理文件 这个错误时,这通常意味着你的系统中没有正确安装 Vue CLI 或者其可执行文件 vue-cli-service 没有被添加到系统的 PATH 环境变量中。以下是一些解决这个问题的步骤:

image-20240712170550777

  1. 确认 Vue CLI 是否已安装

首先,你需要确认 Vue CLI 是否已经安装在你的机器上。打开命令行工具,输入以下命令来检查 Vue CLI 是否安装以及其版本:

1
2
3
bash复制代码

vue --version

如果系统提示 vue 命令找不到,那么你需要安装 Vue CLI。

  1. 安装 Vue CLI

如果 Vue CLI 没有安装,你可以通过 npm(Node.js 的包管理器)来安装它。首先,确保你已经安装了 Node.js 和 npm。然后,在命令行中运行以下命令来全局安装 Vue CLI:

1
2
3
bash复制代码

npm install -g @vue/cli

或者使用 yarn(如果你更倾向于使用 yarn):

1
2
3
bash复制代码

yarn global add @vue/cli
  1. 尝试再次运行你的项目

在完成上述步骤后,回到你的 Vue 项目目录,并尝试再次运行:

1
2
3
bash复制代码

vue-cli-service serve

4.要是还是不行,就直接执行:

1
npm install

本项目后端依赖于这个开源的网易云音乐 API 接口项目,请自行下载并运行:NeteaseCloudMusicApi

后端启动

2024 年 7 月 21 日

本项目后端依赖于这个开源的网易云音乐 API 接口项目,请自行下载并运行:

NeteaseCloudMusicApi

image-20240721134317108

这个错误提示 CERT_HAS_EXPIRED 表示你尝试连接到 npm 注册表时使用的 SSL 证书已经过期。这通常是因为你的 npm 客户端配置使用了过时的注册表 URL 或者你的系统日期和时间设置不正确。以下是一些解决这个问题的步骤:

  1. 检查系统日期和时间
    确保你的计算机的系统日期和时间设置是正确的。错误的日期和时间设置可能导致 SSL 证书验证失败。

  2. 检查 npm 配置
    运行 npm config list 来查看当前的 npm 配置,特别是 registry 的值。它应该指向 https://registry.npmjs.org/。如果指向的是 http 而非 https,或者是一个其他非官方镜像,请考虑修改它。

    你可以使用以下命令来设置 npm 的默认注册表地址:

    1
    2
    3
    bash复制代码

    npm config set registry https://registry.npmjs.org/
  3. 清除 npm 缓存
    有时候清除 npm 缓存可以解决奇怪的安装问题。你可以使用以下命令来清除缓存:

    1
    2
    3
    bash复制代码

    npm cache clean --force
  4. 检查网络设置
    如果你在公司或学校网络环境中,可能存在网络代理或防火墙设置阻止了 https 连接的正确验证。你可以尝试暂时关闭这些设置或使用其他网络环境来查看问题是否仍然存在。

  5. 更新 npm 和 Node.js
    确保你的 npm 和 Node.js 都是最新版本。旧版本的 npm 可能不支持 TLS 1.2 或更高版本。你可以通过运行以下命令来更新 npm:

    1
    2
    3
    bash复制代码

    npm install -g npm

    如果需要更新 Node.js,你可以从 Node.js 官网 下载最新版本。

  6. 检查代理和 SSL 证书
    如果你在使用代理或 SSL 证书,请确保它们是最新的,并且正确配置在你的系统上。

  7. 尝试使用 VPN
    有时网络问题可能由地理位置或 ISP 限制引起。尝试使用 VPN 连接到其他网络,看看是否可以解决问题。

再次执行,又出现这个问题:

image-2024072113500477

1
`ERR_SOCKET_TIMEOUT` 错误表明 npm 在尝试从 npm 注册表下载包时,由于网络问题导致连接超时。这通常与网络连接质量、代理设置、防火墙规则或 npm 服务器的响应速度有关。以下是一些解决这个问题的步骤:

如果你在中国大陆或其他地区,使用 npm 官方注册表可能受到网络延迟或限制的影响。你可以考虑使用 npm 镜像,如淘宝的 npm 镜像(cnpm):

1
2
3
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 然后使用 cnpm 代替 npm
cnpm install

我尝试安装 cnpm,结果有报错:

image-20240721135453761

遇到 CERT_HAS_EXPIRED 错误通常意味着你尝试连接的服务器使用的 SSL 证书已经过期。然而,在这个情况下,你尝试访问的是淘宝的 npm 镜像(https://registry.npm.taobao.org),这是一个被广泛使用的、应该保持证书有效的镜像。

这个问题可能由以下几个原因引起:

  1. 系统时间设置错误:检查你的计算机的系统时间是否正确。错误的系统时间会导致 SSL 证书验证失败,因为证书的有效期是基于时间的。
  2. 网络中间人攻击(MITM):虽然不太可能,但你的网络可能被配置为拦截 SSL/TLS 连接,并使用自己的证书。这通常发生在公司网络或受限制的网络环境中。
  3. 本地 SSL/TLS 证书存储问题:你的系统可能无法正确访问或验证 SSL 证书链。
  4. npm 配置问题:尽管你已经检查了 proxy 配置,但还有其他与 SSL 相关的配置可能需要检查,如 strict-ssl

为了解决这个问题,你可以尝试以下步骤:

  • 检查系统时间:确保你的系统时间是准确的。

  • 使用命令行工具检查 SSL 证书:你可以使用如 openssl 的命令行工具来检查 https://registry.npm.taobao.org 的 SSL 证书是否有效。例如:

    1
    2
    3
    bash复制代码

    openssl s_client -connect registry.npm.taobao.org:443

    查看输出中的证书信息,特别是有效期部分。

  • 暂时禁用 SSL 验证(仅作为测试,不推荐长期使用):
    你可以通过设置 strict-sslfalse 来暂时禁用 npm 的 SSL 验证。但请注意,这会使你的连接容易受到中间人攻击。

    1
    2
    3
    4
    npm config set strict-ssl false
    npm install -g cnpm --registry=https://registry.npm.taobao.org
    # 记得之后将其设置回 true
    npm config set strict-ssl true
  • 清理 npm 缓存
    虽然这不太可能是证书问题的直接解决方案,但清理缓存有时可以解决一些奇怪的问题。

    1
    2
    3
    bash复制代码

    npm cache clean --force
  • 使用其他网络:尝试连接到其他网络(如家庭网络或移动热点),以查看问题是否仍然存在。

  • 更新 npm 和 Node.js:确保你的 npm 和 Node.js 都是最新版本。

  • 联系淘宝 npm 镜像的支持:如果以上步骤都不能解决问题,可能需要联系淘宝 npm 镜像的支持团队,询问他们是否有关于证书过期的已知问题。

请注意,禁用 SSL 验证(strict-ssl=false)应该只作为最后的手段,并且仅在你完全信任你的网络环境时使用。在生产环境中,始终应该保持 SSL 验证启用。

执行成功!

image-20240721140507470

执行以下命令,启动后台:

1
node app.js

image-20240721142332268

启动前台页面:

image-20240721142357687

访问,项目效果如下:

image-20240721142531038

image-20240721142503392

image-20240721142511135

仿 B 站项目

项目启动

2024 年 7 月 21 日

了解整体代码结构,熟悉数据库库表和字段,修改数据库配置。

暂时不做 Elasticsearch 和 阿里云 OSS 对象存储的配置。

xxxxxxxxxx     4.0.0            com.memory.api        memory-api        0.0.1-SNAPSHOT        ../pom.xml    ​    com.memory.client    memory-client    0.0.1-SNAPSHOT​                        com.memory.common            memory-common            0.0.1-SNAPSHOT                            com.belerweb            pinyin4j            2.5.1                            com.memory            memory-client-spring-boot-starter            0.0.1            ​                                        org.springframework.boot                spring-boot-maven-plugin                                                            repackage                                                    repackage                                                                                    ​xml

👆 这是 Category 表没有默认主键,添加上即可:

1
2
3
4
5
6
7
8
9
10
11
12
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Category {
@TableId(type = IdType.AUTO)
private String mcId;
private String scId;
private String mcName;
private String scName;
private String descr;
private String rcmTag;
}

image-20240721192005290

ES 配置问题,直接注销掉 ElasticsearchConfig 配置,以及 ESUtils 自动注入。

OSS 配置问题,同样的,只不过引用的地方比较多,暂时都注释掉相关代码。

当然,可以简单配置自己本地的 Elasticsearch 和 阿里云 OSS ,现在为了简便就直接注释掉部分代码,先把项目跑起来再说。

后端直接启动 BackendApplication 即可。

前端更容易了,执行 npm install 安装依赖无误后,直接执行 vue-cli-service serve 启动项目:

image-20240721193910677

至此,项目启动成功,效果如下:

image-20240721193959515

image-20240721194005561

配置更改

2024 年 7 月 27 日

这天一直在抽空学习 Vue 基础,今晚也总算抽出时间来观摩观摩这个项目。

修改了 Redis 和 Elasticsearch 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
redis:
database: 4
host: localhost
port: 6379
password: Dw990831
jedis:
pool:
min-idle: 10
max-idle: 10
max-active: 100
max-wait: -1
timeout: 5000
1
2
3
4
5
6
# Elasticsearch
elasticsearch:
host: localhost
port: 9200
username: root
password: 123456

image-20240727235753087

这个问题是连接本地 Redis 客户端失败了:

image-20240728000254042

这样问题虽然没解决,但是起码注册流程跑通了,登陆还有问题,归根结底还是 Jedis 数据库连接至配置问题,这部分内容明天学习。

2024 年 8 月 21 日

image-20240821233613716

今天晚上回来分别把 Redis 和 Elasticsearch 在本地配置完善并启动后,成功实现了视频上传功能,视频已经能正确上传至阿里云存储桶中。

前后台用户注册登录也令人相当满意,视频审核也测试完成,就是上传视频的封面显示有些问题,而且目前不支持在线浏览视频。

待解决。

在线聊天

2024 年 10 月 4 日

端口监听,连接管理,发送消息,接收消息,消息存储,消息状态(已读,未读);

聊天列表,窗口状态(在线,离开);

实时通信

2025 年 2 月 28 日

IM即时通讯的实现方式_即时聊天实现-CSDN博客

2024 年 10 月 4 日

假期第四天,总算步入正轨了。

上午学习了仿 B 站项目的基于 Netty 的在线聊天功能,涉及到连接管理,消息管理,窗口管理等核心功能,对在线聊天实现有了更多新的想法。

下午会继续学习 WebSocket 实现实时通信,今天就要把这块儿内容搞定,最好写出 Demo 代码长期巩固记忆,日后在实践中运用。

2024 年 10 月 5 日

OkHttp系列一、使用OkHttp进行网络请求的4个步骤-CSDN博客

OkhttpClient的使用-CSDN博客

WebSocket 入门:简易聊天室大家好,我是前端西瓜哥,今天我们用 WebSocket 来实现一个简单的聊天室。 W - 掘金 (juejin.cn)

Java 项目中的 WebSocket 实现这种方式需要 tomcat 7.x,JEE7 的支持。 这种方式需要 spr - 掘金 (juejin.cn)

服务端

服务端完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package com.memory.simplewebsocket.server;

import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
* ClassName: TomcatWebsocketServer
* Package: com.memory.simplewebsocket.server
* Description:
*
* @Author Memory
* @Create 2024/10/5 10:11
* @Version 1.0
*/

@Component
@ServerEndpoint("/chat/{userId}")
public class TomcatWebsocketServer {
// 管理连接
private static Map<Long, Session> clients = new HashMap<>();
// 日志打印
private Logger logger = LoggerFactory.getLogger(ServerEndpoint.class);
// 用户
private Long userId;

/**
* 开启连接, 触发
*
* @param session 会话
* @param userId 用户
*/
@OnOpen
public void onOpen(Session session, @PathParam("userId") Long userId) {
this.userId = userId;
// 存储用户和对应会话
clients.put(userId, session);
logger.info(String.format("用户 %d 已上线,新的连接 ------------------> %s", this.userId, session.getId()));
}

/**
* 收到消息, 触发
*
* @param message 消息
* @param session 会话
*/
@OnMessage
public void onMessage(String message, Session session) {
logger.info(String.format("收到来自 %d 的消息 ------------------> %s", userId, message));
// 向全体在线成员推送这条消息
sendMessageFromOneToAll(message);
}

/**
* 关闭连接, 触发
*
* @param session 会话
*/
@OnClose
public void onClose(Session session) {
clients.remove(session);
logger.info(String.format("连接关闭 ------------------> %s", session.getId()));
}

/**
* 连接错误, 触发
*
* @param session 会话
* @param throwable 异常
*/
@OnError
public void onError(Session session, Throwable throwable) {
logger.info(String.format("连接错误 ------------------> %s", session.getId()));
throwable.printStackTrace();
}

/**
* 广播消息
*
* @param message 消息
*/
public void sendMessageFromOneToAll(String message) {
clients.forEach((userId, session) -> {
try {
session.getBasicRemote().sendText(String.format("广播来自 %d 的消息 ------------------> %s%n", this.userId, message));
} catch (IOException e) {
e.printStackTrace();
}
});
}
}

客户端

客户端完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.memory.simplewebsocket.listener;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;

import java.util.Scanner;


/**
* ClassName: TomcatWebsocketListener
* Package: com.memory.simplewebsocket.listener
* Description:
*
* @Author Memory
* @Create 2024/10/5 10:20
* @Version 1.0
*/

public class ChatClient1 extends WebSocketListener {
private static final String SERVER_URL = "ws://localhost:8080/chat/1";

public static void main(String[] args) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(SERVER_URL).build();
WebSocket webSocket = client.newWebSocket(request, new ChatClient1());

Scanner scanner = new Scanner(System.in);
System.out.println("请输入消息:");

while (true) {
String message = scanner.nextLine();

if (message.equals("exit")) {
webSocket.close(1000, "Client is closing the connection");
break;
}
webSocket.send(message);
}
}

@Override
public void onOpen(WebSocket webSocket, okhttp3.Response response) {
System.out.println("连接已打开");
}

@Override
public void onMessage(WebSocket webSocket, String text) {
System.out.println("收到消息: " + text);
}

@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
System.out.println("连接已关闭: " + code + " - " + reason);
}

@Override
public void onFailure(WebSocket webSocket, Throwable t, okhttp3.Response response) {
System.out.println("连接失败: " + t.getMessage());
}
}

依赖导入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<dependencies>
<!--spring-boot-starter-web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring-boot-starter-websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!--spring-boot-starter-test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--okhttp-->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
</dependencies>

我使用的 SpringBoot 版本是 3.2.10,这里的 okhttp 版本也要是最新的 4.12.0,否则客户端启动会报错:

image-20241005105327273

这就是版本不兼容了,修改 okhttp 依赖版本即可:

image-20241005104021109

image-20241005105839804

编写 Websocket 配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.memory.simplewebsocket.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
* @author yuanyiwen
* @create 2019-12-03 18:38
* @description
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

启动服务端,

1
2
3
4
5
spring:
application:
name: simple-websocket
server:
port: 8080

image-20241005135826514

基于Java 的 WebSocket 服务器端实现,它使用了Jakarta WebSocket API,这里指定了 WebSocket 服务器端点的路径:

1
2
3
4
5
6
7
8
9
10
11
12
@Component
@ServerEndpoint("/chat/{userId}")
public class TomcatWebsocketServer {
// 管理连接
private static Map<Long, Session> clients = new HashMap<>();
// 日志打印
private Logger logger = LoggerFactory.getLogger(ServerEndpoint.class);
// 用户
private Long userId;

...................................
}

服务端启动后,监听本机 8080 端口,等待客户端连接:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 开启连接, 触发
*
* @param session 会话
* @param userId 用户
*/
@OnOpen
public void onOpen(Session session, @PathParam("userId") Long userId) {
this.userId = userId;
// 存储用户和对应会话
clients.put(userId, session);
logger.info(String.format("用户 %d 已上线,新的连接 ------------------> %s", this.userId, session.getId()));
}

我们编写了两个客户端类,模拟两个用户在线连接到服务器进行通信:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* ClassName: TomcatWebsocketListener
* Package: com.memory.simplewebsocket.listener
* Description:
*
* @Author Memory
* @Create 2024/10/5 10:20
* @Version 1.0
*/

public class ChatClient1 extends WebSocketListener {
private static final String SERVER_URL = "ws://localhost:8080/chat/1";

public static void main(String[] args) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(SERVER_URL).build();
WebSocket webSocket = client.newWebSocket(request, new ChatClient1());

Scanner scanner = new Scanner(System.in);
System.out.println("请输入消息:");

while (true) {
String message = scanner.nextLine();

if (message.equals("exit")) {
webSocket.close(1000, "Client is closing the connection");
break;
}
webSocket.send(message);
}
}

......................................................
}

image-20241005140705618

image-20241005140714226

用户上线后发送消息,显然广播成功了,都能收到对方发来的消息,再看看服务端这边:

image-20241005140909624

显然服务端能正常管理登录用户和对应会话资源,并处理消息广播,让所有在线用户都能收到消息

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 收到消息, 触发
*
* @param message 消息
* @param session 会话
*/
@OnMessage
public void onMessage(String message, Session session) {
logger.info(String.format("收到来自 %d 的消息 ------------------> %s", userId, message));
// 向全体在线成员推送这条消息
sendMessageFromOneToAll(message);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 广播消息
*
* @param message 消息
*/
public void sendMessageFromOneToAll(String message) {
clients.forEach((userId, session) -> {
try {
session.getBasicRemote().sendText(String.format("广播来自 %d 的消息 ------------------> %s%n", this.userId, message));
} catch (IOException e) {
e.printStackTrace();
}
});
}

2024 年 10 月 5 日

再实现两个网页版客户端,交流通信会更加直观。

两个客户端源码基本相同,就这一套:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>在线用户二号</title>
</head>
<body>
<div id="chat">
</div>
<input type="text" id="messageInput" placeholder="Type your message">
<button onclick="sendMessage()">Send</button>
<script>
const socket = new WebSocket('ws://localhost:8080/chat/2');

socket.onopen = (event) => {
console.log('WebSocket connection opened:', event);
};

socket.onmessage = (event) => {
const messageDiv = document.getElementById('chat');
const messageParagraph = document.createElement('p');
messageParagraph.textContent = event.data;
messageDiv.appendChild(messageParagraph);
};

socket.onclose = (event) => {
console.log('WebSocket connection closed:', event);
};

function sendMessage() {
const messageInput = document.getElementById('messageInput');
const message = messageInput.value;
socket.send(message);
messageInput.value = '';
}
</script>
</body>
</html>

这里重新设置下服务端广播逻辑,只广播当前非当前会话的消息,因为当前会话的消息就是自己的消息,不需要给自己广播,特殊处理:

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 收到消息, 触发
*
* @param message 消息
* @param session 会话
*/
@OnMessage
public void onMessage(String message, Session session) {
logger.info(String.format("收到来自 %d 的消息 ------------------> %s", userId, message));
// 向全体在线成员推送这条消息
sendMessageFromOneToAll(session, message);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 广播消息
*
* @param session 会话
* @param message 消息
*/
public void sendMessageFromOneToAll(Session session, String message) {
clients.forEach((userId, client) -> {
try {
if (client != session) {
client.getBasicRemote().sendText(String.format("广播来自 %d 的消息 ------------------> %s%n", this.userId, message));
} else {
client.getBasicRemote().sendText(String.format("自己发送的消息 ------------------> %s%n", message));
}
} catch (IOException e) {
e.printStackTrace();
}
});
}

就这样,我们实现了两个在线用户的通信交流,相当有趣,这也是时隔一年多以来再次系统地研究如何实现实时通信:

image-20241005143136271

image-20241005143131814

很好玩啊,总算亲手实践了 Websocket 实现实时通信。

windows 脚本编程

2024 年 7 月 13 日

image-20240713075227778

image-20240713075309570

毕设小项目

2024 年 7 月 21 日

今天尝试跑几个 Spring + Vue 项目,看看能不能成功运行。

MemorySearch 忆搜阁

2024年8月8日

今天早上刷知乎,看到了这样一段有意义的话,原文我已经记不大清楚,大致意思是这样的:

我面试过很多求职者,现在的IT行业求职的人普遍太水了,只要你稍微努努力都能甩开身边人一大截。

像我以前面试过的那些人,问的那些简单的八股文都很难回答上来,计算机专业最基本的科学素养都没有。

没什么可问的就盘问项目吧,可很多人也是支支吾吾说不清楚,不论是个人项目还是工作中参与到的企业项目,开发过程都跟自己没关系一样好像。

我来教你怎么把项目说清楚,面试官不管从哪个角度问都能回答得滴水不漏:

你整体回顾一遍项目,分别从三个角度来写这个项目是做什么用的,里面涉及到了哪些技术亮点或难点,你又是怎么解决的。

写这个的目的不是为了再巩固一遍如何分析这个项目所用到的技术栈,完全不需要这样细致入微的描述。

只需要从宏观角度上简洁明了的介绍这个项目到底是怎么回事就行,不管别人怎么问,你都能从容不迫面不改色地聊项目,这样在面试中会很加分。

那么,开始吧,我已经完全过了一遍这个项目了,开始动手写一篇文章。

2024 年 8 月 8 日

这个项目是一个基于 Spring Boot + Elastic Stack 技术栈 + Vue.js聚合搜索中台。它不仅是一个强大的搜索引擎,更是一个内容丰富的社区平台。

什么是聚合搜索中台,它最核心的功能就是给使用者提供了丰富的搜索搜索体验。我们经常逛浏览器,打开任何一个搜索引擎,比如百度必应谷歌,在搜索框中查找资料检索数据很方便,体验很好。

所以我也想动手实现这样一个搜索中台,不需要实现很多花哨的操作。像平时做那些简单的后台管理系统项目时,也有实现过简单的搜索功能,根据某个字段的 id 或者描述,写最简单的 SQL 语句加上简单的条件判断,就实现简单的数据查询。

但这样的搜索功能是远远不够的,我注意到了 Elasticsearch,了解到了 Elastic Stack 技术栈,这样的工具很适合用来实现在海量数据中作检索和分析,借此机会也能真正实践运用 Elastic Stack 技术栈。

我连接到了 Elastic Stack 技术栈中的很多有意思的东西:ES 的安装,DSL 查询语句(布尔查询,聚合查询,复合查询等),下载了 Kibana ,在 dash Board 处能清晰地写 DSL 语句。Elasticseach 是一个文档型数据库,ES 和 MySQL 之间经常会有比较。我学习了如何插入索引,更新索引,新增文档数据,作简单的布尔查询。除此之外还有分词器的安装和使用,让我更清晰地理解了 ES 构建索引和基于倒排索引查询文档的底层原理。

我最关心的还是两点:如何使用 Elasticseach 实现高级的查询效果呢,我学习了关键词语高亮,搜索词条建议,热门话题分析等 DSL 语句的编写,用很多的 Demo 语句实践了这些丰富的查询功能。

ElastidSearch 中的数据都要从数据库 MySQL 中同步过来,所以我掌握了 Logstash 数据同步管道的相关配置,学会了如何使用 Logstash 监听本地 MySQL 变更的数据,并同步指定的字段到 Elasticsearch 中。比如说我要实现诗词的关键词语高亮,搜索词条建议和热门话题分析等功能,我会选择同步 MySQL 数据库中诗词数据对应的几个字段,同步这些字段的数据到 Elasticseach 中。

可说的太多了吧,我怎么感觉这种方式不太靠谱,因为写完这段文字之后我都不想再回头看一遍。。

除了简历上提到的:使用 Spring AOP 切面编程实现权限校验和全局请求拦截,配置定时任务抓取外源数据并解析到本地数据库,深入学习 Elastic Stack 技术栈,掌握倒排索引,分词机制,查询 DSL,实现关键词语高亮,搜索词条建议,热门话题分析等功能,运用多种设计模式简化编码提高效率,自主搭建 Logstash 数据同步管道同步数据,使用 CompletableFuture 异步编程减少批量插入数据的等待时间。

还有:限流,Redis 实现热门搜索统计以及缓存性能优化,互动创作平台等功能。

Github 优质项目

2024 年 9 月 21 日

变化挺大。这讯飞星火还更新了嘛,

image-20240921194602183

掘金有个大模型帖子站点,挺不错。

Electron 小白入门手册——跨端桌面应用开发的前世今生简史今天我们就从原生桌面开发、QT、NW、Electron、 - 掘金 (juejin.cn)

疯狂地涉猎了桌面开发,移动端开发等领域,圆满了。

优秀的开源项目 - Java陈序员 (chencoding.top)

AI 图书管理

2024 年 9 月 24 日

GPT智能图书管理系统后台Vue2-SpringBoot2

GPT智能图书管理系统前台Vue2-SpringBoot2

image-20240923092639180

image-20240923093021291

image-20240923093036696

image-20240923093101909

image-20240923093110935

这个项目还是曹老板上网扒下来的,我一看就知道是整合星球内部项目的,做的相当完善,学习了。

2024 年 9 月 25 日

书接上回,今天总算完成了秋招面试中的第二场流程面试 - 深圳捷顺科技一面,期望后续会有消息吧。

下午闲来无事,拉下来跑跑项目学习下,了解认识程序员小白条,是个很有趣的人。

友情链接 | 小白条的个人博客 (luoye6.github.io)

看过了一遍 READE,md 文档,基本了解了整个项目的核心业务逻辑及其功能实现,一年多以来的 bug 跟踪及优化调整,基本掌握。

项目启动

后端启动完成,建库建表完成,修改数据库连接配置,解决 yaml 配置文件中文编码问题,Swagger 接口文档功能正常。

image-20240925162612612

image-20240925162353269

前端项目启动完毕,基本理清页面目录结构,登录失败,奶奶的没有用户数据。

image-20240925163906760

加小白条好友位,要一下模拟数据资源。

Spring 模块

2024 年 10 月 4 日

spring: Spring 学习相关代码 (gitee.com)

image-20241004160256897

一个小时的时间里,从我收录的两个 Sprign Demo 代码专栏中,系统学习了一遍 SpringAOP 相关知识。

特别是切点表达式和通知的使用方法。

拦截器/过滤器

谈谈 Spring 的过滤器和拦截器我们在进行 Web 应用开发时,时常需要对请求进行拦截或处理,故 Spring 为我 - 掘金 (juejin.cn)

从使用教程、实现原理、差异对比全方面带你玩转业务系统中高频使用的过滤器与拦截器 (qq.com)

限流算法

RabbitMQ

Docker 部署

Guava

MyBatis-Plus

函数式编程

SpringMVC 扩展点

Stream 流

LocalDateTime

JWT

生产者/消费者

[05 有哪几种实现生产者消费者模式的方法? (lianglianglee.com)](https://learn.lianglianglee.com/专栏/Java 并发编程 78 讲-完/05 有哪几种实现生产者消费者模式的方法?.md)

商城

2025 年 1 月 10 日

再见Jenkins!一款更适合国人的自动化部署工具,贼带劲!在开发或生产环境中,我们有时候会上服务器器然后敲命令来部署项 - 掘金 (juejin.cn)

项目主页 | mall学习教程 (macrozheng.com)

macro (macrozheng) - Gitee.com

2025 年 1 月 14 日

下午四点多,启动后端四个模块:MallAdminApplicationMallDemoApplicationMallPortalAppliactionMallSearchApplication

修改下配置,MySQL,MongoDB,RabbitMQ,Elasticsearch。

2025 年 1 月 15 日

尝试起下前端页面。

1
npm install

项目主页 | mall学习教程 (macrozheng.com)

官网能看到双端预览效果,商城系统看多了挺头疼,我想想应该怎么改才好,要是能直接拿过来该多好。

不过自己当然也希望能学点新东西,捋清楚代码业务逻辑,写业务能更加熟练点,考虑面更广泛一些,也想能多了解下前端知识。

Vue 从来没有系统学习过,最近这些项目确实看得脑袋昏昏沉沉。

后台管理前端项目起来了。

1
Your application is running here: http://localhost:8090

image-20250115152933952

移动端还没,不过为什么移动端项目缺少 package.json 文件呢。

1
2
3
4
5
6
7
8
15:24:51.213 项目 mall-app-web 开始编译
15:24:51.926 正在下载编译工具,请稍后...
15:26:32.145 编译工具下载成功
15:26:33.673 请注意运行模式下,因日志输出、sourcemap以及未压缩源码等原因,性能和包体积,均不及发行模式。
15:26:33.844 正在编译中...
15:26:34.949 INFO Starting development server...
15:26:44.664 预编译器错误:代码使用了scss/sass语言,但未安装相应的编译器插件,正在从插件市场安装该插件:
15:26:44.665 https://ext.dcloud.net.cn/plugin?name=compile-node-sass at App.vue:1

image-20250115152825451

image-20250115153120208

2025 年 2 月 24 日

今天还不计划该写代码,先根据电影院网上订票系统设计与实现,对应精简下基于JavaWeb的汽配销售管理系统设计与实现。

项目官网:《mall学习教程》

毕业设计

2025 年 1 月 9 日

从现在开始逐步完善下毕设作品和论文撰写吧。

昨天下午起了项目,数据库建表 sql 语句文件都有,不过却缺少一个关键角色表,这些博主们老奸巨猾的操作。

新增角色表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
DROP TABLE IF EXISTS `auth`;
CREATE TABLE auth
(
auth_id INT(10) NOT NULL AUTO_INCREMENT COMMENT '授权ID,主键',
user_group VARCHAR(64) COMMENT '用户组',
mod_name VARCHAR(64) NOT NULL COMMENT '模块名',
table_name VARCHAR(64) NOT NULL COMMENT '表名',
page_title VARCHAR(255) NOT NULL COMMENT '页面标题',
path VARCHAR(255) NOT NULL COMMENT '路由路径',
position VARCHAR(32) NOT NULL COMMENT '位置',
mode VARCHAR(32) NOT NULL DEFAULT '_blank' COMMENT '跳转方式',
`add` TINYINT(3) NOT NULL DEFAULT 1 COMMENT '是否可增加',
`del` TINYINT(3) NOT NULL DEFAULT 1 COMMENT '是否可删除',
`set` TINYINT(3) NOT NULL DEFAULT 1 COMMENT '是否可修改',
`get` TINYINT(3) NOT NULL DEFAULT 1 COMMENT '是否可查看',
field_add TEXT COMMENT '添加字段',
field_set TEXT COMMENT '修改字段',
field_get TEXT COMMENT '查询字段',
table_nav_name VARCHAR(500) COMMENT '跨表导航名称',
table_nav VARCHAR(500) COMMENT '跨表导航',
`option` TEXT COMMENT '配置',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (auth_id)
) COMMENT ='用户权限管理表';

启动项目成功。

image-20250109151140651

image-20250109151124609

不过登录时控制台出现报错,是数据库字符集问题:

1
2
3
4
5
6
7
8
9
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b10b7cc]
2025-01-09 13:14:53.015 ERROR 8720 --- [io-5000-exec-10] o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [/api] threw exception [Request processing failed; nested exception is org.springframework.jdbc.UncategorizedSQLException:
### Error querying database. Cause: java.sql.SQLException: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='
### The error may exist in file [D:\Project\springboot汽车销售管理系统[编号:project97848]\project\target\classes\mapper\BaseMapper.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: select * from `auth` WHERE `user_group` = '管理员'
### Cause: java.sql.SQLException: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='
; uncategorized SQLException; SQL state [HY000]; error code [1267]; Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='; nested exception is java.sql.SQLException: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='] with root cause

就这张表特殊,改掉。

image-20250109151508690

不信了,这样竟然还不行。

1
2
3
4
5
drop database if exists `mall`;
create database if not exists `mall`
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
use `mall`;

起来啦,果然删除重新建库建表完美解决问题。

image-20250109161056301

2025 年 2 月 24 日

今天下午三点多简单过了一遍优秀毕业论文,六篇毕业论文五花八门的,最终选定这一篇作为参考:电影院网上订票系统设计与实现。

2025 年 2 月 26 日

基本搞清楚后台管理系统控制器逻辑。

2025 年 2 月 28 日

这张数据库表是关键。

1
pms_product_category

获取商品分类及其子分类。

1
2
3
4
/**
* 获取商品分类及其子分类
*/
List<PmsProductCategoryWithChildrenItem> listWithChildren();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<select id="selectByExample" parameterType="com.macro.mall.model.PmsBrandExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from pms_brand
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>

获取品牌列表。

1
2
3
4
5
6
7
8
9
10
@ApiOperation(value = "根据品牌名称分页获取品牌列表")
@RequestMapping(value = "/list", method = RequestMethod.GET)
@ResponseBody
public CommonResult<CommonPage<PmsBrand>> getList(@RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "showStatus", required = false) Integer showStatus,
@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize", defaultValue = "5") Integer pageSize) {
List<PmsBrand> brandList = brandService.listBrand(keyword, showStatus, pageNum, pageSize);
return CommonResult.success(CommonPage.restPage(brandList));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<select id="selectByExample" parameterType="com.macro.mall.model.PmsBrandExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from pms_brand
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>

品牌分类总表

品牌ID 品牌名称 所属分类 国家 成立时间 代表产品线 品牌档次
1 博世 (Bosch) 维修保养/车载电器 德国 1886 燃油泵、刹车片、车载电器 高端
2 曼牌 (MANN) 维修保养 德国 1941 滤清器 中高端
3 美孚 (Mobil) 维修保养 美国 1882 全合成润滑油 高端
4 布雷博 (Brembo) 改装件/维修保养 意大利 1961 刹车卡钳、刹车盘 高端
5 70迈 车载电器 中国 2016 行车记录仪 中端
6 盯盯拍 车载电器 中国 2013 智能行车记录仪 中端
7 飞利浦 (Philips) 车载电器 荷兰 1891 车载空气净化器 高端
8 牧宝 汽车装饰 中国 1994 真皮座椅套 中高端
9 尼罗河 汽车装饰 中国 2005 冰丝座椅套 经济型
10 HKS 改装件 日本 1973 涡轮套件、排气系统 高端
11 雅泛迪 (Advanti) 改装件 新加坡 1998 轻量化轮毂 中高端
12 特斯拉 (Tesla) 全新整车 美国 2003 新能源整车 高端
13 丰田 (Toyota) 全新整车 日本 1937 燃油/混动车型 中高端
14 五菱 全新整车 中国 1985 微型电动车 经济型
15 固特异 (Goodyear) 汽车装饰 美国 1898 防水脚垫 中端

库表设计

2025 年 2 月 28 日

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 产品分类 
-- auto-generated definition
create table pms_product_category
(
id bigint auto_increment
primary key,
parent_id bigint null comment '一级分类编号(0表示一级分类)',
name varchar(64) null comment '分类名称',
level int(1) null comment '分类级别(0 - 1级 1 - 2级)',
product_count int null comment '商品数量',
product_unit varchar(64) null comment '商品数量单位',
nav_status int(1) null comment '是否显示在导航栏:0->不显示;1->显示',
show_status int(1) null comment '显示状态:0->不显示;1->显示',
sort int null comment '排序字段',
icon varchar(255) null comment '图标',
keywords varchar(255) null comment '关键词',
description text null comment '分类描述'
)
comment '产品分类' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- 品牌表 
-- auto-generated definition
create table pms_brand
(
id bigint auto_increment comment 'id'
primary key,
name varchar(64) null comment '品牌名称',
first_letter varchar(8) null comment '首字母',
sort int null comment '排序字段',
factory_status int(1) null comment '是否为品牌制造商(0 - 不是 1-是)',
show_status int(1) null,
product_count int null comment '产品数量',
product_comment_count int null comment '产品评论数量',
logo varchar(255) null comment '品牌logo',
big_pic varchar(255) null comment '专区大图',
brand_story text null comment '品牌故事'
)
comment '品牌表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
-- 商品信息 
-- auto-generated definition
create table pms_product
(
id bigint auto_increment comment 'id'
primary key,
brand_id bigint null comment '品牌id',
product_category_id bigint null comment '商品分类',
feight_template_id bigint null,
product_attribute_category_id bigint null comment '属性分类id',
name varchar(200) not null comment '商品名称',
pic varchar(255) null comment '商品样图',
product_sn varchar(64) not null comment '货号',
delete_status int(1) null comment '删除状态(0 - 未删除;1 - 已删除)',
publish_status int(1) null comment '上架状态(0 - 下架;1 - 上架)',
new_status int(1) null comment '新品状态(0 - 不是新品;1 - 新品)',
recommand_status int(1) null comment '推荐状态(0 - 不推荐;1 - 推荐)',
verify_status int(1) null comment '审核状态:0->未审核;1->审核通过',
sort int null comment '排序',
sale int null comment '销量',
price decimal(10, 2) null comment '销售价格',
promotion_price decimal(10, 2) null comment '促销价格',
gift_growth int default 0 null comment '赠送的成长值',
gift_point int default 0 null comment '赠送的积分',
use_point_limit int null comment '限制使用的积分数',
sub_title varchar(255) null comment '副标题',
description text null comment '商品描述',
original_price decimal(10, 2) null comment '市场价',
stock int null comment '库存',
low_stock int null comment '库存预警值',
unit varchar(16) null comment '单位',
weight decimal(10, 2) null comment '商品重量,默认为克',
preview_status int(1) null comment '是否为预告商品:0->不是;1->是',
service_ids varchar(64) null comment '以逗号分割的产品服务:1->无忧退货;2->快速退款;3->免费包邮',
keywords varchar(255) null,
note varchar(255) null,
album_pics varchar(255) null comment '画册图片,连产品图片限制为5张,以逗号分割',
detail_title varchar(255) null,
detail_desc text null,
detail_html text null comment '产品详情网页内容',
detail_mobile_html text null comment '移动端网页详情',
promotion_start_time datetime null comment '促销开始时间',
promotion_end_time datetime null comment '促销结束时间',
promotion_per_limit int null comment '活动限购数量',
promotion_type int(1) null comment '促销类型:0->没有促销使用原价;1->使用促销价;2->使用会员价;3->使用阶梯价格;4->使用满减价格;5->限时购',
brand_name varchar(255) null comment '品牌名称',
product_category_name varchar(255) null comment '商品分类名称'
)
comment '商品信息' charset = utf8
row_format = DYNAMIC;

商品列表,商品分类,品牌列表,基本梳理完毕;商品属性,商品属性分类,商品属性值,待处理。

2025 年 3 月 5 日

完善系统流程图,接下来应该是代码开发环节。

表结构优先处理,十五张表应该是合适的,最多二十张表吧。

  • pms_*:商品模块相关表
  • oms_*:订单模块相关表
  • sms_*:营销模块相关表
  • ums_*:权限模块相关表
  • cms_*:内容模块相关表

商品模块相关表:

1
2
3
相册表,画册图片表,品牌表,商品评价表,商品评价回复表,运费模板表,商品会员价格表,
商品信息表,商品分类表,商品属性表,商品属性分类表,商品属性参数表,商品分类和商品属性关系表,
商品满减表,商品阶梯价格表,商品操作日志表,商品审核记录表,商品库存表,

品牌表,商品信息表,商品分类表,商品属性表,商品属性分类表,商品属性参数表,商品库存表,商品满减表,商品评价表,商品评价回复表。

订单模块相关表:

1
购物车表,公司收发货地址表,订单表,订单商品信息表,订单操作历史记录表,订单退货申请表,退货原因表,设置表,

购物车表,公司收发货地址表,订单表,订单退货申请表。

内容模块相关表:

1
2
3
4
帮助表,帮助分类表,用户举报表,
优选专区表,优选专区和产品关系表,
专题表,专题分类表,专题评论表,专题商品关系表,
话题表,话题分类表,话题评论表,

用户反馈表。

营销模块相关表:

1
2
3
优惠券表,优惠券领取使用记录表,优惠券和产品关系表,优惠券和产品分类关系表,
限时购表,限时购通知表,限时购与商品关系表,限时购场次表,
首页轮播广告表,首页推荐商品表,新鲜好物商品表,人气推荐商品表,首页推荐专题表,

优惠券表,优惠券领取使用表,首页轮播广告表,促销活动通知表。

权限模块相关表:

1
后台用户表,后台用户登录日志表,后台用户和权限关系表,后台用户和角色关系表,成长值变化历史记录表,积分变化历史记录表,积分消费设置表,会员表,会员登记表,会员登录记录表,用户和标签关系表,会员和商品分类关系表,会员收货地址表,会员积分成长规则表,会员统计信息表,用户标签表,会员任务表,后台菜单表,后台用户权限表,后台资源表,资源分类表,后台用户角色表,后台用户角色和菜单关系表,后台用户角色和权限关系表,后台用户角色资源关系表。

用户表,用户角色表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- 品牌表 
-- auto-generated definition
create table pms_brand
(
id bigint auto_increment comment 'id'
primary key,
name varchar(64) null comment '品牌名称',
first_letter varchar(8) null comment '首字母',
sort int null comment '排序字段',
factory_status int(1) null comment '是否为品牌制造商(0 - 不是 1-是)',
show_status int(1) null,
product_count int null comment '产品数量',
product_comment_count int null comment '产品评论数量',
logo varchar(255) null comment '品牌logo',
big_pic varchar(255) null comment '专区大图',
brand_story text null comment '品牌故事'
)
comment '品牌表' charset = utf8
row_format = DYNAMIC;

大概二十一张表。

2025 年 3 月 5 日

商品模块相关表:品牌表,商品信息表,商品分类表,商品属性表,商品属性分类表,商品属性值表,商品满减表,商品评价表,商品评价回复表。

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 品牌表 
create table pms_brand
(
id bigint auto_increment comment 'id'
primary key,
name varchar(64) null comment '品牌名称',
first_letter varchar(8) null comment '首字母',
product_count int null comment '产品数量',
logo varchar(255) null comment '品牌logo',
brand_story text null comment '品牌故事'
)
comment '品牌表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- 商品信息表 
create table pms_product
(
id bigint auto_increment comment 'id'
primary key,
name varchar(200) not null comment '商品名称',
description text null comment '商品描述',
brand_id bigint null comment '所属品牌',
product_category_id bigint null comment '所属分类',
product_attribute_category_id bigint null comment '所属属性分类',
pic varchar(255) null comment '商品样图',
publish_status int(1) null comment '上架状态(0 - 下架;1 - 上架)',
sale int null comment '销量',
price decimal(10, 2) null comment '销售价格',
promotion_price decimal(10, 2) null comment '促销价格',
promotion_type int(1) null comment '促销类型:0->使用原价;1->使用满减价格;2->使用促销价;4->限时购',
stock int null comment '库存',
low_stock int null comment '库存预警值',
weight decimal(10, 2) null comment '商品重量,默认为克',
)
comment '商品信息表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 商品分类表 
create table pms_product_category
(
id bigint auto_increment
primary key,
name varchar(64) null comment '分类名称',
description text null comment '描述',
parent_id bigint null comment '上级分类级别(0表示一级分类)',
level int(1) null comment '所属分类级别(0 - 1级 1 - 2级)',
product_count int null comment '商品数量',
product_unit varchar(64) null comment '商品数量单位',
icon varchar(255) null comment '图标'
)
comment '商品分类表 ' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
13
-- 商品属性表 
create table pms_product_attribute
(
id bigint auto_increment
primary key,
name varchar(64) null comment '属性名称',
product_attribute_category_id bigint null comment '所属分类',
select_type int(1) null comment '选择类型:0->唯一;1->单选;2->多选',
input_list varchar(255) null comment '可选列表,以逗号隔开',
type int(1) null comment '属性类型;0->规格;1->参数'
)
comment '商品属性参数表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
-- 商品属性分类表 
create table pms_product_attribute_category
(
id bigint auto_increment
primary key,
name varchar(64) null comment '属性分类名',
attribute_count int default 0 null comment '包含值数量'
)
comment '商品属性分类表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
-- 商品属性值表 
create table pms_product_attribute_value
(
id bigint auto_increment
primary key,
product_id bigint null comment '所属商品',
product_attribute_id bigint null comment '所属属性',
value varchar(64) null comment '参数值'
)
comment '商品属性值表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 商品评价表 
create table pms_comment
(
id bigint auto_increment
primary key,
product_id bigint null comment '所属商品',
member_id bigint null comment '所属用户',
content text null comment '评价内容',
pics varchar(1000) null comment '上传图片地址,以逗号隔开',
create_time datetime null comment '评价时间',
star int(3) null comment '评价星数:0->5',
collect_counnt int null comment '点赞数量',
read_count int null comment '阅读数量',
replay_count int null comment '回复数量'
)
comment '商品评价表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
-- 评价回复表 
create table pms_comment_replay
(
id bigint auto_increment
primary key,
comment_id bigint null comment '所属评论',
member_id varchar(255) null comment '所属用户',
content varchar(1000) null comment '回复内容',
create_time datetime null comment '回复时间'
)
comment '评价回复表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
-- 商品满减表(只针对同商品) 
create table pms_product_full_reduction
(
id bigint(11) auto_increment
primary key,
product_id bigint null comment '所属商品',
full_price decimal(10, 2) null comment '满减金额',
reduce_price decimal(10, 2) null comment '减少金额'
)
comment '商品满减表(只针对同商品)' charset = utf8
row_format = DYNAMIC;

订单模块相关表:购物车表,公司收发货地址表,订单表,订单退货申请表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 购物车表 
create table oms_cart_item
(
id bigint auto_increment
primary key comment 'id',
product_id bigint null comment '购买商品',
member_id bigint null comment '购买用户',
quantity int null comment '购买数量',
price decimal(10, 2) null comment '需付金额',
price_reduce decimal(10, 2) null comment '实付金额',
product_pic varchar(1000) null comment '商品主图',
create_date datetime null comment '创建时间',
modify_date datetime null comment '修改时间',
delete_status int(1) default 0 null comment '是否删除',
product_category_id bigint null comment '所属分类',
product_brand varchar(200) null comment '所属品牌',
product_attr_id varchar(500) null comment '所属商品属性'
)
comment '购物车表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-- 订单表
create table oms_order
(
id bigint auto_increment comment 'id'
primary key,
member_id bigint not null comment '下单用户',
payment_time datetime null comment '支付时间',
pay_amount decimal(10, 2) null comment '实支金额',
freight_amount decimal(10, 2) null comment '运费金额',
total_amount decimal(10, 2) null comment '订单总金额',
promotion_amount decimal(10, 2) null comment '促销优化金额(促销价、满减)',
coupon_amount decimal(10, 2) null comment '优惠券抵扣金额',
pay_type int(1) null comment '支付方式:0->未支付;1->支付宝;2->微信',
status int(1) null comment '订单状态:0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单',
receiver_name varchar(100) not null comment '收货人姓名',
receiver_phone varchar(32) not null comment '收货人电话',
note varchar(500) null comment '订单备注',
delivery_company varchar(64) null comment '物流公司(配送方式)',
delivery_sn varchar(64) null comment '物流单号',
receiver_detail_address varchar(200) null comment '收货详细地址',
confirm_status int(1) null comment '确认收货状态:0->未确认;1->已确认',
delivery_time datetime null comment '发货时间',
)
comment '订单表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- 退货申请 
create table oms_order_return_apply
(
id bigint auto_increment
primary key comment 'id',
order_id bigint null comment '订单id',
company_address_id bigint null comment '收货地址',
product_id bigint null comment '退货商品',
create_time datetime null comment '申请时间',
return_amount decimal(10, 2) null comment '退款金额',
return_name varchar(100) null comment '退货人姓名',
return_phone varchar(100) null comment '退货人电话',
status int(1) null comment '申请状态:0->待处理;1->退货中;2->已完成;3->已拒绝',
handle_time datetime null comment '处理时间',
product_count int null comment '退货数量',
reason varchar(200) null comment '退货原因',
proof_pics varchar(1000) null comment '凭证图片,以逗号隔开',
handle_note varchar(500) null comment '处理备注',
handle_man varchar(100) null comment '处理人员',
)
comment '退货申请' charset = utf8
row_format = DYNAMIC;

内容模块相关表:用户反馈表。

1
2
3
4
5
6
7
8
9
10
11
12
-- 用户反馈表 
create table cms_member_report
(
id bigint null comment 'id',
report_member_id bigint null comment '反馈人',
report_content varchar(100) null comment '反馈内容',
report_type int(1) null comment '反馈类型:0->商品信息;1->活动内容;2->用户评价',
report_status int(1) null comment '反馈状态:0->未处理;1->已处理',
handle_status int(1) null comment '处理结果:0->无效;1->有效;2->恶意',
)
comment '用户反馈表' charset = utf8
row_format = DYNAMIC

营销模块相关表:优惠券表,优惠券领取使用表,首页轮播广告表,促销活动通知表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 优惠券表 
create table sms_coupon
(
id bigint auto_increment
primary key comment 'id',
type int(1) null comment '所属类型;0->注册赠券;1->购物赠券;2->店铺赠券;3->全场赠券;',
name varchar(100) null comment '名称',
count int null comment '数量',
amount decimal(10, 2) null comment '金额',
per_limit int null comment '每人限领张数',
min_point decimal(10, 2) null comment '使用门槛;0表示无门槛',
start_time datetime null comment '有效时间',
end_time datetime null comment '失效时间',
note varchar(200) null comment '备注',
enable_time datetime null comment '可领取日期',
publish_count int null comment '发行数量',
receive_count int null comment '已领取数量',
)
comment '优惠券表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
13
-- 促销活动表
create table sms_flash_promotion
(
id bigint auto_increment
primary key comment 'id',
title varchar(200) null comment '活动名称',
start_date date null comment '开始日期',
end_date date null comment '结束日期',
status int(1) null comment '上下线状态',
create_time datetime null comment '创建时间'
)
comment '促销活动表' charset = utf8
row_format = DYNAMIC
1
2
3
4
5
6
7
8
9
10
11
12
13
-- 轮播广告表 
create table sms_home_advertise
(
id bigint auto_increment
primary key comment 'id',
name varchar(100) null comment '广告名称',
pic varchar(500) null comment '轮播图片',
start_time datetime null comment '开始时间',
end_time datetime null comment '结束时间',
status int(1) null comment '上下线状态:0->下线;1->上线',
)
comment '轮播广告表' charset = utf8
row_format = DYNAMIC;

权限模块相关表:后台用户表,注册用户表,用户角色表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 后台用户表 
create table ums_admin
(
id bigint auto_increment
primary key comment 'id'
user_name varchar(64) null comment '账号名',
password varchar(64) null comment '密码',
icon varchar(500) null comment '头像',
email varchar(100) null comment '邮箱',
note varchar(500) null comment '备注信息',
user_role int(1) null comment '用户角色',
create_time datetime null comment '创建时间',
login_time datetime null comment '最后登录时间',
status int(1) default 1 null comment '帐号启用状态:0->禁用;1->启用'
)
comment '后台用户表' charset = utf8
row_format = DYNAMIC
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- 注册用户表
create table ums_member
(
id bigint auto_increment
primary key comment 'id',
user_name varchar(64) null comment '用户名',
password varchar(64) null comment '密码',
nickname varchar(64) null comment '昵称',
user_role int(1) null comment '用户角色',
phone varchar(64) null comment '手机号码',
email varchar(100) null comment '邮箱',
status int(1) null comment '帐号启用状态:0->禁用;1->启用',
icon varchar(500) null comment '头像',
gender int(1) null comment '性别:0->未知;1->男;2->女',
birthday date null comment '生日',
city varchar(64) null comment '所在城市',
job varchar(100) null comment '职业',
personalized_signature varchar(200) null comment '个性签名',
create_time datetime null comment '注册时间'
)
comment '注册用户表' charset = utf8
row_format = DYNAMIC;
1
2
3
4
5
6
7
8
9
10
11
12
13
-- 用户角色表 
create table ums_role
(
id bigint auto_increment
primary key comment 'id',
name varchar(100) null comment '角色名称',
description varchar(500) null comment '角色描述',
count int null comment '包含用户数量',
create_time datetime null comment '创建时间',
status int(1) default 1 null comment '启用状态:0->禁用;1->启用',
)
comment '后台用户角色表' charset = utf8
row_format = DYNAMIC;

好极了,目前缩减至十九张表。

2025 年 3 月 6 日

历时两天,完成数据库概念设计和数据库逻辑设计。

功能结构

2025 年 3 月 3 日

项目主页 | mall学习教程 (macrozheng.com)

功能需求分析,前台功能和后台功能。

角色用例分析,管理员角色用例和普通用户角色用例。

系统功能结构设计,前台功能结构设计和后台功能结构设计。

系统流程分析,从注册登录,到检索选择自己想要的商品,完善收获地址信息下单后添加进购物车,最终支付订单的整个流程。

这块儿详细写两个流程分析,用户登录注册,以及购买商品的整个流程。

系统流程图,数据库设计,数据库概念设计和逻辑设计。

系统实现,后台登录模块和后台管理模块,前台登录模块和前台使用模块。

系统测试,网站登录测试,选购商品测试,支付下单测试。

基本就是以上几点内容。针对每一条再做细节优化和内容填充。


功能需求分析。

前台功能:首页智能推荐商品详情展示购物下单功能活动精准推送我的个人空间

后台功能:商品管理功能,订单管理功能,营销管理功能,权限管理功能和用户管理功能。

前台功能通俗版

  1. 首页猜你喜欢
    • 轮播大图推爆款 | 品牌直营专区 | 新人必买清单 | 根据浏览记录智能推荐
  2. 商品详情百科
    • 分类找货更方便 | 商品图文详情页(参数对比一目了然) | 秒杀/新品专属福利区
  3. 从购物车到付款
    • 加购商品随时改 | 自动计算优惠价 | 多支付方式一键下单 | 物流实时追踪
  4. 活动精准推送
    • 节日大促专题页(如618/双11) | 限时抢购倒计时 | 猜你喜欢个性化推荐
  5. 我的个人空间
    • 优惠券/收藏夹管理 | 收货地址簿 | 浏览足迹回溯 | 商品评价记录

角色用例分析。

管理员角色用例:商品管理,订单管理,促销管理,运营管理,权限管理,用户管理,内容管理,统计报表,财务管理。

普通用户角色用例:登录和注册,修改个人资料,查看促销活动,查看优惠券,浏览商品,浏览详情页,查看账户余额,添加购物车,多方式支付下单,查看我的订单。

系统功能结构设计。

系统前台功能:登录,注册,个人中心,首页门户,商品推荐,商品搜索,商品展示,购物车,订单流程,帮助中心,客户服务。

系统后台功能:商品管理,订单管理,促销管理,运营管理,权限管理,用户管理,内容管理,财务管理。

系统流程分析。

本系统涉及到的主要流程有:用户登录注册,浏览选购,选择规格加购,支付订单,收货评价。

登录注册流程:

用户下单流程:用户选择商品检查库存确认订单信息支付订单

本系统主要流程如下

  1. 注册/登录
    • 新用户手机号一键注册,老用户支持微信/账号密码登录
    • 后台支撑:用户权限管理、登录日志风控(防刷号)
  2. 浏览选购
    • 首页搜商品(关键词搜索/分类导航)、看详情页(参数对比/买家秀)
    • 后台支撑:商品分类管理、库存状态实时同步
  3. 选规格加购
    • 选择颜色/尺寸/套餐,加入购物车或直接购买
    • 后台支撑:SKU库存动态扣减、购物车有效期设置
  4. 支付订单
    • 合并购物车商品,选择优惠券抵扣,微信/支付宝/银行卡支付
    • 后台支撑:订单状态流转(待付款→已支付)、支付流水对账
  5. 收货评价
    • 查看物流轨迹,确认收货后发表带图评价
    • 后台支撑:物流接口对接、评价内容审核

用户购物下单流程

  1. 用户选择商品
    • 用户在商城浏览商品,根据喜好选择商品型号(如颜色、尺寸等)。
  2. 检查库存
    • 如果商品库存充足,用户可以加入购物车或立即购买;如果库存不足,则提示“库存不足,无法购买”。
  3. 确认订单信息
    • 用户点击“立即购买”后,进入订单确认页面,显示商品信息、总金额、优惠券抵扣及支付方式(如余额支付、微信支付等)。
  4. 支付订单
    • 用户点击“支付”后:
      • 若支付成功(余额充足或第三方支付成功),订单生成,库存扣减,用户收到订单成功通知;
      • 若支付失败(余额不足或支付超时),订单取消,返回支付页面重新操作。

系统流程图。

数据库设计,数据库概念设计和逻辑设计。

系统测试,网站登录测试,选购商品测试,下单支付测试。

剩下的这三块核心内容今天先暂时不做补充,补充前三章内容先。

【毕业设计】– 如何使用Visio画系统功能结构图_系统功能模块图怎么画-CSDN博客

毕业论文中的系统总体设计流程图如何画-百度经验 (baidu.com)

系统流程

2025 年 3 月 4 日

完成系统流程图。

系统实现

2025 年 3 月 7 日

项目主页 | mall学习教程 (macrozheng.com)

后台功能模块

后台登录模块:

后台管理模块:

前台功能模块

前台登录模块:

前台使用模块:

重学计划

疯狂 Java

2025 年 2 月 10 日

在 Linux 上搭建 Java 环境_linux安装java-CSDN博客

1
yum list | grep jdk
1
yum install java-1.8.0-openjdk-devel.x86_64
1
java -version

2025 年 3 月 15 日

Mybatis,AI接入,MySQL,微服务,消息队列,Dubbo,WebSocket,Vue,小程序。

其实最重要的还是夯实基础,再去到各个公司官网看看相关业务,有助于针对性学习。

【超详细】MyBatis详解-CSDN博客

MySQL实战45讲 (lianglianglee.com)

Vue 基础

2024 年 7 月 26 日

Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org)

Vue.js 基础理论实操 - itsOli 的专栏 - 掘金 (juejin.cn)

2025 年 1 月 16 日

早上第一件事,学学 Vue。

2025 年 2 月 11 日

Vue.js 安装_vue.js下载-CSDN博客

原生 JS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>前端一万小时-Hello World</title>
</head>
<body>
<div id="app"></div>

<script>
var dom = document.getElementById("app");
dom.innerHTML = "Hello World";
</script>
</body>
</html>

引入 Vue:

vue.js如何下载教程 • Worktile社区

快速上手 | Vue.js (vuejs.org)

1
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{content}}
<!-- 2️⃣-⑥:用 {{}} 包裹 content,写在 #app 这个 div 里。 -->
</div>

<script>
var app = new Vue({
// 2️⃣-②:创建一个 Vue 实例;

el: "#app", // 2️⃣-③:这个实例接收的第一个参数 el,稍后会详细讲解它,暂时不管;

data: {
// 2️⃣-④:接收的第二个参数 data,它指的是数据;

content: "hello world" /*
2️⃣-⑤:定义一个叫 content 的数据,内容是“hello world”,
与原生的作区分。
*/,
},
});
</script>
</body>
</html>

嘿,还搞不明白 Vue.js的下载了。

如何在官网外找到并下载Vue.js:CDN方法详解-CSDN博客

Vue.js 安装 | 菜鸟教程 (runoob.com)

vue源码如何下载 • Worktile社区

Node 体系

2024 年 9 月 23 日

Node.js 知识体系(一):基础概念、历史与应用场景Nodejs 的概念 Node.js 是一个基于 Chrome - 掘金 (juejin.cn)

2025 年 1 月 15 日

Github Actions 构建 Node.js 项目的 CICD 流水线本文介绍了 CI / CD 的概念, 主要是 - 掘金 (juejin.cn)

Node.js入门(1):安装和简介携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看 - 掘金 (juejin.cn)

桌面开发

2024 年 9 月 23 日

Electron 小白入门手册——跨端桌面应用开发的前世今生简史今天我们就从原生桌面开发、QT、NW、Electron、 - 掘金 (juejin.cn)

用 Electron 创建你的第一个应用程序:入门指南Electron 是一个强大的开源框架,可以帮助开发人员使用 we - 掘金 (juejin.cn)

2025 年 1 月 16 日

QT入门看这一篇就够了——超详细讲解(40000多字详细讲解,涵盖qt大量知识)-CSDN博客

安卓开发

2024 年 9 月 23 日

Flutter入门概览1-Flutter篇本系列文章共有三篇,计划分别从Flutter、Dart、工具三个方面介绍,快速 - 掘金 (juejin.cn)

Flutter完整开发实战详解(一、Dart语言和Flutter基础) | 掘金技术征文在如今的 Flutter 大潮下 - 掘金 (juejin.cn)

带你高效入门 Flutter本文面向 Flutter 初学者,旨在用易懂的方式带大家入门。除了 Flutter 代码,还 - 掘金 (juejin.cn)

CodeForge

2024 年 9 月 30 日

一周前的今天,也就是二十三号下午,心里第一次有了这个计划的雏形。

趁着这次长假,好好打磨下平日里没工夫钻研的技术,或者也可以称之为爱好、兴趣,不过这些都已经无所谓了。

我又有了两种新的想法:

简历投递,约面想法,求职。

持续精进,技术提升,兴趣。

首先是最近两个月一直在关注着的秋招,简历优化,网申投递,面试邀约,做不完的测评和笔试,遥遥无期的 offer……

刚来到这里的前两周周末里还回小马村那边,在家的时候就能静下心来好好优化简历,八月十七号那天晚上第一次做出了两页版简历。

从那天晚上开始,便进入了紧锣密鼓的简历网申投递中去,同时简历迭代的周期也越来越短。

八月二十六号,八月二十九号,九月六号,九月九号,九月十四号,九月十九号,九月二十一号,九月二十二号,九月二十九号……

最终的简历模板已经在昨天晚上定型,目前暂时还没有要继续迭代简历的打算,估计这是最终版,但这会儿谁又能真正说清楚呢。

随着简历迭代趋于完善,网申计划也趋于完善。

自中秋节后以来,每天都保持网申投递至少30份简历的节奏,更多的时候一天能投递80+份简历,这需要花费三四个小时左右的时间。

另外写了一篇文档提炼出网申阶段出现频率较高的填充内容,比如主修课程,校园经历,荣誉,兴趣爱好等,尽最大限度提高网申效率。

邮箱里陆陆续续收到了很多中大厂的测评和笔试邀请函,为了直观回顾秋招投递反馈日程,我设计了简要的 Excel 表格把这些记录下来。

这段时间里的测评和笔试倒是真不少,可邀约面试却根本没有,出了八月底的字节流程稍快一些,直到九月底才有水滴和捷顺科技约面。

约面很不顺利。

长达一个多月没有流程推进的时间里,我一直在实习僧,智联招聘和牛客直推上尝试沟通和邀约面试,为即将到来的秋招流程做足准备。

这方面我做得很漂亮,思路也确实正确。

我接到了更多的电话邀约,微信推送,邮箱链接,尽可能从更多的渠道获取面试资质,即便最终的结果一定是肯定的。

我决心要在这场秋招中拿下真正的入职 offer,尽管时间可能花费的比我想象中的还要久。

每周两到三个面试已经成为了家常便饭,在这样的环境下能约到面试本身就是件不容易的事情,我每次都能打起十二分的精神去应对。

从刚开始在等待中就惶恐不安,到后来面对面交流的从容不迫,我已经做到可以完全不惧任何面试情景了。

在这期间还特意总结了一篇面试文档,专门记录了面试流程中的各个环节表达要点,自我介绍,项目介绍,项目亮点分析这些。

当然,每场面试结束后都会快速回忆并产出一段面经要点,这些面经记录均已收录在我的真实面经文档中。

这就是我的网申阶段,这段生活确实有些麻木不仁和无可奈何,但无论如何网申还得继续,每多投出一份网申简历就多一分机会。

尽管目前已知的被收纳进人才库的企业,已经超过了五十家,剩下的都做过了测评和笔试后杳无音讯,我相信更多的都还在初筛流程中。

直到昨天晚上,我确乎认真考虑了一番,节后的求职阶段,在其他求职 APP 上也可以找找机会,机会还是挺多的。

有关求职的话题就暂且谈论到这里,后续如果还有更多突破性的进展,我倒是可以考虑在这里记录。

最近这段日子也确实在争分夺秒中考量之后的学习节奏,而不仅仅是应对即将到来的长假,更是为以后平稳的技术精进打下良好的基础。

不知道要学些什么,那当然不打紧,这都什么年代了网上什么都有,上稀土掘金胡乱看两小时就保证会有很多新奇想法。

我这里就不过多废话,直截了当地排列下最近或者说计划长期付诸的实践,也许能保质保量地贯彻下去:

1
1. AI 人工智能:这方面相对来讲比较轻松且有创造性,也是我最感兴趣的一部分,讯飞星火,ChatGPT,通义灵码,智能图书,智谱清言。
1
2. 技术攻关:这方面可能要花费的时间精力会比较多,我想要写一些 Demo 代码来加强巩固这方面的知识,最好能写成系列博客,像拦截器/限流器,限流算法,函数式编程,SpringMVC 扩展点,Stream 流,JWT 实践,WebSocket 实践,生产者消费者实现,消息队列,Guava,Mybatis-Plus 等等,后续有新的内容也会及时补充进来。
1
3. 博文阅读:以上技术攻关的要点,都是最近看到的技术博客提供的新思路,除了公众号进阶笔记,苏三说技术,小报童专栏这些,稀土掘金上最近也喜欢看首页热门文章,又会关注到很多优秀的专栏。
1
4. 项目实践:这里讲到的开源项目,比如 AI 智能图书管理,仿B站项目这样的,更多地想要在秋招备战阶段尽可能地巩固编码基础,切不可忘记手上功夫,不过就跟上面谈到的,首页热门文章也带给了我很多新想法,比如 Github 热点速递这些确实打开了我的思路。
1
5. 技术扩展:有哪些新的思路呢,我越发对桌面开发,Android 开发,游戏开发这些感兴趣了,百忙之中也会抽出时间来学习了解相关技术,权当作是消遣,Node.js,Vue.js,React.js,Electron,Tarui,Flutter,.Net,C# 等。
1
6. 小程序:这个单独拎出来作为一个栏目,是因为这方面以前也做过实操,这次区别于以上观望的态度,我更想做一些真正产品,学习了解小程序的部署上线,我觉得最近关注的那位大佬的专栏会帮助我实现这项愿望的。
1
7. 项目部署:这个可以说是重中之重,我不做过多强调,Linux 环境,Docker 部署,程序员鱼皮教学视频。
1
8. 博客优化:尽管没有新的博文,但壁纸还是要收集,乱序的博客内容也要稍作整理,还有七牛云老是欠费可不太好。

呐,简单的计划已经罗列出来,如此看来任务还是蛮多的,就看七天以后的造化了。

玩不会想到写这玩意儿竟会花费我一个半小时的时间,不过现在心里面确实明朗了不少,祝我顺利吧,假期里也要保持最佳状态。

不过也要注意休息啊,劳逸结合嘛,在最紧张的阶段也要允许自己枯萎几天。

祝假期愉快,愿前程景气,望仕途顺利。

鸿蒙

2025 年 1 月 15 日

创建和运行Hello World-快速开始-DevEco Studio - 华为HarmonyOS开发者 (huawei.com)

Uniapp

2025 年 1 月 15 日

自己开发的App如何上架,详细解读App上架操作流程-腾讯云开发者社区-腾讯云 (tencent.com)

uniapp开发App从开发到上架全过程-腾讯云开发者社区-腾讯云 (tencent.com)

uniapp开发APP从开发到上架全过程(一)-CSDN博客

uniapp开发App从开发到上架全过程(二)-真机调试_uniapp ios真机调试-CSDN博客

Docker

2024 年 12 月 19 日

Docker入门到实践 (一) docker简介与安装_docker与思政-CSDN博客

Docker入门到实践 (二) docker常用命令讲解_docker 入门到实践 (二) docker 常用指令解说-CSDN博客

2025 年 1 月 15 日

centos7安装Docker详细步骤(无坑版教程)-腾讯云开发者社区-腾讯云 (tencent.com)

windows10+VMWare+Centos7下docker的安装,验证与运行(超详细且持续更新) -配置啦-研发运维人员必备网站 (config.net.cn)

centos安装包下载_开源镜像站-阿里云 (aliyun.com)

windows10+VMWare+Centos7下docker的安装,验证与运行(超详细且持续更新) -配置啦-研发运维人员必备网站 (config.net.cn)

Docker 搭建 Minio 对象存储服务MinIO MinIO 是一款基于 Go 语言发开的高性能、分布式的对象存储 - 掘金 (juejin.cn)

手摸手教你使用 Docker 快速搭建 Gitlab 服务本文在 CentOS 虚拟机中使用 Docker 快速搭建了一 - 掘金 (juejin.cn)

上手Linux:安装 Git 的两种方式在 Linux 系统上安装软件有两种常用的方式。一种是下载源码 - 编译 - 安 - 掘金 (juejin.cn)

这篇挺全的:Springboot整合Minio全流程 - 编程导航 - 程序员编程学习交流社区 (codefather.cn)

2025 年 1 月 25 日

今天实践操作下 docker,安装 Docker。

安装

查看 CentOS 操作系统版本和 Linux 内核版本

1
cat /etc/redhat-release
1
uname -r

image-20250125193326081

可以看到 CentOS7 的操作系统为x86_64(64位),系统内核版本为3.10.0,没有问题。

卸载旧版本。

1
yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine

image-20250125193531866

安装docker所需的软件包

1
yum install -y yum-utils device-mapper-persistent-data lvm2

设置yum源为阿里云 (由于国外网站访问速度慢)

1
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

更新yum软件包索引

1
yum makecache fast

安装docker CE(社区版),Docker提供了两个版本:社区版(CE,免费) 和 企业版(EE,收费)

1
yum -y install docker-ce

Linux中yum、rpm、apt-get、wget的区别,yum、rpm、apt-get常用命令,CentOS、Ubuntu中安装wget_apt-get 和yum-CSDN博客

image-20250125194344413

检查版本,是否安装成功。

1
docker version

image-20250125194522470

2025 年 1 月 25 日

Docker入门到实践 (二) docker常用命令讲解_docker 入门到实践 (二) docker 常用指令解说-CSDN博客

2025 年 2 月 10 日

1
yum install -y yum-utils device-mapper-persistent-data lvm2
1
ping: mirrorlist.centos.org: Name or service not known

CentOS7 yum安装报错 “Could not resolve host: mirrorlist.centos.org; Name or service not known” 解决方法_ping: mirrorlist.centos.org: name or service not k-CSDN博客

1、从阿里云下载新的配置文件,两个命令可用,如果虚拟机还没安装wget工具,就使用curl

1
2
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

2、清理缓存

1
yum clean all

3、重新生成缓存

1
yum makecache

4、更新yum源包

1
yum -y update

结束,更换 yum 源成功。

不过这个步骤属实多余,直接按照上面 Doker 安装的命令执行下来,安装 Docker 是相当顺利的。

远程部署

2025 年 2 月 5 日

已经十多天没有学习了吗。

Docker为容器设置环境变量(在docker run命令中设置容器的环境变量、在Dockerfile文件中设置容器的环境变量、在docker-compose.yaml中设置容器的环境变量)_dockerfile设置环境变量-CSDN博客

java获取docker环境变量_mob649e8161738c的技术博客_51CTO博客

新建一个 Web 项目,尝试下 Docker 部署。

docker 部署 java 项目详解-CSDN博客

WAR包和JAR包的区别 - 林泽阿 - 博客园 (cnblogs.com)

IDEA+Docker远程部署Sprin - 编程导航 - 程序员编程学习交流社区 (codefather.cn)

1
2
3
4
5
6
7
8
# 基础镜像
FROM openjdk:8
# 复制主机jar包至镜像内,复制的目录需放置在 Dockerfile 文件同级目录下
ADD target/hello-0.0.1-SNAPSHOT.jar app.jar
# 容器启动执行命令
ENTRYPOINT ["java","-jar", "/app.jar" , "--spring.profiles.active=prod"]
# 对外暴露的端口号
EXPOSE 8080

Docker一键远程部署厚米匹配后端 - 编程导航 - 程序员编程学习交流社区 (codefather.cn)

1
Dw990831@

配置 Docker 一键部署:ssh 远程连接服务器,连接 Docker 守护进程,编写 Dockerfile 文件,配置远程部署。

ssh 远程连接服务器。

image-20250205102013411

连接 Docker 守护进程。

image-20250205103921071

编写 Dockerfile 文件。

1
2
3
4
5
6
7
8
# 基础镜像
FROM openjdk:8
# 复制主机jar包至镜像内,复制的目录需放置在 Dockerfile 文件同级目录下
ADD target/hello-0.0.1-SNAPSHOT.jar app.jar
# 容器启动执行命令
ENTRYPOINT ["java","-jar", "/app.jar"]
# 对外暴露的端口号
EXPOSE 8080

配置远程部署。

image-20250205103822292

怎么查看docker开放的端口通不通_mob64ca12d4a164的技术博客_51CTO博客

特么的,配置都完成了,就看最后一步能不能一键部署成功,结果好像是 Docker 连接失败了。

Docker镜像的创建方法_docker 创建镜像-CSDN博客

那就手动上传 jar 包和 Dockerfile 文件,先构建镜像再运行容器试试看。

学一学。

要构建一个Docker镜像,你需要确保你已经安装了Docker,并且你的Dockerfilehello-0.0.1-SNAPSHOT.jar文件在同一目录下。以下是如何使用Docker命令行工具来构建你的镜像的步骤:

  1. 打开命令行界面

    • 在Windows上,你可以使用PowerShell或命令提示符。
    • 在macOS或Linux上,打开你的终端。
  2. 导航到包含Dockerfile的目录
    使用cd命令导航到包含你的Dockerfilehello-0.0.1-SNAPSHOT.jar文件的目录。例如:

    1
    2
    3
    bash复制代码

    cd path/to/your/directory
  3. 构建Docker镜像
    使用docker build命令来构建你的镜像。你需要为你的镜像指定一个标签(tag),这通常包括一个名称和一个版本号。例如:

    1
    2
    3
    bash复制代码

    docker build -t hello-app:0.0.1 .

    这里的-t hello-app:0.0.1指定了镜像的名称为hello-app和版本号为0.0.1。最后的.表示Dockerfile位于当前目录。

  4. 验证镜像是否构建成功
    使用docker images命令来查看你的本地镜像列表,确认你的hello-app:0.0.1镜像已经成功构建。

    1
    2
    3
    bash复制代码

    docker images
  5. 运行Docker容器
    使用docker run命令来运行你的容器。例如:

    1
    2
    3
    bash复制代码

    docker run -d -p 8080:8080 hello-app:0.0.1

    这里的-d标志表示容器将在后台运行,-p 8080:8080将主机的8080端口映射到容器的8080端口。

  6. 验证容器是否正在运行
    使用docker ps命令来查看正在运行的容器列表。

    1
    2
    3
    bash复制代码

    docker ps
  7. 访问你的应用
    打开你的网页浏览器,访问http://localhost:8080,你应该能够看到你的Java应用正在运行。

试一试。

出问题了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker build -f Dockerfile -t hello 
ERROR: "docker buildx build" requires exactly 1 argument.
See 'docker buildx build --help'.

Usage: docker buildx build [OPTIONS] PATH | URL | -

Start a build
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker build -t hello-app .
[+] Building 30.1s (2/2) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 323B 0.0s
=> ERROR [internal] load metadata for docker.io/library/openjdk:8 30.0s
------
> [internal] load metadata for docker.io/library/openjdk:8:
------
Dockerfile:2
--------------------
1 | # 基础镜像
2 | >>> FROM openjdk:8
3 | # 复制主机jar包至镜像内,复制的目录需放置在 Dockerfile 文件同级目录下
4 | ADD target/hello-0.0.1-SNAPSHOT.jar app.jar
--------------------
ERROR: failed to solve: DeadlineExceeded: DeadlineExceeded: DeadlineExceeded: openjdk:8: failed to resolve source metadata for docker.io/library/openjdk:8: failed to do request: Head "https://registry-1.docker.io/v2/library/openjdk/manifests/8": dial tcp 198.44.185.131:443: i/o timeout

jar 包没有放在同级目录下啊。

算了,看来是基础镜像出问题了,吃完饭上来搞搞。

镜像源修改

docker hello world_docker 输出hello word-CSDN博客

1
docker pull hello-world
1
2
3
4
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker pull hello-world
Using default tag: latest
Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]#

Docker修改国内镜像源_docker更换国内镜像源-CSDN博客

这篇写得很详细了:docker切换国内镜像源_mob64ca12f10f72的技术博客_51CTO博客

使用 docker 命令行设置镜像源,不太好使。

1
sudo docker login --username=<你的用户名> registry.cn-hangzhou.aliyuncs.com

得直接修改 Docker 的 daemon 配置文件。

步骤详解

步骤 1: 备份 Docker 的原始配置文件。

在对 Docker 的配置文件进行修改之前,我们需要先备份原始配置文件,以便在出现问题时能够恢复。

备份原始的配置文件到指定位置

1
sudo cp /etc/docker/daemon.json /etc/docker/daemon.json.bak

代码解释:

  • sudo:以超级用户权限执行命令。

  • cp:复制文件的命令。

  • /etc/docker/daemon.json:Docker 的默认配置文件路径。

  • /etc/docker/daemon.json.bak:备份文件的路径。

步骤 2: 创建或编辑 Docker 的配置文件

确保 Docker 的配置文件存在,如果没有则需要创建一个新的。

检查配置文件是否存在

1
2
sudo mkdir -p /etc/docker/
sudo touch /etc/docker/daemon.json

代码解释:

  • mkdir -p /etc/docker/:创建 Docker 配置目录,如果路径中已存在部分目录则不会报错。

  • touch /etc/docker/daemon.json:创建 daemon.json 文件,如果已存在则更新其时间戳。

步骤 3: 修改镜像源为国内镜像

接下来,我们需要通过编辑 daemon.json 文件来添加国内的镜像源。这里以阿里云的 Docker 镜像为例。

开启编辑器(vi 或其它文本编辑器)

1
sudo vi /etc/docker/daemon.json

在打开的 daemon.json 文件中填写以下内容:

1
2
3
4
5
{
"registry-mirrors": [
"https://<your_ali_cdn>.mirror.aliyuncs.com"
]
}

代码解释:

  • registry-mirrors:这是配置镜像加速器的键,用于指定 Docker 镜像源的地址。

  • “https://.mirror.aliyuncs.com”:将 替换为你在阿里云中获得的加速器地址。你也可以选择其他的国内镜像源,如网易、腾讯等。

步骤 4: 重启 Docker 服务

完成镜像源的配置后,我们需要重启 Docker 服务使其生效。

重启 Docker 服务

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

代码解释:

  • systemctl daemon-reload:重新加载服务配置。

  • systemctl restart docker:重启 Docker 服务。

步骤 5: 验证镜像源是否修改成功

最后一步是验证配置是否成功。我们可以通过拉取一个镜像来检查。

测试拉取一个镜像(例如:hello-world)

1
docker pull hello-world

代码解释:

  • docker pull hello-world:从 Docker 镜像源拉取 hello-world 镜像,用于测试。

如果镜像能够快速拉取并成功完成,那么就表示你已成功切换至国内镜像源。

阿里云地域Region ID? 地域及其RegionID对照表?_陆陆科技 (llxxkj.cn)

649d1f91988cd.png

1
2
3
4
5
{
"registry-mirrors": [
"https://cn-beijing.mirror.aliyuncs.com"
]
}

漂亮,对照这张表修改配置文件内容,直接执行拉取镜像命令,成功了。

1
2
3
4
5
6
[root@iZ2ze4hnl6pls28qt4w1ttZ docker]# docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
Status: Downloaded newer image for he

那么跑一下这个镜像吧。

运行一个名为 hello-world 的镜像,容器名为 helloworld,将容器的 80 端口映射到主机的 8080 端口,并在后台运行:

1
docker run -d -p 8080:80 --name helloworld hello-world:latest

查看正在运行中的容器信息。

1
docker ps -a
1
2
3
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cb2146386e71 hello-world:latest "/hello" 3 minutes ago Exited (0) 3 minutes ago helloworld

删除镜像。

1
docekr remove helloworld

镜像源问题解决了,构建 Docker 镜像的报错问题还没有进展,检查下 Dockerfile 文件内容。

1
2
3
4
5
6
7
8
# 基础镜像
FROM openjdk:8
# 复制主机jar包至镜像内,复制的目录需放置在 Dockerfile 文件同级目录下
ADD target/hello-0.0.1-SNAPSHOT.jar app.jar
# 容器启动执行命令
ENTRYPOINT ["java","-jar", "/app.jar"]
# 对外暴露的端口号
EXPOSE 8080

5 个提升你 Dockerfile 水平 - 编程导航 - 程序员编程学习交流社区 (codefather.cn)

Dockerfile 有挺多技巧:

  1. 使用 alpine 的镜像,而不是默认的 linux 镜像,可以极大减小镜像体积,比如 node:18-alpine3.14 这种
  2. 使用多阶段构建,比如一个阶段来执行 build,一个阶段把文件复制过去,跑起服务来,最后只保留最后一个阶段的镜像。这样使镜像内只保留运行需要的文件以及 dependencies。
  3. 使用 ARG 增加构建灵活性,ARG 可以在 docker build 时通过 –build-arg xxx=yyy 传入,在 dockerfile 中生效,可以使构建过程更灵活。如果是想定义运行时可以访问的变量,可以通过 ENV 定义环境变量,值使用 ARG 传入。
  4. CMD 和 ENTRYPOINT 都可以指定容器跑起来之后运行的命令,CMD 可以被覆盖,而 ENTRYPOINT 不可以,两者结合使用可以实现参数默认值的功能。
  5. ADD 和 COPY 都可以复制文件到容器内,但是 ADD 处理 tar.gz 的时候,还会做一下解压。

Docker镜像构建知识:Dockerfile 命令详解-腾讯云开发者社区-腾讯云 (tencent.com)

1
2
3
4
5
6
7
8
# 基础镜像
FROM scratch
# 复制主机jar包至镜像内,复制的目录需放置在 Dockerfile 文件同级目录下
ADD hello-0.0.1-SNAPSHOT.jar app.jar
# 容器启动执行命令
ENTRYPOINT ["java","-jar", "/app.jar"]
# 对外暴露的端口号
EXPOSE 8080

构建成功了对吧。

1
2
3
4
5
6
7
8
9
10
11
12
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker build -t hello-app . 
[+] Building 0.4s (5/5) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 313B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.2s
=> => transferring context: 17.65MB 0.2s
=> [1/1] ADD hello-0.0.1-SNAPSHOT.jar app.jar 0.0s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:19baea50ee1023afb4c6926836a32e3816a315de477db0fcf3d164e25b1ed5b2

镜像运行失败了。

1
docker run -p 8080:8080 --name helloapp hello-app:latest
1
2
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker run -p 8080:8080 --name helloapp hello-app:latest
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "java": executable file not found in $PATH: unknown.

缺少 Java 环境。

停止容器,删除容器。

1
2
3
4
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eefe17b7f1e2 hello-app "java -jar /app.jar" 2 minutes ago Created 8080/tcp heuristic_jackson
da15a61a2596 hello-app:latest "java -jar /app.jar" 12 minutes ago Created 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp helloapp
1
2
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker remove eefe17b7f1e2
eefe17b7f1e2

删除镜像。

1
2
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker rmi 19baea50ee10
Untagged: hello-app:latest
1
2
3
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 3 years ago 13.3kB

重新构建镜像。

1
2
3
4
5
6
7
8
9
10
11
12
# 基础镜像
FROM scratch
# 作者信息
MAINTAINER memory
# 安装jdk
RUN apt-get update && apt-get install -y openjdk-8-jdk
# 复制主机jar包至镜像内,复制的目录需放置在 Dockerfile 文件同级目录下
ADD hello-0.0.1-SNAPSHOT.jar app.jar
# 容器启动执行命令
ENTRYPOINT ["java","-jar", "/app.jar"]
# 对外暴露的端口号
EXPOSE 8080

很显然这条命令又报错了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker build -t hello-app .
[+] Building 0.3s (4/5)
> [1/2] RUN apt-get update && apt-get install -y openjdk-8-jdk:
0.215 runc run failed: unable to start container process: exec: "/bin/sh": stat /bin/sh: no such file or directory
------
Dockerfile:6
--------------------
4 | MAINTAINER memory
5 | # 安装jdk
6 | >>> RUN apt-get update && apt-get install -y openjdk-8-jdk
7 | # 复制主机jar包至镜像内,复制的目录需放置在 Dockerfile 文件同级目录下
8 | ADD hello-0.0.1-SNAPSHOT.jar app.jar
--------------------
ERROR: failed to solve: process "/bin/sh -c apt-get update && apt-get install -y openjdk-8-jdk" did not complete successfully: exit code: 1

修改 Dockerfile 文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 使用 CentOS 基础镜像
FROM centos:latest
# 作者信息
MAINTAINER memory
# 安装必要的软件包
RUN yum install -y java-1.8.0-openjdk-devel
# 设置工作目录
WORKDIR /app
# 复制 JAR 文件到工作目录
COPY hello-0.0.1-SNAPSHOT.jar app.jar
# 容器启动执行命令
ENTRYPOINT ["java", "-jar", "app.jar"]
# 对外暴露的端口号
EXPOSE 8080

dockerfile安装java环境_mob64ca12f66e6c的技术博客_51CTO博客

docker 容器配置java环境_mob64ca12dd8bce的技术博客_51CTO博客

又忙活了一个多小时许可证后台管理系统,只要着手搞这玩意儿时间就过得可快了,这会儿都快五点钟,该下班了。

再试试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 使用 CentOS 基础镜像
FROM centos:latest
FROM openjdk:8-jdk-alpine
# 作者信息
MAINTAINER memory
# 配置java环境变量
ENV JAVA_HOME /opt/jdk/jdk1.8.0_412
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH $PATH:$JAVA_HOME/bin
# 设置工作目录
WORKDIR /app
# 复制 JAR 文件到工作目录
COPY hello-0.0.1-SNAPSHOT.jar app.jar
# 容器启动执行命令
#ENTRYPOINT ["java", "-jar", "app.jar"]
# 对外暴露的端口号
EXPOSE 8080

待解决问题:

1
unable to start container process: exec: "java": executable file not found in $PATH: unknown.

2025 年 2 月 6 日

exec failed: unable to start container process: exec: “ip“: executable file not found in $PATH_oci runtime exec failed: exec failed: unable to st-CSDN博客

问题报错:

1
OCI runtime exec failed: exec failed: unable to start container process: exec: "ip": executable file not found in $PATH: unknown

报错原因:因为该容器的镜像时精简版,内部缺少iproute2导致无法使用ip命令

解决方式:

进入容器

1
docker exec -it 容器名 /bin/bash

进入后:

1
2
3
4
5
6
7
8
# 更新apt
apt-get update

# 安装iproute2
agt install -y iproute2

# 安装完以后退出exit
docker exec -it 容器名 ip addr

这段不太实用,我的问题不在于容器启动后报错,而是容器根本没有启动成功,没法进入一个不在运行过程中的容器。

镜像 Dockerfile 的问题。

如何顺利进入Docker容器内部?-HCRM博客 (huochengrm.cn)

2025 年 2 月 10 日

本地虚拟机 Docker 安装完成,不过还要修改 Docker Hub 阿里云镜像源。

Docker 系列(3) —— 切换 Docker 镜像源-腾讯云开发者社区-腾讯云 (tencent.com)

这样的配置方法相比上面所提供的,也许会更加全面一些。

1
vi /etc/docker/daemon.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"registry-mirrors": [
"https://7bezldxe.mirror.aliyuncs.com/",
"https://docker.mirrors.ustc.edu.cn/",
"https://hub-mirror.c.163.com",
"https://registry.docker-cn.com"
],
"insecure-registries": [],
"debug": false,
"experimental": false,
"features": {
"buildkit": true
}
}
1
systemctl start docker.service
1
systemctl status docker.service
1
docker pull hello-world

Docker基础命令_docker 查看镜像-CSDN博客

1
docker info
1
2
Registry Mirrors:
https://7bezldxe.mirror.aliyuncs.com/

显然更新配置后再次拉取镜像没有生效,镜像源还是没有修改完成。

明天见吧,我的朋友。

Dockerfile 部署

2025 年 2 月 6 日

启动成功!

Snipaste_2025-02-06_09-35-22

删除容器,删除镜像,重新构建镜像再运行容器。

1
docker ps -a
1
docker remove helloapp
1
docker images
1
docker rmi hello-app

更新 Dockerfile 文件,选择使用官方 JDK 镜像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 使用 CentOS 基础镜像
FROM centos:latest
# 使用官方 JDK 镜像
FROM openjdk:8-jdk-alpine
# 作者信息
MAINTAINER memory
# 查看 JAVA 版本
RUN java -version
# 设置工作目录
WORKDIR /app
# 复制 JAR 文件到工作目录
COPY hello-0.0.1-SNAPSHOT.jar app.jar
# 容器启动执行命令
ENTRYPOINT ["java", "-jar", "app.jar"]
# 对外暴露的端口号
EXPOSE 8080

把 jar 包和编辑完善的 Dockerfile 文件放在同级目录下。

构建镜像。

1
docker build -t hello-app .

image-20250206095024612

创建并运行容器。

1
docker run -p 8080:8080 --name helloapp hello-app:latest

Snipaste_2025-02-06_09-35-22

可以说这是今年的开门红,初步掌握一门新技术:docker 容器部署。

进入正在运行中的容器并以命令行交互。

1
docker exec -it helloapp /bin/bash

或者:

1
docker exec -it helloapp /bin/sh

列表查看。

1
ls
1
2
3
4
5
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker exec -it helloapp /bin/sh
/app # ll
/bin/sh: ll: not found
/app # ls
app.jar

退出容器。

1
exit
1
2
/app # exit
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]#

shell:bash【Bourne-Again SHell】_bourne again shell-CSDN博客

[Linux] Bourne Again Shell-CSDN博客

正巧看到这篇文章,写得很全很详细,点开主页一看竟然是一位年均输出大几百篇技术文章的大佬,不过一九年停更了。

快到饭点了,接下来安排的任务是尝试 docker 部署后台管理项目,以及 docker 远程部署。

同样的步骤,编写 Dockerfile 文件,构建镜像文件,启动并运行容器,接下来就应该开放阿里云服务器端口号了。

倒是接口文档可以正常访问,不过连接数据库失败了。

1
http://8.141.90.145:8082/backend-server/doc.html

获取 docker 容器环境变量。

着手测试。

1
http://localhost:8080/api/test

携带环境变量,启动项目。

1
docker run -p 8080:8080 --name helloapp -e APP_NAME="My Awesome App" -e APP_PORT=8080 hello-app:latest

可以这么干,那就更新下接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 测试接口
*/
@GetMapping("/test")
public String test() {
System.out.println("Hello World");
return "Hello World";
}

/**
* 测试接口2
*/
@GetMapping("/test2")
public String test2() {
Map<String, String> getenv = System.getenv();
System.out.println(getenv);
String appName = System.getenv("APP_NAME");
System.out.println(appName);
String appPort = System.getenv("APP_PORT");
System.out.println(appPort);
return "Hello World";
}

出问题了。

怎么访问不到接口呢。

本地测试没问题啊,docker 部署服务启动也是没问题的,难道是打包更新后的代码出问题了吗,再试试。

1
http://8.141.90.145:8080/api/test2

果然是这样,成功了。

image-20250206153451255

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@iZ2ze4hnl6pls28qt4w1ttZ serInfo]# docker run -p 8080:8080 --name helloapp -e APP_NAME="My Awesome App" -e APP_PORT=8080 hello-app:latest

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.7)

2025-02-06 07:30:58.477 INFO 1 --- [ main] org.tellhow.info.hello.HelloApplication : Starting HelloApplication v0.0.1-SNAPSHOT using Java 1.8.0_212 on 9ed306a10b37 with PID 1 (/app/app.jar started by root in /app)
2025-02-06 07:30:58.484 INFO 1 --- [ main] org.tellhow.info.hello.HelloApplication : The following 1 profile is active: "dev"
2025-02-06 07:30:59.972 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2025-02-06 07:30:59.988 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2025-02-06 07:30:59.988 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.70]
2025-02-06 07:31:00.135 INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2025-02-06 07:31:00.135 INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1499 ms
2025-02-06 07:31:00.679 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2025-02-06 07:31:00.694 INFO 1 --- [ main] org.tellhow.info.hello.HelloApplication : Started HelloApplication in 2.989 seconds (JVM running for 3.58)
Hello world!
2025-02-06 07:31:06.094 INFO 1 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2025-02-06 07:31:06.095 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2025-02-06 07:31:06.096 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
Hello World
{PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin, HOSTNAME=9ed306a10b37, JAVA_ALPINE_VERSION=8.212.04-r0, LD_LIBRARY_PATH=/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64:/usr/lib/jvm/java-1.8-openjdk/jre/../lib/amd64, JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk, APP_NAME=My Awesome App, JAVA_VERSION=8u212, LANG=C.UTF-8, APP_PORT=8080, HOME=/root}
My Awesome App
8080

嘿嘿哈哈,看来通过 Java 代码获取封装在 Docker 容器环境变量中的服务器硬件信息是可取的,开启下一步修改。

1
2
3
4
5
6
Map<String, String> getenv = System.getenv();
System.out.println(getenv);
String appName = System.getenv("APP_NAME");
System.out.println(appName);
String appPort = System.getenv("APP_PORT");
System.out.println(appPort);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 获取现场服务器硬件信息
// 获取容器环境变量
LicenseCheckModel hardwareInfo = new LicenseCheckModel();
String ipAddressEnv = System.getenv(LicenseConstant.IP_ADDRESS_ENV);
String MacAddressEnv = System.getenv(LicenseConstant.MAC_ADDRESS_ENV);
String CpuSerialEnv = System.getenv(LicenseConstant.CPU_SERIAL_ENV);
String MainBoardSerialEnv = System.getenv(LicenseConstant.MAINBOARD_SERIAL_ENV);
if (ObjectUtils.isNotEmpty(ipAddressEnv)) {
hardwareInfo.setIpAddress(Lists.newArrayList(ipAddressEnv.split(",")));
}
if (ObjectUtils.isNotEmpty(MacAddressEnv)) {
hardwareInfo.setMacAddress(Lists.newArrayList(MacAddressEnv.split(",")));
}
if (ObjectUtils.isNotEmpty(CpuSerialEnv)) {
hardwareInfo.setCpuSerial(CpuSerialEnv);
}
if (ObjectUtils.isNotEmpty(MainBoardSerialEnv)) {
hardwareInfo.setMainBoardSerial(MainBoardSerialEnv);
}
// 现场服务器硬件信息
if (ObjectUtils.isEmpty(hardwareInfo)) {
log.error("请输入现场服务器硬件信息!");
throw new CommonException(401, "请输入现场服务器硬件信息!");
}
// 设置现场服务器硬件信息
HardwareInfoContext.setHardwareInfo(hardwareInfo);

接下来的内容,就记录在别的栏目了,纯业务,与技术无关。

2025 年 2 月 7 日

docker 远程部署。

IDEA+Docker远程部署Sprin - 编程导航 - 程序员编程学习交流社区 (codefather.cn)

image-20250207150825887

两天了,刚刚看到这个连接 Docker 失败的提示。

算了,前天的记录内容就网上翻找吧,在此就不做复杂的排版了。

1
Only key-pair ssh auth type is supported for docker connections.

远程部署成功!

image-20250207155252693

2025 年 2 月 8 日

IDEA+Docker远程部署Sprin - 编程导航 - 程序员编程学习交流社区 (codefather.cn)

在IDEA中通过密钥认证的方式使用SSH连接远程Linux服务器_idea ssh密码登录-CSDN博客

SSH

2025 年 2 月 8 日

openssh是什么服务器 • Worktile社区

远程连接服务器,除了账号密码还可以使用 ssh 连接。

IDEA+Docker远程部署Spring - 编程导航 - 程序员编程学习交流社区 (codefather.cn)

在IDEA中通过密钥认证的方式使用SSH连接远程Linux服务器_idea ssh密码登录-CSDN博客

在IDEA中通过密钥认证的方式使用SSH连接远程 Linux 服务器。

昨天使用 Key Pair OpenSSH 连接方式实现 Docker 远程部署,是因为 Docker 远程部署仅支持 Key Pair OpenSSH 连接方式。

然而连接其实是失败了,远程部署显然不应该成功的,还是使用账号密码验证成功,只是来 IDEA 配置中勾选连接方式为 ssh 方式即可。

在 windows 上生成公钥证书。

  • 第一步,执行Win+R命令输入cmd打开DOS命令行窗口。
  • 第二步,在命令行窗口中输入ssh -V查看ssh版本号,判断ssh是否可以用,因为我们需要通过ssh来生成证书文件。
  • 第三步,ssh命令可用的话,就继续在命令行窗口输入ssh-keygen -t rsa生成公钥证书和私钥证书文件。生成的目录也指明了,通常在用户的.ssh目录下,其中id_rsa是私钥证书文件,id_rsa.pub为公钥证书文件。
1
win + R
1
ssh -V
1
ssh-keygen -t rsa

将公钥证书放到 Linux 服务器上。

  • 第一步,复制Windows系统下.ssh目录下生成的公钥证书文件id_rsa.pub的内容。
  • 第二步,在Linux系统的/root/.ssh目录下执行vi authorized_keys命令创建一个名为authorized_keys的文件,然后将第一步复制的id_rsa.pub的内容粘贴到该文件内。这样远程Linux服务器就信任本地的Windows系统服务器了,你可以在本地的Windows系统上通过ssh远程登录Linux系统了。
  • 第三步,测试。在本地Windows系统上输入ssh 用户名@IP地址进行远程登录。如果能登录成功并且能执行Linux命令表示配置成功。
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC9p7KkIDVnVn9XOi4J6qNkwEJ0iVKqMR5gNxW5o1Qhf++ufpzcgro9eDTLkfLA7i9v3oqB6IUzmzF3lKXEnGEcEz+d60QdSUoJFV2+8kGeCyAfYlSh5hL/DJ79zjwfkWnFqDmAUvznqaYSRxWGLGW3q/7a09EaAuJ2rmI2Arz76DV1Knr7mu1HLmm6TUuHX7cHdnez8azIxhfm/0p4OGK9eulK4YGbn1XCqN8oLJfT+MqYx23rpFZBPtd3sjWaxyIqbpzH7r0cfT3tIhO6URyv3kP4YscVccbf4ImP4aJiOjfyGD+JB7hpuhXC3HtH8mhZsOCuDwwkPyi43J7Eew1yXVnPpHIpYXhtryNOEgJfzcbP3QrqnTynrNKiNZQjfo47JBUWFFeWUbEFcJDshKIYOAZb0G9twqbX3ZraVKVAYYd6kKj5a5sge8Ck+CrPXYFgCm3mWkS3W+wPrTOHgqmuKH4gksZT4Zpc1rTmjOLNlRaOggBW8AMvvovteRdF37s= Lenovo@LAPTOP-5U3S75BI
1
vi authorized_keys
1
ssh 用户名@IP地址
1
2
3
4
5
C:\WINDOWS\system32>ssh root@8.141.90.145
Last login: Sat Feb 8 16:39:45 2025 from 218.94.31.98

Welcome to Alibaba Cloud Elastic Compute Service !
[root@iZ2ze4hnl6pls28qt4w1ttZ ~]#

image-20250208164045006

注意:

  • 其实就是将本地Windows系统上的公钥证书文件id_rsa.pub文件上传到远程Linux系统上的/root/.ssh目录下并且重命名为authorized_keys。

  • 如果已经存在authorized_keys文件了,那么直接将复制的内容添加到文件的最后一行。因为每一行都表示一条信任连接,不要去删除。

IDEA通过SSH连接远程Linux服务器。

  • 第一步,打开File,然后选择Settings...
  • 第二步,选择Tools下的SSH Configurations面板,点击+号选择新建SSH连接。
  • 第三步,输入连接参数。Host输入远程Linux服务器的IP地址;Port输入端口号,默认是22;User name输入登录的用户名;Authentication type选择Key pair表示通过密钥进行验证;Private key file则选择Windows系统下私钥证书id_rsa的目录,即在用户目录下的.ssh子目录中;Passphrase不用填。
  • 第四步,如果有多个连接,那么在SSH Terminal面板中的SSH configuration选择框中选择一台默认连接,或者选择Select SSH configuration on every run表示在每次打开时手动选择要连接的主机。
  • 第五步,在菜单条上的Tools中选择Start SSH Session...开启会话。在出现的Select Host to Connect面板中选择要连接的服务器。
  • 第六步,连接成功!
1
2
3
4
Last login: Sat Feb  8 16:41:19 2025 from 218.94.31.98

Welcome to Alibaba Cloud Elastic Compute Service !
[root@iZ2ze4hnl6pls28qt4w1ttZ ~]#

image-20250208165259585

其他:安装 Open SSH。

openssh是什么服务器 • Worktile社区

适用于 Windows 的 OpenSSH 入门 | Microsoft Learn

尝试使用刚新学会的三板斧实现 th-iois-file-server 项目远程部署,很显然失败了。

1
2
Can not construct instance of com.spotify.docker.client.messages.RegistryAuth: no String-argument constructor/factory method to deserialize from String value ('desktop')
at [Source: N/A; line: -1, column: -1] (through reference chain: java.util.LinkedHashMap["credsStore"])

下周见,我的朋友,今天辛苦了。

MinIO

2025 年 1 月 15 日

这年头不会还有谁没碰过minio的吧?这可太…🤡文件存储那些“坑”,你踩过几个?想象一下,你正在开发一个新项目,老 - 掘金 (juejin.cn)

MinIO+Docker从零搭建一个文件 - 编程导航 - 程序员编程学习交流社区 (codefather.cn)

MinIO 对象存储(可以当作图床免费) - 编程导航 - 程序员编程学习交流社区 (codefather.cn)

Springboot整合Minio全流程 - 编程导航 - 程序员编程学习交流社区 (codefather.cn)

centos7安装Docker详细步骤(无坑版教程)-腾讯云开发者社区-腾讯云 (tencent.com)

Docker 搭建 Minio 对象存储服务MinIO MinIO 是一款基于 Go 语言发开的高性能、分布式的对象存储 - 掘金 (juejin.cn)

虚拟机

2025 年 1 月 13 日

ubuntu与centos的对比和选择「建议收藏」-腾讯云开发者社区-腾讯云 (tencent.com)

CentOS、Ubuntu、Debian三个linux比较异同_debian和ubuntu的区别-CSDN博客

虚拟机。

在虚拟机上进行的最多的操作便是部署项目,以及间歇性熟悉基本的 Linux 命令。

最近需要抽出时间来巩固下 Linux 基本操作命令,学习如何编写脚本来获取 Linux 服务器硬件信息。

2025 年 1 月 14 日

Linux获取电脑硬件信息_linux 获取计算机信息-CSDN博客

9个Linux 常用查看系统硬件信息命令(实例详解)-腾讯云开发者社区-腾讯云 (tencent.com)

如何制作centos安装光盘 centos光盘映像文件怎么安装_mob6454cc6c1f4a的技术博客_51CTO博客

centos安装包下载_开源镜像站-阿里云 (aliyun.com)

Linux 脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash

OUTPUT_FILE="$HOME/Desktop/OutputFile.txt"

echo "开始获取本机信息..."

# 清空或创建输出文件
> "$OUTPUT_FILE"

# 获取本机IP地址
echo "本机IP地址:" >> "$OUTPUT_FILE"
ip addr show | grep -Eo 'inet ([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}' | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"

# 获取本机MAC地址
echo "本机MAC地址:" >> "$OUTPUT_FILE"
ip link show | grep -Eo '(([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})' >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"

# 获取本机CPU序列号(注意:Linux系统通常没有CPU序列号的概念,这里用CPU型号代替)
echo "CPU型号:" >> "$OUTPUT_FILE"
lscpu | grep -E 'Model name|CPU(s):' >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"

# 获取本机主板序列号
echo "主板序列号:" >> "$OUTPUT_FILE"
sudo dmidecode -s baseboard-serial-number >> "$OUTPUT_FILE" 2>/dev/null

echo "本机信息获取完成,结果已保存到 $OUTPUT_FILE"

# 暂停,以便用户查看输出文件(在终端中按任意键继续)
read -p "按任意键退出..." dummy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
本机IP地址:
127.0.0.1
192.168.118.16
192.168.122.1
172.30.0.1
172.18.0.1
172.17.0.1

本机MAC地址:
00:00:00:00:00:00
00:00:00:00:00:00
54:14:a7:16:a5:e7
ff:ff:ff:ff:ff:ff
52:54:00:55:4a:6c
ff:ff:ff:ff:ff:ff
52:54:00:55:4a:6c
ff:ff:ff:ff:ff:ff
02:42:21:c3:65:a2

CPU型号:

主板序列号:
/66VXC73/CNPE10009806QG/

本机 CPU 序列号:

1
2
3
4
# 获取本机CPU序列号(注意:Linux系统通常没有CPU序列号的概念,这里用CPU型号代替)
echo "CPU型号:" >> "$OUTPUT_FILE"
lscpu | grep -E 'Model name|CPU(s):' >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
1
lscpu

2025 年 1 月 17 日

WSL是什么?和虚拟机有什么区别_wsl和虚拟机区别-CSDN博客

WSL和虚拟机,哪个更适合你 (baidu.com)

WSL和虚拟机的区别是什么?_linux_我想要身体健康-华为开发者空间 (csdn.net)

手把手教你如何安装使用,适用于 Linux 的 Windows 子系统WSL_wsl安装-CSDN博客

颠覆虚拟机的大神——WSL来了 - zhangzl419 - 博客园 (cnblogs.com)

image-20250117100141936

2025 年 1 月 23 日

解决虚拟机连不上网的五大技巧:从排查到修复,一篇文章让你彻底 (baidu.com)

在线就能用的linux环境(练习命令用)_在线linux模拟环境-CSDN博客

VMware虚拟机无法联网ping不通_vmware虚拟机网络连接不上-CSDN博客

image-20250123113444304

VMware虚拟机网络连接不上怎么办?帮您逐个排查! (abackup.com)

阿里云。

阿里云免费试用 - 阿里云 (aliyun.com)

image-20250123115613845

image-20250123115858152

连上了,他妈的。

image-20250123120205749

Linux系统之安装java开发环境 - 爵岚 - 博客园 (cnblogs.com)

image-20250123120857731

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static String fetchCpuId() {
String cpuId = "";
String[] command = {"/bin/bash", "-c", "sudo dmidecode -t processor | grep 'ID' | awk -F ':' '{print $2}' | head -n 1"};

ProcessBuilder processBuilder = new ProcessBuilder(command);
try {
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
if ((line = reader.readLine()) != null) {
cpuId = line.trim();
}
reader.close();
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new RuntimeException("Command exited with error code: " + exitCode);
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
return cpuId;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static String fetchSerialNumber() {
String serialNumber = "";
// 构建要执行的命令
String[] command = {"/bin/bash", "-c", "sudo dmidecode | grep 'Serial Number' | awk -F ':' '{print $2}' | head -n 1"};

// 创建ProcessBuilder对象
ProcessBuilder processBuilder = new ProcessBuilder(command);
try {
// 启动进程
Process process = processBuilder.start();
// 读取命令输出
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
if ((line = reader.readLine()) != null) {
// 移除输出中的空白字符
serialNumber = line.trim();
}
reader.close();
// 等待进程结束并获取退出码
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new RuntimeException("Command exited with error code: " + exitCode);
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
return serialNumber;
}
1
2
3
4
// CPU序列号(或主板序列号)的正则表达式(宽松匹配)
// 假设序列号由字母、数字、连字符、点和空格组成,长度在10到40个字符之间
private static final String SERIAL_REGEX = "^[A-Za-z0-9\\-.\\s]{8,40}$";
private static final Pattern SERIAL_PATTERN = Pattern.compile(SERIAL_REGEX);

2025 年 1 月 25 日

脚本,命令。

1
sudo dmidecode -t processor | grep 'ID' | awk -F ':' '{print $2}' | head -n 1
1
sudo dmidecode | grep 'Serial Number' | awk -F ':' '{print $2}' | head -n 1
1
ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'
1
ip link show | awk '/ether/ {match($0, /ether ([0-9a-fA-F:]+)/, arr); print $2, arr[1]}'

2025 年 2 月 10 日

CentOS 的安装——超详细教程_centos安装教程详解,面试官不讲武德-CSDN博客

image-20250210094759039

1
2
3
my_CentOS7
admin
admin123

ISO文件_百度百科 (baidu.com)

查看虚拟机centos 7 的 IP 地址和命令 - 数据派 - 博客园 (cnblogs.com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[admin@localhost ~]$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens32: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN qlen 1000
link/ether 00:0c:29:d7:0d:5c brd ff:ff:ff:ff:ff:ff
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN qlen 1000
link/ether 52:54:00:00:81:b0 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN qlen 1000
link/ether 52:54:00:00:81:b0 brd ff:ff:ff:ff:ff:ff
1
vi /etc/sysconfig/network-scripts/ifcfg-ens33

Linux网络基础_route-ens33-CSDN博客

「科普」BIOS是什么?BIOS怎么进入,BIOS里面可以设置什么东西? (baidu.com)

Linux远程连接没有ens33ip地址问题解决_linuxens33没有ip地址-CSDN博客

linux下修改完配置文件如何保存_linux修改配置文件怎么保存退出-CSDN博客

1
2
3
按w是保存
按wq是保存并退出
按wq!是强制保存并退出

Ubuntu user is not in the sudoers file. This incident will be reported解决办法-CSDN博客

特么的总算找着解决办法了。

1
su -
1
vi /etc/sysconfig/network-scripts/ifcfg-ens32

好熟悉的报错:

1
2
[root@localhost ~]# systemctl start network.service
Job for network.service failed because the control process exited with error code. See "systemctl status network.service" and "journalctl -xe" for details.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[root@localhost ~]# journalctl -xe
-- Subject: Unit network.service has begun start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit network.service has begun starting up.
Feb 10 03:31:04 localhost.localdomain network[45746]: Bringing up loopback interface: [ OK ]
Feb 10 03:31:04 localhost.localdomain NetworkManager[743]: <info> [1739187064.9118] audit: op="connection-activate" uuid="28
Feb 10 03:31:04 localhost.localdomain network[45746]: Bringing up interface ens32: Error: Connection activation failed: No s
Feb 10 03:31:04 localhost.localdomain network[45746]: [FAILED]
Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists
Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists
Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists
Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists
Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists
Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists
Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists
Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists
Feb 10 03:31:04 localhost.localdomain network[45746]: RTNETLINK answers: File exists
Feb 10 03:31:04 localhost.localdomain systemd[1]: network.service: control process exited, code=exited status=1
Feb 10 03:31:04 localhost.localdomain systemd[1]: Failed to start LSB: Bring up/down networking.
-- Subject: Unit network.service has failed
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit network.service has failed.
--
-- The result is failed.
Feb 10 03:31:04 localhost.localdomain systemd[1]: Unit network.service entered failed state.
Feb 10 03:31:04 localhost.localdomain systemd[1]: network.service failed.
Feb 10 03:31:04 localhost.localdomain polkitd[628]: Unregistered Authentication Agent for unix-process:45740:499336 (system b
lines 1651-1680/1680 (END)

Linux:Job for network.service failed because the control process exited with error code - 宋霏 - 博客园 (cnblogs.com)

虚拟机重启网卡报错:Job for network.service failed because the control process exited with error code.-CSDN博客

没用。

虚拟机报错:Job for network.service failed because the control process exited with error code - 知乎 (zhihu.com)

network.service - LSB: Bring up/down networking Loaded: loaded (/etc/rc.d/init.d/network; bad; v_源知原味的技术博客_51CTO博客

特么十年前的帖子都找来了,没有解决问题。

1
2
无法连接虚拟设备 ide1:0,因为主机上没有相应的设备。
您要在每次开启此虚拟机时都尝试连接此虚拟设备吗?

无法连接虚拟设备 ide1:0,因为主机上没有相应的设备。您要在每次开启此虚拟机时都尝试连接此虚拟设备吗? - jingjing0920 - 博客园 (cnblogs.com)

无法连接虚拟机设备 ide1:0,因为主机上没有相应的设备。您要每次在开启此虚拟机时都尝试连接此虚拟设备吗?_无法连接虚拟设备 ide1:0,因为主机上没有相应的设备。 您要在每次开启此虚拟机时-CSDN博客

好像跟开启虚拟机时的告警信息也无关,同样解决不了问题。

这个方案挺全,试试看:Job for network.service failed because the control process exited with error code.-CSDN博客

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
DEFROUTE=yes
HWADDR=00:0c:29:d7:0d:5c
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens32
UUID=28699bd2-8cc2-41d1-91c2-12de41c04007
DEVICE=ens32
ONBOOT=yes

静态 ip 把 BOOTPROTO 改为 static,重启成功了。

不过 ifconfig 还是 没有 ip 地址,为什么呢。

1
2
3
4
5
6
7
8
[root@localhost ~]# ifconfig
ens32: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet6 fe80::20c:29ff:fed7:d5c prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:d7:0d:5c txqueuelen 1000 (Ethernet)
RX packets 736 bytes 156623 (152.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 18 bytes 4068 (3.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

查看下你电脑有没有禁用了VMware DHCP service和VMware NAT service 这几个vm服务,如果禁用则开启。

查看了下果真未开启,尝试开启但失败了。

Vmware Linux虚拟机连不上网怎么办?_虚拟机linux无法联网-CSDN博客

我也这么干一遍:先把虚拟机关机,再打开vmware首页 ,打开编辑, 再打开虚拟网络编辑器,选择其中的第一个VMnet0,然后点击左下角的还原默认设置

也还是没啥用。

艹,这就成功了,虚拟机连接网络成功,FinalShell 连接本机虚拟机成功,虚拟机网络配置完成。

这么长时间了,总算搞懂了网络配置里的歪门邪道,年前留下的最后一个问题也总算在今天解决,二十天的时间跨度不过如此。

我什么都能解决。

2025 年 2 月 10 日

一条龙

下载光盘映像文件,根据 .iso 文件创建虚拟机,配置虚拟机硬件信息,设置用户名密码,启动。

看这篇就够了:CentOS 的安装——超详细教程_centos安装教程详解,面试官不讲武德-CSDN博客

重点来了,从去年开始反复困扰我的本机虚拟机连接网络失败的问题,在这里简要分析下整个网络配置中需要注意的点。

1
ifconfig

执行这条命令,虚拟机网卡 ens32 网络连接是有问题的,查看下配置文件。

1
vim /etc/sysconfig/network-scripts/ifcfg-ens32
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
DEFROUTE=yes
HWADDR=00:0c:29:d7:0d:5c
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens32
UUID=28699bd2-8cc2-41d1-91c2-12de41c04007
DEVICE=ens32
ONBOOT=yes

ONBOOT=yes,修改配置文件结束后竟然重启网络服务失败了。

1
2
[root@localhost ~]# systemctl start network.service
Job for network.service failed because the control process exited with error code. See "systemctl status network.service" and "journalctl -xe" for details.

查了很多资料和方案,贴出来最全的博客文章吧,里面所有的方法都试过了.

Job for network.service failed because the control process exited with error code.-CSDN博客

Vmware Linux虚拟机连不上网怎么办?_虚拟机linux无法联网-CSDN博客

最终我尝试把 BOOTPROTO 改为 static 即静态 IP,虚拟机网络服务竟然重启成功,不过 ifconfig 还是 没有 ip 地址,为啥呢。

因为改成静态 ip 了,配置文件里应该相应要增加这些配置信息才对:

1
2
3
IPADDR=192.168.1.100							# 静态ip地址
PREFIX=24 # 或者使用 NETMASK=255.255.255.0 # 子网掩码
GATEWAY=192.168.1.1 # 网关

由于虚拟机未配置动态主机配置协议,那本机即宿主机服务当然不会在运行中,因为win10默认:不存在其他服务应用到这俩服务后就自动关闭。

image-20250210151057680

那还是把 BOOTPROTO 改回 dhcp 即动态主机配置协议吧,结果重启网络服务仍然成功了,执行 ifconfig 命令后结果完全正常。

1
2
3
4
5
6
7
8
9
[admin@localhost ~]$ ifconfig
ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.229.128 netmask 255.255.255.0 broadcast 192.168.229.255
inet6 fe80::20c:29ff:fed7:d5c prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:d7:0d:5c txqueuelen 1000 (Ethernet)
RX packets 36660 bytes 4378000 (4.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 55849 bytes 14707128 (14.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

这是现在的配置文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=dhcp
DEFROUTE=yes
HWADDR=00:0c:29:d7:0d:5c
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens32
UUID=28699bd2-8cc2-41d1-91c2-12de41c04007
ONBOOT=yes

搞半天花里胡哨的,其实就是把 dhcp 改成 static 又改回 dhcp 罢了, 额外操作根本不需要,不过确实节外生枝学到了不少。

本机虚拟机安装及网络配置完全结束。

2025 年 2 月 17 日

filezilla向虚拟机Linux传输文件失败且直接在Linux创建文件夹失败的解决方案_550 could get file size-CSDN博客

SSH客户端连接Linux成功,但是传输文件失败_ssh无法传输文件-CSDN博客

[linux 不能上传文件 - 腾讯云开发者社区 - 腾讯云 (tencent.com)](https://cloud.tencent.com/developer/information/linux 不能上传文件)

VM虚拟机无法传输文件(更新时间24/3/3)-CSDN博客

内网穿透

2025 年 1 月 9 日

有哪些简单实用的端口映射(内网穿透)软件工具?_百度知道 (baidu.com)

内网穿透(frp、zerotier)-CSDN博客

内网穿透几种方式?怎么搭建内网穿透?-贝锐花生壳官网 (oray.com)

内网穿透方案&FRP内网穿透实战(基础版)-CSDN博客

小程序

2025 年 1 月 9 日

从零开始三天学会微信小程序开发(一)看到不少入门的小程序开发者不断的问重复性的问题,我们从实战角度开发了这个课程,希望能 - 掘金 (juejin.cn)

MongoDB

2025 年 1 月 15 日

高效存储,万物皆可Mongo!SpringBoot+MongoDB教程,「从入门到掌握」🏆本文收录于《Spring B - 掘金 (juejin.cn)

云盘

2025 年 1 月 16 日

百度网盘115G,阿里云盘105G,夸克云盘10G,迅雷云盘1TB。

2025 年 1 月 17 日

onedeive作用是什么,类似百度网盘吗,和百度网盘有什么区别没?_one deive-CSDN博客

(18 封私信 / 7 条消息) 为什么微软的网盘Onedrive不像百度网盘一样支持秒传呢? - 知乎 (zhihu.com)

阿里云盘用来同步备份,百度网盘用来上传保存,夸克云盘用来及时救急,迅雷云盘当然是用来下载文件了。

妈的,百度网盘上传文件大小受到限制,超过4GB就得花钱了;迅雷云盘更夸张,稍微大点有个1G就上传失败,看看阿里云盘。

1
2
3
4
5
6
7
8
‌百度网盘普通用户单个文件上传的最大限制为4GB,而会员用户可以享受更大的上传空间。具体来说,百度网盘超级会员(SVIP)用户在使用Windows客户端和Mac客户端进行大文件上传时,可以上传的最大文件大小如下:
‌普通用户‌:单个文件最大上传限制为4GB。
‌会员用户‌:最大可上传单个文件至20GB。
‌超级会员(SVIP)‌:使用Windows客户端和Mac客户端进行大文件上传时,超级会员V1可上传300G大文件,超级会员V10最高可上传2048G超大文件。
不同用户类型的上传限制
‌普通用户‌:普通用户的总存储空间为2TB,单个文件最大上传限制为4GB。
‌会员用户‌:会员用户的总存储空间和上传速度会有所提升,单个文件最大上传限制为20GB。
‌超级会员(SVIP)‌:超级会员在Windows客户端和Mac客户端上可以上传更大文件,具体大小取决于会员等级,从300G到2048G不等。

9.4 文件的上传和下载-CSDN博客

阿里云盘普通用户限制多久 | 百度网盘企业版 (baidu.com)

我的此电脑设备和驱动器里的百度网盘图标怎么删除? (baidu.com)

1
计算机\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\

image-20250117154128751

DeepSeek

2025 年 2 月 13 日

ChatBox可以免费对话Gemini和Claude千次-CSDN博客

DeepSeek本地化部署全攻略,轻松拥有专属 AI 助手-CSDN博客

本地免费部署DeepSeek教程,个人PC都能安装(附软件)_个人电脑部署deepseek-CSDN博客

攻略丨搭建属于自己的 DeepSeek,本地部署「手搓教程」在此!_本地搭建deepseek-CSDN博客

2025 年 2 月 14 日

10分钟接入AI大模型—Spring Cloud Alibaba_spring ai-CSDN博客

1
2
3
4
5
6
企业方面,大模型将带来数智化升级的进一步加速。举几个例子,通过大模型可以实现:
金融领域中的投资组合优化、风险管理、欺诈检测等;
医疗领域中疾病预测、药物研发、医疗影像分析等;
制造业中的生产计划排程、质量控制、物流管理等;
交通运输领域中的自动驾驶、智能交通管理等;
娱乐领域中游戏开发、电影制作、音乐创作等。

从头开始,八步实现大模型接入|如何用好大模型-CSDN博客

2024年末AI大模型盘点:国内外当前主流大数据模型汇总 (baidu.com)

国内:文心一言豆包Kimi讯飞星火智谱清言通义千问腾讯元宝天工AI盘古赤兔

国外:GPT系列Gemini系列Claude系列

2025年全球AI大模型盘点及对比分析 (baidu.com)

AI 模型接入

Spring Boot 对接文心一言_springboot接入文心一言-CSDN博客

springboot+vue项目接入文心一言API_springboot接入文心一言-CSDN博客

2025 年 2 月 17 日

DeepSeek R1 使用指南:架构、训练、本地部署_deepseek本地训练-CSDN博客

2025 年 2 月 19 日

99%的人都不知道的DeepSeek玩法:榨干算力,性能狂飙!_深度思考r1选与不选的区别-CSDN博客

用朴实直白的语言,不要过度发挥或创造新名词,避免使用过于专业的术语或自创概念。

【图片】这四个模式都是什么意思,有什么区别吗?【deepseek吧】_百度贴吧 (baidu.com)

【图片】【关于深度思考】deepseek说开不开深度思考不影响答案本身_deepseek吧_百度贴吧 (baidu.com)

手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!写在前面 最近,DeepSeek 发布的推理大 - 掘金 (juejin.cn)

2025 年 2 月 21 日

DeepSeek+KIMI超强组合,一人就是一家公司! 保姆级教程 - 知乎 (zhihu.com)

Conda

2025 年 2 月 21 日

conda环境管理与包安装实战-CSDN博客

权限认证

2025 年 2 月 27 日

Spring Security 认证流程,长话简说_springsecurity认证流程-CSDN博客

无人机

2025 年 3 月 17 日

[大疆无人机上云API:Java代码实战全攻略-CSDN博客](https://blog.csdn.net/m0_73978383/article/details/146033672?ops_request_misc=&request_id=&biz_id=102&utm_term=Java 无人机&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-8-146033672.142^v102^control&spm=1018.2226.3001.4187)

[无人机飞行数据java版本api大疆无人机SpringBoot_大疆无人机视频数据实时传输api-CSDN博客](https://blog.csdn.net/qq_38821574/article/details/123356320?ops_request_misc=%7B%22request%5Fid%22%3A%22a21ae00631af52d8a114d4d7be5d89b3%22%2C%22scm%22%3A%2220140713.130102334.pc%5Fall.%22%7D&request_id=a21ae00631af52d8a114d4d7be5d89b3&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-8-123356320-null-null.142^v102^control&utm_term=Java 无人机&spm=1018.2226.3001.4187)

Mybatis

SQL

Netty

2025 年 3 月 17 日

理解:什么是同步和异步?什么是阻塞和非阻塞?_什么是同步什么是异步-CSDN博客

【硬核】肝了一月的Netty知识点-CSDN博客

[01 初识 Netty:为什么 Netty 这么流行? (lianglianglee.com)](https://learn.lianglianglee.com/专栏/Netty 核心原理剖析与 RPC 实践-完/01 初识 Netty:为什么 Netty 这么流行?.md)

消息队列

2025 年 3 月 17 日

RabbitMQ详解,用心看完这一篇就够了【重点】-CSDN博客

Node

2025 年 3 月 18 日

Node.js安装与配置(详细步骤)_nodejs安装及环境配置-CSDN博客

SpringBoot

2025 年 3 月 18 日

[09 数据抽象:Spring Data 如何对数据访问过程进行统一抽象? (lianglianglee.com)](https://learn.lianglianglee.com/专栏/Spring Boot 实战开发/09 数据抽象:Spring Data 如何对数据访问过程进行统一抽象?.md)

[17 安全架构:如何理解 Spring 安全体系的整体架构? (lianglianglee.com)](https://learn.lianglianglee.com/专栏/Spring Boot 实战开发/17 安全架构:如何理解 Spring 安全体系的整体架构?.md)

全面梳理基于 Spring Boot 的 Web 应用程序开发技术组件,其中包括配置体系、数据访问、Web 服务、消息通信、系统安全、系统监控、系统测试等专项主题。这些技术组件涵盖了 Java EE 应用程序开发涉及的方方面面,具有广泛的应用场景。

Spring Boot 可以帮助我们构建从 Web 服务层到数据访问层的全栈式响应式编程技术,从而确保系统的各个环节都具备即时响应性。

回调

2025 年 3 月 18 日

回调机制详解-CSDN博客

操作系统

计网

SpringCloud

Elasticsearch

总结

2025 年 1 月 15 日

入职一个一个月以来,每天在整理工作笔记之余,也会抽时间发散思维,记录灵感,去探索一些新的东西。

这个栏目开设在去年夏天,原本计划用来记录拉取学习并系统梳理的新项目,有效扩充技术广度。

这样的想法和行动于我而言很有吸引力,不过在后半年由于就业环境的冲击以及秋招带来的无形压力,国庆以后便被迫短暂搁置了。

从今天开始,我会尝试在这个栏目下持续记录自己的思考过程。

我的编程之旅,或许这个栏目才是其真正的精神续作吧。

最近也会有很多新的想法和开发思路,所有笔记逐步从泰豪实习工作栏目下迁移到这里,并稍作整理了一番。


卓越之旅:在优秀案例中精进,编织技术梦想
https://test.atomgit.net/blog/2024/07/12/卓越之旅:在优秀案例中精进,编织技术梦想/
作者
Memory
发布于
2024年7月12日
更新于
2025年3月26日
许可协议