Spring Boot中Thymeleaf和htmx助手工具庫

banq發表於2024-04-16


該專案提供註釋、輔助類和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(<font>"/users")
public String htmxRequest(){
    return
"partial";
}

此外,如果要將控制器方法的呼叫限制在特定觸發元素上,可以將 HxRequestvalue 設定為元素的 ID 或名稱。如果想更明確,可使用 HxRequesttriggerId 或 HxRequesttriggerName

@HxRequest(<font>"my-element")
@GetMapping(
"/users")
public String htmxRequest(){
    return
"partial";
}

如果您想將控制器方法的呼叫限制為已定義的特定目標元素,請使用 HxRequesttarget

@HxRequest(target = <font>"my-target")
@GetMapping(
"/users")
public String htmxRequest(){
    return
"partial";
}

使用 HtmxRequest 訪問 htmx 傳送的 HTTP 請求頭
HtmxRequest 物件可用作控制器方法引數,以訪問各種 htmx 請求頭。

@HxRequest
@GetMapping(<font>"/users")
public String htmxRequest(HtmxRequest htmxRequest) {
    if(htmxRequest.isHistoryRestoreRequest()){
       
// do something<i>
    }
    return
"partial";
}

響應標頭
有兩種方法可以在控制器方法上設定 htmx 響應頭。

  • 第一種是使用註解,例如 @HxTrigger,
  • 第二種是使用 HtmxResponse 類作為控制器方法的返回型別。

目前支援以下註解:

  • @HxRefresh
  • @HxTrigger

示例
如果希望 htmx 在處理完響應後觸發一個事件,可以使用註解 @HxTrigger 來設定必要的響應頭 HX-Trigger。

@HxRequest
@HxTrigger(<font>"userUpdated") // htmx 將觸發 "userUpdated "事件<i>
@GetMapping(
"/users")
public String hxUpdateUser(){
    return
"partial";
}

如果想以更靈活的方式實現相同的功能,可以在控制器方法中使用 HtmxResponse 作為返回型別。

@HxRequest
@GetMapping(<font>"/users")
public HtmxResponse hxUpdateUser(){
    return HtmxResponse.builder()
        .trigger(
"userUpdated") // the event 'userUpdated' will be triggered by htmx<i>
        .view(
"partial")
        .build();
}

Out Of Band Swaps
htmx 支援透過在單個響應中返回多個部分來更新多個目標,這就是所謂的帶外交換 Out Of Band Swaps
為此,請使用 HtmxResponse 作為控制器方法的返回型別,並在其中新增多個模板。

@HxRequest
@GetMapping(<font>"/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(<font>"/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(<font>"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{
    <font>// 這裡可能還有其他配置<i>

    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(<font>"/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 處理,這只是一個靜態屬性。

例如,這個 Thymeleaf 模板:
<div hx:get=<font>"@{/users/{id}(id=${userId})}" hx-target="otherElement">Load user details</div>

將渲染輸出為:
<div hx-get=<font>"/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=<font>"${ {id: user.id } }"></div>

將渲染輸出為:
<div hx-vals=<font>"{&amp;quot;id&amp;quot;: 1234 }"></div>

(鑑於 user.id 的值為 1234)

 

相關文章