我制作了这个简单的 Spring Boot 应用示例来展示我在 Spring Boot 默认处理错误的方式方面的问题:
package com.pany.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
这是 Spring Security 配置:
package com.pany.app;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").anonymous();
}
}
这是 REST 控制器:
package com.pany.app;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpClientErrorException;
@RestController
public class MyController {
@GetMapping(path = "/", produces = { "application/json" })
public void home() {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "This is my custom 400 Bad Request message");
}
}
现在,Spring Boot 2.1.8.RELEASE
当调用 URL 时,http://localhost:8080/
我得到一个带有 500 代码的 HTTP 响应和以下 JSON 响应:
{
"timestamp": "2020-09-14T07:24:22.061+0000",
"status": 500,
"error": "Internal Server Error",
"message": "400 This is my custom 400 Bad Request message",
"path": "/"
}
然而,HTTP 状态代码与预期不同(500 而不是 400),以及 JSON 中的各种字段(“状态”、“错误”、“消息”,前面有意外的“代码”)。
我也用Spring Boot 2.3.3.RELEASE
...测试了这个,现在它甚至不再像以前那样工作了!!
{
"timestamp": "2020-09-14T07:34:23.154+00:00",
"status": 500,
"error": "Internal Server Error",
"message": "",
"path": "/"
}
所有这些都是通过诸如 和 的类/接口来处理ErrorController
的AbstractErrorController
(BasicErrorController
全部设置在 中ErrorMvcAutoConfiguration
)。显然有一个重定向到 URL/error
的原始请求/和/或响应包装到其他东西中,例如我可以调试我的请求,如下所示:SecurityContextHolderAwareRequestWrapper[FirewalledRequest[org.apache.catalina.core.ApplicationHttpRequest@3751bea4]]
我发现我得到的 JSON 是通过一个名为的 bean 生成的,该 beanDefaultErrorAttributes
从 key 下的请求中提取 HTTP 状态代码"javax.servlet.error.status_code"
。
我在那里读到:https ://github.com/spring-projects/spring-boot/issues/4694#issuecomment-163597864 (2015年12月):
问题实际上出在 BasicErrorController 中,并且特定于 HTML 响应。BasicErrorController.error 使用 ErrorPageFilter 设置的 javax.servlet.error.status_code 属性设置响应状态,但 BasicErrorController.errorHtml 没有。这导致 text/html 错误响应的状态为 200 OK。
事实上,就我而言,ErrorPageFilter
从未调用过。
在 Spring Boot 项目上还发现了另一个问题:https ://github.com/spring-projects/spring-boot/issues/20412这与我的问题非常相关,但仍然没有提供解决方案。
回到我的控制器的设计方式(请记住,这只是一个极其简化的示例):如何“自定义”Spring Boot 以获得带有代码 400 的 HTTP 响应和此 JSON 作为响应:
{
"timestamp": "2020-09-14T07:24:22.061+0000",
"status": 400,
"error": "Bad Request",
"message": "This is my custom 400 Bad Request message",
"path": "/"
}
谢谢。