Commit on 2025/03/21 周五 14:35:28.01

This commit is contained in:
zhangsan 2025-03-21 14:35:28 +08:00
parent c34b41dd9d
commit 6bbb13cc82
16 changed files with 438 additions and 424 deletions

View File

@ -60,7 +60,7 @@ Docker是一个CS架构的程序由两部分组成
1. docker push将本地镜像上传到远程仓库例如 Docker Hub 1. docker push将本地镜像上传到远程仓库例如 Docker Hub
``` ```text
docker login #docker hub登录 docker login #docker hub登录
# 假设已有本地镜像 myimage需要先打上标签 # 假设已有本地镜像 myimage需要先打上标签
docker tag myimage yourusername/myimage:latest docker tag myimage yourusername/myimage:latest
@ -70,31 +70,31 @@ docker push yourusername/myimage:latest
2. docker pull ,从远程仓库拉取镜像到本地。 2. docker pull ,从远程仓库拉取镜像到本地。
``` ```text
docker pull yourusername/myimage:latest docker pull yourusername/myimage:latest
``` ```
3. docker save将本地镜像保存为 tar 文件,方便备份或传输 3. docker save将本地镜像保存为 tar 文件,方便备份或传输
``` ```text
docker save -o myimage.tar yourusername/myimage:latest docker save -o myimage.tar yourusername/myimage:latest
``` ```
4. docker load从 tar 文件中加载镜像到本地 Docker。 4. docker load从 tar 文件中加载镜像到本地 Docker。
``` ```text
docker load -i myimage.tar docker load -i myimage.tar
``` ```
5. docker images ,查看本地镜像 5. docker images ,查看本地镜像
``` ```text
docker images docker images
``` ```
6. docker build ,构建镜像 -t后面跟镜像名 6. docker build ,构建镜像 -t后面跟镜像名
``` ```text
docker build -t yourusername/myimage:latest . docker build -t yourusername/myimage:latest .
``` ```
@ -116,7 +116,7 @@ docker build -t yourusername/myimage:latest .
-v <宿主机目录>:<容器目录>` 或 `--volume 如 -v /host/data:/app/data -v <宿主机目录>:<容器目录>` 或 `--volume 如 -v /host/data:/app/data
``` ```text
docker run --name test-container -d test:latest docker run --name test-container -d test:latest
``` ```
@ -124,49 +124,49 @@ docker run --name test-container -d test:latest
-it : 给当前进入的容器创建一个标准输入、输出终端 -it : 给当前进入的容器创建一个标准输入、输出终端
``` ```text
docker exec -it test-container sh docker exec -it test-container sh
``` ```
3. docker logs ,查看 test-container 的日志输出: 3. docker logs ,查看 test-container 的日志输出:
``` ```text
docker logs --since 1h test-container #查看最近1h docker logs --since 1h test-container #查看最近1h
``` ```
4. docker stop 停止正在运行的 test-container 4. docker stop 停止正在运行的 test-container
``` ```text
docker stop test-container docker stop test-container
``` ```
5. docker start 启动一个已停止的 test-container 5. docker start 启动一个已停止的 test-container
``` ```text
docker start test-container docker start test-container
``` ```
6. docker cp 复制文件或目录到容器内部先cd到文件所在目录 6. docker cp 复制文件或目录到容器内部先cd到文件所在目录
``` ```text
docker cp localfile.txt test-container:/target_dir/ docker cp localfile.txt test-container:/target_dir/
``` ```
7. docker stats 查看docker中运行的所有容器的运行状态CPU 内存占用) 7. docker stats 查看docker中运行的所有容器的运行状态CPU 内存占用)
``` ```text
docker stats docker stats
``` ```
8. docker container ls查看运行容器的创建时间、端口映射等 8. docker container ls查看运行容器的创建时间、端口映射等
``` ```text
docker container ls docker container ls
``` ```
9. docker ps 查看 Docker 容器的状态,默认情况下,它只显示正在运行的容器 9. docker ps 查看 Docker 容器的状态,默认情况下,它只显示正在运行的容器
``` ```text
docker ps -a #查看所有容器,包括已经停止或启动失败的容器 docker ps -a #查看所有容器,包括已经停止或启动失败的容器
``` ```
@ -196,7 +196,7 @@ docker ps -a #查看所有容器,包括已经停止或启动失败的容器
- **示例**:将宿主机的 `/path/on/host` 挂载到容器内的 `/app/data` - **示例**:将宿主机的 `/path/on/host` 挂载到容器内的 `/app/data`
``` ```text
docker run -v /path/on/host:/app/data your_image docker run -v /path/on/host:/app/data your_image
``` ```
@ -212,25 +212,25 @@ docker ps -a #查看所有容器,包括已经停止或启动失败的容器
- **示例**:创建并挂载名为 `my_volume` 的卷到容器内的 `/app/data` - **示例**:创建并挂载名为 `my_volume` 的卷到容器内的 `/app/data`
``` ```text
docker run -v my_volume:/app/data your_image docker run -v my_volume:/app/data your_image
``` ```
创建命名卷 创建命名卷
``` ```text
docker volume create my_volume docker volume create my_volume
``` ```
查看命名卷,这将列出所有 Docker 管理的卷。 查看命名卷,这将列出所有 Docker 管理的卷。
``` ```text
docker volume ls docker volume ls
``` ```
显示该命名卷的详细信息 显示该命名卷的详细信息
``` ```text
zy123@hcss-ecs-588d:~/zbparse$ sudo docker volume inspect html zy123@hcss-ecs-588d:~/zbparse$ sudo docker volume inspect html
[ [
{ {
@ -259,13 +259,13 @@ Docker 网络的主要作用是实现容器之间的**通信和隔离**,同时
1.创建自定义网络 ,名为 `app-net` 1.创建自定义网络 ,名为 `app-net`
``` ```text
docker network create app-net docker network create app-net
``` ```
2.启动 MySQL 容器,并加入 `app-net` 网络,同时为其指定别名 `db` 2.启动 MySQL 容器,并加入 `app-net` 网络,同时为其指定别名 `db`
``` ```text
docker run -d --name mysql \ docker run -d --name mysql \
--network app-net \ --network app-net \
--network-alias db \ --network-alias db \
@ -287,7 +287,7 @@ docker run -d --name mysql \
3.启动 Web 应用容器,加入同一个 `app-net` 网络 3.启动 Web 应用容器,加入同一个 `app-net` 网络
``` ```text
docker run -d --name webapp \ docker run -d --name webapp \
--network app-net \ --network app-net \
your_webapp_image:latest your_webapp_image:latest
@ -295,7 +295,7 @@ docker run -d --name webapp \
4.验证容器间通信,进入 Web 应用容器,尝试通过别名 `db` 连接 MySQL 4.验证容器间通信,进入 Web 应用容器,尝试通过别名 `db` 连接 MySQL
``` ```text
docker exec -it webapp bash docker exec -it webapp bash
# 在 webapp 容器内执行,比如使用 ping 测试网络连通性: # 在 webapp 容器内执行,比如使用 ping 测试网络连通性:
ping db ping db
@ -303,7 +303,7 @@ ping db
举个例子,如果你的 Java 应用运行在容器 B 中,而数据库容器 A 已经通过 `--network-alias db` 起了别名,那么在 Java 应用中,你只需要写: 举个例子,如果你的 Java 应用运行在容器 B 中,而数据库容器 A 已经通过 `--network-alias db` 起了别名,那么在 Java 应用中,你只需要写:
``` ```text
String dbUrl = "jdbc:mysql://db:3306/your_database"; String dbUrl = "jdbc:mysql://db:3306/your_database";
``` ```
@ -311,7 +311,7 @@ String dbUrl = "jdbc:mysql://db:3306/your_database";
否则: 否则:
``` ```text
String dbUrl = "jdbc:mysql://<宿主机IP或localhost>:3306/your_database"; String dbUrl = "jdbc:mysql://<宿主机IP或localhost>:3306/your_database";
``` ```
@ -322,13 +322,13 @@ String dbUrl = "jdbc:mysql://<宿主机IP或localhost>:3306/your_database";
接时可以使用 `--alias` 参数为容器在该网络中设置别名 接时可以使用 `--alias` 参数为容器在该网络中设置别名
``` ```text
docker network connect app-net mysql --alias db docker network connect app-net mysql --alias db
``` ```
6.断开连接 6.断开连接
``` ```text
docker network disconnect app-net mysql docker network disconnect app-net mysql
``` ```
@ -336,7 +336,7 @@ docker network disconnect app-net mysql
需要注意的是,只有当网络中没有容器连接时才能删除。 需要注意的是,只有当网络中没有容器连接时才能删除。
``` ```text
docker network rm app-net docker network rm app-net
docker network prune #删除所有未使用的网络 docker network prune #删除所有未使用的网络
``` ```
@ -361,7 +361,7 @@ sudo apt-get remove docker docker-engine docker.io containerd runc
在安装新版 Docker 前,需要更新 apt 源并安装一些依赖包,以便能够通过 HTTPS 协议访问 Docker 官方仓库。 在安装新版 Docker 前,需要更新 apt 源并安装一些依赖包,以便能够通过 HTTPS 协议访问 Docker 官方仓库。
``` ```text
sudo apt-get update sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
``` ```
@ -372,7 +372,7 @@ sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
**3.添加 Docker 官方 GPG 密钥** **3.添加 Docker 官方 GPG 密钥**
``` ```text
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
``` ```
@ -386,13 +386,13 @@ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o
这是最关键的一步配置docker官方地址往往**很难下载** 这是最关键的一步配置docker官方地址往往**很难下载**
``` ```text
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
``` ```
推荐使用以下阿里云的镜像加速源 推荐使用以下阿里云的镜像加速源
``` ```text
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
``` ```
@ -404,7 +404,7 @@ cat /etc/apt/sources.list.d/docker.list 可以查看是否配置成功
更新 apt 缓存后,安装最新版的 Docker Engine、CLI 工具和 containerd 更新 apt 缓存后,安装最新版的 Docker Engine、CLI 工具和 containerd
``` ```text
sudo apt update #如果是docker官方,这一步可能失败! sudo apt update #如果是docker官方,这一步可能失败!
sudo apt install docker-ce docker-ce-cli containerd.io sudo apt install docker-ce docker-ce-cli containerd.io
``` ```
@ -441,11 +441,11 @@ linux vim
### docker配置代理 ### docker配置代理
``` ```text
sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf
``` ```
``` ```text
[Service] [Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890" Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890" Environment="HTTPS_PROXY=http://127.0.0.1:7890"
@ -454,12 +454,12 @@ Environment="NO_PROXY=localhost,127.0.0.1"
``` ```text
sudo systemctl daemon-reload //加载配置文件,更新环境变量 sudo systemctl daemon-reload //加载配置文件,更新环境变量
sudo systemctl restart docker sudo systemctl restart docker
``` ```
``` ```text
systemctl show --property=Environment docker //验证是否配置成功 systemctl show --property=Environment docker //验证是否配置成功
``` ```
@ -469,13 +469,13 @@ systemctl show --property=Environment docker //验证是否配置成功
1.编辑 Docker 配置文件,如果该文件不存在,可以创建一个新的文件。 1.编辑 Docker 配置文件,如果该文件不存在,可以创建一个新的文件。
``` ```text
sudo vim /etc/docker/daemon.json sudo vim /etc/docker/daemon.json
``` ```
2.添加多个镜像仓库配置 2.添加多个镜像仓库配置
``` ```text
{ {
"registry-mirrors": [ "registry-mirrors": [
"http://hub-mirror.c.163.com", "http://hub-mirror.c.163.com",
@ -491,13 +491,13 @@ sudo vim /etc/docker/daemon.json
3.重启 Docker 服务以应用 3.重启 Docker 服务以应用
``` ```text
sudo systemctl restart docker sudo systemctl restart docker
``` ```
4.验证配置 4.验证配置
``` ```text
docker info docker info
``` ```
@ -513,7 +513,7 @@ docker info
在 Dockerfile 中RUN 指令用于在构建镜像的过程中执行命令,这些命令会在镜像的一个临时容器中执行,然后将执行结果作为新的镜像层保存下来。常见的用途包括安装软件包、修改系统配置、编译代码等。 在 Dockerfile 中RUN 指令用于在构建镜像的过程中执行命令,这些命令会在镜像的一个临时容器中执行,然后将执行结果作为新的镜像层保存下来。常见的用途包括安装软件包、修改系统配置、编译代码等。
``` ```text
RUN cd $JAVA_DIR \ RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \ && tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8 && mv ./jdk1.8.0_144 ./java8
@ -525,7 +525,7 @@ RUN cd $JAVA_DIR \
当你修改原镜像时,只需使用相同的镜像名执行: 当你修改原镜像时,只需使用相同的镜像名执行:
``` ```text
docker build -t zbparse . docker build -t zbparse .
``` ```
@ -544,7 +544,7 @@ Docker 会根据 **Dockerfile 和上下文的变化**来判断哪些层需要重
以下方法可以删除none镜像。 以下方法可以删除none镜像。
``` ```text
# 查找无标签镜像 # 查找无标签镜像
docker images -f "dangling=true" docker images -f "dangling=true"
# 删除无标签镜像 # 删除无标签镜像
@ -561,7 +561,7 @@ docker rmi $(docker images -f "dangling=true" -q)
1. 编写dockerfile文件 1. 编写dockerfile文件
``` ```text
# 使用官方 Python 运行时作为父镜像 # 使用官方 Python 运行时作为父镜像
FROM python:3.8-slim FROM python:3.8-slim
@ -599,19 +599,19 @@ docker rmi $(docker images -f "dangling=true" -q)
5. 构造镜像 -t后面是镜像名 ,最后的点号 (`.`) 代表当前目录 5. 构造镜像 -t后面是镜像名 ,最后的点号 (`.`) 代表当前目录
``` ```text
docker build -t zbparse . docker build -t zbparse .
``` ```
5. 运行容器 -p后面第一个5000代表宿主机端口第二个5000代表容器内端口 zbparse-container为创建的容器名zbparse是使用的镜像名字 5. 运行容器 -p后面第一个5000代表宿主机端口第二个5000代表容器内端口 zbparse-container为创建的容器名zbparse是使用的镜像名字
``` ```text
docker run -d -p 5000:5000 --name zbparse-container zbparse docker run -d -p 5000:5000 --name zbparse-container zbparse
``` ```
6. 查看日志 ,若无报错贼容器正常启动 6. 查看日志 ,若无报错贼容器正常启动
``` ```text
docker logs zbparse-container docker logs zbparse-container
docker logs --tail 10 [容器ID或名称] 查看最近10条日志 docker logs --tail 10 [容器ID或名称] 查看最近10条日志
docker logs --since 1h [容器ID或名称] 查看最近1小时的日志 docker logs --since 1h [容器ID或名称] 查看最近1小时的日志
@ -619,32 +619,32 @@ docker logs --since 1h [容器ID或名称] 查看最近1小时的日志
7. 停止和删除容器,先停止后删除 7. 停止和删除容器,先停止后删除
``` ```text
docker stop zbparse-container docker stop zbparse-container
docker rm zbparse-container docker rm zbparse-container
``` ```
8. 删除镜像 8. 删除镜像
``` ```text
docker rmi zbparse docker rmi zbparse
``` ```
9. 进入容器,可以查看容器内的数据 9. 进入容器,可以查看容器内的数据
``` ```text
docker exec -it zbparse-container /bin/bash docker exec -it zbparse-container /bin/bash
``` ```
10. 保存镜像为tar文件 最简单的应该是上传docker hub镜像库但是现在貌似被墙了 10. 保存镜像为tar文件 最简单的应该是上传docker hub镜像库但是现在貌似被墙了
``` ```text
docker save -o zbparse.tar zbparse docker save -o zbparse.tar zbparse
``` ```
11. 使用scp传输文件 11. 使用scp传输文件
``` ```text
scp zbparse.tar root@118.178.236.139:/home/zy scp zbparse.tar root@118.178.236.139:/home/zy
``` ```
@ -652,13 +652,13 @@ scp zbparse.tar root@118.178.236.139:/home/zy
12. 加载镜像 12. 加载镜像
``` ```text
sudo docker load -i zbparse.tar sudo docker load -i zbparse.tar
``` ```
13. 上传镜像 13. 上传镜像
``` ```text
docker login #输入邮箱 密码 docker login #输入邮箱 密码
docker tag zbparse yourusername/zbparse #标记你的 Docker 镜像 docker tag zbparse yourusername/zbparse #标记你的 Docker 镜像
#其中yourusername/zbparse是标记名 #其中yourusername/zbparse是标记名
@ -676,7 +676,7 @@ docker tag zbparse 646228430smile/zbparse:latest 这里的646228430smile是用
14. 查看镜像 14. 查看镜像
``` ```text
docker images docker images
``` ```
@ -686,7 +686,7 @@ docker images
- **linux中构建镜像问题** - **linux中构建镜像问题**
``` ```text
RuntimeError: cant start new thread。 RuntimeError: cant start new thread。
``` ```
@ -697,7 +697,7 @@ RUN pip config set global.progress_bar off
``` ```text
=> [flask_app internal] load build definition from Dockerfile 0.0s => [flask_app internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 982B 0.0s => => transferring dockerfile: 982B 0.0s
=> ERROR [flask_app internal] load metadata for docker.io/library/python:3.8-slim 60.4s => ERROR [flask_app internal] load metadata for docker.io/library/python:3.8-slim 60.4s
@ -719,14 +719,14 @@ exit status 1
- **docker运行权限问题** - **docker运行权限问题**
``` ```text
OpenBLAS blas_thread_init: pthread_create failed for thread 1 of 4: Operation not permitted OpenBLAS blas_thread_init: pthread_create failed for thread 1 of 4: Operation not permitted
OpenBLAS blas_thread_init: RLIMIT_NPROC -1 current, -1 max OpenBLAS blas_thread_init: RLIMIT_NPROC -1 current, -1 max
``` ```
解决方法: 解决方法:
``` ```text
docker run --name zbparse-container --security-opt seccomp=unconfined zbparse docker run --name zbparse-container --security-opt seccomp=unconfined zbparse
``` ```
@ -740,7 +740,7 @@ docker run --name zbparse-container --security-opt seccomp=unconfined zbparse
验证安装 验证安装
``` ```text
docker compose version docker compose version
``` ```
@ -748,19 +748,19 @@ docker compose version
下载二进制文件(或者下载别人的镜像复制到服务器中的/usr/local/bin下 下载二进制文件(或者下载别人的镜像复制到服务器中的/usr/local/bin下
``` ```text
sudo curl -L "https://mirrors.aliyun.com/docker-ce/linux/static/stable/x86_64/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo curl -L "https://mirrors.aliyun.com/docker-ce/linux/static/stable/x86_64/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
``` ```
赋予执行权限 赋予执行权限
``` ```text
sudo chmod +x /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
``` ```
验证安装 验证安装
``` ```text
docker-compose --version docker-compose --version
``` ```
@ -793,7 +793,7 @@ docker-compose --version
``` ```text
version: '3' version: '3'
services: services:
@ -839,7 +839,7 @@ volumes:
``` ```text
build: build:
context: ./web_app context: ./web_app
dockerfile: Dockerfile dockerfile: Dockerfile
@ -855,13 +855,13 @@ build: ./web_app #两种写法是等效的
**构建镜像:**这个命令根据 docker-compose.yml 中各服务的配置构建镜像。如果你修改了 Dockerfile 或者项目代码需要打包进镜像时,就需要运行该命令来构建新的镜像。 **构建镜像:**这个命令根据 docker-compose.yml 中各服务的配置构建镜像。如果你修改了 Dockerfile 或者项目代码需要打包进镜像时,就需要运行该命令来构建新的镜像。
``` ```text
docker-compose build docker-compose build
``` ```
**启动容器:**这个命令用于启动服务,参数 `-d` 表示以后台守护进程的方式运行。如果镜像不存在,它会自动构建镜像;但如果镜像已经存在,则默认直接使用现有的镜像启动容器。 **启动容器:**这个命令用于启动服务,参数 `-d` 表示以后台守护进程的方式运行。如果镜像不存在,它会自动构建镜像;但如果镜像已经存在,则默认直接使用现有的镜像启动容器。
``` ```text
docker-compose up -d docker-compose up -d
``` ```
@ -869,19 +869,19 @@ docker-compose up -d
**只针对 pyapp 服务进行重构和启动,不影响其他服务运行** **只针对 pyapp 服务进行重构和启动,不影响其他服务运行**
``` ```text
docker-compose build pyapp docker-compose build pyapp
``` ```
启动容器并进入bash 启动容器并进入bash
``` ```text
docker compose run --rm -it pyapp /bin/bash docker compose run --rm -it pyapp /bin/bash
``` ```
运行脚本 运行脚本
``` ```text
python typecho_markdown_upload/main.py python typecho_markdown_upload/main.py
``` ```
@ -889,7 +889,7 @@ python typecho_markdown_upload/main.py
**更新并重启容器** **更新并重启容器**
``` ```text
docker-compose up --build -d docker-compose up --build -d
``` ```
@ -901,40 +901,40 @@ docker-compose up --build -d
**查看服务的日志输出** **查看服务的日志输出**
``` ```text
docker-compose logs flask_app --since 1h #只显示最近 1 小时 docker-compose logs flask_app --since 1h #只显示最近 1 小时
``` ```
**停止并删除所有由 docker-compose 启动的容器、网络等(默认不影响挂载卷)。** **停止并删除所有由 docker-compose 启动的容器、网络等(默认不影响挂载卷)。**
``` ```text
docker-compose down #不能单独指定 docker-compose down #不能单独指定
``` ```
**删除停止的容器** **删除停止的容器**
``` ```text
docker-compose rm docker-compose rm
docker-compose rm flask_app docker-compose rm flask_app
``` ```
**停止运行的容器** **停止运行的容器**
``` ```text
docker-compose stop docker-compose stop
docker-compose stop flask_app #指定某个服务 docker-compose stop flask_app #指定某个服务
``` ```
**启动服务** **启动服务**
``` ```text
docker-compose start #启动所有停止的.. docker-compose start #启动所有停止的..
docker-compose start flask_app docker-compose start flask_app
``` ```
**重启服务(停止+启动)** **重启服务(停止+启动)**
``` ```text
docker-compose restart docker-compose restart
docker-compose restart flask_app #指定某个服务 docker-compose restart flask_app #指定某个服务
``` ```
@ -953,13 +953,13 @@ docker-compose up生成的容器名默认是 `项目名_服务名_索引号`
``` ```text
docker-compose -p my_custom_project up -d docker-compose -p my_custom_project up -d
``` ```
在docker-compose.yml中指定容器名 在docker-compose.yml中指定容器名
``` ```text
version: '3' version: '3'
services: services:
web: web:
@ -986,7 +986,7 @@ services:
一个**基础镜像可以构造多个容器**,互不影响, 一个**基础镜像可以构造多个容器**,互不影响,
``` ```text
db: db:
image: mysql:8.0 image: mysql:8.0
environment: environment:
@ -998,7 +998,7 @@ db:
- db_data_project1:/var/lib/mysql - db_data_project1:/var/lib/mysql
``` ```
``` ```text
db: db:
image: mysql:8.0 image: mysql:8.0
environment: environment:
@ -1036,13 +1036,13 @@ db:
1.创建一个 Docker 网络 1.创建一个 Docker 网络
``` ```text
docker network create my_shared_network docker network create my_shared_network
``` ```
2.创建 MySQL 的 `docker-compose-mysql.yml` 2.创建 MySQL 的 `docker-compose-mysql.yml`
``` ```text
version: '3' version: '3'
services: services:
mysql: mysql:
@ -1063,7 +1063,7 @@ networks:
3.在 `docker-compose-app.yml` 里连接这个 MySQL 3.在 `docker-compose-app.yml` 里连接这个 MySQL
``` ```text
version: '3' version: '3'
services: services:
web_app: web_app:
@ -1100,13 +1100,13 @@ networks:
4.启动 MySQL 容器 4.启动 MySQL 容器
``` ```text
docker-compose -f docker-compose-mysql.yml up -d docker-compose -f docker-compose-mysql.yml up -d
``` ```
5.启动 Web 应用 5.启动 Web 应用
``` ```text
docker-compose -f docker-compose-app.yml up -d docker-compose -f docker-compose-app.yml up -d
``` ```

View File

@ -97,7 +97,7 @@
这里使用了第二种CSS引入方式内嵌样式<style>CSS 这里使用了第二种CSS引入方式内嵌样式<style>CSS
``` ```text
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -221,7 +221,7 @@ box-sizing: border-box此时指定width height为盒子的高宽而不是c
``` ```text
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -386,7 +386,7 @@ function 函数名(参数1,参数2..){
如下示例: 如下示例:
``` ```text
function add(a, b){ function add(a, b){
return a + b; return a + b;
} }
@ -398,7 +398,7 @@ var result=add(10,20)可以接收返回值
第二种可以通过var去定义函数的名字具体格式如下 第二种可以通过var去定义函数的名字具体格式如下
``` ```text
var functionName = function (参数1,参数2..){ var functionName = function (参数1,参数2..){
//要执行的代码 //要执行的代码
} }
@ -406,7 +406,7 @@ var functionName = function (参数1,参数2..){
如下示例: 如下示例:
``` ```text
var add = function(a,b){ var add = function(a,b){
return a + b; return a + b;
} }
@ -464,7 +464,7 @@ var arr = [1,2,3,4]; //1,2,3,4 是存储在数组中的数据(元素)
普通for循环会遍历每个数组元素无论是否有值 普通for循环会遍历每个数组元素无论是否有值
``` ```text
var arr = [1,2,3,4]; var arr = [1,2,3,4];
arr[10] = 50; arr[10] = 50;
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
@ -474,7 +474,7 @@ arr[10] = 50;
foreach foreach
``` ```text
arr.forEach(function(e){ arr.forEach(function(e){
console.log(e); console.log(e);
}) })
@ -482,7 +482,7 @@ arr.forEach(function(e){
在ES6中引入箭头函数的写法语法类似java中lambda表达式修改上述代码如下 在ES6中引入箭头函数的写法语法类似java中lambda表达式修改上述代码如下
``` ```text
arr.forEach((e) => { arr.forEach((e) => {
console.log(e); console.log(e);
}) })
@ -563,7 +563,7 @@ String对象也提供了一些常用的属性和方法如下表格所示
##### 自定义对象 ##### 自定义对象
``` ```text
var 对象名 = { var 对象名 = {
属性名1: 属性值1, 属性名1: 属性值1,
属性名2: 属性值2, 属性名2: 属性值2,
@ -600,7 +600,7 @@ JSON对象**J**ava**S**cript **O**bject **N**otationJavaScript对象标记
JSON字符串示例 JSON字符串示例
``` ```text
var jsonstr = '{"name":"Tom", "age":18, "addr":["北京","上海","西安"]}'; var jsonstr = '{"name":"Tom", "age":18, "addr":["北京","上海","西安"]}';
alert(jsonstr.name); alert(jsonstr.name);
``` ```
@ -609,7 +609,7 @@ alert(jsonstr.name);
JSON字符串=》JS对象 JSON字符串=》JS对象
``` ```text
var obj = JSON.parse(jsonstr); var obj = JSON.parse(jsonstr);
``` ```
@ -617,7 +617,7 @@ var obj = JSON.parse(jsonstr);
JS对象=》JS字符串 JS对象=》JS字符串
``` ```text
var jsonstr=JSON.stringify(obj) var jsonstr=JSON.stringify(obj)
``` ```
@ -646,7 +646,7 @@ fn:函数,需要周期性执行的功能代码
毫秒值:间隔时间 毫秒值:间隔时间
``` ```text
//定时器 - setInterval -- 周期性的执行某一个函数 //定时器 - setInterval -- 周期性的执行某一个函数
var i = 0; var i = 0;
setInterval(function(){ setInterval(function(){
@ -676,7 +676,7 @@ setTimeout(function(){
location是指代浏览器的地址栏对象对于这个对象我们常用的是href**属性**,用于获取或者设置浏览器的地址信息,添加如下代码: location是指代浏览器的地址栏对象对于这个对象我们常用的是href**属性**,用于获取或者设置浏览器的地址信息,添加如下代码:
``` ```text
//获取浏览器地址栏信息 //获取浏览器地址栏信息
alert(location.href); alert(location.href);
//设置浏览器地址栏信息 //设置浏览器地址栏信息
@ -723,7 +723,7 @@ DOMDocument Object Model 文档对象模型。也就是 JavaScript 将 HTML
示例代码: 示例代码:
``` ```text
<body> <body>
<img id="h1" src="img/off.gif"> <br><br> <img id="h1" src="img/off.gif"> <br><br>
@ -738,7 +738,7 @@ DOMDocument Object Model 文档对象模型。也就是 JavaScript 将 HTML
- document.getElementById() 根据标签的id属性获取标签对象id是唯一的所以获取到是单个标签对象。 - document.getElementById() 根据标签的id属性获取标签对象id是唯一的所以获取到是单个标签对象。
``` ```text
<script> <script>
//1. 获取Element元素 //1. 获取Element元素
@ -750,7 +750,7 @@ DOMDocument Object Model 文档对象模型。也就是 JavaScript 将 HTML
- document.getElementsByTagName() : 根据标签的名字获取标签对象,同名的标签有很多,所以返回值是数组。<font color=red>重点!</font> - document.getElementsByTagName() : 根据标签的名字获取标签对象,同名的标签有很多,所以返回值是数组。<font color=red>重点!</font>
``` ```text
var divs = document.getElementsByTagName('div'); var divs = document.getElementsByTagName('div');
for (let i = 0; i < divs.length; i++) { for (let i = 0; i < divs.length; i++) {
alert(divs[i]); alert(divs[i]);
@ -765,7 +765,7 @@ for (let i = 0; i < divs.length; i++) {
![image-20240228185708363](https://pic.bitday.top/i/2025/03/19/u6k7vg-2.png) ![image-20240228185708363](https://pic.bitday.top/i/2025/03/19/u6k7vg-2.png)
``` ```text
var divs = document.getElementsByClassName('cls'); var divs = document.getElementsByClassName('cls');
var div1 = divs[0]; var div1 = divs[0];
div1.innerHTML = "传智教育666"; div1.innerHTML = "传智教育666";
@ -777,7 +777,7 @@ JavaScript对于事件的绑定提供了2种方式
- 方式1通过html标签中的事件属性进行绑定 - 方式1通过html标签中的事件属性进行绑定
``` ```text
<input type="button" id="btn1" value="事件绑定1" onclick="on()"> <input type="button" id="btn1" value="事件绑定1" onclick="on()">
<script> <script>
function on(){ function on(){
@ -788,7 +788,7 @@ JavaScript对于事件的绑定提供了2种方式
- 方式2通过DOM中Element元素的事件属性进行绑定 - 方式2通过DOM中Element元素的事件属性进行绑定
``` ```text
<input type="button" id="btn2" value="事件绑定2"> <input type="button" id="btn2" value="事件绑定2">
<script> <script>
document.getElementById('btn2').onclick = function(){ document.getElementById('btn2').onclick = function(){
@ -831,13 +831,13 @@ MVVM:其实是Model-View-ViewModel的缩写有3个单词具体释义如下
第二步:然后编写&lt;script&gt;标签来引入vue.js文件代码如下 第二步:然后编写&lt;script&gt;标签来引入vue.js文件代码如下
``` ```text
<script src="js/vue.js"></script> <script src="js/vue.js"></script>
``` ```
第三步在js代码区域定义vue对象,代码如下: 第三步在js代码区域定义vue对象,代码如下:
``` ```text
<script> <script>
//定义Vue对象 //定义Vue对象
new Vue({ new Vue({
@ -894,7 +894,7 @@ MVVM:其实是Model-View-ViewModel的缩写有3个单词具体释义如下
data属性中数据变化我们知道可以通过赋值来改变但是视图数据为什么会发生变化呢**只有表单项标签!所以双向绑定一定是使用在表单项标签上的**。 data属性中数据变化我们知道可以通过赋值来改变但是视图数据为什么会发生变化呢**只有表单项标签!所以双向绑定一定是使用在表单项标签上的**。
``` ```text
<body> <body>
<div id="app"> <div id="app">
<a v-bind:href="url">链接1</a> <a v-bind:href="url">链接1</a>
@ -917,19 +917,19 @@ data属性中数据变化我们知道可以通过赋值来改变但是视
v-on: 用来给html标签绑定事件的 v-on: 用来给html标签绑定事件的
``` ```text
<input type="button" value="点我一下" v-on:click="handle()"> <input type="button" value="点我一下" v-on:click="handle()">
``` ```
简写: 简写:
``` ```text
<input type="button" value="点我一下" @click="handle()"> <input type="button" value="点我一下" @click="handle()">
``` ```
script script
``` ```text
<script> <script>
//定义Vue对象 //定义Vue对象
new Vue({ new Vue({
@ -948,14 +948,14 @@ script
#### v-if和v-show #### v-if和v-show
``` ```text
年龄<input type="text" v-model="age">经判定,为: 年龄<input type="text" v-model="age">经判定,为:
<span v-if="age <= 35">年轻人(35及以下)</span> <span v-if="age <= 35">年轻人(35及以下)</span>
<span v-else-if="age > 35 && age < 60">中年人(35-60)</span> <span v-else-if="age > 35 && age < 60">中年人(35-60)</span>
<span v-else>老年人(60及以上)</span> <span v-else>老年人(60及以上)</span>
``` ```
``` ```text
年龄<input type="text" v-model="age">经判定,为: 年龄<input type="text" v-model="age">经判定,为:
<span v-show="age <= 35">年轻人(35及以下)</span> <span v-show="age <= 35">年轻人(35及以下)</span>
<span v-show="age > 35 && age < 60">中年人(35-60)</span> <span v-show="age > 35 && age < 60">中年人(35-60)</span>
@ -968,7 +968,7 @@ v-show和v-if的作用效果是一样的只是原理不一样。v-if指令
v-for: 从名字我们就能看出,这个指令是用来遍历的。其语法格式如下: v-for: 从名字我们就能看出,这个指令是用来遍历的。其语法格式如下:
``` ```text
<div id="app"> <div id="app">
<div v-for="addr in addrs">{{addr}}</div> <div v-for="addr in addrs">{{addr}}</div>
<hr> <hr>
@ -976,7 +976,7 @@ v-for: 从名字我们就能看出,这个指令是用来遍历的。其语法
</div> </div>
``` ```
``` ```text
<script> <script>
//定义Vue对象 //定义Vue对象
new Vue({ new Vue({
@ -1068,13 +1068,13 @@ Axios的使用比较简单主要分为2步
| axios.post(url [, data[, config]]) | 发送post请求 | | axios.post(url [, data[, config]]) | 发送post请求 |
| axios.put(url [, data[, config]]) | 发送put请求 | | axios.put(url [, data[, config]]) | 发送put请求 |
``` ```text
axios.get("http://yapi.smart-xwork.cn/mock/169327/emp/list").then(result => { axios.get("http://yapi.smart-xwork.cn/mock/169327/emp/list").then(result => {
console.log(result.data); console.log(result.data);
}) })
``` ```
``` ```text
axios.post("http://yapi.smart-xwork.cn/mock/169327/emp/deleteById","id=1").then(result => { axios.post("http://yapi.smart-xwork.cn/mock/169327/emp/deleteById","id=1").then(result => {
console.log(result.data); console.log(result.data);
}) })
@ -1089,7 +1089,7 @@ axios.post("http://yapi.smart-xwork.cn/mock/169327/emp/deleteById","id=1").then(
3. 拿到数据数据需要绑定给vue的data属性 3. 拿到数据数据需要绑定给vue的data属性
4. 在&lt;tr&gt;标签上通过v-for指令遍历数据展示数据这里同Vue中的步骤。 4. 在&lt;tr&gt;标签上通过v-for指令遍历数据展示数据这里同Vue中的步骤。
``` ```text
<script> <script>
new Vue({ new Vue({
el: "#app", el: "#app",

View File

@ -99,7 +99,7 @@ IDEA 会自动解析 `pom.xml`,下载依赖并构建项目结构。
1.新建一个上层目录如下MyProject1和MyProject2的内容拷贝过去。 1.新建一个上层目录如下MyProject1和MyProject2的内容拷贝过去。
``` ```text
ParentProject/ ParentProject/
├── pom.xml <-- 父模块聚合模块 ├── pom.xml <-- 父模块聚合模块
├── MyProject1/ <-- 子模块1 ├── MyProject1/ <-- 子模块1
@ -112,7 +112,7 @@ ParentProject/
父模块 `pom.xml` 示例: 父模块 `pom.xml` 示例:
``` ```text
<project> <project>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId> <groupId>com.example</groupId>
@ -130,7 +130,7 @@ ParentProject/
3.修改子模块 `pom.xml` ,加上: 3.修改子模块 `pom.xml` ,加上:
``` ```text
<parent> <parent>
<groupId>com.example</groupId> <groupId>com.example</groupId>
<artifactId>ParentProject</artifactId> <artifactId>ParentProject</artifactId>
@ -155,7 +155,7 @@ ParentProject/
在第二个项目的 `pom.xml` 中添加依赖坐标 在第二个项目的 `pom.xml` 中添加依赖坐标
``` ```text
<dependency> <dependency>
<groupId>com.example</groupId> <groupId>com.example</groupId>
<artifactId>my-first-project</artifactId> <artifactId>my-first-project</artifactId>
@ -181,7 +181,7 @@ Maven 重建
可以到mvn的中央仓库https://mvnrepository.com/)中搜索获取依赖的坐标信息 可以到mvn的中央仓库https://mvnrepository.com/)中搜索获取依赖的坐标信息
``` ```text
<dependencies> <dependencies>
<!-- 第1个依赖 : logback --> <!-- 第1个依赖 : logback -->
<dependency> <dependency>
@ -207,7 +207,7 @@ Maven 重建
A依赖BB依赖C如果A不想将C依赖进来可以同时排除C被排除的资源**无需指定版本**。 A依赖BB依赖C如果A不想将C依赖进来可以同时排除C被排除的资源**无需指定版本**。
``` ```text
<dependency> <dependency>
<groupId>com.itheima</groupId> <groupId>com.itheima</groupId>
<artifactId>maven-projectB</artifactId> <artifactId>maven-projectB</artifactId>
@ -254,7 +254,7 @@ A依赖BB依赖C如果A不想将C依赖进来可以同时排除C
1. 导入依赖junit 1. 导入依赖junit
``` ```text
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
@ -267,7 +267,7 @@ A依赖BB依赖C如果A不想将C依赖进来可以同时排除C
3. 创建test方法 3. 创建test方法
``` ```text
@Test @Test
public void test1(){ public void test1(){
System.out.println("hello1"); System.out.println("hello1");
@ -326,7 +326,7 @@ A依赖BB依赖C如果A不想将C依赖进来可以同时排除C
新建HelloController类 新建HelloController类
``` ```text
package edu.whut.controller; package edu.whut.controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -343,7 +343,7 @@ public class HelloController {
然后启动服务器,main程序 然后启动服务器,main程序
``` ```text
package edu.whut; package edu.whut;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
@ -369,7 +369,7 @@ public class SprintbootQuickstartApplication {
- 在Springboot的环境中对原始的API进行了封装接收参数的形式更加简单。 如果是简单参数,参数名与形参变量名相同,定义同名的形参即可接收参数。 - 在Springboot的环境中对原始的API进行了封装接收参数的形式更加简单。 如果是简单参数,参数名与形参变量名相同,定义同名的形参即可接收参数。
``` ```text
@RestController @RestController
public class RequestController { public class RequestController {
// http://localhost:8080/simpleParam?name=Tom&age=10 // http://localhost:8080/simpleParam?name=Tom&age=10
@ -391,7 +391,7 @@ public class RequestController {
在方法形参前面加上 @RequestParam 然后通过value属性执行请求参数名从而完成映射。代码如下 在方法形参前面加上 @RequestParam 然后通过value属性执行请求参数名从而完成映射。代码如下
``` ```text
@RestController @RestController
public class RequestController { public class RequestController {
// http://localhost:8080/simpleParam?name=Tom&age=20 // http://localhost:8080/simpleParam?name=Tom&age=20
@ -418,7 +418,7 @@ public class RequestController {
![image-20240303112109981](https://pic.bitday.top/i/2025/03/19/u6ndfm-2.png) ![image-20240303112109981](https://pic.bitday.top/i/2025/03/19/u6ndfm-2.png)
``` ```text
@RequestMapping("/complexpojo") @RequestMapping("/complexpojo")
public String complexpojo(User user){ public String complexpojo(User user){
System.out.println(user); System.out.println(user);
@ -426,7 +426,7 @@ public class RequestController {
} }
``` ```
``` ```text
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@ -437,7 +437,7 @@ public class User {
} }
``` ```
``` ```text
package edu.whut.pojo; package edu.whut.pojo;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@ -452,7 +452,7 @@ public class Address {
数组参数:**请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数** 数组参数:**请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数**
``` ```text
@RestController @RestController
public class RequestController { public class RequestController {
//数组集合参数 //数组集合参数
@ -470,7 +470,7 @@ public class RequestController {
json数组 json数组
``` ```text
{ {
"退还时间点": [ "退还时间点": [
"与中标人签订合同后 5日内", "与中标人签订合同后 5日内",
@ -513,7 +513,7 @@ Postman发送JSON格式数据
- 传递json格式的参数在Controller中会使用实体类进行封装。 - 传递json格式的参数在Controller中会使用实体类进行封装。
- 封装规则:**JSON数据键名与形参对象属性名相同定义POJO类型形参即可接收参数。需要使用 @RequestBody标识。** - 封装规则:**JSON数据键名与形参对象属性名相同定义POJO类型形参即可接收参数。需要使用 @RequestBody标识。**
``` ```text
@RestController @RestController
public class RequestController { public class RequestController {
//JSON参数 //JSON参数
@ -532,7 +532,7 @@ public class RequestController {
//把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类) //把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
String json = JSONObject.toJSONString(responseResult); String json = JSONObject.toJSONString(responseResult);
``` ```text
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
@ -553,7 +553,7 @@ http://localhost:880/user/1/0
上述的这种传递请求参数的形式呢,我们称之为:路径参数。 上述的这种传递请求参数的形式呢,我们称之为:路径参数。
``` ```text
@RestController @RestController
public class RequestController { public class RequestController {
//路径参数 //路径参数
@ -595,7 +595,7 @@ public class RequestController {
定义在一个实体类Result来包含以上信息。代码如下 定义在一个实体类Result来包含以上信息。代码如下
``` ```text
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@ -631,7 +631,7 @@ Controller层接收请求调用Service层Service层先调用Dao层获取
**但是**这样每次要更换ServiceA->ServiceB时需要修改Controller层的代码 **但是**这样每次要更换ServiceA->ServiceB时需要修改Controller层的代码
``` ```text
private EmpService empService=new EmpServiceA(); //原来 private EmpService empService=new EmpServiceA(); //原来
private EmpService empService=new EmpServiceB(); //现在 private EmpService empService=new EmpServiceB(); //现在
``` ```
@ -697,7 +697,7 @@ Component衍生注解
1. `@RequestMapping("/jsonParam")`这是一个控制器方法级别的注解用于将HTTP请求映射到相应的处理方法上。在这个例子中它表示当收到路径为 "/jsonParam" 的HTTP请求时应该调用这个方法来处理请求。`@RequestMapping` 注解可以用来指定路径、HTTP方法、请求参数等信息以便Spring框架能够正确地将请求分发到对应的处理方法上。 1. `@RequestMapping("/jsonParam")`这是一个控制器方法级别的注解用于将HTTP请求映射到相应的处理方法上。在这个例子中它表示当收到路径为 "/jsonParam" 的HTTP请求时应该调用这个方法来处理请求。`@RequestMapping` 注解可以用来指定路径、HTTP方法、请求参数等信息以便Spring框架能够正确地将请求分发到对应的处理方法上。
``` ```text
@RequestMapping("/jsonParam") @RequestMapping("/jsonParam")
public String jsonParam(@RequestBody User user){ public String jsonParam(@RequestBody User user){
System.out.println(user); System.out.println(user);
@ -714,7 +714,7 @@ Component衍生注解
4. `@PathVariable` 注解用于将路径变量 `{id}` 的值绑定到方法的参数 `id` 上。当请求的路径是 "/path/123" 时,`@PathVariable` 会将路径中的 "123" 值绑定到方法的参数 `id` 上,使得方法能够获取到这个值。在这个例子中,方法的参数 `id` 的值将会是整数值 123。 4. `@PathVariable` 注解用于将路径变量 `{id}` 的值绑定到方法的参数 `id` 上。当请求的路径是 "/path/123" 时,`@PathVariable` 会将路径中的 "123" 值绑定到方法的参数 `id` 上,使得方法能够获取到这个值。在这个例子中,方法的参数 `id` 的值将会是整数值 123。
``` ```text
public String pathParam(@PathVariable Integer id) { public String pathParam(@PathVariable Integer id) {
System.out.println(id); System.out.println(id);
return "OK"; return "OK";
@ -728,11 +728,11 @@ Component衍生注解
5. `@RequestParam`,如果方法的参数名与请求参数名不同,需要在 `@RequestParam` 注解中指定请求参数的名字。 5. `@RequestParam`,如果方法的参数名与请求参数名不同,需要在 `@RequestParam` 注解中指定请求参数的名字。
``` ```text
@RequestParam(defaultValue = "1" Integer page) //若page为null可以设置page的默认值为1 @RequestParam(defaultValue = "1" Integer page) //若page为null可以设置page的默认值为1
``` ```
``` ```text
@RequestMapping("/example") @RequestMapping("/example")
public String exampleMethod(@RequestParam String name, @RequestParam("age") int userAge) { public String exampleMethod(@RequestParam String name, @RequestParam("age") int userAge) {
// 在方法内部使用获取到的参数值进行处理 // 在方法内部使用获取到的参数值进行处理
@ -770,7 +770,7 @@ Component衍生注解
| @AllArgsConstructor | 为实体类生成除了static修饰的字段之外带有各参数的构造器方法。 | | @AllArgsConstructor | 为实体类生成除了static修饰的字段之外带有各参数的构造器方法。 |
| **@Slf4j** | 可以log.info("输出日志信息"); | | **@Slf4j** | 可以log.info("输出日志信息"); |
``` ```text
//equals 方法用于比较两个对象的内容是否相同 //equals 方法用于比较两个对象的内容是否相同
Address addr1 = new Address("SomeProvince", "SomeCity"); Address addr1 = new Address("SomeProvince", "SomeCity");
Address addr2 = new Address("SomeProvince", "SomeCity"); Address addr2 = new Address("SomeProvince", "SomeCity");
@ -816,7 +816,7 @@ http://localhost:8080/user/deleteUser?id=1 GET删除id为1的用户
**基于REST风格URL如下** **基于REST风格URL如下**
``` ```text
http://localhost:8080/users/1 GET查询id为1的用户 http://localhost:8080/users/1 GET查询id为1的用户
http://localhost:8080/users POST新增用户 http://localhost:8080/users POST新增用户
http://localhost:8080/users PUT修改用户 http://localhost:8080/users PUT修改用户
@ -869,7 +869,7 @@ http://localhost:8080/users/1 DELETE删除id为1的用户
2. 在springboot项目中可以编写main/resources/application.properties文件配置数据库连接信息。 2. 在springboot项目中可以编写main/resources/application.properties文件配置数据库连接信息。
``` ```text
#驱动类名称 #驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url #数据库连接的url
@ -890,7 +890,7 @@ spring.datasource.password=1234
@Select注解代表的就是select查询用于书写select查询语句 @Select注解代表的就是select查询用于书写select查询语句
``` ```text
@Mapper @Mapper
public interface UserMapper { public interface UserMapper {
//查询所有用户数据 //查询所有用户数据
@ -926,7 +926,7 @@ Lombok是一个实用的Java类库可以通过简单的注解来简化和消
**使用** **使用**
``` ```text
import lombok.Data; import lombok.Data;
@Data @Data
@ -947,7 +947,7 @@ public class User {
2. 开启mybatis的日志并指定输出到控制台 2. 开启mybatis的日志并指定输出到控制台
``` ```text
#指定mybatis输出日志的位置, 输出控制台 #指定mybatis输出日志的位置, 输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
``` ```
@ -962,7 +962,7 @@ mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
**作用于单个字段** **作用于单个字段**
``` ```text
@Mapper @Mapper
public interface EmpMapper { public interface EmpMapper {
//SQL语句中的id值不能写成固定数值需要变为动态的数值 //SQL语句中的id值不能写成固定数值需要变为动态的数值
@ -984,7 +984,7 @@ public interface EmpMapper {
**作用于多个字段** **作用于多个字段**
``` ```text
@Mapper @Mapper
public interface EmpMapper { public interface EmpMapper {
//会自动将生成的主键值赋值给emp对象的id属性 //会自动将生成的主键值赋值给emp对象的id属性
@ -1043,7 +1043,7 @@ eg:通过页面原型以及需求描述我们要实现的查询:
解决方案: 解决方案:
``` ```text
@Mapper @Mapper
public interface EmpMapper { public interface EmpMapper {
@ -1093,7 +1093,7 @@ public interface EmpMapper {
<mapper namespace="edu.whut.mapper.EmpMapper"> <mapper namespace="edu.whut.mapper.EmpMapper">
</mapper> </mapper>
``` ```text
XML映射文件的namespace属性为Mapper接口**全限定名**(包+类名) XML映射文件的namespace属性为Mapper接口**全限定名**(包+类名)
@ -1133,7 +1133,7 @@ public interface EmpMapper {
``` ```text
<select id="list" resultType="com.itheima.pojo.Emp"> <select id="list" resultType="com.itheima.pojo.Emp">
select * from emp select * from emp
<where> <where>
@ -1156,7 +1156,7 @@ public interface EmpMapper {
mapper接口: mapper接口:
``` ```text
@Mapper @Mapper
public interface EmpMapper { public interface EmpMapper {
//批量删除 //批量删除
@ -1168,7 +1168,7 @@ xml:
语法: 语法:
``` ```text
<foreach collection="集合名称" item="集合遍历出来的元素/项" separator="每一次遍历使用的分隔符" <foreach collection="集合名称" item="集合遍历出来的元素/项" separator="每一次遍历使用的分隔符"
open="遍历开始前拼接的片段" close="遍历结束后拼接的片段"> open="遍历开始前拼接的片段" close="遍历结束后拼接的片段">
</foreach> </foreach>
@ -1176,7 +1176,7 @@ xml:
``` ```text
<delete id="deleteByIds"> <delete id="deleteByIds">
delete from emp where id in delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")"> <foreach collection="ids" item="id" separator="," open="(" close=")">
@ -1253,7 +1253,7 @@ public PageBean page(Integer page, Integer pageSize) {
4、Controller 4、Controller
``` ```text
@Slf4j @Slf4j
@RestController @RestController
@RequestMapping("/emps") @RequestMapping("/emps")
@ -1284,7 +1284,7 @@ public class EmpController {
![image-20221215180528415](https://pic.bitday.top/i/2025/03/19/u6mjck-2.png) ![image-20221215180528415](https://pic.bitday.top/i/2025/03/19/u6mjck-2.png)
``` ```text
<select id="pageQuery" resultType="com.sky.entity.Employee"> <select id="pageQuery" resultType="com.sky.entity.Employee">
select * from employee select * from employee
<where> <where>
@ -1317,7 +1317,7 @@ public class EmpController {
> - byte[] getBytes(); //获取文件内容的字节数组 > - byte[] getBytes(); //获取文件内容的字节数组
> - InputStream getInputStream(); //获取接收到的文件内容的输入流 > - InputStream getInputStream(); //获取接收到的文件内容的输入流
``` ```text
@Slf4j @Slf4j
@RestController @RestController
public class UploadController { public class UploadController {
@ -1346,7 +1346,7 @@ public class UploadController {
那么如果需要上传大文件可以在application.properties进行如下配置 那么如果需要上传大文件可以在application.properties进行如下配置
``` ```text
#配置单个文件最大上传大小 #配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-file-size=10MB
@ -1390,7 +1390,7 @@ pom文件中添加如下依赖
上传文件的工具类 上传文件的工具类
``` ```text
package edu.whut.utils; package edu.whut.utils;
import com.aliyun.oss.OSS; import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.OSSClientBuilder;
@ -1473,7 +1473,7 @@ public class AliOSSUtils {
对象/map集合 对象/map集合
``` ```text
user: user:
name: zhangsan name: zhangsan
age: 18 age: 18
@ -1482,7 +1482,7 @@ user:
数组/List/Set集合 数组/List/Set集合
``` ```text
hobby: hobby:
- java - java
- game - game
@ -1495,7 +1495,7 @@ hobby:
前面获取配置项中的属性值,需要通过@Value注解,有时过于繁琐!!! 前面获取配置项中的属性值,需要通过@Value注解,有时过于繁琐!!!
``` ```text
@Component @Component
public class AliOSSUtils { public class AliOSSUtils {
@ -1529,7 +1529,7 @@ Spring提供的简化方式套路
4. (可选)引入依赖pom.xml 4. (可选)引入依赖pom.xml
``` ```text
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId> <artifactId>spring-boot-configuration-processor</artifactId>
@ -1593,7 +1593,7 @@ Spring提供的简化方式套路
引入依赖 引入依赖
``` ```text
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId> <artifactId>jjwt</artifactId>
@ -1603,7 +1603,7 @@ Spring提供的简化方式套路
生成与解析: 生成与解析:
``` ```text
public class JwtUtils { public class JwtUtils {
private static String signKey = "itheima"; private static String signKey = "itheima";
@ -1646,7 +1646,7 @@ public class JwtUtils {
**令牌可以存储当前登录用户的信息id、username等等传入claims** **令牌可以存储当前登录用户的信息id、username等等传入claims**
``` ```text
Map<String, Object> claims = new HashMap<>(); Map<String, Object> claims = new HashMap<>();
claims.put("id",emp.getId()); claims.put("id",emp.getId());
claims.put("name",e.getName()); claims.put("name",e.getName());
@ -1656,7 +1656,7 @@ String jwt=JwtUtils.generateJwt(claims);
**解析令牌:** **解析令牌:**
``` ```text
@Autowired @Autowired
private HttpServletRequest request; private HttpServletRequest request;
@ -1684,7 +1684,7 @@ private HttpServletRequest request;
1. **定义拦截器实现HandlerInterceptor接口并重写其所有方法** 1. **定义拦截器实现HandlerInterceptor接口并重写其所有方法**
``` ```text
//自定义拦截器 //自定义拦截器
@Component @Component
public class LoginCheckInterceptor implements HandlerInterceptor { public class LoginCheckInterceptor implements HandlerInterceptor {
@ -1720,7 +1720,7 @@ public class LoginCheckInterceptor implements HandlerInterceptor {
2. **注册配置拦截器实现WebMvcConfigurer接口并重写addInterceptors方法** 2. **注册配置拦截器实现WebMvcConfigurer接口并重写addInterceptors方法**
``` ```text
@Configuration @Configuration
public class WebConfig implements WebMvcConfigurer { public class WebConfig implements WebMvcConfigurer {
@ -1754,7 +1754,7 @@ addPathPatterns指定拦截路径
主要在preHandle中写逻辑 主要在preHandle中写逻辑
``` ```text
@Override //目标资源方法执行前执行。 返回true放行 返回false不放行 @Override //目标资源方法执行前执行。 返回true放行 返回false不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle .... "); System.out.println("preHandle .... ");
@ -1819,7 +1819,7 @@ addPathPatterns指定拦截路径
- 定义全局异常处理器非常简单,就是定义一个类,在类上加上一个注解**@RestControllerAdvice**,加上这个注解就代表我们定义了一个全局异常处理器。 - 定义全局异常处理器非常简单,就是定义一个类,在类上加上一个注解**@RestControllerAdvice**,加上这个注解就代表我们定义了一个全局异常处理器。
- 在全局异常处理器当中,需要定义一个方法来捕获异常,在这个方法上需要加上注解**@ExceptionHandler**。通过@ExceptionHandler注解当中的value属性来指定我们要捕获的是哪一类型的异常 - 在全局异常处理器当中,需要定义一个方法来捕获异常,在这个方法上需要加上注解**@ExceptionHandler**。通过@ExceptionHandler注解当中的value属性来指定我们要捕获的是哪一类型的异常
``` ```text
@RestControllerAdvice @RestControllerAdvice
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
@ -1878,7 +1878,7 @@ logging:
@Transactional注解的后面指定一个属性**propagation**,通过 propagation 属性来指定传播行为。可以在嵌套的子事务上加入。 @Transactional注解的后面指定一个属性**propagation**,通过 propagation 属性来指定传播行为。可以在嵌套的子事务上加入。
``` ```text
@Transactional(propagation = Propagation.REQUIRES_NEW) @Transactional(propagation = Propagation.REQUIRES_NEW)
``` ```
@ -1905,7 +1905,7 @@ AOP英文全称Aspect Oriented Programming面向切面编程、面向方
1. 导入依赖在pom.xml中导入AOP的依赖 1. 导入依赖在pom.xml中导入AOP的依赖
``` ```text
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId> <artifactId>spring-boot-starter-aop</artifactId>
@ -1914,7 +1914,7 @@ AOP英文全称Aspect Oriented Programming面向切面编程、面向方
2. 编写AOP程序针对于特定方法根据业务需要进行编程 2. 编写AOP程序针对于特定方法根据业务需要进行编程
``` ```text
@Component @Component
@Aspect //当前类为切面类 @Aspect //当前类为切面类
@Slf4j @Slf4j
@ -2016,7 +2016,7 @@ eg:@Order(1)
execution主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配语法为 execution主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配语法为
``` ```text
execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) throws 异常?) execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) throws 异常?)
``` ```
@ -2030,7 +2030,7 @@ execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) th
eg: eg:
``` ```text
@Before("execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))") @Before("execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
``` ```
@ -2040,7 +2040,7 @@ eg:
- `*` :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、**任意类型的一个参数**,也可以通配包、类、方法名的一部分 - `*` :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、**任意类型的一个参数**,也可以通配包、类、方法名的一部分
``` ```text
execution(* edu.*.service.*.update*(*)) execution(* edu.*.service.*.update*(*))
``` ```
@ -2058,7 +2058,7 @@ execution(* edu.*.service.*.update*(*))
1. **新建anno包在这个包下**编写自定义注解 1. **新建anno包在这个包下**编写自定义注解
``` ```text
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -2077,7 +2077,7 @@ public @interface MyLog {
2. 在业务类要做为连接点的**方法上添加**自定义注解 2. 在业务类要做为连接点的**方法上添加**自定义注解
``` ```text
@MyLog //自定义注解(表示:当前方法属于目标方法) @MyLog //自定义注解(表示:当前方法属于目标方法)
public void delete(Integer id) { public void delete(Integer id) {
//1. 删除部门 //1. 删除部门
@ -2089,7 +2089,7 @@ public @interface MyLog {
3. aop切面类上使用类似如下的切面表达式 3. aop切面类上使用类似如下的切面表达式
``` ```text
@Before("@annotation(edu.whut.anno.MyLog)") @Before("@annotation(edu.whut.anno.MyLog)")
``` ```
@ -2140,7 +2140,7 @@ Object[] args = joinPoint.**getArgs()**; 可以获取调用方法时传递的
如果项目已经打包上线了这个时候我们又如何来设置Java系统属性和命令行参数呢 如果项目已经打包上线了这个时候我们又如何来设置Java系统属性和命令行参数呢
``` ```text
java -Dserver.port=9000 -jar XXXXX.jar --server.port=10010 java -Dserver.port=9000 -jar XXXXX.jar --server.port=10010
``` ```
@ -2154,7 +2154,7 @@ java -Dserver.port=9000 -jar XXXXX.jar --server.port=10010
- **@Autowired注解**:最常见的方式是使用@Autowired注解自动装配Bean。Spring会自动在其容器中查找匹配类型的Bean并注入到被@Autowired标注的字段或方法中 - **@Autowired注解**:最常见的方式是使用@Autowired注解自动装配Bean。Spring会自动在其容器中查找匹配类型的Bean并注入到被@Autowired标注的字段或方法中
``` ```text
@Service @Service
public class MyService { public class MyService {
@Autowired @Autowired
@ -2203,7 +2203,7 @@ class SpringbootWebConfig2ApplicationTests {
- 如果要管理的bean对象来自于第三方不是自定义的是无法用@Component 及衍生注解声明bean的就需要用到**@Bean**注解。 - 如果要管理的bean对象来自于第三方不是自定义的是无法用@Component 及衍生注解声明bean的就需要用到**@Bean**注解。
- 如果需要定义第三方Bean时 通常会单独定义一个**配置类** - 如果需要定义第三方Bean时 通常会单独定义一个**配置类**
``` ```text
@Configuration //配置类 (在配置类当中对第三方bean进行集中的配置管理) @Configuration //配置类 (在配置类当中对第三方bean进行集中的配置管理)
public class CommonConfig { public class CommonConfig {
@ -2256,7 +2256,7 @@ SpringBoot的自动配置就是当Spring容器启动后一些配置类、bean
**导入普通类:** **导入普通类:**
``` ```text
@Component @Component
public class TokenParser { public class TokenParser {
@ -2267,7 +2267,7 @@ public class TokenParser {
} }
``` ```
``` ```text
@Import(TokenParser.class) //导入的类会被Spring加载到IOC容器中 @Import(TokenParser.class) //导入的类会被Spring加载到IOC容器中
@SpringBootApplication @SpringBootApplication
public class SpringbootWebConfig2Application { public class SpringbootWebConfig2Application {
@ -2328,7 +2328,7 @@ public @interface EnableHeaderConfig {
- 在使用时只需在启动类上加上@EnableXxxxx注解即可 - 在使用时只需在启动类上加上@EnableXxxxx注解即可
``` ```text
@EnableHeaderConfig //使用第三方依赖提供的Enable开头的注解 @EnableHeaderConfig //使用第三方依赖提供的Enable开头的注解
@SpringBootApplication @SpringBootApplication
public class SpringbootWebConfig2Application { public class SpringbootWebConfig2Application {

View File

@ -81,13 +81,13 @@ IDEA快捷键
2. 在 `System.out.println()` 方法中,"ln" 代表 "line",表示换行。因此,`println` 实际上是 "print line" 的缩写。这个方法会在输出文本后自动换行. 2. 在 `System.out.println()` 方法中,"ln" 代表 "line",表示换行。因此,`println` 实际上是 "print line" 的缩写。这个方法会在输出文本后自动换行.
``` ```text
System.out.println("nihao "+1.3331) #Java 会自动将数值转换为字符串 System.out.println("nihao "+1.3331) #Java 会自动将数值转换为字符串
``` ```
当直接打印一个没有重写 `toString()` 方法的对象时Java 默认会调用 `Object` 类的 `toString()` 方法,其输出格式通常为: 当直接打印一个没有重写 `toString()` 方法的对象时Java 默认会调用 `Object` 类的 `toString()` 方法,其输出格式通常为:
``` ```text
java.lang.Object@15db9742 java.lang.Object@15db9742
``` ```
@ -95,7 +95,7 @@ IDEA快捷键
当打印重写`toString()` 方法的对象时: 当打印重写`toString()` 方法的对象时:
``` ```text
class Person { class Person {
private String name; private String name;
private int age; private int age;
@ -120,7 +120,7 @@ IDEA快捷键
``` ```
``` ```text
Person{name='Alice', age=30} Person{name='Alice', age=30}
``` ```
@ -128,7 +128,7 @@ IDEA快捷键
3. 一维数组创建: 3. 一维数组创建:
``` ```text
// 方式1先声明再指定长度默认值为0、null等 // 方式1先声明再指定长度默认值为0、null等
int[] arr1 = new int[10]; // 创建一个长度为10的int数组 int[] arr1 = new int[10]; // 创建一个长度为10的int数组
@ -146,7 +146,7 @@ IDEA快捷键
4. 字符串创建 4. 字符串创建
``` ```text
String str = "Hello, World!"; //1直接赋值 String str = "Hello, World!"; //1直接赋值
String str = new String("Hello, World!"); //使用 new 关键字 String str = new String("Hello, World!"); //使用 new 关键字
@ -196,7 +196,7 @@ LocalDateTime.now(),获取当前时间
``` ```text
// 文件com/example/PrivateExample.java // 文件com/example/PrivateExample.java
package com.example; package com.example;
@ -215,7 +215,7 @@ public class PrivateExample {
修饰符不仅可以用来修饰成员变量和方法,也可以用来**修饰类**。顶级类只能使用 `public` 或默认(即不写任何修饰符,称为包访问权限)。内部类可以使用所有访问修饰符(`public``protected``private` 和默认),这使得你可以更灵活地控制嵌套类的访问范围。 修饰符不仅可以用来修饰成员变量和方法,也可以用来**修饰类**。顶级类只能使用 `public` 或默认(即不写任何修饰符,称为包访问权限)。内部类可以使用所有访问修饰符(`public``protected``private` 和默认),这使得你可以更灵活地控制嵌套类的访问范围。
``` ```text
public class OuterClass { public class OuterClass {
// 内部类使用private只能在OuterClass内部访问 // 内部类使用private只能在OuterClass内部访问
private class InnerPrivateClass { private class InnerPrivateClass {
@ -258,7 +258,7 @@ public class OuterClass {
用途:适用于内部类与外部类关系密切,需要频繁访问外部类成员的情况。 用途:适用于内部类与外部类关系密切,需要频繁访问外部类成员的情况。
``` ```text
public class OuterClass { public class OuterClass {
class InnerClass implements Runnable { class InnerClass implements Runnable {
// static int count = 0; // 编译错误 // static int count = 0; // 编译错误
@ -294,7 +294,7 @@ public class OuterClass {
用途:适用于只在方法或代码块中使用的类,有助于将实现细节隐藏在方法内部。 用途:适用于只在方法或代码块中使用的类,有助于将实现细节隐藏在方法内部。
``` ```text
public class OuterClass { public class OuterClass {
public void startThread() { public void startThread() {
class LocalInnerClass implements Runnable { class LocalInnerClass implements Runnable {
@ -327,7 +327,7 @@ public class OuterClass {
用途:适合当内部类工作不依赖外部类实例时使用,常用于实现与外部类关系不那么密切的帮助类。 用途:适合当内部类工作不依赖外部类实例时使用,常用于实现与外部类关系不那么密切的帮助类。
``` ```text
public class OuterClass { public class OuterClass {
// 外部类的静态成员 // 外部类的静态成员
private static int staticVar = 10; private static int staticVar = 10;
@ -371,7 +371,7 @@ public class OuterClass {
用途:适用于创建一次性使用的实例,通常用于接口或抽象类的实现。 用途:适用于创建一次性使用的实例,通常用于接口或抽象类的实现。
``` ```text
//eg1 //eg1
public class OuterClass { public class OuterClass {
public static void main(String[] args) { public static void main(String[] args) {
@ -413,7 +413,7 @@ public class GUIApp {
1. 创建`ActionListener`实例 1. 创建`ActionListener`实例
``` ```text
new ActionListener() { new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
System.out.println("Button was clicked!"); System.out.println("Button was clicked!");
@ -432,7 +432,7 @@ new ActionListener() {
2. 将匿名内部类添加为事件监听器 2. 将匿名内部类添加为事件监听器
``` ```text
button.addActionListener(...); button.addActionListener(...);
``` ```
@ -446,7 +446,7 @@ Lambda表达式特别适用于**只有单一抽象方法**的接口(也即**
**`@FunctionalInterface` 注解**:这是一个可选的注解,用于表示接口是一个函数式接口。虽然不是强制的,但它可以帮助编译器识别意图,并检查接口是否确实只有一个抽象方法。 **`@FunctionalInterface` 注解**:这是一个可选的注解,用于表示接口是一个函数式接口。虽然不是强制的,但它可以帮助编译器识别意图,并检查接口是否确实只有一个抽象方法。
``` ```text
public class LambdaExample { public class LambdaExample {
// 定义函数式接口doSomething 有两个参数 // 定义函数式接口doSomething 有两个参数
@FunctionalInterface @FunctionalInterface
@ -479,7 +479,7 @@ public class LambdaExample {
可选的大括号:如果主体只有一个语句,可以不使用大括号。 可选的大括号:如果主体只有一个语句,可以不使用大括号。
可选的返回关键字如果主体只有一个表达式返回值则编译器会自动返回值使用大括号需显示retrun如果函数是void则不需要返回值。 可选的返回关键字如果主体只有一个表达式返回值则编译器会自动返回值使用大括号需显示retrun如果函数是void则不需要返回值。
``` ```text
// 定义一个函数式接口 // 定义一个函数式接口
interface Calculator { interface Calculator {
int add(int a, int b); int add(int a, int b);
@ -507,7 +507,7 @@ public class LambdaReturnExample {
`list.forEach`这个方法接受一个**函数式接口**作为参数。它只有一个抽象方法 `accept(T t)`因此,可以使用 lambda 表达式来**实现**。 `list.forEach`这个方法接受一个**函数式接口**作为参数。它只有一个抽象方法 `accept(T t)`因此,可以使用 lambda 表达式来**实现**。
``` ```text
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -536,7 +536,7 @@ public class Main {
如果返回正数,则 `a` 应该排在 `b` 的后面。 如果返回正数,则 `a` 应该排在 `b` 的后面。
``` ```text
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -564,7 +564,7 @@ public class Main {
**1.静态初始化块Static Initialization Block** **1.静态初始化块Static Initialization Block**
``` ```text
public class MyClass { public class MyClass {
static int num1, num2; static int num1, num2;
@ -590,7 +590,7 @@ public class MyClass {
输出: 输出:
``` ```text
静态代码块1执行 静态代码块1执行
静态代码块2执行 静态代码块2执行
main方法执行 main方法执行
@ -603,7 +603,7 @@ main方法执行
**2.在声明时直接初始化** **2.在声明时直接初始化**
``` ```text
public class MyClass { public class MyClass {
// 直接在声明时初始化静态成员变量 // 直接在声明时初始化静态成员变量
public static int staticVariable = 42; public static int staticVariable = 42;
@ -614,7 +614,7 @@ public class MyClass {
静态成员变量的访问不需要创建 `MyClass` 的实例,可以直接通过类名访问: 静态成员变量的访问不需要创建 `MyClass` 的实例,可以直接通过类名访问:
``` ```text
int value = MyClass.staticVariable; int value = MyClass.staticVariable;
MyClass obj = new MyClass(); MyClass obj = new MyClass();
System.out.println("obj.num1 = " + obj.staticVariable); #通过示例访问也可以 System.out.println("obj.num1 = " + obj.staticVariable); #通过示例访问也可以
@ -638,7 +638,7 @@ System.out.println("obj.num1 = " + obj.staticVariable); #通过示例访问也
- 非静态成员变量。 - 非静态成员变量。
- 非静态方法(必须通过对象实例访问)。 - 非静态方法(必须通过对象实例访问)。
``` ```text
public class MyClass { public class MyClass {
private static int staticVar = 10; private static int staticVar = 10;
private int instanceVar = 20; private int instanceVar = 20;
@ -664,7 +664,7 @@ public class MyClass {
调用静态方法: 调用静态方法:
``` ```text
MyClass.staticMethod(); // 通过类名直接调用静态方法 MyClass.staticMethod(); // 通过类名直接调用静态方法
``` ```
@ -680,7 +680,7 @@ MyClass.staticMethod(); // 通过类名直接调用静态方法
因为父类的成员变量和方法都是默认的访问修饰符可以继承给子类而子类也定义了同名的xxx发生了**变量隐藏**shadowing 因为父类的成员变量和方法都是默认的访问修饰符可以继承给子类而子类也定义了同名的xxx发生了**变量隐藏**shadowing
``` ```text
class Parent { class Parent {
int num = 10; int num = 10;
void display() { void display() {
@ -711,7 +711,7 @@ MyClass.staticMethod(); // 通过类名直接调用静态方法
输出: 输出:
``` ```text
Child class num: 20 Child class num: 20
Parent class num: 10 Parent class num: 10
Parent class method Parent class method
@ -721,7 +721,7 @@ MyClass.staticMethod(); // 通过类名直接调用静态方法
可以使用 `super` 关键字调用父类的构造方法。这通常在子类的构造方法中使用,用于显式地调用父类的构造方法。 可以使用 `super` 关键字调用父类的构造方法。这通常在子类的构造方法中使用,用于显式地调用父类的构造方法。
``` ```text
class Parent { class Parent {
Parent() { Parent() {
System.out.println("Parent class constructor"); System.out.println("Parent class constructor");
@ -745,7 +745,7 @@ public class Main {
输出: 输出:
``` ```text
Parent class constructor Parent class constructor
Child class constructor Child class constructor
``` ```
@ -771,7 +771,7 @@ final 关键字,意思是最终的、不可修改的,最见不得变化
3. **数据类型**变量的数据类型如int、String、class等。 3. **数据类型**变量的数据类型如int、String、class等。
4. **变量名**:变量的名称。 4. **变量名**:变量的名称。
``` ```text
public static final int MAX_COUNT = 100; #定义常量 public static final int MAX_COUNT = 100; #定义常量
protected static volatile int counter; #定义成员变量 protected static volatile int counter; #定义成员变量
``` ```
@ -790,7 +790,7 @@ protected static volatile int counter; #定义成员变量
**继承** **继承**
``` ```text
[修饰符] class 子类名 extends 父类名{ [修饰符] class 子类名 extends 父类名{
类体部分 类体部分
} }
@ -820,7 +820,7 @@ Java继承了父类**非私有**的成员变量和成员方法,但是请注意
2. **向上转型Upcasting**:动态多态;子类对象可以赋值给父类引用,这样做可以隐藏对象的真实类型,只能调用**父类中声明的方法**。 2. **向上转型Upcasting**:动态多态;子类对象可以赋值给父类引用,这样做可以隐藏对象的真实类型,只能调用**父类中声明的方法**。
``` ```text
class Animal { class Animal {
public void makeSound() { public void makeSound() {
System.out.println("Animal makes sound"); System.out.println("Animal makes sound");
@ -856,7 +856,7 @@ Java继承了父类**非私有**的成员变量和成员方法,但是请注意
- **重载**发生在同一个类中,与继承无关; - **重载**发生在同一个类中,与继承无关;
- **重写**发生在子类中,依赖继承关系,实现运行时多态。 - **重写**发生在子类中,依赖继承关系,实现运行时多态。
``` ```text
class Calculator { class Calculator {
int add(int a, int b) { int add(int a, int b) {
return a + b; return a + b;
@ -879,7 +879,7 @@ class Calculator {
**必须实现抽象方法** **必须实现抽象方法**
如果一个子类继承了抽象类,通常必须实现抽象类中的所有抽象方法,否则该子类也必须声明为抽象类。例如: 如果一个子类继承了抽象类,通常必须实现抽象类中的所有抽象方法,否则该子类也必须声明为抽象类。例如:
``` ```text
abstract class Animal { abstract class Animal {
// 抽象方法,没有方法体 // 抽象方法,没有方法体
public abstract void makeSound(); public abstract void makeSound();
@ -908,7 +908,7 @@ class Dog extends Animal {
1. **定义一个新的子类** 1. **定义一个新的子类**
创建一个子类继承抽象类并实现所有抽象方法,然后使用子类实例化对象: 创建一个子类继承抽象类并实现所有抽象方法,然后使用子类实例化对象:
``` ```text
Animal animal = new Dog(); Animal animal = new Dog();
animal.makeSound(); // 输出Dog barks animal.makeSound(); // 输出Dog barks
``` ```
@ -916,7 +916,7 @@ class Dog extends Animal {
2. **使用匿名内部类** 2. **使用匿名内部类**
使用匿名内部类实现抽象类相当于临时创建了一个**未命名的子类**,并且立即实例化了这个子类的对象。 使用匿名内部类实现抽象类相当于临时创建了一个**未命名的子类**,并且立即实例化了这个子类的对象。
``` ```text
Animal animal = new Animal() { Animal animal = new Animal() {
@Override @Override
public void makeSound() { public void makeSound() {
@ -956,7 +956,7 @@ class Dog extends Animal {
- 类可以实现多个接口(多继承)。 - 类可以实现多个接口(多继承)。
- 类只能继承一个抽象类(单继承)。 - 类只能继承一个抽象类(单继承)。
``` ```text
// 定义接口 // 定义接口
interface Flyable { interface Flyable {
void fly(); void fly();
@ -1009,7 +1009,7 @@ public class Main {
- `void clear()`:移除集合中的所有元素。 - `void clear()`:移除集合中的所有元素。
- `boolean isEmpty()`:如果集合为空,则返回 `true` - `boolean isEmpty()`:如果集合为空,则返回 `true`
``` ```text
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -1051,7 +1051,7 @@ public class CollectionExample {
2. `next()`:返回迭代器的下一个元素,并将迭代器移动到下一个位置。 2. `next()`:返回迭代器的下一个元素,并将迭代器移动到下一个位置。
3. `remove()`:从迭代器当前位置删除元素。该方法是可选的,不是所有的迭代器都支持。 3. `remove()`:从迭代器当前位置删除元素。该方法是可选的,不是所有的迭代器都支持。
``` ```text
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
@ -1093,7 +1093,7 @@ public class Main {
![image-20240227152019078](https://pic.bitday.top/i/2025/03/19/u6utmg-2.png) ![image-20240227152019078](https://pic.bitday.top/i/2025/03/19/u6utmg-2.png)
``` ```text
// 使用 entrySet() 方法获取 Map 中所有键值对的集合,并使用增强型 for 循环遍历键值对 // 使用 entrySet() 方法获取 Map 中所有键值对的集合,并使用增强型 for 循环遍历键值对
System.out.println("Entries in the map:"); System.out.println("Entries in the map:");
for (Map.Entry<String, Integer> entry : map.entrySet()) { for (Map.Entry<String, Integer> entry : map.entrySet()) {
@ -1109,7 +1109,7 @@ public class Main {
默认是小根堆输出1258 默认是小根堆输出1258
``` ```text
import java.util.PriorityQueue; import java.util.PriorityQueue;
public class Main { public class Main {
@ -1140,7 +1140,7 @@ public class Main {
### JAVA异常处理 ### JAVA异常处理
``` ```text
public class ExceptionExample { public class ExceptionExample {
// 方法声明中添加 throws 关键字,指定可能抛出的异常类型 // 方法声明中添加 throws 关键字,指定可能抛出的异常类型
public static void main(String[] args) throws SomeException, AnotherException { public static void main(String[] args) throws SomeException, AnotherException {
@ -1181,7 +1181,7 @@ Arrays.toString()
作用:方便地输出数组。 作用:方便地输出数组。
这个方法是是用来将数组转换成String类型输出的入参可以是longfloatdoubleintbooleanbyteobject 型的数组。 这个方法是是用来将数组转换成String类型输出的入参可以是longfloatdoubleintbooleanbyteobject 型的数组。
``` ```text
import java.util.Arrays; import java.util.Arrays;
public class Main { public class Main {
@ -1211,7 +1211,7 @@ public class Main {
**类路径**是JVM在运行时用来查找类文件和资源文件的一组目录或JAR包。在许多项目例如Maven或Gradle项目`src/main/resources`目录下的内容在编译时会被复制到输出目录(如`target/classes``src/main/java` 下编译后的 class 文件也会放到这里。 **类路径**是JVM在运行时用来查找类文件和资源文件的一组目录或JAR包。在许多项目例如Maven或Gradle项目`src/main/resources`目录下的内容在编译时会被复制到输出目录(如`target/classes``src/main/java` 下编译后的 class 文件也会放到这里。
``` ```text
MyProject/ MyProject/
├── src/ ├── src/
│ └── main/ │ └── main/
@ -1226,7 +1226,7 @@ MyProject/
``` ```
``` ```text
// 获取 resources 根目录下的 emp.xml 文件路径 // 获取 resources 根目录下的 emp.xml 文件路径
String empFile = this.getClass().getClassLoader().getResource("emp.xml").getFile(); String empFile = this.getClass().getClassLoader().getResource("emp.xml").getFile();
@ -1261,7 +1261,7 @@ String ttImgPath = resourceUrl != null ? resourceUrl.getFile() : null;
**1.获取类的字节码Class对象**:有三种方法 **1.获取类的字节码Class对象**:有三种方法
``` ```text
public class Test1Class{ public class Test1Class{
public static void main(String[] args){ public static void main(String[] args){
Class c1 = Student.class; Class c1 = Student.class;
@ -1282,7 +1282,7 @@ public class Test1Class{
**2.获取类的构造器** **2.获取类的构造器**
``` ```text
public class Cat{ public class Cat{
private String name; private String name;
private int age; private int age;
@ -1301,7 +1301,7 @@ public class Cat{
- 获取构造器列表 - 获取构造器列表
``` ```text
public class TestConstructor { public class TestConstructor {
@Test @Test
@ -1386,7 +1386,7 @@ public class Test2Constructor(){
示例:`Cat` 类与测试类 示例:`Cat` 类与测试类
``` ```text
public class Cat { public class Cat {
private String name; private String name;
public int age; public int age;
@ -1406,7 +1406,7 @@ public class Cat {
} }
``` ```
``` ```text
import org.junit.Test; import org.junit.Test;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -1478,7 +1478,7 @@ public class FieldReflectionTest {
![image-20240307172717512](https://pic.bitday.top/i/2025/03/19/u75u7l-2.png) ![image-20240307172717512](https://pic.bitday.top/i/2025/03/19/u75u7l-2.png)
``` ```text
@Test @Test
public void testListUser(){ public void testListUser(){
List<User>list=userMapper.list(); List<User>list=userMapper.list();
@ -1494,7 +1494,7 @@ public class FieldReflectionTest {
原理可能是: 原理可能是:
``` ```text
//自定义注解 //自定义注解
@Retention(RetentionPolicy.RUNTIME) //指定注解在运行时可用,这样才能通过反射获取到该注解。 @Retention(RetentionPolicy.RUNTIME) //指定注解在运行时可用,这样才能通过反射获取到该注解。
@Target(ElementType.METHOD) //指定注解可用于方法上。 @Target(ElementType.METHOD) //指定注解可用于方法上。
@ -1539,7 +1539,7 @@ public class AnnotationTest4 {
定义: 定义:
``` ```text
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -1564,7 +1564,7 @@ public @interface MyAnnotation {
**简化使用**:当注解只有一个元素需要设置时,且该元素的名字是`value`,在使用该注解时可以不用显式地指定元素名 **简化使用**:当注解只有一个元素需要设置时,且该元素的名字是`value`,在使用该注解时可以不用显式地指定元素名
``` ```text
@MyAnnotation(5) // 等同于 @MyAnnotation(value = 5) @MyAnnotation(5) // 等同于 @MyAnnotation(value = 5)
public void someMethod() { public void someMethod() {
// 方法实现 // 方法实现
@ -1576,7 +1576,7 @@ public void someMethod() {
如果要同时设置`description`,则不能省略元素名: 如果要同时设置`description`,则不能省略元素名:
``` ```text
@MyAnnotation(value = 5, description = "Specific description") @MyAnnotation(value = 5, description = "Specific description")
public void anotherMethod() { public void anotherMethod() {
// 方法实现 // 方法实现
@ -1588,7 +1588,7 @@ public void anotherMethod() {
**获得注解上的value**反射 **获得注解上的value**反射
``` ```text
public class MyClass { public class MyClass {
@MyAnnotation(value = "specific value") @MyAnnotation(value = "specific value")
@ -1601,7 +1601,7 @@ public class MyClass {
``` ```text
import java.lang.reflect.Method; import java.lang.reflect.Method;
public class AnnotationReader { public class AnnotationReader {

View File

@ -4,14 +4,14 @@
### 启动Mysql ### 启动Mysql
``` ```text
net start mysql // 启动mysql服务 net start mysql // 启动mysql服务
net stop mysql // 停止mysql服务 net stop mysql // 停止mysql服务
``` ```
### 修改root账户密码 ### 修改root账户密码
``` ```text
mysqladmin -u root password 123456 mysqladmin -u root password 123456
``` ```
@ -19,11 +19,11 @@ mysqladmin -u root password 123456
### 登录 ### 登录
``` ```text
mysql -u用户名 -p密码 [-h数据库服务器的IP地址 -P端口号] mysql -u用户名 -p密码 [-h数据库服务器的IP地址 -P端口号]
``` ```
``` ```text
mysql -uroot -p123456 mysql -uroot -p123456
``` ```
@ -109,13 +109,13 @@ drop database if exists itcast; -- itcast数据库存在时删除不存在也
**查询当前数据库下所有表** **查询当前数据库下所有表**
``` ```text
show tables; show tables;
``` ```
**查看指定表的结构(字段)** **查看指定表的结构(字段)**
``` ```text
desc tb_tmps tb_tmps为表名 desc tb_tmps tb_tmps为表名
``` ```
@ -136,7 +136,7 @@ eg
![image-20220829143005524](https://pic.bitday.top/i/2025/03/19/u7brwj-2.png) ![image-20220829143005524](https://pic.bitday.top/i/2025/03/19/u7brwj-2.png)
``` ```text
create table tb_user ( create table tb_user (
id int comment 'ID,唯一标识', # id是一行数据的唯一标识不能重复 id int comment 'ID,唯一标识', # id是一行数据的唯一标识不能重复
username varchar(20) comment '用户名', username varchar(20) comment '用户名',
@ -156,7 +156,7 @@ create table tb_user (
| 默认约束 | 保存数据时,如果未指定该字段值,则采用默认值 | default | | 默认约束 | 保存数据时,如果未指定该字段值,则采用默认值 | default |
| **外键约束** | 让两张表的数据建立连接,保证数据的一致性和完整性 | foreign key | | **外键约束** | 让两张表的数据建立连接,保证数据的一致性和完整性 | foreign key |
``` ```text
create table tb_user ( create table tb_user (
id int primary key auto_increment comment 'ID,唯一标识', id int primary key auto_increment comment 'ID,唯一标识',
username varchar(20) not null unique comment '用户名', username varchar(20) not null unique comment '用户名',
@ -268,7 +268,7 @@ DQL英文全称是Data Query Language(数据查询语言),用来查询数据
### 语法 ### 语法
``` ```text
SELECT SELECT
字段列表 字段列表
FROM FROM
@ -330,7 +330,7 @@ LIMIT
案例:查询 入职时间 在 '2000-01-01' (包含) 到 '2010-01-01'(包含) 之间 且 性别为女 的员工信息 案例:查询 入职时间 在 '2000-01-01' (包含) 到 '2010-01-01'(包含) 之间 且 性别为女 的员工信息
``` ```text
select * select *
from tb_emp from tb_emp
where entrydate between '2000-01-01' and '2010-01-01' where entrydate between '2000-01-01' and '2010-01-01'
@ -339,7 +339,7 @@ where entrydate between '2000-01-01' and '2010-01-01'
案例8查询 职位是 2 (讲师), 3 (学工主管), 4 (教研主管) 的员工信息 案例8查询 职位是 2 (讲师), 3 (学工主管), 4 (教研主管) 的员工信息
``` ```text
select * select *
from tb_emp from tb_emp
where job in (2,3,4); where job in (2,3,4);
@ -367,7 +367,7 @@ select 聚合函数(字段列表) from 表名 ;
> 注意 : 聚合函数会忽略空值对NULL值不作为统计。 > 注意 : 聚合函数会忽略空值对NULL值不作为统计。
``` ```text
# count(*) 推荐此写法MySQL底层进行了优化 # count(*) 推荐此写法MySQL底层进行了优化
select count(*) from tb_emp; select count(*) from tb_emp;
``` ```
@ -382,13 +382,13 @@ select count(*) from tb_emp;
> >
> 分组查询通常会使用**聚合函数**进行计算。 > 分组查询通常会使用**聚合函数**进行计算。
``` ```text
select 字段列表 from 表名 [where 条件] group by 分组字段名 [having 分组后过滤条件]; select 字段列表 from 表名 [where 条件] group by 分组字段名 [having 分组后过滤条件];
``` ```
例如,假设我们有一个名为 `orders` 的表,其中包含 `customer_id``amount` 列,我们想要计算每个客户的订单总金额,可以这样写查询: 例如,假设我们有一个名为 `orders` 的表,其中包含 `customer_id``amount` 列,我们想要计算每个客户的订单总金额,可以这样写查询:
``` ```text
SELECT customer_id, SUM(amount) AS total_amount SELECT customer_id, SUM(amount) AS total_amount
FROM orders FROM orders
GROUP BY customer_id; GROUP BY customer_id;
@ -398,7 +398,7 @@ GROUP BY customer_id;
``` ```text
SELECT customer_id, SUM(amount) AS total_amount SELECT customer_id, SUM(amount) AS total_amount
FROM orders FROM orders
GROUP BY customer_id GROUP BY customer_id
@ -435,7 +435,7 @@ order by 字段1 排序方式1 , 字段2 排序方式2 … ;
### 分页查询 ### 分页查询
``` ```text
select 字段列表 from 表名 limit 起始索引, 每页显示记录数 ; select 字段列表 from 表名 limit 起始索引, 每页显示记录数 ;
``` ```
@ -549,7 +549,7 @@ where tb_emp.dept_id = tb_dept.id; -- 消除笛卡尔积
- 显示内连接 - 显示内连接
``` ```text
select tb_emp.name , tb_dept.name select tb_emp.name , tb_dept.name
from tb_emp inner join tb_dept from tb_emp inner join tb_dept
on tb_emp.dept_id = tb_dept.id; on tb_emp.dept_id = tb_dept.id;
@ -575,7 +575,7 @@ select 字段列表 from 表1 right [ outer ] join 表2 on 连接条
``` ```text
-- 右外连接 -- 右外连接
select dept.name , emp.name select dept.name , emp.name
from tb_emp AS emp right join tb_dept AS dept from tb_emp AS emp right join tb_dept AS dept
@ -696,7 +696,7 @@ select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left j
` `
``` ```text
-- 开启事务 -- 开启事务
start transaction ; start transaction ;
@ -738,7 +738,7 @@ rollback ;
**创建索引** **创建索引**
``` ```text
-- 添加索引 -- 添加索引
create index idx_sku_sn on tb_sku (sn); #在添加索引时,也需要消耗时间 create index idx_sku_sn on tb_sku (sn); #在添加索引时,也需要消耗时间

View File

@ -2,7 +2,7 @@
**linux上安装Git** **linux上安装Git**
``` ```text
sudo apt update sudo apt update
sudo apt install git sudo apt install git
``` ```
@ -195,7 +195,10 @@ git config --global https.proxy https://127.0.0.1:7890
git config --global http.proxy socks5://127.0.0.1:7890 git config --global http.proxy socks5://127.0.0.1:7890
git config --global https.proxy socks5://127.0.0.1:7890 git config --global https.proxy socks5://127.0.0.1:7890
**取消代理**
git config --global --unset http.proxy
git config --global --unset https.proxy
**或者使用国产的gitee或者自己服务器上搭建gitea进行代码托管** **或者使用国产的gitee或者自己服务器上搭建gitea进行代码托管**
@ -221,7 +224,7 @@ git config --global https.proxy socks5://127.0.0.1:7890
如果还不想提交本地修改,可以将更改暂存起来: 如果还不想提交本地修改,可以将更改暂存起来:
``` ```text
git stash git stash
git pull git pull
git stash pop git stash pop
@ -235,7 +238,7 @@ git stash pop
如果确定不需要这些修改,可以放弃它们: 如果确定不需要这些修改,可以放弃它们:
``` ```text
git reset --hard git reset --hard
git pull git pull
``` ```
@ -244,7 +247,7 @@ git pull
**但是推荐先提交本地的代码!!!** **但是推荐先提交本地的代码!!!**
``` ```text
git add . git add .
git commit -m "描述本次修改的提交信息" git commit -m "描述本次修改的提交信息"
git pull git pull
@ -305,7 +308,7 @@ remote: Support for password authentication was removed on August 13, 2021. remo
- 如果你还没有 SSH 密钥,可以使用以下命令生成: - 如果你还没有 SSH 密钥,可以使用以下命令生成:
``` ```text
ssh-keygen -t rsa -b 4096 -C "your_email@example.com" ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
``` ```
@ -320,7 +323,7 @@ remote: Support for password authentication was removed on August 13, 2021. remo
**使用 SSH URL 克隆仓库** **使用 SSH URL 克隆仓库**
``` ```text
git clone git@github.com:zhangww-web/reptile.git git clone git@github.com:zhangww-web/reptile.git
``` ```
@ -343,7 +346,7 @@ SSH 连接 GitHub 并触发身份验证,流程如下:
**如果避免每次git pull都要验证身份** **如果避免每次git pull都要验证身份**
``` ```text
git config --global credential.helper store //将凭据保存到磁盘上(明文存储): git config --global credential.helper store //将凭据保存到磁盘上(明文存储):
``` ```
@ -355,7 +358,7 @@ git config --global credential.helper store //将凭据保存到磁盘上(明
到项目根目录git bash here 到项目根目录git bash here
``` ```text
git rm -r --cached 'dictory'/ git rm -r --cached 'dictory'/
``` ```

View File

@ -65,7 +65,7 @@ DNS解析可能需等待几分钟生效
- head 查看前n行 - head 查看前n行
``` ```text
head -n 100 文件名 head -n 100 文件名
``` ```
@ -75,7 +75,7 @@ DNS解析可能需等待几分钟生效
- **ls** 列出所有文件但默认只是显示出最基础的文件和文件夹如果需要更详细的信息则使用ls -la这将列出包括隐藏文件在内的所有文件和文件夹并且给出对应的权限、大小和日期等信息。 - **ls** 列出所有文件但默认只是显示出最基础的文件和文件夹如果需要更详细的信息则使用ls -la这将列出包括隐藏文件在内的所有文件和文件夹并且给出对应的权限、大小和日期等信息。
``` ```text
zy123@hcss-ecs-588d:~$ ls -la zy123@hcss-ecs-588d:~$ ls -la
total 44 total 44
drwxr-xr-x 6 zy123 zy123 4096 Feb 26 08:53 . drwxr-xr-x 6 zy123 zy123 4096 Feb 26 08:53 .
@ -122,19 +122,19 @@ DNS解析可能需等待几分钟生效
- **mv** 移动文件和文件夹,也可以用来修改名称,如: - **mv** 移动文件和文件夹,也可以用来修改名称,如:
``` ```text
mv /home/hello.py /home/helloworld.py mv /home/hello.py /home/helloworld.py
``` ```
将上文的hello.py重命名为helloworld.py 将上文的hello.py重命名为helloworld.py
``` ```text
mv /home/helloworld.py /home/Python/helloworld.py mv /home/helloworld.py /home/Python/helloworld.py
``` ```
将helloworld.py 由home文件夹移动到了次级的Python文件夹。 将helloworld.py 由home文件夹移动到了次级的Python文件夹。
``` ```text
mv /home/hello.py . mv /home/hello.py .
``` ```
@ -142,7 +142,7 @@ DNS解析可能需等待几分钟生效
- **cp** 复制文件 - **cp** 复制文件
``` ```text
cp /home/Python/hellowrold.py /home/Python/HelloWorld.py cp /home/Python/hellowrold.py /home/Python/HelloWorld.py
``` ```
@ -154,7 +154,7 @@ DNS解析可能需等待几分钟生效
- **grep **是用于在文件或标准输入中搜索**符合条件的行**的命令。 - **grep **是用于在文件或标准输入中搜索**符合条件的行**的命令。
``` ```text
grep "pattern" filename #pattern可以是一个正则表达式 grep "pattern" filename #pattern可以是一个正则表达式
``` ```
@ -162,7 +162,7 @@ DNS解析可能需等待几分钟生效
- **awk** 是一个功能强大的文本处理工具,它可以对文本文件进行分列处理、模式匹配和报告生成。它的语法类似一种简单的脚本语言。 - **awk** 是一个功能强大的文本处理工具,它可以对文本文件进行分列处理、模式匹配和报告生成。它的语法类似一种简单的脚本语言。
``` ```text
awk 'pattern { action }' filename awk 'pattern { action }' filename
``` ```
@ -174,7 +174,7 @@ DNS解析可能需等待几分钟生效
`$1, $2, ...`:代表各个字段(默认分隔符是空白字符,可以通过 `-F` 参数指定其他分隔符)。 `$1, $2, ...`:代表各个字段(默认分隔符是空白字符,可以通过 `-F` 参数指定其他分隔符)。
``` ```text
awk '{print $1, $3}' filename #印指定列 awk '{print $1, $3}' filename #印指定列
``` ```
@ -187,7 +187,7 @@ DNS解析可能需等待几分钟生效
10.0.0.5 27/Feb/2025:10:32:10 "GET /error_page HTTP/1.1" 500 2048 ERROR 10.0.0.5 27/Feb/2025:10:32:10 "GET /error_page HTTP/1.1" 500 2048 ERROR
``` ```
``` ```text
grep 'ERROR' access.log | awk '{print $2}' grep 'ERROR' access.log | awk '{print $2}'
``` ```
@ -195,13 +195,13 @@ DNS解析可能需等待几分钟生效
- **lsof**"List Open Files"显示系统中当前打开的文件。 `-i`*会显示所有正在使用网络连接的进程* - **lsof**"List Open Files"显示系统中当前打开的文件。 `-i`*会显示所有正在使用网络连接的进程*
``` ```text
lsof -i :80 #查看 80 端口上的进程,或者判断80端口是否被占用 lsof -i :80 #查看 80 端口上的进程,或者判断80端口是否被占用
``` ```
- **usermode** 修改用户账户信息的命令 - **usermode** 修改用户账户信息的命令
``` ```text
sudo usermod -aG docker zy123 #-aG一起用添加zy123到group组 sudo usermod -aG docker zy123 #-aG一起用添加zy123到group组
``` ```
@ -209,14 +209,14 @@ DNS解析可能需等待几分钟生效
1. 数字方式:数字方式使用三个(或四个)数字来表示所有者、组用户和其他用户的权限。每个数字代表读 (4)、写 (2)、执行 (1) 权限的和。 1. 数字方式:数字方式使用三个(或四个)数字来表示所有者、组用户和其他用户的权限。每个数字代表读 (4)、写 (2)、执行 (1) 权限的和。
``` ```text
chmod 644 filename chmod 644 filename
#所有者:读 + 写 = 6 组用户:读 = 4 其他用户:读 = 4 #所有者:读 + 写 = 6 组用户:读 = 4 其他用户:读 = 4
``` ```
2. 符号方式 2. 符号方式
``` ```text
chmod [用户类别][操作符][权限] filename chmod [用户类别][操作符][权限] filename
``` ```
@ -239,7 +239,7 @@ DNS解析可能需等待几分钟生效
- `w`:写权限 - `w`:写权限
- `x`:执行权限 - `x`:执行权限
``` ```text
chmod u+x filename #为所有者增加执行权限 chmod u+x filename #为所有者增加执行权限
``` ```
@ -249,7 +249,7 @@ DNS解析可能需等待几分钟生效
**nano**Debian 11自带了简便易用的nano文本编辑器 **nano**Debian 11自带了简便易用的nano文本编辑器
``` ```text
nano /etc/apt/sources.list #打开sources.list文件 nano /etc/apt/sources.list #打开sources.list文件
``` ```
@ -317,7 +317,7 @@ Ctrl+X:退出
### 抓包 ### 抓包
``` ```text
sudo tcpdump -nn -i any port 1000 //查看请求端口1000的源 IP 地址 sudo tcpdump -nn -i any port 1000 //查看请求端口1000的源 IP 地址
``` ```
@ -327,7 +327,7 @@ Ctrl+X:退出
生成密钥 生成密钥
``` ```text
ssh-keygen -t rsa -b 4096 -C "your_email@example.com" ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
``` ```
@ -344,7 +344,7 @@ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
除此之外,还需要给文件和相关文件夹合适的权限: 除此之外,还需要给文件和相关文件夹合适的权限:
``` ```text
chmod 600 authorized_keys chmod 600 authorized_keys
chmod 700 ~/.ssh chmod 700 ~/.ssh
``` ```
@ -415,7 +415,7 @@ chmod 700 ~/.ssh
### Bash ### Bash
``` ```text
#!/bin/bash #!/bin/bash
# 定义变量,注意等号两边不能有空格 # 定义变量,注意等号两边不能有空格
@ -447,13 +447,13 @@ greet $name
赋予可执行权限 赋予可执行权限
``` ```text
chmod +x hello_world.sh chmod +x hello_world.sh
``` ```
执行 执行
``` ```text
./hello_world.sh ./hello_world.sh
或者 或者
./hello_world.sh Alice #传参 ./hello_world.sh Alice #传参
@ -465,7 +465,7 @@ chmod +x hello_world.sh
**如何设置定时任务?** **如何设置定时任务?**
``` ```text
sudo crontab -e sudo crontab -e
#在里面添加 #在里面添加
10 0 * * * /path/toyour/xx.sh #让gpt写 10 0 * * * /path/toyour/xx.sh #让gpt写
@ -501,7 +501,7 @@ sudo crontab -e
**docker 部署** **docker 部署**
``` ```text
version: '3' version: '3'
services: services:
app: app:
@ -576,7 +576,7 @@ wget -O /home/zy123/VPN/config.yaml "https://illo1.no-mad-world.club/link/2zXAEz
类似这样: 类似这样:
``` ```text
port: 7890 port: 7890
socks-port: 7891 socks-port: 7891
allow-lan: false allow-lan: false
@ -637,7 +637,7 @@ proxies:
**启动Clash** **启动Clash**
``` ```text
./CrashCore -d . & //后台启动 ./CrashCore -d . & //后台启动
``` ```
@ -645,13 +645,13 @@ proxies:
1.创建 `systemd` 服务文件 1.创建 `systemd` 服务文件
``` ```text
sudo vim /etc/systemd/system/clash.service sudo vim /etc/systemd/system/clash.service
``` ```
2.在文件中添加以下内容: 2.在文件中添加以下内容:
``` ```text
[Unit] [Unit]
Description=Clash Proxy Service Description=Clash Proxy Service
After=network.target After=network.target
@ -676,19 +676,19 @@ WantedBy=multi-user.target
启动服务: 启动服务:
``` ```text
sudo systemctl start clash sudo systemctl start clash
``` ```
停止服务: 停止服务:
``` ```text
sudo systemctl stop clash sudo systemctl stop clash
``` ```
查看服务状态: 查看服务状态:
``` ```text
sudo systemctl status clash sudo systemctl status clash
``` ```
@ -704,7 +704,7 @@ YACD 是一个基于 **Clash** 的 Web 管理面板,用于管理您的 Clash
下载yacd 下载yacd
``` ```text
git clone https://github.com/haishanh/yacd.git git clone https://github.com/haishanh/yacd.git
``` ```
@ -712,7 +712,7 @@ git clone https://github.com/haishanh/yacd.git
构建yacd 构建yacd
``` ```text
cd ~/VPN/yacd cd ~/VPN/yacd
pnpm install pnpm install
pnpm build pnpm build
@ -720,7 +720,7 @@ pnpm build
启动yacd 启动yacd
``` ```text
nohup pnpm serve --host 0.0.0.0 & //如果不是0.0.0.0 不能在windows上打开 nohup pnpm serve --host 0.0.0.0 & //如果不是0.0.0.0 不能在windows上打开
``` ```
@ -728,7 +728,7 @@ nohup pnpm serve --host 0.0.0.0 & //如果不是0.0.0.0 不能在windows上
**停止进程** **停止进程**
``` ```text
ps aux | grep pnpm ps aux | grep pnpm
kill xxx kill xxx
@ -752,19 +752,19 @@ kill xxx
1.创建数据目录 1.创建数据目录
``` ```text
mkdir -p /data/filebrowser/{srv,config,db} mkdir -p /data/filebrowser/{srv,config,db}
``` ```
2.目录授权 2.目录授权
``` ```text
chmod -R 777 /data/filebrowser/ chmod -R 777 /data/filebrowser/
``` ```
3.编辑 docker-compose.yaml 文件 3.编辑 docker-compose.yaml 文件
``` ```text
version: '3' version: '3'
services: services:
filebrowser: filebrowser:
@ -786,7 +786,7 @@ services:
[Gitea Docker 安装与使用详解:轻量级自托管 Git 服务教程-CSDN博客](https://blog.csdn.net/m0_70878103/article/details/144908188) [Gitea Docker 安装与使用详解:轻量级自托管 Git 服务教程-CSDN博客](https://blog.csdn.net/m0_70878103/article/details/144908188)
``` ```text
version: "3" version: "3"
services: services:
gitea: gitea:
@ -811,7 +811,7 @@ services:
github地址[icret/EasyImages2.0: 简单图床 - 一款功能强大无数据库的图床 2.0版](https://github.com/icret/EasyImages2.0) github地址[icret/EasyImages2.0: 简单图床 - 一款功能强大无数据库的图床 2.0版](https://github.com/icret/EasyImages2.0)
``` ```text
sudo -i # 切换到root用户 sudo -i # 切换到root用户
apt update -y # 升级packages apt update -y # 升级packages
@ -822,7 +822,7 @@ apt install wget curl sudo vim git # Debian系统比较干净安装常用的
``` ```text
version: '3.3' version: '3.3'
services: services:
easyimage: easyimage:
@ -843,7 +843,7 @@ services:
网页打开显示bug 网页打开显示bug
``` ```text
cd /data/easyimage/config/config.php cd /data/easyimage/config/config.php
``` ```
@ -902,13 +902,13 @@ py脚本3将本地图片上传到easyimage图床并将链接返回替换md文
注意nginx一定要对typecho目录有操作权限 注意nginx一定要对typecho目录有操作权限
``` ```text
sudo chmod 755 -R ./typecho sudo chmod 755 -R ./typecho
``` ```
``` ```text
services: services:
nginx: nginx:
image: nginx image: nginx
@ -973,7 +973,7 @@ networks:
卸载: 卸载:
``` ```text
sudo -i # 切换到root sudo -i # 切换到root
cd /root/data/docker_data/typecho # 进入docker-compose所在的文件夹 cd /root/data/docker_data/typecho # 进入docker-compose所在的文件夹
@ -1062,11 +1062,11 @@ slug为页面缩略名在新增文章时可以传入默认是index数字
[【好玩的Docker项目】10分钟搭建你专属的下载神器——qbittorrent-我不是咕咕鸽](https://blog.laoda.de/archives/docker-install-qbittorrent) [【好玩的Docker项目】10分钟搭建你专属的下载神器——qbittorrent-我不是咕咕鸽](https://blog.laoda.de/archives/docker-install-qbittorrent)
``` ```text
docker pull linuxserver/qbittorrent docker pull linuxserver/qbittorrent
``` ```
``` ```text
cd ~ cd ~
mkdir /root/data/docker_data/qBittorrent #创建qbitorrent数据文件夹 mkdir /root/data/docker_data/qBittorrent #创建qbitorrent数据文件夹
cd /root/data/docker_data/qBittorrent cd /root/data/docker_data/qBittorrent
@ -1075,7 +1075,7 @@ nano docker-compose.yml #创建并编辑文件
``` ```
``` ```text
services: services:
qbittorrent: qbittorrent:
image: linuxserver/qbittorrent image: linuxserver/qbittorrent

View File

@ -19,7 +19,7 @@
int[] arr1 = {1, 2, 3}; int[] arr1 = {1, 2, 3};
int[] arr2 = {1, 2, 3}; int[] arr2 = {1, 2, 3};
boolean isEqual = Arrays.equals(arr1, arr2); // true boolean isEqual = Arrays.equals(arr1, arr2); // true
``` ```text
@ -43,7 +43,7 @@
- 如果返回零,说明 `o1` 等于 `o2` - 如果返回零,说明 `o1` 等于 `o2`
- 如果返回正数,说明 `o1` 排在 `o2`后面。 - 如果返回正数,说明 `o1` 排在 `o2`后面。
``` ```text
public class TestComparator { public class TestComparator {
// 定义一个升序排序的 Comparator // 定义一个升序排序的 Comparator
static Comparator<Integer> ascComparator = new Comparator<Integer>() { static Comparator<Integer> ascComparator = new Comparator<Integer>() {
@ -78,7 +78,7 @@ public class TestComparator {
**自定义比较器排序二维数组** 用Lambda表达式实现`Comparator<int[]>接口` **自定义比较器排序二维数组** 用Lambda表达式实现`Comparator<int[]>接口`
``` ```text
import java.util.Arrays; import java.util.Arrays;
public class IntervalSort { public class IntervalSort {
@ -107,7 +107,7 @@ public class IntervalSort {
**逻辑比较** **逻辑比较**
``` ```text
boolean flag = false; boolean flag = false;
if (!flag) { //! 是 Java 中的逻辑非运算符,只能用于对布尔值取反。 if (!flag) { //! 是 Java 中的逻辑非运算符,只能用于对布尔值取反。
@ -140,7 +140,7 @@ if (flag == false) { //更常用!
需要String先转为char [] 数组排序好之后再转为String类型 需要String先转为char [] 数组排序好之后再转为String类型
``` ```text
char[] charArray = str.toCharArray(); char[] charArray = str.toCharArray();
Arrays.sort(charArray); Arrays.sort(charArray);
String sortedStr = new String(charArray); String sortedStr = new String(charArray);
@ -205,7 +205,7 @@ String sortedStr = new String(charArray);
System.out.println("After removal: " + map); // 输出 {apple=10, banana=20} System.out.println("After removal: " + map); // 输出 {apple=10, banana=20}
} }
} }
``` ```text
@ -334,7 +334,7 @@ String sortedStr = new String(charArray);
System.out.println("Array length: " + length); // 输出 5 System.out.println("Array length: " + length); // 输出 5
} }
} }
``` ```text
@ -372,7 +372,7 @@ public void setZeroes(int[][] matrix) {
System.out.println(); // 换行,便于输出格式化 System.out.println(); // 换行,便于输出格式化
} }
} }
``` ```text
@ -398,7 +398,7 @@ for (int i = 0; i < list.size(); i++) {
} }
System.out.println(); // 换行 System.out.println(); // 换行
} }
``` ```text
@ -410,7 +410,7 @@ List<int[]> merged = new ArrayList<>();
merged.add(current); merged.add(current);
return merged.toArray(new int[merged.size()][]); return merged.toArray(new int[merged.size()][]);
``` ```text
@ -545,7 +545,7 @@ return merged.toArray(new int[merged.size()][]);
System.out.println("队列是否为空: " + minHeap.isEmpty()); // 输出 true System.out.println("队列是否为空: " + minHeap.isEmpty()); // 输出 true
} }
} }
``` ```text
@ -585,7 +585,7 @@ public class QueueExample {
} }
} }
``` ```text
@ -604,7 +604,7 @@ Deque<Integer> stack = new ArrayDeque<>();
stack.push(1); // 入栈 stack.push(1); // 入栈
Integer top1=stack.peek() Integer top1=stack.peek()
Integer top = stack.pop(); // 出栈 Integer top = stack.pop(); // 出栈
``` ```text
@ -671,7 +671,7 @@ public class DequeExample {
} }
} }
``` ```text
@ -707,7 +707,7 @@ public class Main {
} }
} }
} }
``` ```text
@ -729,7 +729,7 @@ public class ArraySortExample {
System.out.println(Arrays.toString(numbers)); // 输出 [1, 2, 5, 5, 6, 9] System.out.println(Arrays.toString(numbers)); // 输出 [1, 2, 5, 5, 6, 9]
} }
} }
``` ```text
#### 集合排序 #### 集合排序
@ -752,7 +752,7 @@ public class ListSortExample {
System.out.println(numbers); // 输出 [1, 2, 5, 5, 6, 9] System.out.println(numbers); // 输出 [1, 2, 5, 5, 6, 9]
} }
} }
``` ```text
#### **自定义排序** #### **自定义排序**
@ -795,7 +795,7 @@ public class ComparatorSortExample {
System.out.println(people); // 输出 [Alice (25), Bob (20), Charlie (30)] System.out.println(people); // 输出 [Alice (25), Bob (20), Charlie (30)]
} }
} }
``` ```text

View File

@ -25,13 +25,13 @@ build.gradle(:app)中引入了hwtxtreaderlib的依赖而app只是个demo测
- 在app的build.gradle中添加依赖 - 在app的build.gradle中添加依赖
``` ```text
implementation project(':hwtxtreaderlib') implementation project(':hwtxtreaderlib')
``` ```
- 在settings.gradle中设置项目包括的模块 - 在settings.gradle中设置项目包括的模块
``` ```text
include ':app', ':hwtxtreaderlib' include ':app', ':hwtxtreaderlib'
``` ```

View File

@ -20,7 +20,7 @@
修改mp-demo中的`com.itheima.mp.mapper`包下的`UserMapper`接口,让其继承`BaseMapper` 修改mp-demo中的`com.itheima.mp.mapper`包下的`UserMapper`接口,让其继承`BaseMapper`
``` ```text
public interface UserMapper extends BaseMapper<User> { public interface UserMapper extends BaseMapper<User> {
} }
``` ```
@ -68,7 +68,7 @@ public class User {
| value | String | 否 | "" | 主键字段名 | | value | String | 否 | "" | 主键字段名 |
| type | Enum | 否 | IdType.NONE | 指定主键类型 | | type | Enum | 否 | IdType.NONE | 指定主键类型 |
``` ```text
@TableName("user") @TableName("user")
public class User { public class User {
@TableId(value="id",type=IdType.AUTO) @TableId(value="id",type=IdType.AUTO)
@ -93,7 +93,7 @@ public class User {
exist:默认为true表示是数据库字段 exist:默认为true表示是数据库字段
``` ```text
@TableField(exist=false) @TableField(exist=false)
private String address; private String address;
``` ```
@ -151,7 +151,7 @@ mybatis-plus:
**QueryWrapper** **QueryWrapper**
``` ```text
/**查询出名字中带o的存款大于等于1000元的人的idusername,info,balance /**查询出名字中带o的存款大于等于1000元的人的idusername,info,balance
* SELECT id,username,info,balance * SELECT id,username,info,balance
* FROM user * FROM user
@ -171,7 +171,7 @@ void testQueryWrapper(){
``` ```text
//更新用户名为jack的用户的余额为2000 //更新用户名为jack的用户的余额为2000
@Test @Test
void testUpdateByQueryWrapper() { void testUpdateByQueryWrapper() {
@ -192,7 +192,7 @@ void testUpdateByQueryWrapper() {
UPDATE user SET balance = balance - 200 WHERE id in (1, 2, 4) UPDATE user SET balance = balance - 200 WHERE id in (1, 2, 4)
``` ```
``` ```text
@Test @Test
void testUpdateWrapper() { void testUpdateWrapper() {
List<Long> ids = List.of(1L, 2L, 4L); List<Long> ids = List.of(1L, 2L, 4L);
@ -215,7 +215,7 @@ void testUpdateWrapper() {
- LambdaQueryWrapper - LambdaQueryWrapper
- LambdaUpdateWrapper - LambdaUpdateWrapper
``` ```text
@Test @Test
void testLambdaQueryWrapper() { void testLambdaQueryWrapper() {
// 1.构建条件 WHERE username LIKE "%o%" AND balance >= 1000 // 1.构建条件 WHERE username LIKE "%o%" AND balance >= 1000
@ -242,7 +242,7 @@ void testLambdaQueryWrapper() {
1.先在业务层利用wrapper创建条件传递参数 1.先在业务层利用wrapper创建条件传递参数
``` ```text
@Test @Test
void testCustomWrapper() { void testCustomWrapper() {
// 1.准备自定义查询条件 // 1.准备自定义查询条件
@ -256,7 +256,7 @@ void testCustomWrapper() {
2. 自定义mapper层把wrapper和其他业务参数传进去自定义sql语句书写sql的前半部分后面拼接。 2. 自定义mapper层把wrapper和其他业务参数传进去自定义sql语句书写sql的前半部分后面拼接。
``` ```text
package com.itheima.mp.mapper; package com.itheima.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@ -287,7 +287,7 @@ selectBatchIds根据主键 ID 批量查询记录。
selectOne根据指定条件查询单条记录。 selectOne根据指定条件查询单条记录。
``` ```text
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username", "alice"); queryWrapper.eq("username", "alice");
User user = userMapper.selectOne(queryWrapper); User user = userMapper.selectOne(queryWrapper);
@ -296,7 +296,7 @@ User user = userMapper.selectOne(queryWrapper);
selectList根据指定条件查询多条记录。 selectList根据指定条件查询多条记录。
``` ```text
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age", 18); queryWrapper.ge("age", 18);
List<User> users = userMapper.selectList(queryWrapper); List<User> users = userMapper.selectList(queryWrapper);
@ -309,7 +309,7 @@ List<User> users = userMapper.selectList(queryWrapper);
insert插入一条记录。 insert插入一条记录。
``` ```text
User user = new User(); User user = new User();
user.setUsername("alice"); user.setUsername("alice");
user.setAge(20); user.setAge(20);
@ -321,7 +321,7 @@ int rows = userMapper.insert(user);
updateById根据主键 ID 更新记录。 updateById根据主键 ID 更新记录。
``` ```text
User user = new User(); User user = new User();
user.setId(1L); user.setId(1L);
user.setAge(25); user.setAge(25);
@ -331,7 +331,7 @@ int rows = userMapper.updateById(user);
update根据指定条件更新记录。 update根据指定条件更新记录。
``` ```text
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(); UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("username", "alice"); updateWrapper.eq("username", "alice");
@ -350,7 +350,7 @@ deleteBatchIds根据主键 ID 批量删除记录。
delete根据指定条件删除记录。 delete根据指定条件删除记录。
``` ```text
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username", "alice"); queryWrapper.eq("username", "alice");
@ -376,7 +376,7 @@ int rows = userMapper.delete(queryWrapper);
首先,定义`IUserService`,继承`IService` 首先,定义`IUserService`,继承`IService`
``` ```text
package com.itheima.mp.service; package com.itheima.mp.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
@ -389,7 +389,7 @@ public interface IUserService extends IService<User> {
然后,编写`UserServiceImpl`类,继承`ServiceImpl`,实现`UserService` 然后,编写`UserServiceImpl`类,继承`ServiceImpl`,实现`UserService`
``` ```text
package com.itheima.mp.service.impl; package com.itheima.mp.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

View File

@ -72,20 +72,20 @@ build context`context: .`
COPY . .(在 Dockerfile 中): COPY . .(在 Dockerfile 中):
这条指令会将构建上下文中的所有内容复制到镜像中的当前工作目录(这里是 `/flask_project`)。 这条指令会将构建上下文中的所有内容复制到镜像中的当前工作目录(这里是 `/flask_project`)。
``` ```text
docker exec -it zbparse-flask_app-1 sh docker exec -it zbparse-flask_app-1 sh
``` ```
这个命令会直接进入到flask_project目录内部ls之后可以看到 这个命令会直接进入到flask_project目录内部ls之后可以看到
``` ```text
Dockerfile README.md docker-compose.yml flask_app md_files requirements.txt Dockerfile README.md docker-compose.yml flask_app md_files requirements.txt
``` ```
如果这个基础上再` cd / `会切换到这个容器的根目录可以看到flask_project文件夹以及其他基础系统环境。如 如果这个基础上再` cd / `会切换到这个容器的根目录可以看到flask_project文件夹以及其他基础系统环境。如
``` ```text
bin boot dev etc flask_project home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var bin boot dev etc flask_project home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
``` ```
@ -101,7 +101,7 @@ bin boot dev etc flask_project home lib lib64 media mnt opt proc roo
**完整的容器名** **完整的容器名**
``` ```text
<项目名>-<服务名>-<序号> <项目名>-<服务名>-<序号>
``` ```
@ -121,7 +121,7 @@ docker exec -it **zbparse-flask_app-1** sh
**删除所有悬空镜像**(无容器引用的 `<none>` 镜像) **删除所有悬空镜像**(无容器引用的 `<none>` 镜像)
``` ```text
docker image prune docker image prune
``` ```
@ -149,7 +149,7 @@ docker image prune
1.编写ps1脚本 1.编写ps1脚本
``` ```text
# 切换到指定目录 # 切换到指定目录
cd D:\PycharmProjects\zbparse cd D:\PycharmProjects\zbparse
@ -189,7 +189,7 @@ python flask_app\run_serve.py
打开系统环境变量Path添加一条C:\ProgramData\anaconda3\condabin 打开系统环境变量Path添加一条C:\ProgramData\anaconda3\condabin
或者 CMD 中 set PATH=%PATH%;新添加的路径 或者 CMD 中 set PATH=%PATH%;新添加的路径
``` ```text
- 重启终端可以刷新环境变量 - 重启终端可以刷新环境变量
@ -197,7 +197,7 @@ python flask_app\run_serve.py
``` ```
conda init powershell conda init powershell
``` ```text
4.进入到存放run.ps1文件的目录在搜索栏中输入powershell 4.进入到存放run.ps1文件的目录在搜索栏中输入powershell
@ -205,7 +205,7 @@ conda init powershell
``` ```
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
``` ```text
@ -213,7 +213,7 @@ Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
``` ```
.\run.ps1 .\run.ps1
``` ```text
**注意!!!** **注意!!!**
@ -277,19 +277,19 @@ find "$ROOT_DIR" -mindepth 2 -depth -type d -mtime +7 -print -exec rm -rf {} \;
echo "清理完成。" echo "清理完成。"
``` ```text
2. 添加权限。 2. 添加权限。
``` ```
sudo chmod +x ./clean_dir.sh sudo chmod +x ./clean_dir.sh
``` ```text
3. 执行 3. 执行
``` ```
sudo ./clean_dir.sh sudo ./clean_dir.sh
``` ```text
4. 以 root 用户的身份编辑 crontab 文件从而设置或修改系统定时任务cron jobs。每天零点10分清理 4. 以 root 用户的身份编辑 crontab 文件从而设置或修改系统定时任务cron jobs。每天零点10分清理
@ -298,7 +298,7 @@ sudo crontab -e
在里面添加: 在里面添加:
10 0 * * * /home/Z/clean_dir.sh 10 0 * * * /home/Z/clean_dir.sh
``` ```text
**目前测试服务器和正式服务器都写上了!无需变动** **目前测试服务器和正式服务器都写上了!无需变动**
@ -329,7 +329,7 @@ END {
print "管道FD:", pipe print "管道FD:", pipe
print "其他FD:", other print "其他FD:", other
}' }'
``` ```text
**可以发现文件FD很大基本上发送一个请求文件FD就加一且不会衰减** **可以发现文件FD很大基本上发送一个请求文件FD就加一且不会衰减**
@ -362,7 +362,7 @@ def create_logger(app, subfolder):
logger.propagate = False logger.propagate = False
g.logger = logger g.logger = logger
g.output_folder = output_folder #输出文件夹路径 g.output_folder = output_folder #输出文件夹路径
``` ```text
handler每当 logger 生成一条日志信息时,这条信息会被传递给所有关联的 handler由 handler 决定如何输出这条日志。例如,`FileHandler` 会把日志写入文件,而 `StreamHandler` 会将日志输出到控制台。 handler每当 logger 生成一条日志信息时,这条信息会被传递给所有关联的 handler由 handler 决定如何输出这条日志。例如,`FileHandler` 会把日志写入文件,而 `StreamHandler` 会将日志输出到控制台。
@ -402,7 +402,7 @@ mem_before = memory_usage()[0]
result=my_function() result=my_function()
mem_after = memory_usage()[0] mem_after = memory_usage()[0]
print(f"Memory before: {mem_before} MiB, Memory after: {mem_after} MiB") print(f"Memory before: {mem_before} MiB, Memory after: {mem_after} MiB")
``` ```text
@profile注解加在函数上,可以逐行分析内存增减情况。 @profile注解加在函数上,可以逐行分析内存增减情况。
@ -425,7 +425,7 @@ def extract_text_by_page(file_path):
page = reader.pages[page_num] page = reader.pages[page_num]
text = page.extract_text() text = page.extract_text()
return "" return ""
``` ```text
![1](https://pic.bitday.top/i/2025/03/19/u7ukfk-2.png) ![1](https://pic.bitday.top/i/2025/03/19/u7ukfk-2.png)
@ -463,7 +463,7 @@ for stat in stats[:10]:
print(stat) print(stat)
# 停止内存分配跟踪 # 停止内存分配跟踪
tracemalloc.stop() tracemalloc.stop()
``` ```text
![1](https://pic.bitday.top/i/2025/03/19/u7vdu0-2.png) ![1](https://pic.bitday.top/i/2025/03/19/u7vdu0-2.png)
@ -479,7 +479,7 @@ tracemalloc能更深入的分析不仅是自己写的代码**调用的库
``` ```
reader =PdfReader(file_path) reader =PdfReader(file_path)
``` ```text
能够确保文件正常关闭。但是没有效果。 能够确保文件正常关闭。但是没有效果。
@ -532,7 +532,7 @@ def run_in_subprocess(main_func, output_folder, file_path, file_type, unique_id)
yield item yield item
p.join() p.join()
``` ```text
如果开子线程,线程共享同一进程的内存空间,所以如果发生内存泄漏,泄漏的内存会累积在整个进程中,影响所有线程。 如果开子线程,线程共享同一进程的内存空间,所以如果发生内存泄漏,泄漏的内存会累积在整个进程中,影响所有线程。
@ -562,7 +562,7 @@ def judge_zbfile_exec_sub(file_path):
args=(file_path,) args=(file_path,)
) )
return result return result
``` ```text
但是存在一个问题:**第一次发送请求执行时间较慢!** 但是存在一个问题:**第一次发送请求执行时间较慢!**
@ -589,7 +589,7 @@ def warmup_request():
print(f"Warm-up 请求发送成功,状态码:{response.status_code}") print(f"Warm-up 请求发送成功,状态码:{response.status_code}")
except Exception as e: except Exception as e:
print(f"Warm-up 请求出错:{e}") print(f"Warm-up 请求出错:{e}")
``` ```text
threading.Thread(target=warmup_request, daemon=True).start() threading.Thread(target=warmup_request, daemon=True).start()
@ -621,7 +621,7 @@ def get_next_api_key():
return next(api_keys) return next(api_keys)
api_key = get_next_api_key() api_key = get_next_api_key()
``` ```text
只需轮流使用不同的api_key即可。目前没有启用。 只需轮流使用不同的api_key即可。目前没有启用。
@ -639,7 +639,7 @@ general/llm下的doubao.py 和通义千问long_plus.py
@limits(calls=10, period=1) # 每秒最多调用10次 @limits(calls=10, period=1) # 每秒最多调用10次
def rate_limiter(): def rate_limiter():
pass # 这个函数本身不执行任何操作,只用于限流 pass # 这个函数本身不执行任何操作,只用于限流
``` ```text
2. 这是qianwen-plus的限制针对tpm为1000万每个请求2万tokens那么linux和windows总的qps为8时8x60x2=960<1000单个为4 2. 这是qianwen-plus的限制针对tpm为1000万每个请求2万tokens那么linux和windows总的qps为8时8x60x2=960<1000单个为4
**经过2.11号测试calls=4时最高TPM为800因此把目前稳定版把calls设为5** **经过2.11号测试calls=4时最高TPM为800因此把目前稳定版把calls设为5**
@ -651,14 +651,14 @@ def rate_limiter():
@limits(calls=7, period=1) # 每秒最多调用7次 @limits(calls=7, period=1) # 每秒最多调用7次
def qianwen_plus(user_query, need_extra=False): def qianwen_plus(user_query, need_extra=False):
logger = logging.getLogger('model_log') # 通过日志名字获取记录器 logger = logging.getLogger('model_log') # 通过日志名字获取记录器
``` ```text
3. qianwen_turbo的限制TPM为500万由于它是plus后的手段稳妥一点qps设为6两个服务器分流即calls=3 3. qianwen_turbo的限制TPM为500万由于它是plus后的手段稳妥一点qps设为6两个服务器分流即calls=3
``` ```
@sleep_and_retry @sleep_and_retry
@limits(calls=3, period=1) # 500万tpm每秒最多调用6次两个服务器分流就是3次 plus超限后的保底手段稳妥一点 @limits(calls=3, period=1) # 500万tpm每秒最多调用6次两个服务器分流就是3次 plus超限后的保底手段稳妥一点
``` ```text
**重点!!**后续阿里扩容之后成倍修改这块**calls=?** **重点!!**后续阿里扩容之后成倍修改这块**calls=?**
@ -675,7 +675,7 @@ app.connection_limiters['upload'] = ConnectionLimiter(max_connections=100)
app.connection_limiters['get_deviation'] = ConnectionLimiter(max_connections=100) app.connection_limiters['get_deviation'] = ConnectionLimiter(max_connections=100)
app.connection_limiters['default'] = ConnectionLimiter(max_connections=100) app.connection_limiters['default'] = ConnectionLimiter(max_connections=100)
app.connection_limiters['judge_zbfile'] = ConnectionLimiter(max_connections=100) app.connection_limiters['judge_zbfile'] = ConnectionLimiter(max_connections=100)
``` ```text
2. ConnectionLimiter.py以及每个接口上的装饰器 2. ConnectionLimiter.py以及每个接口上的装饰器
@ -683,7 +683,7 @@ app.connection_limiters['upload'] = ConnectionLimiter(max_connections=100)
@require_connection_limit(timeout=1800) @require_connection_limit(timeout=1800)
def zbparse(): def zbparse():
``` ```text
这里限制了每个接口内部执行的时间暂时设置到了30分钟不包括排队时间超时就是解析失败 这里限制了每个接口内部执行的时间暂时设置到了30分钟不包括排队时间超时就是解析失败
@ -885,7 +885,7 @@ start_up.py是启动脚本run_serve也是启动脚本是对start_up.py的
yield sse_format(shangwu_deviation_response) yield sse_format(shangwu_deviation_response)
yield sse_format(shangwu_star_deviation_response) yield sse_format(shangwu_star_deviation_response)
yield sse_format(proof_materials_response) yield sse_format(proof_materials_response)
``` ```text
1. 工程标解析目前仍没有解析采购要求这一块,因此后处理返回的只有'资格审查'和''证明材料"和"extracted_info",没有''商务偏离''及'商务带星偏离',也没有'技术偏离'和'技术带星偏离',而货物标解析是完全版。 1. 工程标解析目前仍没有解析采购要求这一块,因此后处理返回的只有'资格审查'和''证明材料"和"extracted_info",没有''商务偏离''及'商务带星偏离',也没有'技术偏离'和'技术带星偏离',而货物标解析是完全版。
@ -938,7 +938,7 @@ if __name__ == '__main__':
# 使用 Waitress 启动(生产环境) # 使用 Waitress 启动(生产环境)
from waitress import serve from waitress import serve
serve(app, host='0.0.0.0', port=8080) serve(app, host='0.0.0.0', port=8080)
``` ```text
**Waitress 的工作方式** **Waitress 的工作方式**
@ -986,14 +986,14 @@ serve(app, host='0.0.0.0', port=8080)
``` ```
pip install gevent pip install gevent
``` ```text
启动 Gunicorn 时指定 worker 类型和数量,例如: 启动 Gunicorn 时指定 worker 类型和数量,例如:
``` ```
gunicorn -k gevent -w 4 --max-requests 100 flask_app.start_up:create_app --bind 0.0.0.0:5000 gunicorn -k gevent -w 4 --max-requests 100 flask_app.start_up:create_app --bind 0.0.0.0:5000
``` ```text
使用 `-k gevent`(或者 `-k eventlet`)就可以使用异步 worker单个 worker 能够处理多个 I/O 密集型请求。 使用 `-k gevent`(或者 `-k eventlet`)就可以使用异步 worker单个 worker 能够处理多个 I/O 密集型请求。
@ -1063,7 +1063,7 @@ Python特别是 CPython 实现中有一个叫做全局解释器锁Globa
``` ```
pool =Pool(processes=10, maxtasksperchild=3) pool =Pool(processes=10, maxtasksperchild=3)
``` ```text
**concurrent.futures.ProcessPoolExecutor**更高级、更统一,没有类似 `maxtasksperchild` 的参数,意味着进程在整个执行期内会一直存活,适合任务本身**比较稳定**的场景。 **concurrent.futures.ProcessPoolExecutor**更高级、更统一,没有类似 `maxtasksperchild` 的参数,意味着进程在整个执行期内会一直存活,适合任务本身**比较稳定**的场景。
@ -1105,7 +1105,7 @@ if __name__ == '__main__':
t1.join() t1.join()
t2.join() t2.join()
print('主线程执行结果',num) print('主线程执行结果',num)
``` ```text
运行结果: 运行结果:
@ -1115,7 +1115,7 @@ work 1551626
work1 1615783 work1 1615783
主线程执行结果 1615783 主线程执行结果 1615783
``` ```text
这些数值都小于预期的 2000000因为 这些数值都小于预期的 2000000因为
@ -1166,7 +1166,7 @@ if __name__ == '__main__':
t2.join() t2.join()
print('主线程执行结果',num) print('主线程执行结果',num)
``` ```text
@ -1200,7 +1200,7 @@ if __name__ == '__main__':
results.append(q.get()) results.append(q.get())
print("Collected data:", results) print("Collected data:", results)
``` ```text
- 当你在主进程中创建了一个 `Queue` 对象,然后将它作为参数传递给子进程时,子进程会获得一个能够与主进程通信的“句柄”。 - 当你在主进程中创建了一个 `Queue` 对象,然后将它作为参数传递给子进程时,子进程会获得一个能够与主进程通信的“句柄”。

View File

@ -47,7 +47,7 @@
因为一般后台服务地址不会暴露所以使用浏览器不能直接访问可以把nginx作为请求访问的入口请求到达nginx后转发到具体的服务中从而保证后端服务的安全。 因为一般后台服务地址不会暴露所以使用浏览器不能直接访问可以把nginx作为请求访问的入口请求到达nginx后转发到具体的服务中从而保证后端服务的安全。
``` ```text
server{ server{
listen 80; listen 80;
server_name localhost; server_name localhost;
@ -62,7 +62,7 @@ server{
**2.负载均衡配置**(有两个后端服务器) **2.负载均衡配置**(有两个后端服务器)
``` ```text
upstream webservers{ upstream webservers{
server 192.168.100.128:8080; server 192.168.100.128:8080;
server 192.168.100.129:8080; server 192.168.100.129:8080;
@ -156,7 +156,7 @@ protected void addResourceHandlers(ResourceHandlerRegistry registry) {
EmployeeLoginDTO.java EmployeeLoginDTO.java
``` ```text
@Data @Data
@ApiModel(description = "员工登录时传递的数据模型") @ApiModel(description = "员工登录时传递的数据模型")
public class EmployeeLoginDTO implements Serializable { public class EmployeeLoginDTO implements Serializable {
@ -188,7 +188,7 @@ spring security中提供了一个加密类BCryptPasswordEncoder。
- 添加依赖 - 添加依赖
``` ```text
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
@ -197,7 +197,7 @@ spring security中提供了一个加密类BCryptPasswordEncoder。
- 添加配置 - 添加配置
``` ```text
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@ -218,7 +218,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
- 使用 - 使用
``` ```text
@Autowired @Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder; private BCryptPasswordEncoder bCryptPasswordEncoder;
@ -256,7 +256,7 @@ ThreadLocal为**每个线程**提供**单独**一份存储空间,具有线程
**每次请求代表一个线程**请求可以先经过拦截器再经过controller=>service=>mapper,都是在一个线程里。 **每次请求代表一个线程**请求可以先经过拦截器再经过controller=>service=>mapper,都是在一个线程里。
``` ```text
public class BaseContext { public class BaseContext {
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>(); public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
@ -321,7 +321,7 @@ public class BaseContext {
JacksonObjectMapper()文件: JacksonObjectMapper()文件:
``` ```text
public class JacksonObjectMapper extends ObjectMapper { public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
@ -373,7 +373,7 @@ public void startOrStop(Integer status, Long id) {
还有一种把源对象source的属性值赋给目标**对象**target中与源**对象**source的中有着同属性名的属性 还有一种把源对象source的属性值赋给目标**对象**target中与源**对象**source的中有着同属性名的属性
``` ```text
BeanUtils.copyProperties(source,target); BeanUtils.copyProperties(source,target);
``` ```
@ -566,7 +566,7 @@ public class SpringDataRedisTest {
**哈希测试** **哈希测试**
``` ```text
/** /**
* 操作哈希类型的数据 * 操作哈希类型的数据
*/ */
@ -725,7 +725,7 @@ public class SpringDataRedisTest {
``` ```text
public static String doGet(String url,Map<String,String> paramMap){ public static String doGet(String url,Map<String,String> paramMap){
// 创建Httpclient对象 // 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpClient httpClient = HttpClients.createDefault();
@ -800,7 +800,7 @@ public static String doGet(String url,Map<String,String> paramMap){
- 每个分类下的菜品保存一份缓存数据 - 每个分类下的菜品保存一份缓存数据
- 数据库中菜品数据有**变更时清理缓存数据** - 数据库中菜品数据有**变更时清理缓存数据**
``` ```text
@Autowired @Autowired
private RedisTemplate redisTemplate; private RedisTemplate redisTemplate;
/** /**
@ -847,7 +847,7 @@ public static String doGet(String url,Map<String,String> paramMap){
清理缓冲方法: 清理缓冲方法:
``` ```text
private void cleanCache(String pattern){ private void cleanCache(String pattern){
Set keys = redisTemplate.keys(pattern); Set keys = redisTemplate.keys(pattern);
redisTemplate.delete(keys); redisTemplate.delete(keys);
@ -860,7 +860,7 @@ public static String doGet(String url,Map<String,String> paramMap){
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。 Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
``` ```text
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId> <version>2.7.3</version> <artifactId>spring-boot-starter-cache</artifactId> <version>2.7.3</version>
@ -894,7 +894,7 @@ Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要
``` ```text
@PostMapping @PostMapping
@CachePut(value = "userCache", key = "#user.id")//key的生成userCache::1 @CachePut(value = "userCache", key = "#user.id")//key的生成userCache::1
public User save(@RequestBody User user){ public User save(@RequestBody User user){
@ -917,7 +917,7 @@ Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要
所以,@Cacheable(cacheNames = "userCache",key="#id")中的#id表示的是函数形参中的id而不能是返回值中的user.id 所以,@Cacheable(cacheNames = "userCache",key="#id")中的#id表示的是函数形参中的id而不能是返回值中的user.id
``` ```text
@GetMapping @GetMapping
@Cacheable(cacheNames = "userCache",key="#id") @Cacheable(cacheNames = "userCache",key="#id")
public User getById(Long id){ public User getById(Long id){
@ -930,7 +930,7 @@ Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要
作用: 清理指定缓存 作用: 清理指定缓存
``` ```text
@DeleteMapping @DeleteMapping
@CacheEvict(cacheNames = "userCache",key = "#id")//删除某个key对应的缓存数据 @CacheEvict(cacheNames = "userCache",key = "#id")//删除某个key对应的缓存数据
public void deleteById(Long id){ public void deleteById(Long id){
@ -992,13 +992,13 @@ https://pay.weixin.qq.com/static/product/product_index.shtml
输入代码: 输入代码:
``` ```text
cpolar.exe authtoken ZmIwMmQzZDYtZDE2ZS00ZGVjLWE2MTUtOGQ0YTdhOWI2M2Q1 cpolar.exe authtoken ZmIwMmQzZDYtZDE2ZS00ZGVjLWE2MTUtOGQ0YTdhOWI2M2Q1
``` ```
3获取临时域名 3获取临时域名
``` ```text
cpolar.exe http 8080 cpolar.exe http 8080
``` ```
@ -1060,7 +1060,7 @@ cron表达式在线生成器https://cron.qqe2.com/
``` ```text
@Component @Component
@Slf4j @Slf4j
public class OrderTask { public class OrderTask {

11
update.bat Normal file
View File

@ -0,0 +1,11 @@
@echo off
REM 添加所有改动
git add .
REM 使用当前的日期和时间作为提交信息
git commit -m "Commit on %date% %time%"
REM 推送到远程仓库
git push
pause

View File

@ -83,7 +83,7 @@ $$
当误差超过某个预定阈值时禁用积分作用仅使用比例P和微分D控制来快速减小误差避免因积分作用导致的控制器输出过度响应。 当误差超过某个预定阈值时禁用积分作用仅使用比例P和微分D控制来快速减小误差避免因积分作用导致的控制器输出过度响应。
``` ```text
if (abs(error) > threshold) { if (abs(error) > threshold) {
// 积分作用被分离,即暂时禁用积分作用 // 积分作用被分离,即暂时禁用积分作用
integral = 0; integral = 0;

View File

@ -321,7 +321,7 @@ $$
假设我们有一个简单的无向图,包含 4 个节点和 4 条边,结构如下: 假设我们有一个简单的无向图,包含 4 个节点和 4 条边,结构如下:
``` ```text
1 — 2 — 3 1 — 2 — 3
| |
4 4

View File

@ -22,7 +22,7 @@
3. **对节点顺序敏感** ,节点编号顺序一变,输入就完全变样,但其实图的拓扑并没变(仅节点编号/排列方式不同)。 3. **对节点顺序敏感** ,节点编号顺序一变,输入就完全变样,但其实图的拓扑并没变(仅节点编号/排列方式不同)。
``` ```text
A —— B A —— B
| | | |
D —— C D —— C
@ -78,7 +78,7 @@
1. **聚合Aggregation**:将邻居节点的特征聚合起来(如求和、均值、最大值等)。 1. **聚合Aggregation**:将邻居节点的特征聚合起来(如求和、均值、最大值等)。
2. **变换Transformation**:将聚合后的特征通过一个神经网络(如 MLP进行非线性变换。 2. **变换Transformation**:将聚合后的特征通过一个神经网络(如 MLP进行非线性变换。
``` ```text
A A
| |
B B