当前位置: 首页 > 知识库问答 >
问题:

Spring TemplateEngine进程在th:field上

吴鸿彩
2023-03-14
<form th:object="${customer}" xmlns:th="http://www.w3.org/1999/xhtml">
    <label>Name</label>
    <input type="text" th:field="*{name}" />
</form>
package project;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

@Controller
public class AjaxController {

    @Autowired
    private TemplateEngine templateEngine;
    private ObjectMapper objectMapper = new ObjectMapper();

    @ResponseBody
    @GetMapping(value="/form1")
    public String form1() throws JsonProcessingException {

        Customer customer = new Customer("Burger King");

        Context templateContext = new Context();
        templateContext.setVariable("customer", customer);

        AjaxResponse response = new AjaxResponse();
        response.html = templateEngine.process("form", templateContext);
        response.additionalData = "ab123";

        return objectMapper.writeValueAsString(response);
    }

    @GetMapping(value="/form2")
    public String form2(Model model) throws JsonProcessingException {

        Customer customer = new Customer("Burger King");

        model.addAttribute("customer", customer);

        return "form";
    }

    class Customer {
        private String name;

        public Customer(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    class AjaxResponse {
        public String html;
        public String additionalData;
    }
}

form1是一个崩溃的,我试图返回由thymeleaf模板解析的html代码,并在这个json响应中包含额外的数据。它在行TemplateEngine.Process(“Form”,templateContext)上崩溃;

将form.html替换为:

客户名称为:[[${Customer.name}]]

org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/form.html]")

Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Cannot process attribute '{th:field,data-th-field}': no associated BindStatus could be found for the intended form binding operations. This can be due to the lack of a proper management of the Spring RequestContext, which is usually done through the ThymeleafView or ThymeleafReactiveView (template: "form" - line 3, col 21)

更新1:将th:field替换为th:value使其工作,似乎在使用TemplateEngine.process时表单内部的th:field是产生错误的原因。

更新2:好吧,经过大量的侦探工作后,我想出了一种方法,让这个暂时工作。问题是TemplateEngine时,TymeLeaf需要IThymeleafRequestContext来处理带有表单的模板。可以像下面这样将其注入到模型中:

@Autowired
ServletContext servletContext;

private String renderToString(HttpServletRequest request, HttpServletResponse response, String viewName, Map<String, Object> parameters) {
    Context templateContext = new Context();
    templateContext.setVariables(parameters);

    RequestContext requestContext = new RequestContext(request, response, servletContext, parameters);
    SpringWebMvcThymeleafRequestContext thymeleafRequestContext = new SpringWebMvcThymeleafRequestContext(requestContext, request);
            templateContext.setVariable("thymeleafRequestContext", thymeleafRequestContext);

    return templateEngine.process(viewName, templateContext);
}

现在你用这样的方法:

@ResponseBody
@GetMapping(value="/form1")
public String form1(HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException {

    Customer customer = new Customer("Burger King");
    BindingAwareModelMap bindingMap = new BindingAwareModelMap();
    bindingMap.addAttribute("customer", customer);
    String html = renderToString(request, response, "form", bindingMap);

    AjaxResponse resp = new AjaxResponse();
    resp.html = html;
    resp.additionalData = "ab123";

    String json = objectMapper.writeValueAsString(resp);
    return json;
}

共有1个答案

魏凡
2023-03-14

欢迎来到SO。

表单标记中删除xmlns:th=“http://www.w3.org/1999/xhtml”。这不是正确的语法。这将属于html标记。

您可以在文档中找到大量清晰的示例。

 类似资料: