逗号的博客

这里有一句格言,但我还没想好

问题描述

首先创建一个 Spring Boot 项目,然后创建一个实体类 User,它有两个字段姓名 name 和生日 birthday,其中 birthday 的类型是 OffsetDataTime

1
2
3
4
5
@Data
public class User {
private String name;
private OffsetDateTime birthday;
}

最后创建对应的控制器 UserController,GET 请求的第二种形式将参数封装成了对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/query1")
public OffsetDateTime query1(OffsetDateTime birthday) {
return birthday;
}

@GetMapping("/query2")
public User query2(User user) {
return user;
}

@PostMapping("/create")
public User create(@RequestBody User user) {
return user;
}
}

我们要实现接收前端传递过来的形如 yyyy-MM-dd HH:mm:ss 的字符串并自动将它转换为能够使用 OffsetDateTime 类型。

阅读全文 »

问题描述

在 SpringBoot 应用中可以使用以下几种方式来控制是否返回值为空的字段

  1. 在配置文件 application.yml 中配置全局自动忽略
    1
    2
    3
    spring:
    jackson:
    default-property-inclusion: NON_NULL
  2. 在类或字段上添加注解 @JsonInclude(JsonInclude.Include.NON_NULL)
  3. 实现一个 Jackson2ObjectMapperBuilderCustomizer 定制器
    1
    2
    3
    4
    5
    6
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
    return jacksonObjectMapperBuilder -> {
    jacksonObjectMapperBuilder.serializationInclusion(JsonInclude.Include.NON_NULL);
    };
    }
  4. 参考 JacksonObjectMapperConfiguration 自定义一个 ObjectMapper,覆盖默认的定义
    1
    2
    3
    4
    5
    6
    7
    8
    @Bean
    @Primary
    @ConditionalOnMissingBean
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper mapper = builder.createXmlMapper(false).build();
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    return mapper;
    }

这 4 种方式要么是全局的要么是局部的,它们都是一次性的,设置后就不能改变,每次请求都会返回相同的结果。现在我们要实现根据请求参数中是否包含某个值动态的设置是否返回值为空的字段,具体的说我们要根据请求头中是否包含 X-Include-Non-Null 来控制是否返回值为空的字段。

阅读全文 »

问题描述

在上一篇文章中我们通过继承 GenericResponseService 类并重写 build 方法和实现 OperationCustomizer 接口的方式实现了 SpringDoc 的统一应答类型处理,但是实现的方式有点不够好,侵入 SpringDoc 的流程比较多,是否有更好的实现方式呢?

阅读全文 »

问题描述

在日常开发中我们会定义类似下面的 Result 类来统一接口返回结果的结构

1
2
3
4
5
6
7
8
9
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;

private Integer code;

private String message;

private T data;
}

此时 Controller 中的方法就会写成这个样子

1
2
3
4
5
@GetMapping("/detail1/{userId}")
public Result<User> detail1(@PathVariable(name = "userId") Long userId) {
User user = ....
return Result.<User>builder().data(user).build();
}

在每个方法上都写上类似 Result<User> 这样的代码还是比较繁琐的,我们期望写成 User 这样简单的形式

1
2
3
4
5
@GetMapping("/detail2/{userId}")
public User detail2(@PathVariable(name = "userId") Long userId) {
User user = ....
return user;
}

而由框架去处理返回结果的包装。此时就会使用到 Spring 的 ResponseBodyAdvice 接口

1
2
3
4
@RestControllerAdvice
public class ResultResponseBodyAdvice implements ResponseBodyAdvice<Object> {
// ...
}

同时我们也会使用 SpringDoc 对外提供可访问的文档。此时问题出现了,我们发现在 Swagger 的文档中方法 detail1 和方法 detail2 对应的 Schema 不一样

我们期望 detail2 展示的结果和 detail1 一样。

阅读全文 »

场景描述

根据上一行填充本行的空白栏位[1]。这是在参考资料中提出的一个问题,它给出了在 SQL Server 数据库中的解决方案,现在要在 PostgreSQL 中来模拟并解决它。

阅读全文 »

场景描述

假设有用户 u1、u2、u3、u4、u5、u6、u7,他们可以根据自己的喜好加入小组 g1、g2、g3、g4、g5,现在要找出加入了 g2 但是没有加入 g5 的用户。

阅读全文 »

集群规划

这里搭建的集群由一个控制平面节点和两个工作节点组成

服务器 IP 角色 备注
192.168.59.116 control plane master
192.168.59.117 worker node node1
192.168.59.118 worker node node2

选用的软件及其版本清单如下所示

软件名称 版本号
CentOS 7.9.2009
containerd 1.6.19
runc 1.1.4
CNI Plugins 1.2.0
Kubernetes 1.26.2
阅读全文 »
0%