表单验证,是最为常见的,今天演示的是利用hibernate-validtor进行校验,有的时候,虽然前端方面通过jQuery或者require.js校验框架进行校验,可以减轻服务器的压力和改善用户体验,但是比如第三方请求接口方面也需要校验,在Controller里面套着一大堆if-elseif-else等等,两层嵌套还好,三层或者三层以上就不好了,日子久了继续嵌套,就会导致后面变得难以维护。我有一个朋友在一家国企,据他所说,他遇到的最烂代码是if-else if里面套者十几层,而且一个类的代码居然上千行,正常合理情况,当达到上千行代码就要考虑抽象继承或者多态,再设计模式了。设计模式,我不懂,只是了解,这里就不提了,后续博文会讲到设计模式的。
这里说Validator的意义在于,通过注解减少if-else等重复判断代码,从而使Java代码行数减少,因为加载类中的代码是需要时间的。代码行数减少,意味着加载时间减少,从而提高代码效率。
演示示例如下:
一、导入maven依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework</groupId> <artifactId>gs-validating-form-input</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.4.1.Final</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-el</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
二、编写实体
package hello; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; public class PersonForm { @NotNull @Size(min=2, max=30) private String name; @NotNull @Min(18) private Integer age; public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String toString() { return "Person(Name: " + this.name + ", Age: " + this.age + ")"; } }
三、编写Controller
package hello; import java.util.List; import javax.validation.Valid; import org.springframework.format.FormatterRegistry; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.Validator; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Controller public class WebController implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/results").setViewName("results"); } @GetMapping("/") public String showForm(PersonForm personForm) { return "form"; } @PostMapping("/") public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return "form"; } return "/results"; } @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> arg0) { // TODO Auto-generated method stub } @Override public void addCorsMappings(CorsRegistry arg0) { // TODO Auto-generated method stub } @Override public void addFormatters(FormatterRegistry arg0) { // TODO Auto-generated method stub } @Override public void addInterceptors(InterceptorRegistry arg0) { // TODO Auto-generated method stub } @Override public void addResourceHandlers(ResourceHandlerRegistry arg0) { // TODO Auto-generated method stub } @Override public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> arg0) { // TODO Auto-generated method stub } @Override public void configureAsyncSupport(AsyncSupportConfigurer arg0) { // TODO Auto-generated method stub } @Override public void configureContentNegotiation(ContentNegotiationConfigurer arg0) { // TODO Auto-generated method stub } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer arg0) { // TODO Auto-generated method stub } @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> arg0) { // TODO Auto-generated method stub } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> arg0) { // TODO Auto-generated method stub } @Override public void configurePathMatch(PathMatchConfigurer arg0) { // TODO Auto-generated method stub } @Override public void configureViewResolvers(ViewResolverRegistry arg0) { // TODO Auto-generated method stub } @Override public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> arg0) { // TODO Auto-generated method stub } @Override public void extendMessageConverters(List<HttpMessageConverter<?>> arg0) { // TODO Auto-generated method stub } @Override public MessageCodesResolver getMessageCodesResolver() { // TODO Auto-generated method stub return null; } @Override public Validator getValidator() { // TODO Auto-generated method stub return null; } }
四、编写html代码
form.html
<html xmlns:th="http://www.thymeleaf.org"> <body> <form action="#" th:action="@{/}" th:object="${personForm}" method="post"> <table> <tr> <td>Name:</td> <td><input type="text" th:field="*{name}" /></td> <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</td> </tr> <tr> <td>Age:</td> <td><input type="text" th:field="*{age}" /></td> <td th:if="${#fields.hasErrors('age')}" th:errors="*{age}">Age Error</td> </tr> <tr> <td><button type="submit">Submit</button></td> </tr> </table> </form> </body> </html>
result.html
<html xmlns:th="http://www.thymeleaf.org"> <body> Congratulations! You are old enough to sign up for this site. </body> </html>
五、编写配置文件
application.properties
server.port=8080
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.check-template-location=true
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.mode=HTML5
六、编写启动类
package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } }
最后运行main方法,在浏览器输入localhost:8080/
会出现对应的表单页面,输入不合法会出现提示,表示验证成功