spring - th:field 上的 Spring TemplateEngine 进程错误
问题描述
我正在使用 Spring 用 Java 开发一个 Web 应用程序。
该应用程序在 javascript 中包含 Ajax 调用,该调用请求 html 代码,然后将其插入到 html 文档中。
为了将百里香模板处理成字符串,我正在使用 TemplateEngine process(..) 方法。
当 thymeleaf 模板包含表单时,我遇到了错误。
我的示例代码:
表单.html:
<form th:object="${customer}" xmlns:th="http://www.w3.org/1999/xhtml">
<label>Name</label>
<input type="text" th:field="*{name}" />
</form>
AjaxController.java:
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); 线上崩溃。
form1 在将 form.html 替换为:
客户名称是:[[${customer.name}]]
这使我得出结论,它是表单标签和 th:object 导致它崩溃。
form2 按预期工作,但没有任何方法来操纵 thymeleaf 返回值。证明thymeleaf模板本身是有效的。
整个错误输出有点太大,无法粘贴到这里,但是:
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)
我的问题是:这是 Spring 框架中的错误吗?或者如果不是那么我做错了什么?
更新 1:用 th:value 替换 th:field 使其工作,似乎 th:field 在使用 TemplateEngine .process 时表单内是产生错误的原因。
更新 2:好的,经过大量侦探工作后,我想出了一种技巧来暂时完成这项工作。问题是 thymeleaf 需要 IThymeleafRequestContext 来处理带有表单的模板,当 TemplateEngine .process 运行时,它将不会被创建。可以将其注入您的模型中,如下所示:
@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;
}
我不会将此作为答案,因为我认为没有任何理由打算以这种方式使用它。我正在与春天的人们沟通,以获得真正的解决方案。
解决方案
推荐阅读
- mysql - 检查mysql中是否存在记录
- cryptography - Airflow Broken DAG 错误 - 加密版本与加载的共享对象不匹配
- python - 如何在列表中找到特定模式?
- python - 找出保存的 Tensorflow h5 模型的架构
- python - 我该如何尝试,除了:阻止此错误?
- python - Tkinter 窗口在启动进度条后挂起
- python - 有人可以解释一下“d.maximumDifference”最终是如何工作的吗?就像我们甚至可以在类内的函数内调用变量吗?
- c++ - 如何遍历 C++ 中对象的指针列表
- python - 将两个列表按行合并为一个
- reactjs - 如何在反应中将对象列表添加到 useState([])?