【问题标题】:swagger-ui.html 400 bad requestswagger-ui.html 400 错误请求
【发布时间】:2018-03-07 12:39:07
【问题描述】:

我在我的 Spring Boot 项目中集成了 swagger。所有 swagger 端点都工作正常,但 /product/swagger-ui.html 给出 400 错误。

经过一些调试,我发现两个端点之间存在冲突。

在我的 application.properties 文件中,我使用的是server.contextPath=/product

在我的控制器中,我有以下我认为导致错误的映射。

ProductRestController.java

@RestController
public class ProductRestController {

    // some autowired services

    @GetMapping("/{id}")
    public ResponseEntity<ProductDTO> getProductById(
            @Min(value = 1, message = "id {javax.validation.constraints.Min.message}") @PathVariable Long id,
            @RequestAttribute Long tenantId) {
        return ResponseEntity.ok(productService.getProductById(id, tenantId));
    }

    @PutMapping("/{id}")
    public ResponseEntity<ProductDTO> updateProduct(
            @Min(value = 1, message = "id {javax.validation.constraints.Min.message}") @PathVariable Long id,
            @RequestBody HashMap<String, Object> requestBody, @RequestAttribute Long tenantId,
            @RequestAttribute Long userId) {

        ProductDTO productDTO;
        try {
            productDTO = objectMapper.convertValue(requestBody, ProductDTO.class);
        } catch (IllegalArgumentException e) {
            throw new HttpMessageNotReadableException(e.getMessage(), e);
        }

        Set<ConstraintViolation<ProductDTO>> errors = validator.validate(productDTO, ProductDTO.UpdateProduct.class);

        if (!errors.isEmpty()) {
            throw new ConstraintViolationException(errors);
        }

        return ResponseEntity.ok(productService.updateProduct(productDTO, requestBody, id, tenantId, userId));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<?> deleteProduct(
            @Min(value = 1, message = "id {javax.validation.constraints.Min.message}") @PathVariable Long id,
            @RequestAttribute Long tenantId,
            @RequestParam(required = false, name = "delete_members") boolean deleteMembers) {
        productService.deleteProduct(id, tenantId, deleteMembers);
        return ResponseEntity.status(HttpStatus.NO_CONTENT).body(null);
    }

    //other mappings
}

我调试发现HandlerExecutionChain已经将此请求转发到getProductById方法,然后抛出异常不能从String转换为Long。

所以我删除了该映射并再次检查它是否正常工作,但这次我收到了 HTTP 405 错误。再次通过调试,我发现堆栈跟踪显示允许的方法是 PUT & DELETE。

然后我删除了这两个映射并检查了它,它工作正常。

据我所知,spring 正在为 /product/swagger-ui.html 端点选择 /product/{id} 映射,然后由于类型不匹配而引发错误。

问题是为什么会发生这种情况以及如何解决这个问题?

EDIT:DispatcherServlet.doDispatch 方法中捕获的异常: org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "swagger-ui"

删除 GET 映射后在同一方法中捕获的异常: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported

【问题讨论】:

  • 什么是错误日志?
  • 实际上 Spring 没有打印错误日志,这就是我调试并发现错误所在的原因。我已经写了这个问题
  • 嗨@Kaushal28,我已经编辑了问题并包含了错误日志。

标签: java spring-boot swagger


【解决方案1】:

@GetMapping("/{id}")String 中给出id 值,而您直接尝试将String 映射到Long。尝试使用:@PathVariable String id,然后将您的 String 转换为 Long,如下所示:

Long longId = Long.parseLong(id);

【讨论】:

  • 我已经尝试过了,但 Spring 仍然选择了错误的处理程序,即它选择 /{id} 处理程序,然后为@Min 验证提供错误
  • 我也删除了该验证,现在执行 getProductById 中的代码并引发解析错误。
  • 但是没有不明确的处理程序,它如何选择错误的处理程序?
  • 这就是我的问题。如果我删除所有这些 /{id} 映射,那么 swagger 端点就可以正常工作。
  • 几天前我遇到了类似的错误,这里是我要寻找的:1. 检查您是否有任何没有 value = "\" 的 GET 端点 2. 评论所有在方法中具有 Long 的端点论点,然后尝试仅保留一两个端点来运行。根据错误跟踪,将 String 解析为 Long 似乎是错误的,这是不正确的。提供 github URL 以检查代码。
【解决方案2】:

你是对的:通过执行 /{id} spring 假设 swagger-ui.html 是一个 id。如果您的 baseUrl=/ ,这是网址:http://localhost:8080/swagger-ui.html

【讨论】:

    【解决方案3】:

    虽然它是一个旧线程,但提供我的观点以防万一它对某人有所帮助。

    swagger URL 指向 ProductRestController,因为它没有任何自己的上下文路径。因此,要解决它,请尝试向 ProductRestController 添加上下文路径,例如 @RequestMapping("v1")。

    然后你的 http://localhost:8080/swagger-ui.html 的招摇 URL 应该可以工作,因为它不会指向任何控制器。

    【讨论】: