Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在使用SpringBean验证API验证表单时,解析Thymeleaf模板失败_Spring_Thymeleaf_Bean Validation - Fatal编程技术网

在使用SpringBean验证API验证表单时,解析Thymeleaf模板失败

在使用SpringBean验证API验证表单时,解析Thymeleaf模板失败,spring,thymeleaf,bean-validation,Spring,Thymeleaf,Bean Validation,我遵循这本书“Spring In Action第5版”的示例,但每当表单输入验证发现无效内容时,就会出现此错误 错误: Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Sun Oct 27 17:26:07 SGT 2019 There was an unexpected error (type=Internal Se

我遵循这本书“Spring In Action第5版”的示例,但每当表单输入验证发现无效内容时,就会出现此错误

错误:

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Oct 27 17:26:07 SGT 2019
There was an unexpected error (type=Internal Server Error, status=500).
An error happened during template parsing (template: "class path resource [templates/design.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/design.html]")
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241)
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100)
    at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072)
    at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362)
    at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1371)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1117)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1056)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.attoparser.ParseException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "design" - line 59, col 20)
    at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
    at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
    ... 52 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "design" - line 59, col 20)
    at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:117)
    at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95)
    at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633)
    at org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:918)
    at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleStandaloneElementEnd(TemplateHandlerAdapterMarkupHandler.java:260)
    at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleStandaloneElementEnd(InlinedOutputExpressionMarkupHandler.java:256)
    at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleStandaloneElementEnd(OutputExpressionInlinePreProcessorHandler.java:169)
    at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleStandaloneElementEnd(InlinedOutputExpressionMarkupHandler.java:104)
    at org.attoparser.HtmlElement.handleStandaloneElementEnd(HtmlElement.java:79)
    at org.attoparser.HtmlMarkupHandler.handleStandaloneElementEnd(HtmlMarkupHandler.java:241)
    at org.attoparser.MarkupEventProcessorHandler.handleStandaloneElementEnd(MarkupEventProcessorHandler.java:327)
    at org.attoparser.ParsingElementMarkupUtil.parseStandaloneElement(ParsingElementMarkupUtil.java:96)
    at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:706)
    at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301)
    ... 54 more
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'design' available as request attribute
    at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:153)
    at org.springframework.web.servlet.support.RequestContext.getBindStatus(RequestContext.java:903)
    at org.thymeleaf.spring5.context.webmvc.SpringWebMvcThymeleafRequestContext.getBindStatus(SpringWebMvcThymeleafRequestContext.java:227)
    at org.thymeleaf.spring5.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:306)
    at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:253)
    at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:227)
    at org.thymeleaf.spring5.processor.AbstractSpringFieldTagProcessor.doProcess(AbstractSpringFieldTagProcessor.java:174)
    at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74)
    ... 67 more

我在显示表单方面没有问题。所有输入字段都得到了良好的接收和处理。但每当出现验证错误,并且
处理表单方法
调用表单页面“设计”时,表单就无法解析,出现上述错误。

我试过:
1。禁用Taco.name字段上的验证
2。删除显示名称字段错误的

但它们都不起作用。


提前感谢您的帮助。

我也遇到了类似的问题。这就是我为修复它所做的

第一个-将design.html中的开头标题更改为以下内容

<form method="POST" th:object="${design}">
我希望,这会有所帮助,我不会太晚。总的来说,书中有很多类似的错误,需要修复,但是周围的社区都很好,所以不必担心


干杯

我尝试更改此代码

@PostMapping
public String processDesign(@Valid Taco taco, Errors errors)
{
    if (errors.hasErrors())
    {
        return "design";
    }

    // Save the taco design...
    // We will do this in chapter 3
    log.info("Processing design: " + taco);

    return "redirect:/orders/current";
}


它可以工作。

书中的代码有一些错误,以下是书中github的正确代码:

// tag::head[]
package tacos.web;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.slf4j.Slf4j;
import tacos.Ingredient;
import tacos.Ingredient.Type;
import tacos.Taco;

@Slf4j
@Controller
@RequestMapping("/design")
public class DesignTacoController {

//end::head[]

@ModelAttribute
public void addIngredientsToModel(Model model) {
    List<Ingredient> ingredients = Arrays.asList(
      new Ingredient("FLTO", "Flour Tortilla", Type.WRAP),
      new Ingredient("COTO", "Corn Tortilla", Type.WRAP),
      new Ingredient("GRBF", "Ground Beef", Type.PROTEIN),
      new Ingredient("CARN", "Carnitas", Type.PROTEIN),
      new Ingredient("TMTO", "Diced Tomatoes", Type.VEGGIES),
      new Ingredient("LETC", "Lettuce", Type.VEGGIES),
      new Ingredient("CHED", "Cheddar", Type.CHEESE),
      new Ingredient("JACK", "Monterrey Jack", Type.CHEESE),
      new Ingredient("SLSA", "Salsa", Type.SAUCE),
      new Ingredient("SRCR", "Sour Cream", Type.SAUCE)
    );

    Type[] types = Ingredient.Type.values();
    for (Type type : types) {
      model.addAttribute(type.toString().toLowerCase(),
          filterByType(ingredients, type));
    }
}

//tag::showDesignForm[]
  @GetMapping
  public String showDesignForm(Model model) {
    model.addAttribute("design", new Taco());
    return "design";
  }

//end::showDesignForm[]

/*
//tag::processDesign[]
  @PostMapping
  public String processDesign(Design design) {
    // Save the taco design...
    // We'll do this in chapter 3
    log.info("Processing design: " + design);

    return "redirect:/orders/current";
  }

//end::processDesign[]
 */

//tag::processDesignValidated[]
  @PostMapping
  public String processDesign(@Valid @ModelAttribute("design") Taco design, Errors errors, Model model) {
    if (errors.hasErrors()) {
      return "design";
    }

    // Save the taco design...
    // We'll do this in chapter 3
    log.info("Processing design: " + design);

    return "redirect:/orders/current";
  }

//end::processDesignValidated[]

//tag::filterByType[]
  private List<Ingredient> filterByType(
      List<Ingredient> ingredients, Type type) {
    return ingredients
              .stream()
              .filter(x -> x.getType().equals(type))
              .collect(Collectors.toList());
  }

//end::filterByType[]
// tag::foot[]
}
// end::foot[]

