You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.8 KiB
123 lines
3.8 KiB
|
2 months ago
|
package com.youlai.boot.common.result;
|
||
|
|
|
||
|
|
import cn.hutool.extra.servlet.JakartaServletUtil;
|
||
|
|
import cn.hutool.json.JSONUtil;
|
||
|
|
import jakarta.servlet.http.HttpServletResponse;
|
||
|
|
import lombok.extern.slf4j.Slf4j;
|
||
|
|
import org.springframework.http.HttpStatus;
|
||
|
|
import org.springframework.http.MediaType;
|
||
|
|
|
||
|
|
import java.nio.charset.StandardCharsets;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 响应写入器
|
||
|
|
* <p>
|
||
|
|
* 用于在过滤器、Security处理器等无法使用 @RestControllerAdvice 的场景中统一写入HTTP响应。
|
||
|
|
* 支持写入成功响应和错误响应。
|
||
|
|
* 此类为工具类,所有方法均为静态方法,禁止实例化。
|
||
|
|
*
|
||
|
|
* @author Ray.Hao
|
||
|
|
* @since 2.0.0
|
||
|
|
*/
|
||
|
|
@Slf4j
|
||
|
|
public final class ResponseWriter {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 私有构造函数,防止实例化
|
||
|
|
*/
|
||
|
|
private ResponseWriter() {
|
||
|
|
throw new UnsupportedOperationException("工具类不允许实例化");
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 写入成功响应
|
||
|
|
*
|
||
|
|
* @param response HttpServletResponse
|
||
|
|
* @param data 响应数据(可选)
|
||
|
|
*/
|
||
|
|
public static void writeSuccess(HttpServletResponse response, Object data) {
|
||
|
|
writeResult(response, Result.success(data), HttpStatus.OK.value());
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 写入成功响应(无数据)
|
||
|
|
*
|
||
|
|
* @param response HttpServletResponse
|
||
|
|
*/
|
||
|
|
public static void writeSuccess(HttpServletResponse response) {
|
||
|
|
writeSuccess(response, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 写入错误响应
|
||
|
|
*
|
||
|
|
* @param response HttpServletResponse
|
||
|
|
* @param resultCode 响应结果码
|
||
|
|
*/
|
||
|
|
public static void writeError(HttpServletResponse response, ResultCode resultCode) {
|
||
|
|
writeError(response, resultCode, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 写入错误响应(带自定义消息)
|
||
|
|
*
|
||
|
|
* @param response HttpServletResponse
|
||
|
|
* @param resultCode 响应结果码
|
||
|
|
* @param message 自定义消息(可选,为 null 时使用 resultCode 的默认消息)
|
||
|
|
*/
|
||
|
|
public static void writeError(HttpServletResponse response, ResultCode resultCode, String message) {
|
||
|
|
Result<?> result = message == null
|
||
|
|
? Result.failed(resultCode)
|
||
|
|
: Result.failed(resultCode, message);
|
||
|
|
|
||
|
|
int httpStatus = mapHttpStatus(resultCode);
|
||
|
|
writeResult(response, result, httpStatus);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 写入响应结果(通用方法)
|
||
|
|
*
|
||
|
|
* @param response HttpServletResponse
|
||
|
|
* @param result 响应结果对象
|
||
|
|
* @param httpStatus HTTP状态码
|
||
|
|
*/
|
||
|
|
private static void writeResult(HttpServletResponse response, Result<?> result, int httpStatus) {
|
||
|
|
try {
|
||
|
|
// 设置HTTP状态码
|
||
|
|
response.setStatus(httpStatus);
|
||
|
|
|
||
|
|
// 设置响应编码和内容类型
|
||
|
|
response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
|
||
|
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||
|
|
|
||
|
|
// 写入响应
|
||
|
|
JakartaServletUtil.write(response,
|
||
|
|
JSONUtil.toJsonStr(result),
|
||
|
|
MediaType.APPLICATION_JSON_VALUE
|
||
|
|
);
|
||
|
|
|
||
|
|
} catch (Exception e) {
|
||
|
|
log.error("写入响应时发生未知异常: httpStatus={}, result={}", httpStatus, result, e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 根据业务结果码映射HTTP状态码
|
||
|
|
* 401: 未认证(token无效/过期)
|
||
|
|
* 403: 权限不足
|
||
|
|
* 400: 其他业务错误
|
||
|
|
*
|
||
|
|
* @param resultCode 业务结果码
|
||
|
|
* @return HTTP状态码
|
||
|
|
*/
|
||
|
|
private static int mapHttpStatus(ResultCode resultCode) {
|
||
|
|
return switch (resultCode) {
|
||
|
|
case ACCESS_UNAUTHORIZED,
|
||
|
|
ACCESS_TOKEN_INVALID,
|
||
|
|
REFRESH_TOKEN_INVALID -> HttpStatus.UNAUTHORIZED.value();
|
||
|
|
case ACCESS_PERMISSION_EXCEPTION -> HttpStatus.FORBIDDEN.value();
|
||
|
|
default -> HttpStatus.BAD_REQUEST.value();
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|