未使用 Spring Boot 2.3 调用 RestControllerAdvice

Posted

技术标签:

【中文标题】未使用 Spring Boot 2.3 调用 RestControllerAdvice【英文标题】:RestControllerAdvice not called with Spring Boot 2.3 【发布时间】:2020-11-13 01:25:45 【问题描述】:

我想将我的应用程序从 Spring Boot 2.2.8 更新到 2.3.1 当我在更新后运行应用程序时,我的 globalExceptionHandler 将无法正常工作。 我的情况是在请求中包含无效的 JSON-Body 时处理错误。

应用

package com.schaerer.coffeelink.remote;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.kafka.annotation.EnableKafka;

@Slf4j
@SpringBootApplication
@EnableKafka
public class Application 

  public static void main(final String[] args)  //NOSONAR
    SpringApplication.run(Application.class, args);
    log.info("Started application. Swagger available at http://localhost:8080/swagger-ui.html");
  

控制器

package com.schaerer.coffeelink.remote.boundary.v1;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.schaerer.coffeelink.remote.boundary.v1.dto.*;
import com.schaerer.coffeelink.remote.controller.v1.ActionController;
import com.schaerer.coffeelink.remote.controller.v1.BidiCommandController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@RestController
@Validated
@RequestMapping(value = "v1/remote", produces = MediaType.APPLICATION_JSON_VALUE)
@Tag(name = "remote-bidi-command")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class BidiCommandResource 

  private final BidiCommandController bidiCommandController;
  private final ActionController actionController;
  private final ObjectMapper mapper;

  @ExceptionHandler(IllegalArgumentException.class)
  public ResponseEntity<Object> handleException(final IllegalArgumentException illegalArgumentException) 
    return new ResponseEntity<>(illegalArgumentException.getMessage(), HttpStatus.BAD_REQUEST);
  

  @PostMapping
  @Operation(summary = "apply bidi command 2.0")
  public BidiCommandReturnDto applyBidiCommand(@Parameter(name = "applyBidiCommand")
                                                         @Validated(ActionDto.CreateValidation.class, BidiCommandDto.CreateValidation.class)
                                           @RequestBody final BidiCommandDto bidiCommandDto) 
        return bidiCommandController.applyBidiCommand(bidiCommandDto);
  

异常处理程序

package com.schaerer.coffeelink.remote.boundary.v1;

import com.fasterxml.jackson.databind.JsonMappingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler 

  @ExceptionHandler(value = JsonMappingException.class)
  public ResponseEntity<Object> handleJacksonError(final JsonMappingException ex, final WebRequest request) 
    log.error("Cannot parse request. ", request.getDescription(true), ex);
    return handleExceptionInternal(ex, ex.getMessage(), new HttpHeaders(), HttpStatus.BAD_REQUEST, null);
  

自更新以来我没有更改任何代码。响应代码与之前的 400 Bad Request 相同,但响应正文为空,并且未调用我的处理程序。

日志:

13:13:53.987 [http-nio-8080-exec-3] TRACE org.hibernate.internal.SessionImpl - 打开的会话 [6570b352-8067-49d2-bc46-c503917f4c8d] 在时间戳:1595502833972 13:13:53.991 [http-nio-8080-exec-3] 跟踪 ostsTransactionSynchronizationManager - 键 [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@38c55a8a] 的绑定值 [org.springframework.orm.jpa.EntityManagerHolder@72dd1712]线程 [http-nio-8080-exec-3] 13:13:54.011 [http-nio-8080-exec-3] 调试 oswsmmaServletInvocableHandlerMethod - 无法解析公共 com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandReturnDto com.schaerer.coffeelink 中的参数 [0]。 remote.boundary.v1.BidiCommandResource.applyBidiCommand(com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto):JSON 解析错误:意外字符(''(代码 92)):期待双引号开始字段姓名;嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('' (code 92)): was expecting double-quote to start field name 在 [来源:(PushbackInputStream); line: 8, column: 54](通过引用链:com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto["parameters"]) 13:13:54.012 [http-nio-8080-exec-3] TRACE o.s.b.f.s.DefaultListableBeanFactory - 返回单例 bean 'globalExceptionHandler' 的缓存实例 13:13:54.012 [http-nio-8080-exec-3] 调试 o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - 使用 @ExceptionHandler com.schaerer.coffeelink.remote.boundary.v1.GlobalExceptionHandler#handleException(Exception, WebRequest) 13:13:54.013 [http-nio-8080-exec-3] TRACE oswsmmaServletInvocableHandlerMethod - 参数:[org.springframework.http.converter.HttpMessageNotReadableException:JSON 解析错误:意外字符(''(代码 92)):期待双引号以开始字段名称;嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('' (code 92)): was expecting double-quote to start field name 在 [来源:(PushbackInputStream); line: 8, column: 54] (通过引用链: com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto["parameters"]), ServletWebRequest: uri=/v1/remote/;client=0:0 :0:0:0:0:0:1] 13:13:54.015 [http-nio-8080-exec-3] 调试 o.s.w.s.m.m.a.HttpEntityMethodProcessor - [/] 不匹配,支持:[] 13:13:54.016 [http-nio-8080-exec-3] 调试 oswsmmaExceptionHandlerExceptionResolver - 已解决 [org.springframework.http.converter.HttpMessageNotReadableException:JSON 解析错误:意外字符(''(代码 92)):期待双- 引用开始字段名称;嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('' (code 92)): was expecting double-quote to start field name 在 [来源:(PushbackInputStream); line: 8, column: 54] (通过引用链:com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto["parameters"])] 13:13:54.016 [http-nio-8080-exec-3] TRACE o.s.web.servlet.DispatcherServlet - 没有视图渲染,返回 null ModelAndView。

有什么想法吗?

【问题讨论】:

你能用@SpringBootApplication 类和其他任何一个控制器更新你的问题吗? 好的,我看到这个异常不再从 spring 抛出,所以 ExceptionHandler 不能再工作了。任何想法如何在其他地方处理错误? 现在抛出了什么错误? 您可以尝试更改 @ExceptionHandler 以捕获所有异常,并查看 Spring 是否可能引发另一个您现在可以使用的异常。 不幸的是不再抛出异常:( 【参考方案1】:

我在删除 ResponseEntityExceptionHandler 扩展时找到了解决方案。 这是我的解决方案:

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler 

  @ExceptionHandler(value = HttpMessageNotReadableException.class)
  public ResponseEntity<Object> handleJacksonError(final JsonMappingException ex, final WebRequest request) 
    log.error("Cannot parse request. ", request.getDescription(true), ex);
    return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
  

【讨论】:

以上是关于未使用 Spring Boot 2.3 调用 RestControllerAdvice的主要内容,如果未能解决你的问题,请参考以下文章

Ajax 请求未调用 Spring Boot 控制器

Spring Boot @RepositoryEventHandler 未调用

Spring Boot 2.0 Actuator git 属性未添加到 /info

未调用 Spring Boot Rest API 过滤器

HTTP 状态 404 - 在 Spring Boot 中调用 url 时未找到

Java Spring Boot json 文件未找到异常