拦截器中优雅接收JSON对象的完整指南
在Java Web开发中,拦截器(Interceptor)是处理请求前后逻辑的重要组件,当需要拦截并处理JSON格式的请求体时,如何正确接收和解析JSON对象成为关键问题,本文将详细介绍在拦截器中接收JSON对象的多种方法及最佳实践。
核心原理:获取请求流并解析
拦截器本质上是一个过滤器,可以通过HttpServletRequest对象获取请求体数据,JSON数据通常以POST请求的形式通过application/json Content-Type发送,因此核心步骤是:
- 获取请求输入流
- 读取流数据
- 使用JSON库解析为对象
具体实现方案
使用Jackson(Spring Boot默认)
@Component
public class JsonInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 只处理POST/PUT等包含请求体的方法
if ("POST".equals(request.getMethod()) || "PUT".equals(request.getMethod())) {
// 获取请求输入流
ServletInputStream inputStream = request.getInputStream();
// 使用Jackson解析
ObjectMapper objectMapper = new ObjectMapper();
try {
// 直接读取为Map或自定义对象
Map<String, Object> jsonMap = objectMapper.readValue(inputStream, new TypeReference<Map<String, Object>>() {});
// 将解析后的JSON存入request属性,供后续Controller使用
request.setAttribute("jsonData", jsonMap);
// 示例:解析为自定义DTO
UserDTO user = objectMapper.readValue(inputStream, UserDTO.class);
request.setAttribute("userDto", user);
} catch (IOException e) {
throw new RuntimeException("JSON解析失败", e);
}
}
return true;
}
}
使用Spring的@RequestBody结合拦截器
更推荐的方式是让Spring自动解析JSON,拦截器直接处理已解析的对象:
@Component
public class JsonBodyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 检查是否是带有@RequestBody的方法
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
MethodParameter[] parameters = handlerMethod.getMethodParameters();
for (MethodParameter parameter : parameters) {
if (parameter.hasParameterAnnotation(RequestBody.class)) {
// Spring已经解析了JSON,可以通过getAttribute获取
Object requestBody = request.getAttribute("org.springframework.web.servlet.HandlerMapping.readableRequestBody");
if (requestBody != null) {
// 处理已解析的JSON对象
processJsonBody(requestBody);
}
break;
}
}
}
return true;
}
private void processJsonBody(Object jsonBody) {
// 业务逻辑处理
}
}
使用ContentCachingRequestWrapper
对于需要多次读取请求体的场景:
@Component
public class CachingJsonInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 包装请求以支持多次读取
if (!(request instanceof ContentCachingRequestWrapper)) {
request = new ContentCachingRequestWrapper(request);
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 在请求完成后处理缓存的内容
if (request instanceof ContentCachingRequestWrapper) {
ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request;
byte[] buf = cachingRequest.getContentAsByteArray();
if (buf.length > 0) {
String jsonBody = new String(buf, StandardCharsets.UTF_8);
// 解析并处理JSON
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> data = mapper.readValue(jsonBody, new TypeReference<Map<String, Object>>() {});
// 业务逻辑
}
}
}
}
关键注意事项
-
Content-Type检查:确保请求头包含
application/jsonString contentType = request.getContentType(); if (contentType != null && contentType.contains("application/json")) { // 处理JSON } -
流关闭问题:使用
try-with-resources确保流正确关闭try (ServletInputStream inputStream = request.getInputStream()) { // 解析逻辑 } -
字符编码:明确指定UTF-8编码
request.setCharacterEncoding("UTF-8"); -
性能考虑:避免在拦截器中进行复杂的JSON解析,可以结合Spring的
HttpMessageConverter机制
最佳实践建议
-
优先使用Spring的自动解析:让Spring的
MappingJackson2HttpMessageConverter处理JSON解析,拦截器专注于业务逻辑 -
自定义注解:结合自定义注解实现更灵活的拦截控制
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface JsonProcess { } -
异常处理:在拦截器中添加适当的异常处理机制
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { if (ex != null) { // 处理JSON解析异常 } }
完整示例
@Component
public class JsonProcessingInterceptor implements HandlerInterceptor {
private final ObjectMapper objectMapper;
public JsonProcessingInterceptor(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (shouldProcessJson(request)) {
try {
JsonNode jsonNode = objectMapper.readTree(request.getInputStream());
request.setAttribute("parsedJson", jsonNode);
// 转换为特定DTO
if (jsonNode.has("user")) {
UserDTO user = objectMapper.treeToValue(jsonNode.get("user"), UserDTO.class);
request.setAttribute("userDto", user);
}
} catch (IOException e) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid JSON format");
}
}
return true;
}
private boolean shouldProcessJson(HttpServletRequest request) {
return "POST".equals(request.getMethod()) ||
"PUT".equals(request.getMethod()) ||
(request.getContentType() != null && request.getContentType().contains("application/json"));
}
}
通过以上方法,你可以在拦截器中灵活地接收和处理JSON对象,同时保持代码的健壮性和可维护性,根据项目具体需求选择最适合的实现方案,并注意处理各种边界情况。
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
新浪足球直播
新浪足球直播
足球直播
足球直播
快连VPN
快连官网
足球直播
足球直播
快连VPN
快连官网
Google Chrome
Google Chrome
快连VPN
letsVPN
chrome浏览器
谷歌浏览器
足球直播
足球直播
欧易平台
欧易平台
欧易下载
欧易平台
欧易下载
欧易平台
欧易下载
欧易下载
欧易
欧易下载
欧易APP
欧易下载
欧易APP
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
欧易app
欧易app
欧易
欧易
NBA直播
足球直播
NBA直播
nba直播
英超直播
篮球直播
西甲直播
德甲直播



还没有评论,来说两句吧...