[{"content":"微服务网关 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // 必须写Component,否则不会生效,因为需要注册为spring Bean @Component public class MyGlobalFilter implements GlobalFilter, Ordered { @Override public Mono\u0026lt;Void\u0026gt; filter(ServerWebExchange exchange, GatewayFilterChain chain) { // TODO 模拟登录校验 ServerHttpRequest request = exchange.getRequest(); HttpHeaders headers = request.getHeaders(); System.out.println(request); System.out.println(headers); return chain.filter(exchange); } @Override public int getOrder() { // 过滤器执行顺序，值越小，优先级越高 return 0; } } 配置文件 gateway下面是路由配置，注意Path = /items/** ,/search/** 这里写在一行用逗号隔开 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 server: port: 8080 spring: application: name: gateway cloud: nacos: server-addr: 192.168.146.129:8848 gateway: routes: - id: item-service # 路由规则id，自定义，唯一 uri: lb://item-service # 路由的目标服务，lb代表负载均衡，会从注册中心拉取服务列表 predicates: # 路由断言，判断当前请求是否符合当前规则，符合则路由到目标服务 - Path=/items/**,/search/** - id: cart-service # 路由规则id，自定义，唯一 uri: lb://cart-service predicates: - Path=/carts/** - id: user-service uri: lb://user-service predicates: - Path=/users/**,/addresses/** - id: trade-service uri: lb://trade-service predicates: - Path=/orders/** - id: pay-service uri: lb://pay-service predicates: - Path=/pay-orders/** # default-filters: Maven配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 \u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;UTF-8\u0026#34;?\u0026gt; \u0026lt;project xmlns=\u0026#34;http://maven.apache.org/POM/4.0.0\u0026#34; xmlns:xsi=\u0026#34;http://www.w3.org/2001/XMLSchema-instance\u0026#34; xsi:schemaLocation=\u0026#34;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\u0026#34;\u0026gt; \u0026lt;parent\u0026gt; \u0026lt;artifactId\u0026gt;hmall\u0026lt;/artifactId\u0026gt; \u0026lt;groupId\u0026gt;com.heima\u0026lt;/groupId\u0026gt; \u0026lt;version\u0026gt;1.0.0\u0026lt;/version\u0026gt; \u0026lt;/parent\u0026gt; \u0026lt;modelVersion\u0026gt;4.0.0\u0026lt;/modelVersion\u0026gt; \u0026lt;artifactId\u0026gt;hm-gateway\u0026lt;/artifactId\u0026gt; \u0026lt;properties\u0026gt; \u0026lt;maven.compiler.source\u0026gt;11\u0026lt;/maven.compiler.source\u0026gt; \u0026lt;maven.compiler.target\u0026gt;11\u0026lt;/maven.compiler.target\u0026gt; \u0026lt;/properties\u0026gt; \u0026lt;dependencies\u0026gt; \u0026lt;!--common--\u0026gt; \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;com.heima\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;hm-common\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;1.0.0\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt; \u0026lt;!--网关--\u0026gt; \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.cloud\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-cloud-starter-gateway\u0026lt;/artifactId\u0026gt; \u0026lt;/dependency\u0026gt; \u0026lt;!--nacos discovery--\u0026gt; \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;com.alibaba.cloud\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-cloud-starter-alibaba-nacos-discovery\u0026lt;/artifactId\u0026gt; \u0026lt;/dependency\u0026gt; \u0026lt;!--负载均衡--\u0026gt; \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.cloud\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-cloud-starter-loadbalancer\u0026lt;/artifactId\u0026gt; \u0026lt;/dependency\u0026gt; \u0026lt;/dependencies\u0026gt; \u0026lt;build\u0026gt; \u0026lt;finalName\u0026gt;${project.artifactId}\u0026lt;/finalName\u0026gt; \u0026lt;plugins\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-boot-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;/plugins\u0026gt; \u0026lt;/build\u0026gt; \u0026lt;/project\u0026gt; ","date":"2026-03-16T00:00:00Z","permalink":"https://shuimo0413.github.io/p/gateway/","title":"微服务网关"},{"content":"自定义镜像 Dockerfile Docker 镜像采用分层存储（基于 UnionFS 联合文件系统）： 基础镜像（如ubuntu:20.04）是最底层的只读层；\n你每执行一个定制操作（如安装软件、复制文件），都会在原有层之上新增一个只读层； 最终所有层叠加，形成完整的自定义镜像，容器启动时会在镜像层之上挂载一个可写层。 这种分层机制的好处是：复用已有层（节省空间）、构建增量更新（只重新构建修改的层）。 示例：制作预装 Python3 的 Ubuntu 自定义镜像 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # Dockerfile # 1. 指定基础镜像（必选，第一层） FROM ubuntu:20.04 # 2. 维护者信息（可选） LABEL maintainer=\u0026#34;yourname \u0026lt;your@email.com\u0026gt;\u0026#34; # 3. 执行命令（安装Python3，清理缓存减少镜像体积） RUN apt-get update \u0026amp;\u0026amp; \\ apt-get install -y python3 python3-pip \u0026amp;\u0026amp; \\ rm -rf /var/lib/apt/lists/* # 关键：清理缓存，避免层过大 # 4. 设置工作目录（后续命令的默认目录） WORKDIR /app # 5. 容器启动默认命令 CMD [\u0026#34;python3\u0026#34;, \u0026#34;--version\u0026#34;] 构建镜像 1 2 # 假设 Dockerfile 所在目录为当前目录 docker build -t docker-demo . 这句话分为三个部分 docker build：构建镜像命令； -t docker-demo：指定镜像名称和标签； .：当前目录，即 Dockerfile 所在目录。 然后我们创建容器 1 docker build -t docker-demo . 此时观察容器状态 容器已经跑起来了 1 2 3 4 5 6 [root@localhost ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e6ff2fceb771 docker-demo \u0026#34;java -jar /app.jar\u0026#34; About a minute ago Up About a minute 0.0.0.0:8080-\u0026gt;8080/tcp, :::8080-\u0026gt;8080/tcp dd bfb1069106a2 mysql:8.0 \u0026#34;docker-entrypoint.s…\u0026#34; 17 hours ago Up 19 minutes 0.0.0.0:3306-\u0026gt;3306/tcp, :::3306-\u0026gt;3306/tcp, 33060/tcp mysql 7bf0d447a7f9 nginx \u0026#34;/docker-entrypoint.…\u0026#34; 21 hours ago Exited (0) 18 hours ago nginx [root@localhost ~]# 创建自定义docker网络 docker自定义网络可以直接使用容器名相互访问，不需要知道ip 查看自定义网络 1 docker network ls 创建自定义docker网络 1 2 # 创建自定义docker网络 docker network create shuimo 让mysql容器加入自定义网络 1 docker network connect shuimo mysql 创建容器的时候自己连接自定义网络 1 docker run -d --name dd -p 8080:8080 --network shuimo docker-demo 连接配置成功的结果 docker run -d \u0026ndash;name mysql \u0026ndash;network shuimo -p 3306:3306 \\ -v /root/mysql/data:/var/lib/mysql -v /root/mysql/conf:/etc/mysql/conf.d \\ -v /root/mysql/sql:/docker-entrypoint-initdb.d -e MYSQL_ROOT_PASSWORD=1743355601 -e MYSQL_INITDB_SKIP_TZINFO=1 \\ -e LANG=C.UTF-8 \u0026ndash;restart always \\ mysql:8.0\n","date":"2026-03-15T00:00:00Z","permalink":"https://shuimo0413.github.io/p/docker-network/","title":"自定义docker网络"},{"content":"mybatis plus 常见注解 @TableName\n作用：指定实体类对应的数据库表名 位置：实体类上 属性：value（指定表名） @TableId\n作用：指定实体类中主键字段对应的数据库表字段 位置：主键字段上 属性：value（指定表字段名），type（指定主键生成策略） @TableField\n作用：指定实体类中非主键字段对应的数据库表字段 位置：非主键字段上 属性：value（指定表字段名） #IdType\n作用：指定主键生成策略 位置：@TableId注解上 属性：value（指定主键生成策略） 类型 核心作用 AUTO 数据库自增（需表主键开启自增，插入时无需赋值） INPUT 手动输入（插入前必须给主键赋值，否则报错） ASSIGN_ID 默认策略，雪花算法生成全局唯一的 Long 型主键（无需赋值） ASSIGN_UUID 生成全局唯一的 UUID 字符串主键（需主键字段为 String 类型） NONE 无特定策略，跟随 MyBatis-Plus 全局主键配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //假如tb_user是真正的表名，和类名不一样，那么需要对应一下呢 @TableName(\u0026#34;tb_user\u0026#34;) public class User { // 主键字段也对应一下,并指定主键生成策略为自增，一般主键就是自增的，加了这个之后，插入数据时，主键会自动增长 @TableId(value = \u0026#34;id\u0026#34;, type = IdType.AUTO) private Long id; @TableField(\u0026#34;username\u0026#34;) private String username; private String password; private String name; // 标记非表字段 @TableField(exist = false) private Integer address; } 总结 mybatis plus默认以类名驼峰转下划线作为表名 默认把名为id的字段作为主键 默认把变量名驼峰转下划线作为表的字段名 IService接口 条件查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Test void testQueryWrapper() { QueryWrapper\u0026lt;User\u0026gt; wrapper = new QueryWrapper\u0026lt;User\u0026gt;(); wrapper.select(\u0026#34;id\u0026#34;, \u0026#34;username\u0026#34;,\u0026#34;info\u0026#34;, \u0026#34;balance\u0026#34;) .like(\u0026#34;username\u0026#34;, \u0026#34;o\u0026#34;) .ge(\u0026#34;balance\u0026#34;, 1000); List\u0026lt;User\u0026gt; users = userMapper.selectList(wrapper); users.forEach(System.out::println); } // 或者你还可以这样写 @Test void testQueryWrapper() { QueryWrapper\u0026lt;User\u0026gt; wrapper = new QueryWrapper\u0026lt;User\u0026gt;() .select(\u0026#34;id\u0026#34;, \u0026#34;username\u0026#34;,\u0026#34;info\u0026#34;, \u0026#34;balance\u0026#34;) .like(\u0026#34;username\u0026#34;, \u0026#34;o\u0026#34;) .ge(\u0026#34;balance\u0026#34;, 1000); // 执行查询 List\u0026lt;User\u0026gt; users = userMapper.selectList(wrapper); users.forEach(System.out::println); } 更新数据 1 2 3 4 5 6 7 8 9 10 11 @Test void testUpdateWrapper() { User user = new User(); user.setBalance(114514); QueryWrapper\u0026lt;User\u0026gt; wrapper = new QueryWrapper\u0026lt;User\u0026gt;() .eq(\u0026#34;username\u0026#34;,\u0026#34;jack\u0026#34;); // user是你要更新的数据，wrapper是你要更新的条件 userMapper.update(user,wrapper); } 插入数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test void testInsertWrapper() { User user = new User(); user.setUsername(\u0026#34;shuimo\u0026#34;); user.setPassword(\u0026#34;1234565165\u0026#34;); user.setBalance(114514); user.setPhone(\u0026#34;18688990011\u0026#34;); user.setInfo(\u0026#34;{\\\u0026#34;age\\\u0026#34;: 24, \\\u0026#34;intro\\\u0026#34;: \\\u0026#34;英文老师\\\u0026#34;, \\\u0026#34;gender\\\u0026#34;: \\\u0026#34;female\\\u0026#34;}\u0026#34;); user.setCreateTime(LocalDateTime.now()); user.setUpdateTime(LocalDateTime.now()); userMapper.insert(user); } 删除数据 1 2 3 4 5 6 @Test void testDeleteWrapper() { QueryWrapper\u0026lt;User\u0026gt; wrapper = new QueryWrapper\u0026lt;User\u0026gt;() .eq(\u0026#34;username\u0026#34;,\u0026#34;shuimo\u0026#34;); userMapper.delete(wrapper); } 批量修改 1 2 3 4 5 6 7 8 @Test void testAllUpdateWrapper() { List\u0026lt;Long\u0026gt; ids = List.of(1L, 2L, 3L); UpdateWrapper\u0026lt;User\u0026gt; wrapper = new UpdateWrapper\u0026lt;User\u0026gt;() .set(\u0026#34;balance\u0026#34;, 0) // 设置了balance为0 .in(\u0026#34;id\u0026#34;, ids); userMapper.update(null, wrapper); } 分页查询 1 2 3 4 5 6 7 8 9 10 11 @Test void testQueryByPage(){ // 分页查询 int start = 0; int size = 2; QueryWrapper\u0026lt;User\u0026gt; wrapper = new QueryWrapper\u0026lt;User\u0026gt;() .select(\u0026#34;id\u0026#34;, \u0026#34;username\u0026#34;,\u0026#34;info\u0026#34;, \u0026#34;balance\u0026#34;) .last(\u0026#34;limit \u0026#34; + start + \u0026#34;,\u0026#34; + size); userMapper.selectList(wrapper).forEach(System.out::println); } 自定义sql 查询两个表都有的数据 测试类 1 2 3 4 5 6 7 @Test void testQuery(){ // 复杂的查询，自定义sql,mq只支持单表 // 查询address和address1表都有的数据 List\u0026lt;Address\u0026gt; Address = addressMapper.query(); Address.forEach(System.out::println); } 实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Data @TableName(\u0026#34;address\u0026#34;) public class Address { // 自增 @TableId(type = IdType.AUTO) private Long id; private String userId; private String province; private String city; private String towm; private String mobile; private String street; private String contact; private String isDefault; private String nodes; private String deleted; } mapper类 1 2 3 4 5 6 7 8 public interface AddressMapper extends BaseMapper\u0026lt;Address\u0026gt; { // 查询address和address1表都有的数据 @Select(\u0026#34;select * from address inner join address1 on address.id = address1.id\u0026#34;) List\u0026lt;Address\u0026gt; query(); } UserServiceImpl 类 1 2 3 4 5 // 通过继承复用了 ServiceImpl 中已经提前写好的方法 @Service public class UserServiceImpl extends ServiceImpl\u0026lt;UserMapper, User\u0026gt; implements IUserService { } IUserService 接口 1 2 3 public interface IUserService extends IService\u0026lt;User\u0026gt; { } UserMapper 接口 1 2 3 4 //继承BaseMapper，指定泛型为User public interface UserMapper extends BaseMapper\u0026lt;User\u0026gt; { } 分析原理： UserServiceImpl继承了ServiceImpl，并实现了IUserService接口,因此继承了ServiceImpl中的方法，并实现了IUserService中的方法 ServiceImpl.class 1 2 3 4 // ServiceImpl.class 是一个泛型类，继承了BaseMapper\u0026lt;T\u0026gt;，并实现了IService\u0026lt;T\u0026gt;接口 public class ServiceImpl\u0026lt;M extends BaseMapper\u0026lt;T\u0026gt;, T\u0026gt; implements IService\u0026lt;T\u0026gt; { } 实际上相当于 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class UserServiceImpl implements IUserService { @Autowired private UserMapper userMapper; // 实现save方法 @Override public boolean save(User user) { return userMapper.insert(user) \u0026gt; 0; } // 实现getById方法 @Override public User getById(Long id) { return userMapper.selectById(id); } // 实现list方法 @Override public List\u0026lt;User\u0026gt; list() { return userMapper.selectList(null); } // 其他所有CRUD方法... } MybatisPlus不仅提供了BaseMapper，还提供了通用的Service接口及默认实现，封装了一些常用的service模板方法。 通用接口为IService，默认实现为ServiceImpl，其中封装的方法可以分为以下几类：\nsave：新增 remove：删除 update：更新 get：查询单个结果 list：查询集合结果 count：计数 page：分页查询 CRUD save是新增单个元素 saveBatch是批量新增 saveOrUpdate是根据id判断，如果数据存在就更新，不存在则新增 saveOrUpdateBatch是批量的新增或修改 removeById：根据id删除 removeByIds：根据id批量删除 removeByMap：根据Map中的键值对为条件删除 remove(Wrapper)：根据Wrapper条件删除 自定义方法 1 2 3 4 5 6 @PutMapping(\u0026#34;{id}/deduction/{money}\u0026#34;) @ApiOperation(\u0026#34;扣减用户余额\u0026#34;) public Json deductBalance(@PathVariable(\u0026#34;id\u0026#34;) Long id, @PathVariable(\u0026#34;money\u0026#34;)Integer money){ userService.deductBalance(id, money); return new Json(\u0026#34;{\\\u0026#34;code\\\u0026#34;:200,\\\u0026#34;msg\\\u0026#34;:\\\u0026#34;success\\\u0026#34;,\\\u0026#34;data\\\u0026#34;:null}\u0026#34;); } 1 2 3 4 5 6 public interface IUserService extends IService\u0026lt;User\u0026gt; { // 自定义的方法 void deductBalance(Long id, Integer money); } Service层 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Service // 交给Spring管理 public class UserServiceImpl extends ServiceImpl\u0026lt;UserMapper, User\u0026gt; implements IUserService { @Override public void deductBalance(Long id, Integer money){ // 获取用户,这个是BaseMapper中的方法，所以不需要自己写 User user = getById(id); if (user == null || user.getStatus() == 2) { throw new RuntimeException(\u0026#34;用户状态异常\u0026#34;); } if (user.getBalance() \u0026lt; money) { throw new RuntimeException(\u0026#34;用户余额不足\u0026#34;); } // 这个方法是不存在的，所以要手动创建 baseMapper.deductMoneyById(id, money); } } Mapper层 1 2 3 4 5 6 public interface UserMapper extends BaseMapper\u0026lt;User\u0026gt; { // sql你可以写进xml文件，也可以写进接口中 @Update(\u0026#34;UPDATE shuimo_user SET balance = balance - #{money} WHERE id = #{id}\u0026#34;) void deductMoneyById(@Param(\u0026#34;id\u0026#34;) Long id, Integer money); } ","date":"2026-03-01T00:00:00Z","permalink":"https://shuimo0413.github.io/p/mybatis-plus/","title":"mybatis plus使用"},{"content":"judge0的部署与使用 请先下载judge0的压缩包 https://github.com/judge0/judge0/releases/tag/v1.13.1 下载完成后仍然是这个页面，它上面有部署过程 部署judge0 docker-compose.yml文件 我这里使用了一个自定义网络，名字是shuimo，你可以根据自己的情况修改 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 x-logging: \u0026amp;default-logging logging: driver: json-file options: max-size: 100M # 自定义网络：保留你的原有配置 networks: shuimo: driver: bridge # 必须定义数据卷：app-logs用于SpringBoot日志持久化，否则启动报错 volumes: app-logs: # 保留你MySQL的数据卷（如果需要持久化，也可改用本地挂载，和Judge0保持一致） mysql-data: services: # ====================== 你的原有Judge0服务（完全保留，仅改Redis密码） ====================== server: image: docker.1ms.run/judge0/judge0:1.13.1-extra volumes: - ./judge0.conf:/judge0.conf:ro ports: - \u0026#34;2358:2358\u0026#34; privileged: true \u0026lt;\u0026lt;: *default-logging restart: always depends_on: - db - redis networks: - shuimo workers: image: docker.1ms.run/judge0/judge0:1.13.1-extra command: [\u0026#34;./scripts/workers\u0026#34;] volumes: - ./judge0.conf:/judge0.conf:ro privileged: true \u0026lt;\u0026lt;: *default-logging restart: always depends_on: - db - redis networks: - shuimo db: image: postgres:16.2 env_file: judge0.conf volumes: - /opt/judge0/postgres-data:/var/lib/postgresql/data/ # 保留你的本地挂载 \u0026lt;\u0026lt;: *default-logging restart: always networks: - shuimo ports: - \u0026#34;5432:5432\u0026#34; # 修正Redis：硬编码你的密码，彻底解决变量警告 redis: image: redis:7.2.4 command: [ \u0026#34;bash\u0026#34;, \u0026#34;-c\u0026#34;, # 硬编码你自己的Redis密码：1ac4f00fdbd09fd17ad58187972bcf1f，删除变量引用 \u0026#39;docker-entrypoint.sh --appendonly yes --requirepass \u0026#34;1ac4f00fdbd09fd17ad58187972bcf1f\u0026#34;\u0026#39; ] # 删掉env_file：不再依赖judge0.conf的变量，避免警告 volumes: - /opt/judge0/redis-data:/data # 保留你的本地挂载+AOF持久化 \u0026lt;\u0026lt;: *default-logging restart: always networks: - shuimo # ====================== 你的MySQL服务（已改名为mysql，保留所有配置） ====================== mysql: image: mysql:8.0 container_name: mysql environment: MYSQL_ROOT_PASSWORD: 1743355601 # 你的MySQL密码 MYSQL_DATABASE: oj # 自动创建oj库，无需手动建 TZ: Asia/Shanghai # 同步时区，避免时间错乱 MYSQL_INITDB_SKIP_TZINFO: 1 # 跳过时区初始化，避免启动报错 ports: - \u0026#34;3306:3306\u0026#34; volumes: - mysql-data:/var/lib/mysql # 数据持久化，避免数据丢失 networks: - shuimo # 健康检查：确保MySQL真正启动后，SpringBoot再启动 healthcheck: test: [\u0026#34;CMD\u0026#34;, \u0026#34;mysqladmin\u0026#34;, \u0026#34;ping\u0026#34;, \u0026#34;-h\u0026#34;, \u0026#34;localhost\u0026#34;, \u0026#34;-uroot\u0026#34;, \u0026#34;-p1743355601\u0026#34;] interval: 10s timeout: 5s retries: 5 \u0026lt;\u0026lt;: *default-logging restart: always # ====================== SpringBoot的app服务（仅改MySQL连接名，其余保留你的修改） ====================== app: build: context: /root/oj/ # 保留你修改后的构建路径 dockerfile: Dockerfile container_name: oj-app ports: - \u0026#34;8080:8080\u0026#34; environment: # 核心修正：MySQL服务名从oj-mysql改成mysql，和上面的MySQL服务名完全匹配 SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/oj?useUnicode=true\u0026amp;characterEncoding=utf8\u0026amp;serverTimezone=Asia/Shanghai\u0026amp;useSSL=false\u0026amp;allowMultiQueries=true SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: 1743355601 # Redis配置保留你的正确配置 SPRING_REDIS_HOST: redis SPRING_REDIS_PORT: 6379 SPRING_REDIS_PASSWORD: 1ac4f00fdbd09fd17ad58187972bcf1f SPRING_PROFILES_ACTIVE: prod # Judge0地址保留正确配置 JUDGE0_BASE_URL: http://server:2358 # 依赖已正确改成mysql，无需修改 depends_on: mysql: condition: service_healthy redis: condition: service_started server: condition: service_started networks: - shuimo volumes: - app-logs:/app/logs \u0026lt;\u0026lt;: *default-logging restart: always judge0.conf文件 实在是太长了，但是你可以使用crtl+f搜索关键字，找到你需要的 搜索PASSWORD，找到redis/postgres的密码 注意，此项目用的不是mysql 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 ################################################################################ # Judge0 Configuration File ################################################################################ # Judge0 is a highly configurable which allows you to use it for many # different use-cases. Please, before deploying Judge0 take a look at this # configuration file that is divided in several logical sections that will help # you understand what can you do with Judge0. # # This default configuration file is designed to work out of the box for you and # you can start with it when deploying Judge0 on your server. # # If you have any questions please don\u0026#39;t hasitate to send an email or open an # issue on the GitHub page of the project. ################################################################################ # Judge0 Server Configuration ################################################################################ # Enable or disable Judge0 Telemetry. # Read more about it here: https://github.com/judge0/judge0/blob/master/TELEMETRY.md # Default: true JUDGE0_TELEMETRY_ENABLE= # Automatically restart Judge0 server if it fails to start. # Default: 10 RESTART_MAX_TRIES= # Maintenance mode is a mode in which clients cannot # create or delete submissions while maintenance is enabled. # Default: false MAINTENANCE_MODE= # Set custom maintenance message that will be returned to clients # who try to create or delete submisions. # Default: Judge0 is currently in maintenance. MAINTENANCE_MESSAGE= # If enabled user can request to synchronically wait for # submission result on submission create. # Default: true, i.e. user can request to wait for the result ENABLE_WAIT_RESULT= # If enabled user is allowed to set custom compiler options. # Default: true ENABLE_COMPILER_OPTIONS= # List language names, separated by space, for which setting compiler options is allowed. # Note that ENABLE_COMPILER_OPTIONS has higher priority, so this option will be # ignored if setting compiler options is disabled with ENABLE_COMPILER_OPTIONS. # For example, ALLOWED_LANGUAGES_FOR_COMPILER_OPTIONS=\u0026#34;C C++ Java\u0026#34; would only # allow setting compiler options for languages C, C++ and Java. # Default: empty - for every compiled language setting compiler options is allowed. ALLOWED_LANGUAGES_FOR_COMPILER_OPTIONS= # If enabled user is allowed to set custom command line arguments. # Default: true ENABLE_COMMAND_LINE_ARGUMENTS= # If enabled autorized users can delete a submission. # Default: false ENABLE_SUBMISSION_DELETE= # If enabled user can GET and POST batched submissions. # Default: true ENABLE_BATCHED_SUBMISSIONS= # Maximum number of submissions that can be created or get in a batch. # Default: 20 MAX_SUBMISSION_BATCH_SIZE= # If enabled user can use callbacks. # Default: true ENABLE_CALLBACKS= # Maximum number of callback tries before giving up. # Default: 3 CALLBACKS_MAX_TRIES= # Timeout callback call after this many seconds. # Default: 5 CALLBACKS_TIMEOUT= # If enabled user can preset additional files in the sandbox. # Default: true ENABLE_ADDITIONAL_FILES= # Duration (in seconds) of submission cache. Decimal numbers are allowed. # Set to 0 to turn of submission caching. Note that this does not apply to # batched submissions. # Default: 1 SUBMISSION_CACHE_DURATION= # If true the documentation page will be used as a homepage, otherwise, the # homepage will be empty. You can always access the documentation page via /docs. # Default: false USE_DOCS_AS_HOMEPAGE= ################################################################################ # Judge0 Workers Configuration ################################################################################ # Specify polling frequency in seconds. Decimal numbers are allowed. # Default: 0.1 INTERVAL= # Specify how many parallel workers to run. # Default: 2*nproc (https://linux.die.net/man/1/nproc) COUNT= # Specify maximum queue size. Represents maximum number of submissions that # can wait in the queue at once. If request for new submission comes and the # queue if full then submission will be rejected. # Default: 100 MAX_QUEUE_SIZE= ################################################################################ # Judge0 Server Access Configuration ################################################################################ # Allow only specified origins. # If left blank, then all origins will be allowed (denoted with \u0026#39;*\u0026#39;). # Example: # ALLOW_ORIGIN=\u0026#34;www.judge0.com judge0.com www.example.com blog.example.com\u0026#34; ALLOW_ORIGIN= # Disallow only specified origins. # If left blank, then no origin will be disallowed. # Example: # DISALLOW_ORIGIN=\u0026#34;www.judge0.com judge0.com www.example.com blog.example.com\u0026#34; DISALLOW_ORIGIN= # Allow only specified IP addresses. # If left blank, then all IP addresses will be allowed. # Example: # ALLOW_IP=\u0026#34;192.168.10.10 96.239.226.228 208.23.207.242\u0026#34; ALLOW_IP= # Disallow only specified IP addresses. # If left blank, then no IP addresses will be disallowed. # Example: # DISALLOW_IP=\u0026#34;192.168.10.10 96.239.226.228 208.23.207.242\u0026#34; DISALLOW_IP= ################################################################################ # Judge0 Authentication Configuration ################################################################################ # You can protect your API with (AUTHN_HEADER, AUTHN_TOKEN) pair. # Each request then needs to have this pair either in headers or # query parameters. For example let AUTHN_HEADER=X-Judge0-Token and # AUTHN_TOKEN=mySecretToken. Then user should authenticate by sending this # in headers or query parameters in each request, e.g.: # https://api.judge0.com/system_info?X-Judge0-Token=mySecretToken # Specify authentication header name. # Default: X-Auth-Token AUTHN_HEADER= # Specify valid authentication tokens. # Default: empty - authentication is disabled AUTHN_TOKEN= ################################################################################ # Judge0 Authorization Configuration ################################################################################ # Protected API calls can be issued with (AUTHZ_HEADER, AUTHZ_TOKEN) pair. # To see exactly which API calls are protected with authorization tokens # please read the docs at https://api.judge0.com. # API authorization ensures that only specified users call protected API calls. # For example let AUTHZ_HEADER=X-Judge0-User and AUTHZ_TOKEN=mySecretToken. # Then user should authorize be sending this in headers or query parameters in # each request, e.g.: https://api.judge0.com/system_info?X-Judge0-User=mySecretToken # Note that if you enabled authentication, then user should also send valid # authentication token. # Specify authorization header name. # Default: X-Auth-User AUTHZ_HEADER= # Specify valid authorization tokens. # Default: empty - authorization is disabled, protected API calls cannot be issued AUTHZ_TOKEN= ################################################################################ # Redis Configuration ################################################################################ # Specify Redis host # Default: localhost REDIS_HOST=redis # Specify Redis port. # Default: 6379 REDIS_PORT= # Specify Redis password. Cannot be blank. # Default: NO DEFAULT! MUST BE SET! REDIS_PASSWORD=1ac4f00fdbd09fd17ad58187972bcf1f ################################################################################ # PostgreSQL Configuration ################################################################################ # Specify Postgres host. # Default: localhost POSTGRES_HOST=db # Specify Postgres port. # Default: 5432 POSTGRES_PORT= # Name of the database to use. Used only in production. # Default: postgres POSTGRES_DB=judge0 # User who can access this database. Used only in production. # Default: postgres POSTGRES_USER=judge0 # Password of the user. Cannot be blank. Used only in production. # Default: NO DEFAULT, YOU MUST SET YOUR PASSWORD POSTGRES_PASSWORD=6df9671d172a1536f6ffb442a718a59b ################################################################################ # Submission Configuration ################################################################################ # Judge0 uses isolate as an sandboxing environment. # Almost all of the options you see here can be mapped to one of the options # that isolate provides. For more information about these options please # check for the isolate documentation here: # https://raw.githubusercontent.com/ioi/isolate/master/isolate.1.txt # Default runtime limit for every program (in seconds). Decimal numbers are allowed. # Time in which the OS assigns the processor to different tasks is not counted. # Default: 15 CPU_TIME_LIMIT= # Maximum custom CPU_TIME_LIMIT. # Default: 20 MAX_CPU_TIME_LIMIT= # When a time limit is exceeded, wait for extra time (in seconds), before # killing the program. This has the advantage that the real execution time # is reported, even though it slightly exceeds the limit. # Default: 1 CPU_EXTRA_TIME= # Maximum custom CPU_EXTRA_TIME. # Default: 5 MAX_CPU_EXTRA_TIME= # Limit wall-clock time in seconds. Decimal numbers are allowed. # This clock measures the time from the start of the program to its exit, # so it does not stop when the program has lost the CPU or when it is waiting # for an external event. We recommend to use CPU_TIME_LIMIT as the main limit, # but set WALL_TIME_LIMIT to a much higher value as a precaution against # sleeping programs. # Default: 20 WALL_TIME_LIMIT= # Maximum custom WALL_TIME_LIMIT. # Default: 25 MAX_WALL_TIME_LIMIT= # Limit address space of the program in kilobytes. # Default: 128000 MEMORY_LIMIT= # Maximum custom MEMORY_LIMIT. # Default: 512000 MAX_MEMORY_LIMIT= # Limit process stack in kilobytes. # Default: 64000 STACK_LIMIT= # Maximum custom STACK_LIMIT. # Default: 128000 MAX_STACK_LIMIT= # Maximum number of processes and/or threads program can create. # Default: 100 MAX_PROCESSES_AND_OR_THREADS= # Maximum custom MAX_PROCESSES_AND_OR_THREADS. # Default: 120 MAX_MAX_PROCESSES_AND_OR_THREADS= # If true then CPU_TIME_LIMIT will be used as per process and thread. # Default: false, i.e. CPU_TIME_LIMIT is set as a total limit for all processes and threads. ENABLE_PER_PROCESS_AND_THREAD_TIME_LIMIT= # If false, user won\u0026#39;t be able to set ENABLE_PER_PROCESS_AND_THREAD_TIME_LIMIT. # Default: true ALLOW_ENABLE_PER_PROCESS_AND_THREAD_TIME_LIMIT= # If true then MEMORY_LIMIT will be used as per process and thread. # Default: false, i.e. MEMORY_LIMIT is set as a total limit for all processes and threads. ENABLE_PER_PROCESS_AND_THREAD_MEMORY_LIMIT= # If false, user won\u0026#39;t be able to set ENABLE_PER_PROCESS_AND_THREAD_MEMORY_LIMIT. # Default: true ALLOW_ENABLE_PER_PROCESS_AND_THREAD_MEMORY_LIMIT= # Limit size of files created (or modified) by the program in kilobytes. # Default: 5120 MAX_FILE_SIZE= # Maximum custom MAX_FILE_SIZE. # Default: 20480 MAX_MAX_FILE_SIZE= # Run each program this many times and take average of time and memory. # Default: 1 NUMBER_OF_RUNS= # Maximum custom NUMBER_OF_RUNS. # Default: 20 MAX_NUMBER_OF_RUNS= # Redirect stderr to stdout. # Default: false REDIRECT_STDERR_TO_STDOUT= # Maximum total size (in kilobytes) of extracted files from additional files archive. # Default: 10240, i.e. maximum of 10MB in total can be extracted. MAX_EXTRACT_SIZE= # If false, user won\u0026#39;t be able to set ENABLE_NETWORK. # Default: true, i.e. allow user to permit or deny network calls from the submission. ALLOW_ENABLE_NETWORK= # If true submission will by default be able to do network calls. # Default: true, i.e. programs can do network calls. ENABLE_NETWORK= ################################################################################ # Rails Configuration ################################################################################ # Specify Rails environment: production or development # Default: production RAILS_ENV= # Specify maximum number of concurrent Rails threads. # Default: nproc (https://linux.die.net/man/1/nproc) RAILS_MAX_THREADS= # Specify how many processes will be created for handing requests. Each process # will aditionally create RAILS_MAX_THREADS threads. # Default: 2 RAILS_SERVER_PROCESSES= # Secret key base for production, if not set it will be randomly generated # Default: randomly generated SECRET_KEY_BASE= 如何查看judge0的接口文档 这个是我的judge0的接口文档地址，前面是你的虚拟机的IP地址，端口号2358，后面加上docs http://192.168.146.129:2358/docs\n进入之后是这样的 容器网络配置 我使用的是一个叫shuimo的网络，结构如下 1 2 3 4 5 6 7 8 9 10 11 【前端（独立）】 ↓ 访问 8080 端口 【shuimo 网络】 ├─ 自研后端→ 调用 MySQL【自研专属】 + Redis【共用】 + Judge0-Server ├─ Judge0 组件 │ ├─ Server→ 调用 Workers + Redis │ └─ Workers → 调用 Postgres └─ 存储组件 ├─ MySQL 【自研专属】 ├─ Redis【共用】 └─ Postgres【Judge0专属】 judge0和自己的oj后端都使用的是shuimo这个网络 ","date":"2026-02-02T00:00:00Z","permalink":"https://shuimo0413.github.io/p/oj_judge0_01/","title":"judge0的部署与使用"},{"content":"Docker 装 MySQL 一、前置准备：设置 Docker 加速镜像 1. 操作步骤 进入 Docker 配置目录（无则创建）：\n1 cd /etc/docker 创建/编辑配置文件 daemon.json：\n1 vi daemon.json 写入以下加速镜像配置（JSON 格式）：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { \u0026#34;builder\u0026#34;: { \u0026#34;gc\u0026#34;: { \u0026#34;defaultKeepStorage\u0026#34;: \u0026#34;20GB\u0026#34;, \u0026#34;enabled\u0026#34;: true } }, \u0026#34;experimental\u0026#34;: false, \u0026#34;registry-mirrors\u0026#34;: [ \u0026#34;https://docker.hpcloud.cloud\u0026#34;, \u0026#34;https://docker.m.daocloud.io\u0026#34;, \u0026#34;https://docker.unsee.tech\u0026#34;, \u0026#34;https://docker.1panel.live\u0026#34;, \u0026#34;http://mirrors.ustc.edu.cn\u0026#34;, \u0026#34;https://docker.chenby.cn\u0026#34;, \u0026#34;http://mirror.azure.cn\u0026#34;, \u0026#34;https://dockerpull.org\u0026#34;, \u0026#34;https://dockerhub.icu\u0026#34;, \u0026#34;https://hub.rat.dev\u0026#34; ] } 二、步骤1：拉取 MySQL 镜像 1. 拉取命令 1 2 docker pull mysql 2. 验证拉取结果 查看已拉取的镜像：\n1 2 docker images 3. 预期输出示例 1 2 3 4 5 REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest a830707172e8 4 weeks ago 192MB mysql latest 2c849dee4ca9 4 weeks ago 859MB hello-world latest 74cc54e27dc4 3 months ago 10.1kB 三、步骤2：配置 MySQL 并创建容器 1. 准备 MySQL 配置文件 创建配置文件 my.cnf（建议放在自定义目录，如 /gxp/dockersoft/mysql/conf），内容如下：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 [mysqld] pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock datadir = /var/lib/mysql secure-file-priv=NULL # 网络设置 bind-address = 0.0.0.0 port = 3306 skip-name-resolve # 字符集设置 character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci # 日志设置 log-error = /var/log/mysqld.log slow-query-log = 1 slow-query-log-file = /var/log/mysql-slow.log long_query_time = 2 log-queries-not-using-indexes = 1 # InnoDB 设置（根据服务器内存调整） innodb_buffer_pool_size = 512M innodb_log_file_size = 128M innodb_flush_log_at_trx_commit = 2 innodb_file_per_table = 1 innodb_open_files = 400 innodb_io_capacity = 4000 innodb_flush_method = O_DIRECT # 连接设置 max_connections = 200 wait_timeout = 600 interactive_timeout = 600 # 查询缓存（建议生产环境关闭） query_cache_type = 0 query_cache_size = 0 [client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4 2. 创建并运行容器 （1）命令格式 1 2 3 4 5 6 7 8 docker run --name mysqlserver \\ -p 3306:3306 \\ -v $PWD/conf:/etc/mysql/my.cnf \\ -v $PWD/data:/var/lib/mysql \\ -v $PWD/logs:/var/log \\ -e MYSQL_ROOT_PASSWORD=root \\ mysql （2）参数说明 参数 含义 --name mysqlserver 容器名称（自定义，如 mysqlserver） -p 3306:3306 端口映射：主机 3306 端口 → 容器 3306 端口 -v 主机路径:容器路径 目录挂载（实现主机与容器文件同步，无需进入容器修改配置） $PWD 当前命令执行目录（建议先 cd 到自定义目录，如 /gxp/dockersoft/mysql） -e MYSQL_ROOT_PASSWORD=root 设置 MySQL root 用户密码（自定义，如 root） （3）推荐目录结构（示例） 1 2 3 4 5 /gxp/dockersoft/mysql/ ├── conf/ # 挂载容器的 /etc/mysql/my.cnf（配置文件目录） ├── data/ # 挂载容器的 /var/lib/mysql（数据存储目录） └── logs/ # 挂载容器的 /var/log（日志目录） 目录权限设置（可选）：\n1 2 chmod -R 777 /gxp/dockersoft/mysql （4）挂载逻辑说明 Docker 容器内的配置/数据默认仅存储在容器中，通过 -v 挂载后：\n主机 conf 目录 → 容器 my.cnf 配置文件（修改主机文件即同步容器配置）\n主机 data 目录 → 容器数据目录（避免容器删除后数据丢失）\n主机 logs 目录 → 容器日志目录（方便在主机查看 MySQL 日志）\n四、步骤3：连接 MySQL 容器启动后，可通过 Navicate、SQLyog 等工具连接：\n主机地址：Docker 所在服务器 IP\n端口：3306（已映射）\n用户名：root\n密码：root（创建容器时设置的密码）\n五、Docker 常用命令 功能 命令 拉取镜像 docker pull 镜像名称（如 mysql） 查看所有已拉取镜像 docker images 查看所有容器（运行+停止） docker ps -a 启动容器 docker start 容器名称/ID 停止容器 docker stop 容器名称/ID 删除容器 docker rm 容器名称/ID 查看容器日志 docker logs 容器名称/ID 进入容器内部 docker exec -it 容器名称/ID /bin/bash ","date":"2026-01-20T00:00:00Z","permalink":"https://shuimo0413.github.io/p/docker-install-mysql/","title":"docker安装MySQL"},{"content":"docker基本命令 常用命令 命令 功能 docker pull 拉取镜像 docker push 推送镜像 docker images 查看本地镜像 docker rmi 删除本地镜像 docker run 创建并运行容器（不能重复创建） docker stop 停止指定容器 docker start 启动指定容器 docker restart 重新启动容器 docker rm 删除指定容器 docker ps 查看容器 docker logs 查看容器运行日志 docker exec 进入容器 docker save 保存镜像到本地压缩文件 docker load 加载本地压缩文件到镜像 docker inspect 查看容器详细信息 启动容器 1 2 3 4 5 6 7 8 # 查看正在运行的容器 docker ps # 查看所有容器（包括已停止的） docker ps -a # 启动mysql容器 docker start mysql # 设置容器自启动 docker update mysql --restart=unless-stopped 关闭容器 1 2 # 关闭mysql容器 docker stop mysql 重启容器 1 2 # 重启mysql容器 docker restart mysql ","date":"2026-01-20T00:00:00Z","permalink":"https://shuimo0413.github.io/p/docker-commands/","title":"docker基本命令"},{"content":"启动服务器 1 hugo server -D 重构 1 hugo -D ","date":"2026-01-20T00:00:00Z","permalink":"https://shuimo0413.github.io/p/upload-to-github/","title":"hugo命令行"},{"content":"本地上传思路 引入Post请求注解，传参数，获取文件 获取文件名（主要是获取文件后缀）然后再用UUID类创建一个随机的名字 1 newFileName + originalFilename.substring(originalFilename.lastIndexOf(\u0026#34;.\u0026#34;)); 文件名加上获取的文件后缀 保存文件 1 file.transferTo(new File(\u0026#34;C:/Users/17433/Desktop/images/\u0026#34; + resFileName)); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.UUID; @Slf4j @RestController public class UploadController { @PostMapping(\u0026#34;/upload\u0026#34;) public Result upload(String name, String age, MultipartFile file) throws IOException { log.info(\u0026#34;文件上传中...\u0026#34;); String originalFilename = file.getOriginalFilename(); String newFileName = UUID.randomUUID().toString(); String resFileName = newFileName + originalFilename.substring(originalFilename.lastIndexOf(\u0026#34;.\u0026#34;)); // 保存文件 file.transferTo(new File(\u0026#34;C:/Users/17433/Desktop/images/\u0026#34; + resFileName)); return Result.success(); } } ","date":"2026-01-20T00:00:00Z","image":"https://shuimo0413.github.io/p/java-upload-file/image_hu_59893eac55594321.png","permalink":"https://shuimo0413.github.io/p/java-upload-file/","title":"java后端上传文件"},{"content":"JVM 字节码 注：指令按「功能大类」划分，同一类内按使用频率排序，每个指令包含「格式」「作用」「使用场景」，结合实际代码案例便于理解。\n一、数据操作指令（最常用，占字节码总量 60%+） 1. 局部变量操作指令（操作方法内的局部变量，如参数、临时变量） 指令格式 作用 使用场景举例 iload_n（n=0-3） 加载第 n 个局部变量（int/boolean 类型）到操作数栈 int a=1; 中加载a（iload_1） istore_n（n=0-3） 从操作数栈存 int/boolean 值到第 n 个局部变量 a=2; 中存值到a（istore_1） aload_n（n=0-3） 加载第 n 个局部变量（引用类型，如对象 / 数组）到操作数栈 int[] arr=new int[3]; 加载arr（aload_1） astore_n（n=0-3） 从操作数栈存引用值到第 n 个局部变量 arr=new int[3]; 存arr到局部变量（astore_1） iload index 加载指定索引（\u0026gt;3）的 int/boolean 局部变量 局部变量超过 4 个时使用（如iload 4） aload index 加载指定索引（\u0026gt;3）的引用局部变量 局部变量超过 4 个时使用（如aload 5） 2. 常量操作指令（往操作数栈压入常量值） 指令格式 作用 使用场景举例 iconst_n（n=-1~5） 压入 int 常量 n（boolean 用 1=true/0=false） return true;（iconst_1）、int a=3;（iconst_3） lconst_n（n=0/1） 压入 long 常量 n（占 2 个操作数栈位置） long b=1L;（lconst_1） fconst_n（n=0-2） 压入 float 常量 n float c=2.0f;（fconst_2） dconst_n（n=0/1） 压入 double 常量 n（占 2 个操作数栈位置） double d=1.0;（dconst_1） ldc 常量 压入 int/long/float/double/ 字符串常量（从常量池取） String s=\u0026ldquo;abc\u0026rdquo;;（ldc \u0026ldquo;abc\u0026rdquo;）、int a=100;（ldc 100） ldc2_w 常量 压入 long/double 常量（常量池索引 \u0026gt; 255 时用） long e=1000L;（ldc2_w 1000L） 3. 数组操作指令（操作数组的创建、赋值、取值） 指令格式 作用 使用场景举例 newarray 类型 创建一维基本类型数组（如 int/char） int[] arr=new int[3];（iconst_3→newarray int） anewarray 类 创建一维引用类型数组（如 Object []/int [][]） int[][] grid=new int[3][];（iconst_3→anewarray \u0026ldquo;[I\u0026rdquo;） iaload 从 int 数组中取元素（数组引用 + 索引→元素值） int a=arr[2];（aload_1→iconst_2→iaload） iastore 往 int 数组中存元素（数组引用 + 索引 + 值→存值） arr[2]=5;（aload_1→iconst_2→iconst_5→iastore） aaload 从引用数组中取元素（如 int [][] 取某一行） int[] row=grid[0];（aload_1→iconst_0→aaload） aastore 往引用数组中存元素（如 int [][] 存某一行） grid[0]=new int[3];（aload_1→iconst_0→aload_2→aastore） arraylength 获取数组长度（数组引用→长度值） int len=arr.length;（aload_1→arraylength→istore_2） multianewarray 类 维度 创建多维数组（如 int [2][3]） 较少用，int[][][] arr=new int[2][3][4];（iconst_2→iconst_3→iconst_4→multianewarray \u0026ldquo;[[[I\u0026rdquo; 3） 二、算术与逻辑指令（常用，处理数值计算和比较） 1. 算术指令（int/long/float/double 类型的加减乘除） 指令格式 作用 使用场景举例 iadd 操作数栈顶两个 int 值相加（a+b→结果压栈） int c=a+b;（iload_1→iload_2→iadd→istore_3） isub 操作数栈顶两个 int 值相减（a-b→结果压栈） int c=a-b;（iload_1→iload_2→isub→istore_3） imul 操作数栈顶两个 int 值相乘（a*b→结果压栈） int c=a*b;（iload_1→iload_2→imul→istore_3） idiv 操作数栈顶两个 int 值相除（a/b→结果压栈，整除） int c=a/b;（iload_1→iload_2→idiv→istore_3） irem 操作数栈顶两个 int 值取余（a% b→结果压栈） int c=a%b;（iload_1→iload_2→irem→istore_3） ladd/lsub long 类型的加减（占 2 个操作数栈位置） long c=a+b;（lload_1→lload_2→ladd→lstore_3） fadd/dadd float/double 类型的加法 较少用，float c=a+b;（fload_1→fload_2→fadd→fstore_3） 2. 比较指令（比较操作数栈顶值，结果用于分支跳转） 指令格式 作用（int 类型，其他类型类似：lcmp/fcmpg 等） 使用场景举例 if_icmpeq 目标行 比较两个 int 值：相等则跳转到目标行 if(a==b) { \u0026hellip; }（iload_1→iload_2→if_icmpeq 10） if_icmpne 目标行 比较两个 int 值：不相等则跳转到目标行 if(a!=b) { \u0026hellip; }（iload_1→iload_2→if_icmpne 10） if_icmplt 目标行 比较两个 int 值：a\u0026lt;b 则跳转到目标行 if(a\u0026lt;b) { \u0026hellip; }（iload_1→iload_2→if_icmplt 10） if_icmpge 目标行 比较两个 int 值：a\u0026gt;=b 则跳转到目标行 for(int i=0;i\u0026lt;len;i++)（iload_1→iload_2→if_icmpge 20） ifeq 目标行 比较 int 值与 0：等于 0 则跳转 if(flag==false) { \u0026hellip; }（iload_1→ifeq 10，因 false=0） ifne 目标行 比较 int 值与 0：不等于 0 则跳转 if(flag==true) { \u0026hellip; }（iload_1→ifne 10，因 true=1） acmp_eq 目标行 比较两个引用类型：地址相等则跳转 if(obj1==obj2) { \u0026hellip; }（aload_1→aload_2→if_acmpeq 10） 三、分支与循环指令（常用，控制代码执行流程） 指令格式 作用 使用场景举例 goto 目标行 无条件跳转到目标行（不依赖条件） while(true) { \u0026hellip; }（循环体结束→goto 5） if_icmpne 目标行 见「比较指令」，常用于 if/for 条件判断 if(a!=1) return false;（iload_1→iconst_1→if_icmpne 7） tableswitch 按 int 值跳转（用于 switch-case，值连续时） switch(a) { case 1: \u0026hellip; case 2: \u0026hellip; } lookupswitch 按 int 值跳转（用于 switch-case，值不连续时） switch(a) { case 1: \u0026hellip; case 100: \u0026hellip; } 四、方法调用与返回指令（常用，调用方法和返回结果） 1. 方法调用指令（按调用类型排序，静态方法最常用） 指令格式 作用 使用场景举例 invokestatic 类.方法 调用静态方法（无 this） Math.min(a,b)（iload_1→iload_2→invokestatic java/lang/Math.min:(II)I） invokevirtual 类.方法 调用实例方法（有 this，动态绑定） System.out.println(a)（getstatic→iload_1→invokevirtual java/io/PrintStream.println:(I)V） invokespecial 类.方法 调用特殊方法（构造方法、private 方法、super 方法） 构造方法（aload_0→invokespecial java/lang/Object.\u0026quot;\u0026quot;:()V） invokeinterface 接口.方法 调用接口方法（动态绑定） 较少用，List.add(obj)（aload_1→aload_2→invokeinterface java/util/List.add:(Ljava/lang/Object;)Z） invokedynamic 引导方法 调用动态方法（Lambda/Stream 用） Java 8 + 特性，List.forEach(System.out::println) 2. 方法返回指令（按返回值类型排序） 指令格式 作用 使用场景举例 ireturn 返回 int/boolean 类型结果 return true;（iconst_1→ireturn）、return 5;（iconst_5→ireturn） lreturn 返回 long 类型结果 return 100L;（lconst_1→lreturn） freturn 返回 float 类型结果 return 2.0f;（fconst_2→freturn） dreturn 返回 double 类型结果 return 3.0;（dconst_1→dreturn） areturn 返回引用类型结果（对象 / 数组 / 字符串） return arr;（aload_1→areturn） return 无返回值（void 方法） void func() { \u0026hellip; }（方法结束→return） 五、类型相关指令（较常用，处理类型转换、静态变量） 指令格式 作用 使用场景举例 i2l/i2f/i2d int 转 long/float/double（宽转换，无溢出） long a=1;（iconst_1→i2l→lstore_1） l2i/f2i/d2i long/float/double 转 int（窄转换，可能溢出） int a=(int)100L;（lconst_1→l2i→istore_1） checkcast 类 检查引用类型强制转换是否合法（如 Object→String） String s=(String)obj;（aload_1→checkcast java/lang/String→astore_2） instanceof 类 判断引用是否为某类 / 接口的实例（返回 boolean） if(obj instanceof String) { \u0026hellip; }（aload_1→instanceof java/lang/String→ifne 10） getstatic 类.字段 获取静态变量值（如 System.out） PrintStream out=System.out;（getstatic java/lang/System.out:Ljava/io/PrintStream;→astore_1） putstatic 类.字段 给静态变量赋值（如 Math.PI 不可用，用自定义静态变量） MyClass.count=5;（iconst_5→putstatic com/xxx/MyClass.count:I） 六、异常与同步指令（不常用，处理异常和线程安全） 指令格式 作用 使用场景举例 athrow 抛出异常对象（如 throw new Exception ()） throw new RuntimeException();（new→dup→invokespecial→athrow） monitorenter 获取对象监视器锁（synchronized 代码块入口） synchronized(obj) { \u0026hellip; }（aload_1→monitorenter） monitorexit 释放对象监视器锁（synchronized 代码块出口） synchronized 代码块结束→aload_1→monitorexit jsr 目标行 跳转到异常处理代码（Java 6 前用，现已被异常表替代） 极少用，现代字节码用「异常表」记录异常处理逻辑 七、栈操作指令（较常用，操作操作数栈） 指令格式 作用 使用场景举例 dup 复制操作数栈顶元素（常用于对象创建后调用构造方法） new Object()（new→dup→invokespecial） dup_x1 复制栈顶元素，插入到栈顶下第 1 个元素前 较少用，复杂栈操作（如a,b→a,b,a） pop 弹出操作数栈顶元素（丢弃，无返回） 不需要的计算结果（如a+b;→iadd→pop） pop2 弹出栈顶 2 个元素（用于 long/double） long a=1L;→lconst_1→pop2（丢弃 a） ","date":"2026-01-20T00:00:00Z","permalink":"https://shuimo0413.github.io/p/jvm-bytecode/","title":"JVM 字节码"},{"content":"Redis 核心知识 Redis 集合（Set） Redis Set 是 string 类型的无序集合，集合成员唯一，不允许重复数据。\n常用命令 SADD key member1 [member2]：向集合添加一个或多个成员\nSMEMBERS key：返回集合中的所有成员\nSCARD key：获取集合的成员数\nSINTER key1 [key2]：返回给定所有集合的交集\nSUNION key1 [key2]：返回所有给定集合的并集\nSREM key member1 [member2]：删除集合中一个或多个成员\nRedis 有序集合（Sorted Set） Redis 有序集合是 string 类型元素的集合，不允许重复成员，每个元素会关联一个 double 类型的分数（用于排序）。\n常用命令 ZADD key score1 member1 [score2 member2]：向有序集合添加一个或多个成员\nZRANGE key start stop [WITHSCORES]：通过索引区间返回有序集合中指定区间内的成员\nZINCRBY key increment member：有序集合中对指定成员的分数加上增量 increment\nZREM key member [member...]：移除有序集合中的一个或多个成员\nRedis 通用命令 通用命令不分数据类型，均可使用：\nKEYS pattern：查找所有符合给定模式（pattern）的 key\nEXISTS key：检查给定 key 是否存在\nTYPE key：返回 key 所储存的值的类型\nDEL key：在 key 存在时删除 key\n在 Spring 中使用 Redis 1. 增加 String 类型数据 无过期时间 1 2 stringRedisTemplate.opsForValue().set(\u0026#34;name\u0026#34;, \u0026#34;张三\u0026#34;); 带过期时间（10分钟后过期） 1 2 3 4 import java.util.concurrent.TimeUnit; stringRedisTemplate.opsForValue().set(\u0026#34;code\u0026#34;, \u0026#34;123456\u0026#34;, 10, TimeUnit.MINUTES); 2. 哈希表（Hash）操作 向哈希表添加字段 1 2 3 4 // 向哈希表\u0026#34;user:100\u0026#34;中添加字段\u0026#34;name\u0026#34;和\u0026#34;age\u0026#34; stringRedisTemplate.opsForHash().put(\u0026#34;user:100\u0026#34;, \u0026#34;name\u0026#34;, \u0026#34;李四\u0026#34;); stringRedisTemplate.opsForHash().put(\u0026#34;user:100\u0026#34;, \u0026#34;age\u0026#34;, \u0026#34;20\u0026#34;); 3. 列表（List）操作 右侧添加元素（右插，类似队列） 1 2 3 stringRedisTemplate.opsForList().rightPush(\u0026#34;fruits\u0026#34;, \u0026#34;苹果\u0026#34;); stringRedisTemplate.opsForList().rightPush(\u0026#34;fruits\u0026#34;, \u0026#34;香蕉\u0026#34;); 左侧添加元素（左插，类似栈） 1 2 stringRedisTemplate.opsForList().leftPush(\u0026#34;fruits\u0026#34;, \u0026#34;西瓜\u0026#34;); 4. 集合（Set）操作 向集合添加元素 1 2 stringRedisTemplate.opsForSet().add(\u0026#34;tags\u0026#34;, \u0026#34;java\u0026#34;, \u0026#34;spring\u0026#34;, \u0026#34;redis\u0026#34;); 5. 有序集合（Sorted Set）操作 向有序集合添加元素（score 为排序权重） 1 2 3 stringRedisTemplate.opsForZSet().add(\u0026#34;ranking\u0026#34;, \u0026#34;用户A\u0026#34;, 90); stringRedisTemplate.opsForZSet().add(\u0026#34;ranking\u0026#34;, \u0026#34;用户B\u0026#34;, 85); 6. 查询操作 查询 String 类型值 1 2 String name = stringRedisTemplate.opsForValue().get(\u0026#34;name\u0026#34;); // 结果：\u0026#34;张三\u0026#34; 查询哈希表指定字段值 1 2 Object userName = stringRedisTemplate.opsForHash().get(\u0026#34;user:100\u0026#34;, \u0026#34;name\u0026#34;); // 结果：\u0026#34;李四\u0026#34; 查询哈希表所有字段和值 1 2 3 Map\u0026lt;Object, Object\u0026gt; userMap = stringRedisTemplate.opsForHash().entries(\u0026#34;user:100\u0026#34;); // userMap 结果：{\u0026#34;name\u0026#34;:\u0026#34;李四\u0026#34;, \u0026#34;age\u0026#34;:\u0026#34;20\u0026#34;} 查询列表所有元素 1 2 3 List\u0026lt;String\u0026gt; fruits = stringRedisTemplate.opsForList().range(\u0026#34;fruits\u0026#34;, 0, -1); // 结果：[\u0026#34;西瓜\u0026#34;, \u0026#34;苹果\u0026#34;, \u0026#34;香蕉\u0026#34;]（左插的\u0026#34;西瓜\u0026#34;在最前） 查询集合所有元素 1 2 3 Set\u0026lt;String\u0026gt; tags = stringRedisTemplate.opsForSet().members(\u0026#34;tags\u0026#34;); // 结果：[\u0026#34;java\u0026#34;, \u0026#34;spring\u0026#34;, \u0026#34;redis\u0026#34;]（无序） （注：文档部分内容可能由 AI 生成）\n","date":"2026-01-20T00:00:00Z","permalink":"https://shuimo0413.github.io/p/redis/","title":"redis入门"},{"content":"操作git控制github仓库 生成SSH密钥 1 ssh-keygen -t rsa -b 4096 -C \u0026#34;你的GitHub邮箱@qq.com\u0026#34; 执行后按提示操作： 密钥保存路径：默认C:\\Users\\你的用户名/.ssh/id_rsa，直接回车即可；\n密码短语（passphrase）：可留空（直接回车），也可设置密码（每次推送需输入）； 若提示密钥已存在，输入y覆盖（如之前已生成过密钥）。\n1 ssh -T git@github.com 首次连接会提示验证主机真实性，输入完整的 yes（不可输y），回车后若看到以下提示，说明 SSH 配置成功： 1 Hi 你的GitHub用户名! You\u0026#39;ve successfully authenticated, but GitHub does not provide shell access. 上传公钥至 GitHub 打开本地公钥文件：C:\\Users\\你的用户名/.ssh/id_rsa.pub（记事本即可打开）；\n复制文件内的全部内容；\n登录 GitHub，进入「Settings」→「SSH and GPG keys」→「New SSH key」；\n填写标题（如「Windows 电脑」），粘贴公钥内容，点击「Add SSH key」完成绑定。 上传文件 先在github上创建一个仓库，什么都不用勾选，直接创建。 在项目目录打开git命令行 初始化仓库 1 git init 链接远程仓库 1 git remote add origin git@github.com:你的用户名/仓库名.git 查看远程仓库 1 git remote -v 添加所有文件 1 git add . 提交变更 1 git commit -m \u0026#34;初始化Vue+MQTT上位机前端项目\u0026#34; 推送变更到远程仓库 1 git push -u origin main 如果你不是第一次上传 1 git push 拉取文件, 例如拉取n8n项目 1 git clone https://github.com/n8n-io/n8n.git 提交到分支并合并 1 2 git add . git commit -m \u0026#34;初始化Vue+MQTT上位机前端项目\u0026#34; 1 2 3 4 # 查看所有分支 git branch # 查看状态 git status 选择分支 1 git checkout -b new_test 提交new_test分支 1 git push -u origin new_test 合并 1 2 3 4 5 6 # 切换到main分支 git checkout main # 2. 拉取主分支最新内容（避免合并时冲突） git pull origin main # 合并new_test分支到main分支 git merge new_test 至此，项目已成功上传至 GitHub 仓库。 如果你想使用http，一般先生成一个token 添加token，记得勾选workflow 然后再在.github/workflows/xxx.yml中修改配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 name: deploy on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 submodules: recursive - name: Setup Hugo uses: peaceiris/actions-hugo@v3 with: hugo-version: \u0026#34;latest\u0026#34; extended: true - name: Build Web run: hugo -D - name: Deploy Web uses: peaceiris/actions-gh-pages@v4 with: PERSONAL_TOKEN: ${{ secrets.TOKEN }} EXTERNAL_REPOSITORY: shuimo0413/shuimo0413.github.io PUBLISH_BRANCH: main PUBLISH_DIR: ./public commit_message: auto deploy ","date":"2026-01-20T00:00:00Z","permalink":"https://shuimo0413.github.io/p/upload-to-github/","title":"使用git操作github"},{"content":"安装mqttx MQTTX: 点我下载 https://mqttx.app/ 安装 Mosquitto Ubuntu 系统：\n创建好系统后，打开所有端口，防止访问不到\nsudo apt update # 更新包索引\nsudo apt install mosquitto mosquitto-clients # 安装服务器和客户端工具\n步骤 2：启动 Mosquitto 服务 启动服务 1 sudo systemctl start mosquitto 设置开机自启动（可选，避免重启后需手动启动） 1 sudo systemctl enable mosquitto 步骤 3：验证服务是否启动成功 查看服务状态： 1 2 3 sudo systemctl status mosquitto # 查看端口是否被监听 ss -tuln | grep 1883 步骤 4：（可选，建议必选）配置 Mosquitto 位置可能有出入，请自己使用cd指令打开文件夹手动检查，一定要使用sudo 1 sudo vim /etc/mosquitto/mosquitto.conf # 打开配置文件 在配置文件中使用i键进入insert模式，在配置文件末尾添加 允许所有网络接口访问（监听所有IP地址） 1 2 3 listener 1883 0.0.0.0 # 允许匿名用户连接 allow_anonymous true 执行完后按zz（大写）退出 步骤 5：重启 Mosquitto 服务 如果你修改了配置文件，必须重启服务才能让配置文件生效 1 sudo systemctl restart mosquitto 步骤 6：查看mqtt服务器日志，确定是否连接成功 查看日志文件，如果连接成功，日志文件里面会有你的公网地址信息 1 tail -f /var/log/mosquitto/mosquitto.log ","date":"2026-01-20T00:00:00Z","image":"https://shuimo0413.github.io/p/mqtt/mqtt-server_hu_ea7d5af1c24f6b49.jpg","permalink":"https://shuimo0413.github.io/p/mqtt/","title":"在linux上搭建一个mqtt服务器"},{"content":"首先我们得有一个jar包，自己打包就行了 maven配置里面必须写上再打包才行 1 2 3 4 5 6 7 8 \u0026lt;build\u0026gt; \u0026lt;plugins\u0026gt; \u0026lt;plugin\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-boot-maven-plugin\u0026lt;/artifactId\u0026gt; \u0026lt;/plugin\u0026gt; \u0026lt;/plugins\u0026gt; \u0026lt;/build\u0026gt; 1 2 3 4 5 # 仅跳过测试执行（仍编译测试代码） mvn clean package -DskipTests # 彻底跳过测试（不编译、不执行测试代码，速度更快） mvn clean package -Dmaven.test.skip=true 然后我们得编写Dockerfile 1 2 3 4 5 6 7 8 9 10 11 # 设置环境 FROM openjdk:11.0-jre-buster # 设置时区 ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \u0026amp;\u0026amp; echo $TZ \u0026gt; /etc/timezone # 复制jar包到容器中 COPY sentinel-dashboard.jar /sentinel-dashboard.jar # 指定端口号 EXPOSE 8090 # 启动 ENTRYPOINT [\u0026#34;java\u0026#34;, \u0026#34;-jar\u0026#34;, \u0026#34;/sentinel-dashboard.jar\u0026#34;, \u0026#34;--server.port=8090\u0026#34;] 创建容器 1 docker build -t sentinel:8090 . 参数 作用 -t 镜像名称 sentinel 镜像名称 8090 镜像端口 . Dockerfile所在目录 最后我们运行 1 2 3 4 5 docker run -d \\ -p 8090:8090 \\ --name sentinel \\ --network shuimo \\ sentinel:8090 参数 作用 -d 后台运行 -p 端口映射 8090:8090 宿主机端口:容器端口 \u0026ndash;name 容器名称 \u0026ndash;network 网络名称 sentinel:8090 镜像名称:镜像端口 ","date":"2026-01-19T00:00:00Z","permalink":"https://shuimo0413.github.io/p/jar%E5%8C%85docker%E9%83%A8%E7%BD%B2/","title":"Jar包docker部署"},{"content":"mybatis plus常见配置 springBoot工程 1 2 3 4 5 6 7 8 9 @SpringBootApplication @MapperScan(\u0026#34;com.baomidou.mybatisplus.samples.quickstart.mapper\u0026#34;) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } pom.xml(maven依赖) 1 2 3 4 5 \u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;com.baomidou\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;mybatis-plus-boot-starter\u0026lt;/artifactId\u0026gt; \u0026lt;version\u0026gt;3.5.15\u0026lt;/version\u0026gt; \u0026lt;/dependency\u0026gt; 1 2 3 4 5 6 7 8 9 10 11 # 继承了mybatis的配置 mybatis-plus: type-aliases-package: com.itheima.mp.domain.po # 别名扫描包 mapper-locations: \u0026#34;classpath*:/mapper/**/*.xml\u0026#34; # Mapper.xml文件地址, 默认值 configuration: map-underscore-to-camel-case: true # 是否开启下划线和驼峰的映射 cache-enabled: false # 是否开启二级缓存 global-config: db-config: id-type: assign_id # id为雪花算法生成 update-strategy: not_null # 更新策略: 只更新非空字段 1 2 3 4 5 6 // 插入一条记录（选择字段，策略插入） boolean save(T entity); // 插入（批量） boolean saveBatch(Collection\u0026lt;T\u0026gt; entityList); // 插入（批量） boolean saveBatch(Collection\u0026lt;T\u0026gt; entityList, int batchSize); 1 2 3 4 5 6 7 8 9 10 // 假设有一个 User 实体对象 User user = new User(); user.setName(\u0026#34;John Doe\u0026#34;); user.setEmail(\u0026#34;john.doe@example.com\u0026#34;); boolean result = userService.save(user); // 调用 save 方法 if (result) { System.out.println(\u0026#34;User saved successfully.\u0026#34;); } else { System.out.println(\u0026#34;Failed to save user.\u0026#34;); } ","date":"2026-01-19T00:00:00Z","image":"https://shuimo0413.github.io/p/mybatis-plus%E5%B8%B8%E8%A7%81%E9%85%8D%E7%BD%AE/1007104420_hu_79a1e8113603663e.jpg","permalink":"https://shuimo0413.github.io/p/mybatis-plus%E5%B8%B8%E8%A7%81%E9%85%8D%E7%BD%AE/","title":"mybatis plus常见配置"}]