绑定结果给出 Whitelabel Error Page

Posted

技术标签:

【中文标题】绑定结果给出 Whitelabel Error Page【英文标题】:Binding result gives Whitelabel Error Page 【发布时间】:2021-03-01 16:30:09 【问题描述】:

我有一个 thymeleaf 表单,我可以在其中将子类别添加到父类别:

<div th:if="$parentCategories.size() == 0">
        <span>There are no categories, please, add some categories!</span>
    </div>
    <div th:unless="$parentCategories.size() == 0">
        <label for="subcategoryForm">Add a subcategory</label>
        <form id="subcategoryForm" th:action="@/category/add-subcategory" th:object="$category" method="post">

            <label for="name">Category name</label>
            <input id="name" type="text" th:field="*categoryName"/>
            <span th:if="$#fields.hasErrors('categoryName')" th:errors="*categoryName" th:errorclass="error"></span>

            <label for="selectParentCategory">Enter a parent category</label>
            <select id="selectParentCategory" th:field="*parentCategoryName">
                <option th:each="category : $parentCategories"
                        th:value="$category.categoryName"
                        th:text="$category.categoryName"/>
                <span th:if="$#fields.hasErrors('parentCategoryName')" th:errors="*parentCategoryName" th:errorclass="error"></span>
            </select>

            <button type="submit">Add category</button>
        </form>
    </div>

我有一个 CategoryDTO:

@Setter
@Getter
public class CategoryDTO 

    @CategoryValidator
    private String categoryName;

    @ParentCategoryValidator
    private String parentCategoryName;


@CategoryValidator 由 CategoryValidatorImpl 验证:

@Autowired
    private CategoryRepository categoryRepository;

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) 
        if(value.isBlank())
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate("categoryDTO.blank").addConstraintViolation();
            return false;
        

        Optional<Category> optionalCategory = categoryRepository.findByName(value);
        if (optionalCategory.isPresent()) 
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate("categoryDTO.alreadyExists").addConstraintViolation();
            return false;
        

        Pattern pattern = Pattern.compile("[a-zA-Z\\s]*");
        Matcher matcher = pattern.matcher(value);
        if (!matcher.matches()) 
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate("categoryDTO.name.invalid").addConstraintViolation();
            return false;
        

        return true;
    

以及 CategoryController 的一部分:

@GetMapping("/subcategory-form")
public String getSubcategoryForm(Model model)
    List<CategoryDTO> listOfParentCategories = categoryService.getParentCategories();
    model.addAttribute("category", new CategoryDTO());
    model.addAttribute("parentCategories", listOfParentCategories);
    return "add-subcategory-form";


@PostMapping("/add-subcategory")
public String addSubcategory(@Valid @ModelAttribute("category") CategoryDTO categoryDTO, BindingResult bindingResult)
   

 if(bindingResult.hasErrors())
            return "add-subcategory-form";
        
        categoryService.add(categoryDTO);
        return "redirect:/category/subcategory-form";
      

在输入字段中,当我输入空白时,验证器会使用控制器中的 hasErrors 正确发现它,但是当我在发现空白并返回 false 后返回表单时,它会给出:

Whitelabel 错误页面 此应用程序没有明确的映射 /error,因此您将其视为后备。

EET 2020 年 11 月 18 日星期三 13:45:26 出现意外错误 (类型=内部服务器错误,状态=500)。期间发生错误 模板解析(模板:“类路径资源 [模板/add-subcategory-form.html]") org.thymeleaf.exceptions.TemplateInputException:发生错误 在模板解析期间(模板:“类路径资源 [模板/add-subcategory-form.html]") 在 org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241) 在 org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100) 在 org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666) 在 org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) 在 org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) 在 org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362) 在 org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189) 在 org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373) 在 org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118) 在 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057) 在 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) 在 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) 在 org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:652) 在 org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:733) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) 在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) 在 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) 在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) 在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) 在 org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) 在 org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) 在 org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) 在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) 在 org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 在 java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) 在 java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) 在 org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 在 java.base/java.lang.Thread.run(Thread.java:834) 引起: org.attoparser.ParseException:评估 SpringEL 的异常 表达式:“parentCategories.size() == 0”(模板: “添加子类别形式” - 第 13 行,第 10 列)在 org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393) 在 org.attoparser.MarkupParser.parse(MarkupParser.java:257) 在 org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230) ... 52 更多原因: org.thymeleaf.exceptions.TemplateProcessingException:异常 评估 SpringEL 表达式:“parentCategories.size() == 0” (模板:“add-subcategory-form” - 第 13 行,第 10 列) org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:290) 在 org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166) 在 org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66) 在 org.thymeleaf.standard.expression.Expression.execute(Expression.java:109) 在 org.thymeleaf.standard.expression.Expression.execute(Expression.java:138) 在 org.thymeleaf.standard.expression.Expression.execute(Expression.java:125) 在 org.thymeleaf.standard.processor.StandardIfTagProcessor.isVisible(StandardIfTagProcessor.java:59) 在 org.thymeleaf.standard.processor.AbstractStandardConditionalVisibilityTagProcessor.doProcess(AbstractStandardConditionalVisibilityTagProcessor.java:61) 在 org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74) 在 org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) 在 org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633) 在 org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314) 在 org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleOpenElementEnd(TemplateHandlerAdapterMarkupHandler.java:304) 在 org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:278) 在 org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleOpenElementEnd(OutputExpressionInlinePreProcessorHandler.java:186) 在 org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:124) 在 org.attoparser.HtmlElement.handleOpenElementEnd(HtmlElement.java:109) 在 org.attoparser.HtmlMarkupHandler.handleOpenElementEnd(HtmlMarkupHandler.java:297) 在 org.attoparser.MarkupEventProcessorHandler.handleOpenElementEnd(MarkupEventProcessorHandler.java:402) 在 org.attoparser.ParsingElementMarkupUtil.parseOpenElement(ParsingElementMarkupUtil.java:159) 在 org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:710) 在 org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301) ... 54 更多原因: org.springframework.expression.spel.SpelEvaluationException:EL1011E: 方法调用:尝试在空上下文对象上调用方法 size() 在 org.springframework.expression.spel.ast.MethodReference.throwIfNotNullSafe(MethodReference.java:154) 在 org.springframework.expression.spel.ast.MethodReference.getValueRef(MethodReference.java:83) 在 org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:70) 在 org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:91) 在 org.springframework.expression.spel.ast.OpEQ.getValueInternal(OpEQ.java:42) 在 org.springframework.expression.spel.ast.OpEQ.getValueInternal(OpEQ.java:32) 在 org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:112) 在 org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:337) 在 org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:263) ... 75 更多

问题是,对于我必须添加父类别的另一种形式,如果我添加一个空白,它会返回百里香叶并打印我写的错误消息,但我无法弄清楚这一点表格。

【问题讨论】:

【参考方案1】:

stacktrace 对问题有以下提示:

评估 SpringEL 表达式的异常:“parentCategories.size() == 0”(模板:“add-subcategory-form” - 第 13 行,第 10 列)

和:

试图在空上下文对象上调用方法 size()

这意味着 parentCategories 在 Thymeleaf 上下文中不再存在。

出现错误时需要在模型中重新添加parentCategories

@PostMapping("/add-subcategory")
public String addSubcategory(@Valid @ModelAttribute("category") CategoryDTO categoryDTO, BindingResult bindingResult) 
   
        if(bindingResult.hasErrors())
            List<CategoryDTO> listOfParentCategories = categoryService.getParentCategories();
            model.addAttribute("parentCategories", listOfParentCategories);
            return "add-subcategory-form";
        
        categoryService.add(categoryDTO);
        return "redirect:/category/subcategory-form";
      

【讨论】:

不幸的是,问题仍然存在:/ 在这种情况下,你能举一个在某处重现问题的例子吗?

以上是关于绑定结果给出 Whitelabel Error Page的主要内容,如果未能解决你的问题,请参考以下文章

whitelabel error page调用哪个类

在 Spring Boot Web 应用程序中刷新后的 Whitelabel 错误页面

Whitelabel 错误页面 - 应用程序没有 /error 的显式映射

springboot的页面出现Whitelabel Error Page

Whitelabel Error Page图片不能加载的原因

SpringBoot接口服务处理Whitelabel Error Page