//标记::头[]
包装tacos.web;
导入java.util.array;
导入java.util.List;
导入java.util.stream.collector;
导入javax.validation.Valid;
导入org.springframework.stereotype.Controller;
导入org.springframework.ui.Model;
导入org.springframework.validation.Errors;
导入org.springframework.web.bind.annotation.GetMapping;
导入org.springframework.web.bind.annotation.ModelAttribute;
导入org.springframework.web.bind.annotation.PostMapping;
导入org.springframework.web.bind.annotation.RequestMapping;
导入lombok.extern.slf4j.slf4j;
进口玉米卷.配料;
进口玉米卷.配料.类型;
进口玉米卷;
@Slf4j
@控制器
@请求映射(“/design”)
公共类设计控制器{
//结束::头[]
@模型属性
公共void添加到模型(模型){
List components=Arrays.asList(
新配料(“FLTO”,“面粉玉米饼”,包装类型),
新成分(“科托”、“玉米饼”、包装类型),
新成分(“GRBF”,“碎牛肉”,类型。蛋白质),
新成分(“CARN”、“Carnitas”、类型蛋白质),
新成分(“TMTO”,“番茄丁”,蔬菜类),
新成分(“LETC”,“莴苣”,蔬菜类),
新配料(“切得”、“切达”、奶酪类型),
新配料(“杰克”,“蒙特雷杰克”,奶酪类型),
新配料(“SLSA”、“萨尔萨”、类型酱),
新配料(“SRCR”,“酸奶油”,类型:酱汁)
);
Type[]types=component.Type.values();
对于(类型:类型){
model.addAttribute(type.toString().toLowerCase(),
过滤器类型(成分、类型);
}
}
//标签::showDesignForm[]
@GetMapping
公共字符串showDesignForm(模型){
model.addAttribute(“design”,new Taco());
返回“设计”;
}
//结束::showDesignForm[]
/*
//标记::processDesign[]
@邮戳
公共字符串进程设计(设计){
//保存塔可设计。。。
//我们将在第三章中介绍
log.info(“处理设计:”+设计);
返回“重定向:/orders/current”;
}
//end::processDesign[]
*/
//标记::processDesignValidated[]
@邮戳
公共字符串processDesign(@Valid@modeldattribute(“设计”)Taco设计,错误,模型模型){
if(errors.hasErrors()){
返回“设计”;
}
//保存塔可设计。。。
//我们将在第三章中介绍
log.info(“处理设计:”+设计);
返回“重定向:/orders/current”;
}
//结束::processDesignValidated[]
//标记::filterByType[]
私有列表筛选器ByType(
列出成分、类型){
返回成分
.stream()
.filter(x->x.getType().equals(类型))
.collect(Collectors.toList());
}
//结束::filterByType[]
//标签::英尺[]
}
//结束::英尺[]
您可以从中获取所有源代码
ps:在我看来,可能的原因是
@valide Taco
将名为
Taco
的Taco对象传输到模板,而我们在tempalte中使用
设计
,因此模板无法找到导致错误的
设计。而
@modeldattribute('design')
可以将
Taco
对象重命名为
design
。另一方面,每当我们访问tacoDesign html时,我们都需要成分列表来初始化模板,这就是我们将
addingreditentstomodel
方法分离并在其上方使用
@modeldattribute
的原因。

我没有看到
th:action
Hi@vphilipnyc,没有
th:action
的表单将调用相同的请求路径。我在向我的控制器提交表单输入验证的POST请求时没有问题。谢谢您的回复。您是否尝试过在post方法中添加模型属性,如
@modeldattribute(“design”)Taco Taco
    @PostMapping
    public String processDesign(@Valid Taco taco, Errors errors)
    {
        if (errors.hasErrors())
        {
            return "design";
        }

        // Save the taco design...
        // We will do this in chapter 3
        log.info("Processing design: " + taco);

        return "redirect:/orders/current";
    }
<form method="POST" th:object="${design}">
public String processDesign(@Valid @ModelAttribute("design") Taco taco, Errors errors) {

    if (errors.hasErrors()) {
        return "design";
    }

    // this will save our Taco Design
    // log.info("Processing design: " + design);

    return "redirect:/orders/current";
}
@PostMapping
public String processDesign(@Valid Taco taco, Errors errors)
{
    if (errors.hasErrors())
    {
        return "design";
    }

    // Save the taco design...
    // We will do this in chapter 3
    log.info("Processing design: " + taco);

    return "redirect:/orders/current";
}
@PostMapping
public String processDesign(@Valid Taco taco, Errors errors)
{
    if (errors.hasErrors())
    {
        return "redirect:/design";
    }

    // Save the taco design...
    // We will do this in chapter 3
    log.info("Processing design: " + taco);

    return "redirect:/orders/current";
}
// tag::head[]
package tacos.web;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.slf4j.Slf4j;
import tacos.Ingredient;
import tacos.Ingredient.Type;
import tacos.Taco;

@Slf4j
@Controller
@RequestMapping("/design")
public class DesignTacoController {

//end::head[]

@ModelAttribute
public void addIngredientsToModel(Model model) {
    List<Ingredient> ingredients = Arrays.asList(
      new Ingredient("FLTO", "Flour Tortilla", Type.WRAP),
      new Ingredient("COTO", "Corn Tortilla", Type.WRAP),
      new Ingredient("GRBF", "Ground Beef", Type.PROTEIN),
      new Ingredient("CARN", "Carnitas", Type.PROTEIN),
      new Ingredient("TMTO", "Diced Tomatoes", Type.VEGGIES),
      new Ingredient("LETC", "Lettuce", Type.VEGGIES),
      new Ingredient("CHED", "Cheddar", Type.CHEESE),
      new Ingredient("JACK", "Monterrey Jack", Type.CHEESE),
      new Ingredient("SLSA", "Salsa", Type.SAUCE),
      new Ingredient("SRCR", "Sour Cream", Type.SAUCE)
    );

    Type[] types = Ingredient.Type.values();
    for (Type type : types) {
      model.addAttribute(type.toString().toLowerCase(),
          filterByType(ingredients, type));
    }
}

//tag::showDesignForm[]
  @GetMapping
  public String showDesignForm(Model model) {
    model.addAttribute("design", new Taco());
    return "design";
  }

//end::showDesignForm[]

/*
//tag::processDesign[]
  @PostMapping
  public String processDesign(Design design) {
    // Save the taco design...
    // We'll do this in chapter 3
    log.info("Processing design: " + design);

    return "redirect:/orders/current";
  }

//end::processDesign[]
 */

//tag::processDesignValidated[]
  @PostMapping
  public String processDesign(@Valid @ModelAttribute("design") Taco design, Errors errors, Model model) {
    if (errors.hasErrors()) {
      return "design";
    }

    // Save the taco design...
    // We'll do this in chapter 3
    log.info("Processing design: " + design);

    return "redirect:/orders/current";
  }

//end::processDesignValidated[]

//tag::filterByType[]
  private List<Ingredient> filterByType(
      List<Ingredient> ingredients, Type type) {
    return ingredients
              .stream()
              .filter(x -> x.getType().equals(type))
              .collect(Collectors.toList());
  }

//end::filterByType[]
// tag::foot[]
}
// end::foot[]