我在spring mvc应用程序中显示错误,但出现问题。因此,让我描述更多有关问题的细节。
如果我要显示自定义错误页面而不是默认的whitelabel错误页面,我已经知道该怎么办。我在这里阅读了有关此内容,并观看了youtube上的一些教程。这很简单,但是问题在于用户将始终重定向到包含错误描述的新页面。
我想将所有后端异常以特定格式显示为模式窗口,警报消息或吐司,如此处所示,但适用于百里香。最好的解决方案是模式页面,这使我可以更灵活地显示内容。但是模态可以使用前端的JavaScript来调用,如何使用控制器异常作为打开模态页面的触发器(如果可能,则不使用AJAX)?
这实际上是我想要的,当控制器中的某些方法可能引发异常时,调用该异常并引发异常
@GetMapping
public ModelAndView throwException() throws Exception {
throw new Exception("Oops :( something went wrong");
}
像这样的东西会显示错误窗口
请帮助我找到解决方案。非常感谢您的关注。
PS,如果这很复杂或不可能,我想至少知道如何显示来自控制器的错误消息+与当前(同一)页面上的错误相关的一些按钮或输入字段,而无需重定向到新页面?
没有捷径。如果您是我,我会坚持使用通用错误页面。您可以针对不同类型的错误自定义它们。
IMO您所描述的问题将更适合在任何具有Java后端公开REST API的现代前端框架中编写的SPA(单页应用程序)。通常enpoint将返回包含实际请求数据的json。但是,如果发生任何错误,您可以简单地返回带有错误描述的4xx代码作为有效内容。然后,JavaScript中的表示逻辑可以在不重新加载页面的情况下显示任何内容。
由于您已决定使用作为模板引擎的百里香叶,因此您应该接受其局限性。对控制器的大多数调用是对视图的请求。Spring and Thymeleaf接收一个模板文件,用模型数据填充该文件,然后将整个页面发送回浏览器。如果此过程在收集数据时失败,则无法正确呈现页面。因此,最合理的做法是重定向到错误页面。
如果通用错误页面吓坏了您,则可以付出额外的努力。代替一般的错误处理,您可以处理每个Controller方法中的异常。如果出错,您可能会提供其他“错误”模型,这些模型将用于填充模板。它使您可以灵活地显示错误。这将取决于您如何准备模板。
例如
view.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>Data:</h1>
<div th:if="${actualData}">
<p th:text="${actualData}"></p>
</div>
<!-- Instead of div below, you could supply a modal and pice of javascript opening it -->
<div th:if="${errorData}">
<h3>Error occurred:</h3>
<p th:text="${errorData}"></p>
</div>
</body>
</html>
MyController.java
@Controller
class MyController {
@GetMapping("/view")
public String view(Model model) {
try {
model.addAttribute("actualData", mayThrowExceptionDataFetch());
} catch(Exception e) {
model.addAttribute("errorData", e.getMessage());
}
return "view";
}
private String mayThrowExceptionDataFetch() {
// Either return a value or throw an exception
}
}
这样一来,视图将始终返回。即使发生错误,也可以对其进行处理和显示。
重要说明:这仅是演示。当然,我不会在生产中尝试它。
我发现您的要求如此异常(控制器异常作为打开模式页面的触发器),我想检查是否有可能实现类似的要求。我想象过一个解决方案可能是这样的:
然后,我提出了这个有效的演示,它确实不会导致页面重新加载,但显示错误:
index.html
<!DOCTYPE HTML>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
</head>
<body>
<a th:href="@{/exception}">Click for exception</a>
<script>
var sse = new EventSource('http://localhost:8080/sse');
sse.onmessage = function (evt) {
alert(evt.data);
};
</script>
</body>
</html>
MyService.java
@Service
public class MyService {
private final SseEmitter emitter = new SseEmitter();
public SseEmitter getEmitter() {
return emitter;
}
}
MyExceptionHandler.java
@ControllerAdvice
public class MyExceptionHandler {
private final MyService service;
@Autowired
public MyExceptionHandler(MyService service) {
this.service = service;
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.CONTINUE) // I don't figure out how to abort request
public ResponseEntity<Void> handle(Exception ex) {
try {
service.getEmitter().send(SseEmitter.event().data(ex.getMessage()));
} catch (IOException e) {
// TODO
}
}
}
MyController.java
@Controller
public class MyController {
private final MyService service;
@Autowired
public MyCtrl(MyService service) {
this.service = service;
}
@GetMapping("/sse")
public SseEmitter sse() {
return service.getEmitter();
}
@GetMapping("/index")
public String index() {
return "index";
}
@GetMapping("/exception")
public String exception() {
throw new RuntimeException("Oops :o");
}
}
上面的所有内容都是带有spring-boot-starter-thymeleaf
和spring-boot-starter-web
依赖项的spring-boot项目。运行应用程序,转到localhost:8080/index
然后单击链接。警报应出现而无需重新加载页面。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句