该项目提供注释、辅助类和Thymeleaf方言,以便 在Spring Boot应用程序中轻松使用htmx。
- htmx-spring-boot:提供注释和帮助器类。
<dependency> <groupId>io.github.wimdeblauwe</groupId> <artifactId>htmx-spring-boot</artifactId> <version>LATEST_VERSION_HERE</version> </dependency> |
- htmx-spring-boot-thymeleaf:提供Thymeleaf方言以轻松使用 htmx 属性。
<dependency> <groupId>io.github.wimdeblauwe</groupId> <artifactId>htmx-spring-boot-thymeleaf</artifactId> <version>LATEST_VERSION_HERE</version> </dependency> |
包含的 Spring Boot 自动配置将启用 htmx 集成。
1、将控制器方法映射到 htmx 请求 控制器方法可以注释为 HxRequest,只有在基于 htmx 的请求(如 hx-get)时才会被选中。
只有当请求是由 htmx 发出时,才会调用以下方法。
@HxRequest @GetMapping("/users") public String htmxRequest(){ return "partial"; } |
此外,如果要将控制器方法的调用限制在特定触发元素上,可以将 HxRequest#value 设置为元素的 ID 或名称。如果想更明确,可使用 HxRequest#triggerId 或 HxRequest#triggerName
@HxRequest("my-element") @GetMapping("/users") public String htmxRequest(){ return "partial"; } |
如果您想将控制器方法的调用限制为已定义的特定目标元素,请使用 HxRequest#target
@HxRequest(target = "my-target") @GetMapping("/users") public String htmxRequest(){ return "partial"; } |
使用 HtmxRequest 访问 htmx 发送的 HTTP 请求头 HtmxRequest 对象可用作控制器方法参数,以访问各种 htmx 请求头。
@HxRequest @GetMapping("/users") public String htmxRequest(HtmxRequest htmxRequest) { if(htmxRequest.isHistoryRestoreRequest()){ // do something } return "partial"; } |
响应标头 有两种方法可以在控制器方法上设置 htmx 响应头。
- 第一种是使用注解,例如 @HxTrigger,
- 第二种是使用 HtmxResponse 类作为控制器方法的返回类型。
目前支持以下注解:
示例 如果希望 htmx 在处理完响应后触发一个事件,可以使用注解 @HxTrigger 来设置必要的响应头 HX-Trigger。
@HxRequest @HxTrigger("userUpdated") // htmx 将触发 "userUpdated "事件 @GetMapping("/users") public String hxUpdateUser(){ return "partial"; } |
如果想以更灵活的方式实现相同的功能,可以在控制器方法中使用 HtmxResponse 作为返回类型。
@HxRequest @GetMapping("/users") public HtmxResponse hxUpdateUser(){ return HtmxResponse.builder() .trigger("userUpdated") // the event 'userUpdated' will be triggered by htmx .view("partial") .build(); } |
Out Of Band Swaps htmx 支持通过在单个响应中返回多个部分来更新多个目标,这就是所谓的带外交换 Out Of Band Swaps。 为此,请使用 HtmxResponse 作为控制器方法的返回类型,并在其中添加多个模板。
@HxRequest @GetMapping("/partials/main-and-partial") public HtmxResponse getMainAndPartial(Model model){ model.addAttribute("userCount", 5); return HtmxResponse.builder() .view("users-list") .view("users-count") .build(); } |
HtmxResponse 可以由视图名称(如上所述)或完全解析的 View 实例(如果控制器知道如何进行解析)或 ModelAndView 实例(已解析或未解析)组成。例如
@HxRequest @GetMapping("/partials/main-and-partial") public HtmxResponse getMainAndPartial(Model model){ return HtmxResponse.builder() .view(new ModelAndView("users-list") .view(new ModelAndView("users-count", Map.of("userCount",5)) .build(); } |
使用 ModelAndView 意味着每个片段都可以有自己的模型(在渲染前与控制器模型合并)。
错误处理程序 可以使用 HtmxResponse 作为错误处理程序的返回类型。这样就可以很容易地声明一个全局错误处理程序,只要出现错误,它就会在某处显示一条信息:
@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 请求的正常交换行为,以避免发生交换。如果错误信息片段被声明为 "带外交换",而页面布局中又有一个空 div 来 "接收 "该 HTML 片段,那么屏幕上将只显示该片段。
Spring 安全性 库中有一个 HxRefreshHeaderAuthenticationEntryPoint,可以用来让 htmx 在身份验证失败时强制刷新整个页面。如果不使用该功能,登录页面可能会出现在你要进行的交换的地方。详细信息请参阅 htmx-authentication-error-handling 博文。
要使用它,请像这样将其添加到安全配置中:
@Bean public SecurityFilterChain filterChain(HttpSecurity http)throws Exception{ // 这里可能还有其他配置 var entryPoint = new HxRefreshHeaderAuthenticationEntryPoint(); var requestMatcher = new RequestHeaderRequestMatcher("HX-Request"); http.exceptionHandling(exception -> exception.defaultAuthenticationEntryPointFor(entryPoint, requestMatcher)); return http.build(); } |
Thymeleaf
1、标记选择器和带外交换 用于 Spring 的 Thymeleaf 集成支持为视图指定标记选择器。标记选择器将用于选择模板中需要处理的部分,而舍弃模板的其他部分。这在处理 htmx 和带外交换(Out Of Band Swaps)等只需返回部分模板的情况时非常方便。
下面的示例通过 HtmxResponse 将两个部分与一个标记选择器相结合,该标记选择器从模板用户中选择片段列表(th:fragment="list")和另一个片段计数(th:fragment="count")。
@HxRequest @GetMapping("/partials/main-and-partial") public HtmxResponse getMainAndPartial(Model model){ model.addAttribute("userCount", 5); return HtmxResponse.builder() .view("users :: list") .view("users :: count") .build(); } |
2、方言 Thymeleaf 方言拥有适当的处理器,使 Thymeleaf 能够在 htmx 相关属性中执行计算和表达。
注意 以冒号代替典型的连字符。
- hx:get:这是一个启用了 Thymeleaf 处理功能的属性
- hx-get:如果不需要 Thymeleaf 处理,这只是一个静态属性。
<div hx:get="@{/users/{id}(id=${userId})}" hx-target="#otherElement">Load user details</div> |
<div hx-get="/users/123" hx-target="#otherElement">Load user details</div> |
Thymeleaf 方言为大多数 hx-* 属性提供了相应的处理器。
- 小心在值中使用 #。如果你使用 hx:target="#mydiv",那么这将不起作用,因为 Thymeleaf 对翻译键使用 # 符号。要么使用 hx-target="#mydiv" 或 hx:target="${'#mydiv'}"
映射支持 hx:vals hx-vals 属性允许添加到将随 AJAX 请求提交的参数中。该属性的值应为 JSON 字符串。
通过添加对内联map的支持,该库使编写这样的 JSON 字符串变得更加容易。
例如,这个 Thymeleaf 表达式:
<div hx:vals="${ {id: user.id } }"></div> |
<div hx-vals="{&quot;id&quot;: 1234 }"></div> |