SpringBoot实战(九)之Validator
表单验证,是最为常见的,今天演示的是利用hibernate-validtor进行校验,有的时候,虽然前端方面通过jQuery或者require.js校验框架进行校验,可以减轻服务器的压力和改善用户体验,但是比如第三方请求接口方面也需要校验,在Controller里面套着一大堆if-elseif-else等等,两层嵌套还好,三层或者三层以上就不好了,日子久了继续嵌套,就会导致后面变得难以维护。我有一个朋友在一家国企,据他所说,他遇到的最烂代码是if-else if里面套者十几层,而且一个类的代码居然上千行,正常合理情况,当达到上千行代码就要考虑抽象继承或者多态,再设计模式了。设计模式,我不懂,只是了解,这里就不提了,后续博文会讲到设计模式的。
这里说Validator的意义在于,通过注解减少if-else等重复判断代码,从而使Java代码行数减少,因为加载类中的代码是需要时间的。代码行数减少,意味着加载时间减少,从而提高代码效率。
演示示例如下:
一、导入maven依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <? 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/
会出现对应的表单页面,输入不合法会出现提示,表示验证成功
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述