thymeleaf + spring-boot 验证错误未显示在 html 上
Posted
技术标签:
【中文标题】thymeleaf + spring-boot 验证错误未显示在 html 上【英文标题】:thymleaf + spring-boot Validaiton error not displaying on html 【发布时间】:2021-11-17 00:46:39 【问题描述】:我可以在控制台上看到验证错误,但百里香模板没有显示错误。它应该在百里香模板上显示错误。 我正在使用 Spring Boot 2.5.4
提前致谢。
我的 Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.ttl</groupId>
<artifactId>cps-admission-portal</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cps-admission-portal</name>
<description>CPS Admission Portal</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.0.0-2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
我的控制器
package com.ttl.cpsadmissionportal.controller;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.validation.Valid;
import javax.validation.executable.ValidateOnExecution;
import javax.xml.bind.annotation.XmlRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
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 org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.ttl.cpsadmissionportal.model.AdmissionForm;
import com.ttl.cpsadmissionportal.service.CampusService;
import com.ttl.cpsadmissionportal.service.OfferProgramService;
import com.ttl.cpsadmissionportal.serviceimpl.AdmissionFormServiceImple;
@Controller
public class AdmissionFormController
@Autowired
private OfferProgramService offerProgramService;
@Autowired
private AdmissionFormServiceImple admissionFormServiceImple;
@Autowired
private CampusService campusService;
@GetMapping("admissionform")
public String viewAdmissionForm(Model model)
AdmissionForm admissionForm = new AdmissionForm();
model.addAttribute("admissionForm",admissionForm);
model.addAttribute("listCampuses",campusService.getAllCampuses());
return "admissionform";
@PostMapping("saveadmissionform")
public String saveAdmissionForm(@Valid @ModelAttribute("admissionForm") AdmissionForm admissionForm
,RedirectAttributes redirectAttributes
, BindingResult bindingResulted)
if (bindingResulted.hasErrors())
System.out.println("ERROR IN VALIDATION");
return "admissionform";
admissionFormServiceImple.addAdmissionForm(admissionForm);
redirectAttributes.addAttribute("candidateName",admissionForm.getCandidateName());
redirectAttributes.addAttribute("refNbr",admissionForm.getRefNbr());
return "redirect:/thankyou";
@GetMapping("thankyou")
public String thankyou()
return "thankyou";
型号
package com.ttl.cpsadmissionportal.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import com.sun.istack.NotNull;
@Entity
@Table(name="ADMISSION_FORM", schema = "UCP")
public class AdmissionForm
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "af_id_gen")
@SequenceGenerator(name="af_id_gen", sequenceName="SEQ_AF_ID", schema = "UCP",allocationSize=1)
@Column(name="AF_ID")
private int afId;
@Column(name="OP_ID")
private int opId;
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ref_nbr_gen")
@SequenceGenerator(name="ref_nbr_gen", sequenceName="SEQ_REF_NBR", schema = "UCP",allocationSize=1)
@Column(name="REF_NBR")
private String refNbr;
@NotEmpty
@NotNull
@Size(min=10,max=50)
@Column(name="CANDIDATE_NAME")
private String candidateName;
@NotEmpty
@NotNull
@Column(name="GENDER_IND")
private String genderInd;
@NotEmpty
@NotNull
@Column(name="FATHER_NAME")
private String fatherName;
@NotEmpty
@NotNull
@Column(name="RELATIONSHIP_IND")
private String relationshipInd;
@NotEmpty
@NotNull
@Column(name="PARENT_CNIC_NBR")
private String parentCnicNbr;
@NotEmpty
@NotNull
@Column(name="PARENT_CONTACT_NBR")
private String parentContactNbr;
@NotEmpty
@NotNull
@Column(name="STUDENT_CNIC_NBR")
private String studentCnicNbr;
@NotEmpty
@NotNull
@Column(name="STUDENT_CONTACT_NBR")
private String studentContactNbr;
@NotEmpty
@NotNull
@Email
@Column(name="STUDENT_EMAIL_ADD")
private String studentEmailAdd;
@Column(name="ADDRESS")
private String address;
public int getAfId()
return afId;
public void setAfId(int afId)
this.afId = afId;
public int getOpId()
return opId;
public void setOpId(int opId)
this.opId = opId;
public String getRefNbr()
return refNbr;
public void setRefNbr(String refNbr)
this.refNbr = refNbr;
public String getCandidateName()
return candidateName;
public void setCandidateName(String candidateName)
this.candidateName = candidateName;
public String getGenderInd()
return genderInd;
public void setGenderInd(String genderInd)
this.genderInd = genderInd;
public String getFatherName()
return fatherName;
public void setFatherName(String fatherName)
this.fatherName = fatherName;
public String getRelationshipInd()
return relationshipInd;
public void setRelationshipInd(String relationshipInd)
this.relationshipInd = relationshipInd;
public String getParentCnicNbr()
return parentCnicNbr;
public void setParentCnicNbr(String parentCnicNbr)
this.parentCnicNbr = parentCnicNbr;
public String getParentContactNbr()
return parentContactNbr;
public void setParentContactNbr(String parentContactNbr)
this.parentContactNbr = parentContactNbr;
public String getStudentCnicNbr()
return studentCnicNbr;
public void setStudentCnicNbr(String studentCnicNbr)
this.studentCnicNbr = studentCnicNbr;
public String getStudentContactNbr()
return studentContactNbr;
public void setStudentContactNbr(String studentContactNbr)
this.studentContactNbr = studentContactNbr;
public String getStudentEmailAdd()
return studentEmailAdd;
public void setStudentEmailAdd(String studentEmailAdd)
this.studentEmailAdd = studentEmailAdd;
public String getAddress()
return address;
public void setAddress(String address)
this.address = address;
我的百里香模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Admission Form</title>
<link th:rel="stylesheet"
th:href="@/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css " />
<link rel="stylesheet" href="sb-admin-2.css" />
<link th:href="@/css/sb-admin-2.css" rel="stylesheet" />
</head>
<body>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<form action="#" role="form" th:action="@/saveadmissionform"
th:object="$admissionForm" method="post">
<div class="container-fluid mt-n10">
<div class="card card-header-actions mb-4">
<div class="card-body">
<div class="row mt-2 mb-2">
<div class="row">
<div class="col-md-12">
<h2 class="heading">Personal Info</h2>
</div>
</div>
<div class="row mt-2 mb-2">
<div class="col-md-3">
<div class="form-group">
<label for=candidateName>Full Name <span style="color: red">
*</span></label> <input type="text" th:field="*candidateName"
class="form-control form-control-solid" id="candidateName"
placeholder="Enter Full Name" required>
<span th:if="$#fields.hasErrors('candidateName')" th:errors="*candidateName">Full name error</span>
</div>
</div>
</form>
</body>
</html>
出现以下错误,但应在候选人姓名前显示错误。
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Sep 23 20:14:01 PKT 2021
There was an unexpected error (type=Bad Request, status=400).
Validation failed for object='admissionForm'. Error count: 1
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'admissionForm' on field 'candidateName': rejected value [a]; codes [Size.admissionForm.candidateName,Size.candidateName,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [admissionForm.candidateName,candidateName]; arguments []; default message [candidateName],50,10]; default message [size must be between 10 and 50]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:175)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:170)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1064)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1726)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
【问题讨论】:
【参考方案1】:BindingResult
必须直接跟在控制器方法中的 ModelAttribute
参数之后。
这应该可行:
public String saveAdmissionForm(@Valid @ModelAttribute("admissionForm")
AdmissionForm admissionForm,
BindingResult bindingResulted,
RedirectAttributes redirectAttribute)
见Cannot get validation working with Spring Boot and Thymeleaf
【讨论】:
以上是关于thymeleaf + spring-boot 验证错误未显示在 html 上的主要内容,如果未能解决你的问题,请参考以下文章
Spring-boot,thymeleaf 加载上传的图片,无需重启应用服务器
Spring-Boot + Spring-MVC + Thymeleaf + Apache Tiles
Thymeleaf 无法检测到 spring-boot 项目中的模板