|
|
|
@ -0,0 +1,131 @@
|
|
|
|
|
package com.yami.shop.common.handler;
|
|
|
|
|
|
|
|
|
|
// 导入 Hutool 工具库中处理字符集相关的工具类,用于设置响应的字符编码
|
|
|
|
|
import cn.hutool.core.util.CharsetUtil;
|
|
|
|
|
// 导入 Jackson 库中用于将对象转换为 JSON 字符串以及反序列化等操作的核心类
|
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
|
// 导入自定义的业务异常类,可能在项目中用于处理特定业务逻辑出错的情况
|
|
|
|
|
import com.yami.shop.common.exception.YamiShopBindException;
|
|
|
|
|
// 导入自定义的用于封装服务器响应信息的实体类,包含响应状态码、消息、数据等内容
|
|
|
|
|
import com.yami.shop.common.response.ServerResponseEntity;
|
|
|
|
|
// 导入 Slf4j 框架的日志记录相关类,用于创建日志记录器来记录不同情况的日志信息
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
// 导入 Spring 框架用于实现依赖注入的注解,表明某个属性需要由 Spring 容器进行注入
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
// 导入 Spring 框架中定义媒体类型的枚举类,用于设置响应的内容类型为 JSON 格式
|
|
|
|
|
import org.springframework.http.MediaType;
|
|
|
|
|
// 导入 Spring 框架用于将类标记为组件的注解,表明该类是一个 Spring 管理的组件,可被自动扫描并注入到其他需要的地方
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
// 导入 Spring 框架中用于获取请求上下文相关信息的类和接口
|
|
|
|
|
import org.springframework.web.context.request.RequestContextHolder;
|
|
|
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
|
|
|
|
|
|
|
// 导入 Servlet 相关的用于操作 HTTP 响应的类,用于设置响应的各种属性以及向客户端输出内容
|
|
|
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.io.PrintWriter;
|
|
|
|
|
import java.util.Objects;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* HttpHandler 类主要用于处理将服务器响应信息输出到 Web 端(客户端)的相关操作,
|
|
|
|
|
* 它能够根据不同的输入参数(如服务器响应实体或特定业务异常),将对应的响应信息以 JSON 格式正确地写入到 HTTP 响应中,
|
|
|
|
|
* 同时进行了必要的日志记录以及异常处理,确保响应输出过程的可靠性和稳定性。
|
|
|
|
|
*
|
|
|
|
|
* @author 菠萝凤梨
|
|
|
|
|
* @date 2022/3/28 14:15
|
|
|
|
|
*/
|
|
|
|
|
@Component
|
|
|
|
|
public class HttpHandler {
|
|
|
|
|
|
|
|
|
|
// 创建一个日志记录器,用于记录该类中不同操作阶段的日志信息,方便后续进行问题排查和调试
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(HttpHandler.class);
|
|
|
|
|
|
|
|
|
|
// 通过 Spring 的依赖注入机制,注入一个 ObjectMapper 对象,用于将对象转换为 JSON 字符串以便输出到客户端
|
|
|
|
|
@Autowired
|
|
|
|
|
private ObjectMapper objectMapper;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 将服务器响应实体(ServerResponseEntity)的内容以 JSON 格式输出到 Web 端(客户端)的 HTTP 响应中。
|
|
|
|
|
* 如果传入的服务器响应实体为 null,则仅记录相应日志并直接返回,不进行实际的输出操作。
|
|
|
|
|
* 同时会进行一系列的有效性检查,确保能够获取到正确的 HTTP 响应对象,并设置响应的字符编码和内容类型等属性,
|
|
|
|
|
* 若在输出过程中出现 I/O 异常,则抛出自定义的业务异常(YamiShopBindException)。
|
|
|
|
|
*
|
|
|
|
|
* @param serverResponseEntity 要输出到客户端的服务器响应实体,包含了响应的各种信息,如状态码、消息、数据等
|
|
|
|
|
* @param <T> 泛型参数,用于表示服务器响应实体中携带的数据的具体类型,具有通用性,可以适应不同类型的数据返回情况
|
|
|
|
|
*/
|
|
|
|
|
public <T> void printServerResponseToWeb(ServerResponseEntity<T> serverResponseEntity) {
|
|
|
|
|
// 如果传入的服务器响应实体为 null,记录日志提示信息,并直接返回,不进行后续操作
|
|
|
|
|
if (serverResponseEntity == null) {
|
|
|
|
|
logger.info("print obj is null");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从 Spring 的请求上下文中获取 ServletRequestAttributes 对象,它包含了与当前请求相关的信息,如请求和响应对象等
|
|
|
|
|
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
|
|
|
|
|
.getRequestAttributes();
|
|
|
|
|
// 如果获取到的 ServletRequestAttributes 对象为 null,说明无法获取到请求上下文相关信息,记录错误日志并返回,无法进行响应输出操作
|
|
|
|
|
if (requestAttributes == null) {
|
|
|
|
|
logger.error("requestAttributes is null, can not print to web");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从 ServletRequestAttributes 对象中获取 HttpServletResponse 对象,用于后续设置响应属性和向客户端输出内容
|
|
|
|
|
HttpServletResponse response = requestAttributes.getResponse();
|
|
|
|
|
// 如果获取到的 HttpServletResponse 对象为 null,说明无法获取到有效的 HTTP 响应对象,记录错误日志并返回,无法进行响应输出操作
|
|
|
|
|
if (response == null) {
|
|
|
|
|
logger.error("httpServletResponse is null, can not print to web");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 记录响应的错误消息(这里假设 getMsg 方法获取的是错误相关信息,实际情况可能根据 ServerResponseEntity 的具体实现而定)到日志中,方便排查问题
|
|
|
|
|
logger.error("response error: " + serverResponseEntity.getMsg());
|
|
|
|
|
|
|
|
|
|
// 设置 HTTP 响应的字符编码为 UTF-8,确保输出的内容能够正确地被客户端解析,尤其是包含中文等多字节字符的情况
|
|
|
|
|
response.setCharacterEncoding(CharsetUtil.UTF_8);
|
|
|
|
|
// 设置 HTTP 响应的内容类型为 application/json,表明响应的内容是 JSON 格式的数据,让客户端能够正确识别并解析
|
|
|
|
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
|
|
|
|
|
|
|
|
|
// 用于向 HTTP 响应中写入字符数据的对象,初始化为 null,后续通过获取响应的输出流来实例化
|
|
|
|
|
PrintWriter printWriter = null;
|
|
|
|
|
try {
|
|
|
|
|
// 获取 HttpServletResponse 的输出流对象,用于向客户端写入响应内容(这里是将服务器响应实体转换后的 JSON 字符串写入)
|
|
|
|
|
printWriter = response.getWriter();
|
|
|
|
|
// 使用注入的 ObjectMapper 对象将服务器响应实体转换为 JSON 字符串,并写入到 HTTP 响应的输出流中,从而输出到客户端
|
|
|
|
|
printWriter.write(objectMapper.writeValueAsString(serverResponseEntity));
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
// 如果在写入过程中出现 I/O 异常,抛出自定义的业务异常(YamiShopBindException),并将原始的 I/O 异常作为原因传递,方便上层进行统一的异常处理和日志记录
|
|
|
|
|
throw new YamiShopBindException("io 异常", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 针对 YamiShopBindException 类型的异常进行处理,将其相关的响应信息以 JSON 格式输出到 Web 端(客户端)的 HTTP 响应中。
|
|
|
|
|
* 如果传入的异常对象为 null,则仅记录相应日志并直接返回,不进行实际的输出操作。
|
|
|
|
|
* 如果异常对象中已经包含了服务器响应实体(ServerResponseEntity),则调用 printServerResponseToWeb 方法直接输出该实体内容。
|
|
|
|
|
* 否则,会根据异常对象中的错误码和错误消息构建一个新的服务器响应实体,并调用 printServerResponseToWeb 方法输出到客户端。
|
|
|
|
|
*
|
|
|
|
|
* @param yamiShopBindException 要处理并输出响应信息的 YamiShopBindException 异常对象,包含了业务异常相关的错误码、消息等信息
|
|
|
|
|
* @param <T> 泛型参数,用于表示服务器响应实体中携带的数据的具体类型(虽然此处构建新实体时可能没有实际数据,但保持与其他方法的通用性)
|
|
|
|
|
*/
|
|
|
|
|
public <T> void printServerResponseToWeb(YamiShopBindException yamiShopBindException) {
|
|
|
|
|
// 如果传入的 YamiShopBindException 异常对象为 null,记录日志提示信息,并直接返回,不进行后续操作
|
|
|
|
|
if (yamiShopBindException == null) {
|
|
|
|
|
logger.info("print obj is null");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 判断异常对象中是否包含了服务器响应实体(ServerResponseEntity),如果包含则直接调用 printServerResponseToWeb 方法输出该实体内容到客户端
|
|
|
|
|
if (Objects.nonNull(yamiShopBindException.getServerResponseEntity())) {
|
|
|
|
|
printServerResponseToWeb(yamiShopBindException.getServerResponseEntity());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果异常对象中没有包含服务器响应实体,则创建一个新的 ServerResponseEntity 对象,用于封装异常中的错误码和错误消息等信息
|
|
|
|
|
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
|
|
|
|
|
serverResponseEntity.setCode(yamiShopBindException.getCode());
|
|
|
|
|
serverResponseEntity.setMsg(yamiShopBindException.getMessage());
|
|
|
|
|
// 调用 printServerResponseToWeb 方法将构建好的服务器响应实体输出到客户端,完成响应信息的输出操作
|
|
|
|
|
printServerResponseToWeb(serverResponseEntity);
|
|
|
|
|
}
|
|
|
|
|
}
|