Spring Boot + React 写聊天软件 Ep.2 - 一些细节与技巧

本系列记录了我从零开始学习 Spring + React 并完成一个小项目的经历和心得, 仅供参考, 并不是相关的教程. 项目概要见本系列 Ep.0.

上篇未讲完的一些琐碎的问题, 就在这里记录一下, 主要是一些我找到的能让 Coding 效率变高, 代码更简洁的方法.

Lombok

Springboot 搭配 Lombok 食用风味更佳~

@Slf4j 直接在当前类中加入 logger 对象, 方便地打 log.

比如一个 Entity 所有的 Getter/Setter 不再需要使用 IDE 生成, 可以直接使用 @Data 注解一键生成. @Builder 一键生成 Builder, @AllArgsConstructor 还可以一键生成构造器.

新版本的 Spring 直接在 Field 上使用 @Autowired 会给出 not recommend 的警告, 这时只要将需要注入的 Bean 设置为 final 并添加 @RequiredArgsContructor 即可.

1
2
3
4
5
6
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
private final UserDao userDao; // 这里的 Dao 能自动注入
// ....
}

统一响应格式

项目的一开始就要统一一下响应格式, 我定义了一个 CommonResponse 表示所有响应都遵循的格式.

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
public class CommonResponse<T> {
@Schema(description = "响应码")
private int code;
@Schema(description = "响应消息")
private String msg;
@Schema(description = "响应数据")
private T data;

@Hidden
@JsonIgnore
// used to define http status code
private int httpCode;

public static <T> CommonResponse<T> success() {
return success(null);
}

public static <T> CommonResponse<T> success(T data) {
return success(data, 200);
}

public static <T> CommonResponse<T> success(T data, int httpCode) {
return new CommonResponse<>(0, "success", data, httpCode);
}

public static <T> CommonResponse<T> error(ErrorType type) {
return new CommonResponse<>(type.getCode(), type.getMessage(), null, type.getHttpCode());
}

public static <T> CommonResponse<T> error(ErrorType type, String msg) {
return new CommonResponse<>(type.getCode(), msg, null, type.getHttpCode());
}

public static <T> CommonResponse<T> error(BizException exception) {
return new CommonResponse<>(exception.getCode(), exception.getMessage(), null, exception.getHttpCode());
}
}

统一异常处理

RESTful 要求使用 Http status code 表示响应的状态.

但 status code 的表达能力有限, 为了更好的表现出细致的业务异常, 我选择同时使用 Http status code 和自定义的响应状态码.

我是用枚举表示了可能遇到的异常状态, 并赋予对应的 code 和 httpCode.

https://github.com/lyc8503/LycChat-backend/blob/master/src/main/java/site/lyc8503/chat/exception/ErrorType.java

在 Service 类中业务出错时, 则直接 throw new BizException(ErrorType.xxx), 上层捕获异常后能直接取出其中的错误类型并返回给前端.

捕获异常使用自定义的 ExceptionHandler:

https://github.com/lyc8503/LycChat-backend/blob/master/src/main/java/site/lyc8503/chat/controller/GlobalExceptionHandler.java

为了处理 CommonReponse 中的 httpCode, 我使用了 ControllerAdvice 拦截响应并将 Http 状态码设置为预期的值.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@ControllerAdvice
public class HttpStatusCodeControllerAdvice implements ResponseBodyAdvice<CommonResponse<?>> {
/**
* Used to set http status code
*/

@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return returnType.getParameterType().isAssignableFrom(CommonResponse.class);
}

@Override
public CommonResponse<?> beforeBodyWrite(CommonResponse<?> body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (body != null) {
response.setStatusCode(HttpStatus.valueOf(body.getHttpCode()));
}
return body;
}
}

本文采用 CC BY-NC-SA 4.0 许可协议发布.

作者: lyc8503, 文章链接: https://blog.lyc8503.net/post/my-chat-2-backend-misc/
如果本文给你带来了帮助或让你觉得有趣, 可以考虑赞助我¬_¬