htmx -spring-boot 库 3.2.0刚刚发布,现在支持用作HtmxResponse错误处理程序的返回类型。这篇博文展示了如何使用它。
错误处理是任何应用程序的重要组成部分。它确保用户始终了解应用程序发生了什么并且可以采取行动。按下按钮却没有任何反应总是比看到错误消息出现更糟糕。显然,我们应该努力避免它们,但是有一个全局错误回退以防万一出现问题肯定是一个好主意。
让我们创建一个小示例来展示新功能。使用ttcli并选择“NPM Based with TailwindCSS”、“htmx”和“DaisyUI”。
我们添加 2 条路线HomeController:
@GetMapping("/test") @HxRequest public String test() { return "fragments :: message"; }
@GetMapping("/test-exception") @HxRequest public String testException() { throw new RuntimeException("Fake exception"); }
|
第一个返回一个简单的结果<div>,第二个则模拟发生异常。
src/main/resources/templates/fragments.html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <div th:fragment="message"> Button clicked! </div>
|
在 index.html中,我们放置了两个按钮来触发我们的两条路线:
<div layout:fragment="content"> <div class="m-4"> <button class="btn btn-neutral" hx:get="@{/test}" hx-swap="outerHTML" >Do something</button> </div> <div class="m-4"> <button class="btn btn-neutral" hx:get="@{/test-exception}" hx-swap="outerHTML" >Do something</button> </div> </div>
|
在 中index.html,添加一个空字符div作为占位符来放置错误消息:
<div layout:fragment="content"> <div class="mx-8 mt-4"> <div id="global-error"></div> </div> ...
|
我们创建一个可用于带外交换的片段:
src/main/resources/templates/fragments.html
<div th:fragment="error-message(message)" id="global-error" role="alert" class="alert alert-error" hx-swap-oob="true"> <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg> <span th:text="${message}">Error!</span> </div>
|
这两件事很重要:
- hx-swap-oob="true" 允许 htmx 使用带外交换。
- 片段的 id 必须与 index.html 模板中占位符 div 的 id 一致。
最后一块拼图是在 HomeController 中添加异常处理程序:
HomeController.java
@ExceptionHandler(Exception.class) public HtmxResponse handleError(Exception ex) { return HtmxResponse.builder() .reswap(HtmxReswap.none()) .view(new ModelAndView("fragments :: error-message", Map.of("message", ex.getMessage()))) .build(); }
|
- 处理异常Exception 和异常的所有子类。
- 将交换行为设置为 "无",这样我们就不会意外地交换我们不想交换的东西。我们只希望通过带外交换来显示错误信息。
- 使用 error-message 片段,并将捕获的异常信息传递给该片段。
如果希望错误处理适用于应用程序的所有控制器,可以使用 @ControllerAdvice 来实现:
import io.github.wimdeblauwe.htmx.spring.boot.mvc.HtmxResponse; import io.github.wimdeblauwe.htmx.spring.boot.mvc.HtmxReswap; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.servlet.ModelAndView;
import java.util.Map;
@ControllerAdvice public class GlobalErrorHandler {
@ExceptionHandler(Exception.class) public HtmxResponse handleError(Exception ex) { return HtmxResponse.builder() .reswap(HtmxReswap.none()) .view(new ModelAndView("fragments :: error-message", Map.of("message", ex.getMessage()))) .build(); } }
|
结论
确保回退错误处理程序并不那么困难,随着 htmx-spring-boot 3.2.0 版本的发布,这变得更加容易。
请参阅GitHub 上的htmx-global-error-handler以获取此示例的完整源代码。