java - 尝试使用 Spring Boot 显示自定义错误页面时出现问题
问题描述
我正在维护一个 Spring Boot 应用程序,它使用 Swagger 定义 Rest web 服务并使用 Maven 进行依赖管理。它使用 application.yml 文件作为属性。默认情况下,当发生错误时,任何浏览器都会显示一个 Whitelabel 页面。
应用程序的 pom.xml 中的父级定义如下:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
我在 resources/templates/error 和 resources/public/error 中分别为一般错误、404 错误、401 错误和 500 错误创建了 HTML 页面。
之后,我尝试了以下解决方案但没有成功:
- 根据https://www.baeldung.com/spring-boot-custom-error-page,我必须按照以下步骤操作:
1.1。从属性文件或主类禁用 Whitelabel 显示。我选择从主要课程中进行:
@SpringBootApplication(scanBasePackages = "com.mycompanyname")
@EnableConfigurationProperties(AppProperties.class)
@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class}) // <- Like this!
public class BuySellBackendApplication {
public static void main(String[] args) {
SpringApplication.run(BuySellBackendApplication.class, args);
}
}
1.2. 定义实现ÈrrorController
接口的自定义错误控制器。我的定义如下:
@Controller
public class BazaarErrorController implements ErrorController {
@Override
public String getErrorPath() {
return "/custom-error";
}
@RequestMapping("/custom-error")
public String handleError() {
return "error";
}
}
1.3. 添加从属性文件定义的错误映射的路径。由于我使用的是 yml 文件,因此属性添加如下:
server:
error:
path: "/custom-error"
期望的结果是显示我定义的通用错误页面。但是得到的结果是Tomcat定义的错误页面。此外,Tomcat 的错误页面是从应用程序中使用 Spring Security 的以下类触发的:
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(RestAuthenticationEntryPoint.class);
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
logger.error("Responding with unauthorized error. Message - {}", e.getMessage());
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getLocalizedMessage()); // <- This line of code
}
}
在这种情况下,即使使用@RequestBody
注解和/或根据获得的 HTTP 错误代码返回不同的页面也是没有用的。
由于公司的要求,我无法删除认证入口点的代码行。此外,它不会将我重定向到我的错误页面,而是打开浏览器的下载对话框。
- 根据https://www.logicbig.com/tutorials/spring-framework/spring-boot/servlet-error-handling-outside-mvc.html,我必须定义一个错误页面寄存器。Spring Web 提供了
ErrorPageRegistrar
执行此操作的接口:
@Bean
public ErrorPageRegistrar errorPageRegistrar() {
return registry -> {
ErrorPage e404=new ErrorPage(HttpStatus.NOT_FOUND, "/error/" + HttpStatus.NOT_FOUND.value());
ErrorPage e401=new ErrorPage(HttpStatus.UNAUTHORIZED, "/error/" + HttpStatus.UNAUTHORIZED.value());
ErrorPage e500=new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/" + HttpStatus.INTERNAL_SERVER_ERROR.value());
ErrorPage egeneric=new ErrorPage("/error/error");
registry.addErrorPages(e401, e404, e500, egeneric);
};
}
得到的结果与解决方案 1 中覆盖 Authentication 入口点并转到浏览器的下载对话框相同。另外,不清楚ErrorPage
构造函数中的 String 参数是物理 HTML 文件还是 servlet 映射。
- 使用 Spring 的 ErrorViewResolver 接口定义错误视图解析器,如https://forketyfork.medium.com/how-to-customize-error-page-selection-logic-in-spring-boot-8ea1a6ae122d中所述:
@Configuration
public class ErrorPageConfig {
private static final Logger logger = LoggerFactory.getLogger(ErrorPageConfig.class);
@Bean
public ErrorViewResolver errorViewResolver(ApplicationContext context, ResourceProperties properties){
ErrorViewResolver resolver=(request, status, model) -> {
String pathFormat="error/%d";
String path="";
switch(status.value()) {
case 401: case 404: case 500:
path=String.format(pathFormat, status.value());
break;
default:
logger.info("Codigo de error obtenido {}", status.value());
path="error/error";
break;
}
return new ModelAndView(path);
};
return resolver;
}
}
它给了我与解决方案 2 相同的结果。
我该如何解决这个问题?提前致谢
解决方案
解决了
解决方法如下:
不要从属性文件或主类禁用 Whitelabel 显示。
像解决方案 3 一样完全定义错误视图解析器。
HTML 页面必须在资源/模板中
您必须将以下依赖项添加到应用程序的 pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
我希望这对需要它的每个人都有帮助。
推荐阅读
- julia - 替换“occursin”函数在 Array{String,1} 中查找字符串
- .net - 使用 UnitOfWork 模式提交更改的最佳策略是什么?
- python - 如何在 Windows 10 上安装omniORB 和omniORBpy?
- python - Tkinter 窗口中的透明背景和顶部窗口边框
- python - 为什么 MNIST CNN 的预测会出错?
- angular - TypeError:虽然已定义,但无法读取未定义的属性“xyz”
- html - 滚动后粘性导航栏未修复
- javascript - 将标签的href更改为使用 JavaScript 标记 onClick
- git - 为什么我不能在 Stash/Bitbucket 中版本压缩/二进制文件?
- scala - sbt:在跨平台项目中生成共享源