新闻中心

在Spring Boot中实现表单字段校验的教程

2025-12-12
浏览次数:
返回列表

在Spring Boot中实现表单字段校验的教程

本教程详细介绍了如何在spring boot应用中实现表单字段校验,涵盖了服务器端和客户端两种方法。服务器端通过引入`spring-boot-starter-validation`依赖,在模型(pojo)中使用`@notblank`、`@min`等jsr 303/380注解,并在控制器方法中结合`@valid`和`@modelattribute`进行校验。客户端则利用html5的`required`属性和合适的`input`类型提供即时反馈。结合使用这两种方法能有效提升应用的数据完整性和用户体验。

在构建Web应用时,表单数据校验是确保数据完整性和提升用户体验的关键环节。Spring Boot提供了强大的校验机制,结合HTML5的客户端校验,可以构建健壮的表单处理流程。本教程将详细阐述如何在Spring Boot项目中为表单字段添加必填校验。

一、理解校验的重要性

在用户提交表单数据时,如果某些关键字段缺失或格式不正确,可能导致后端业务逻辑错误,甚至引发应用异常(如本例中未输入价格导致的Whitelabel Error Page)。因此,无论是在客户端还是服务器端,都必须对用户输入进行严格的校验。

二、服务器端校验:使用Spring Validation

Spring Boot通过集成JSR 303/380 (Bean Validation) 规范,提供了强大的服务器端校验能力。

1. 引入校验依赖

首先,需要在pom.xml文件中添加spring-boot-starter-validation依赖。这个依赖包含了Hibernate Validator,它是JSR 303/380规范的一个实现。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2. 在模型(POJO)中定义校验规则

在代表表单数据的POJO类(例如Product类)的字段上,使用JSR 303/380提供的注解来定义校验规则。

  • @NotBlank: 适用于字符串,表示字段不能为空且不能只包含空白字符。
  • @NotNull: 适用于任何类型,表示字段不能为null。
  • @NotEmpty: 适用于字符串、集合、数组,表示字段不能为null且长度或大小不能为0。
  • @Min(value): 适用于数值类型,表示字段值必须大于或等于指定值。
  • @Max(value): 适用于数值类型,表示字段值必须小于或等于指定值。
  • @Size(min=x, max=y): 适用于字符串、集合、数组,表示字段的长度或大小必须在指定范围内。
  • @Email: 适用于字符串,表示字段必须是有效的电子邮件格式。

以下是为Product类添加校验注解的示例:

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "products")
public class Product {

    @Id
    private String id;

    @NotBlank(message = "产品名称不能为空") // 产品名称不能为空
    private String prodName;

    @NotBlank(message = "产品描述不能为空") // 产品描述不能为空
    private String prodDesc;

    @Min(value = 0, message = "产品价格不能为负数") // 产品价格不能小于0
    private Double prodPrice;

    // prodImage可以为空,如果需要必填,可以添加@NotBlank
    private String prodImage;

    public Product() {
    }

    public Product(String prodName, String prodDesc, Double prodPrice, String prodImage) {
        this.prodName = prodName;
        this.prodDesc = prodDesc;
        this.prodPrice = prodPrice;
        this.prodImage = prodImage;
    }

    // Getters and Setters
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    public String getProdName() { return prodName; }
    public void setProdName(String prodName) { this.prodName = prodName; }
    public String getProdDesc() { return prodDesc; }
    public void setProdDesc(String prodDesc) { this.prodDesc = prodDesc; }
    public Double getProdPrice() { return prodPrice; }
    public void setProdPrice(Double prodPrice) { this.prodPrice = prodPrice; }
    public String getProdImage() { return prodImage; }
    public void setProdImage(String prodImage) { this.prodImage = prodImage; }
}

注意:@Min(0.01d)可以确保价格大于0,如果允许价格为0,则使用@Min(0d)。

3. 在控制器中触发校验

在控制器方法中,将表单数据绑定到带有校验注解的POJO对象上,并通过@Valid注解触发校验。同时,为了捕获校验结果,通常会紧跟一个BindingResult参数。

import jakarta.validation.Valid;
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.web.bind.annotation.*;

@Controller
public class ProductController {

    @Autowired
    ProductRepository productRepository;

    // ... 其他方法 ...

    @RequestMapping(value = "/s*e", method = RequestMethod.POST) // 推荐使用POST方法处理表单提交
    public String s*e(@Valid @ModelAttribute Product product, BindingResult bindingResult, Model model) {
        if (bindingResult.hasErrors()) {
            // 如果有校验错误,返回到创建页面并显示错误信息
            model.addAttribute("product", product); // 将带有错误的product对象传回表单
            model.addAttribute("errors", bindingResult.getAllErrors()); // 传递所有错误信息
            return "create"; // 返回到创建产品页面
        }

        productRepository.s*e(product);
        return "redirect:/show/" + product.getId();
    }

    @RequestMapping(value = "/update", method = RequestMethod.POST) // 推荐使用POST方法处理表单提交
    public String update(@Valid @ModelAttribute Product product, BindingResult bindingResult, Model model) {
        if (bindingResult.hasErrors()) {
            // 如果有校验错误,返回到编辑页面并显示错误信息
            model.addAttribute("product", product);
            model.addAttribute("errors", bindingResult.getAllErrors());
            return "edit"; // 返回到编辑产品页面
        }

        // 确保ID不丢失
        Optional<Product> existingProduct = productRepository.findById(product.getId());
        if (existingProduct.isPresent()) {
            Product p = existingProduct.get();
            p.setProdName(product.getProdName());
            p.setProdDesc(product.getProdDesc());
            p.setProdPrice(product.getProdPrice());
            p.setProdImage(product.getProdImage());
            productRepository.s*e(p);
        } else {
            // 处理产品不存在的情况,例如重定向到错误页或产品列表
            return "redirect:/product";
        }

        return "redirect:/show/" + product.getId();
    }

    @RequestMapping("/create")
    public String create(Model model) {
        model.addAttribute("product", new Product()); // 为表单提供一个空的Product对象
        return "create";
    }

    @RequestMapping("/edit/{id}")
    public String edit(@PathVariable String id, Model model) {
        model.addAttribute("product", productRepository.findById(id).orElse(new Product())); // 确保不会返回null
        return "edit";
    }

    // ... 其他方法 ...
}

重要提示

  • 将@RequestParam替换为@ModelAttribute Product product,这样Spring会自动将表单参数绑定到Product对象的属性上。
  • @Valid注解告诉Spring对Product对象执行校验。
  • BindingResult参数必须紧跟在@Valid参数之后,它包含了校验结果,通过hasErrors()方法可以判断是否存在错误。
  • 在create和edit方法中,确保为模板提供一个Product对象,以便Thymeleaf能够正确绑定表单数据和显示错误。

4. 在Thymeleaf模板中显示校验错误

当BindingResult检测到错误时,可以将错误信息传递回前端页面进行显示。

在create.html和edit.html中,可以这样显示错误信息:

文心智能体平台 文心智能体平台

百度推出的基于文心大模型的Agent智能体平台,已上架2000+AI智能体

文心智能体平台 393 查看详情 文心智能体平台
<!-- 在表单顶部或其他位置显示所有全局错误 -->
<div th:if="${#fields.hasErrors('global')}" class="alert alert-danger">
    <p th:each="err : ${#fields.errors('global')}" th:text="${err}"></p>
</div>

<!-- 为每个字段显示具体的错误信息 -->
<div class="form-group" th:classappend="${#fields.hasErrors('prodName')} ? 'has-error'">
    <label for="prodName">Product Name:</label>
    <input type="text" class="form-control" name="prodName" th:field="*{prodName}" />
    <span th:if="${#fields.hasErrors('prodName')}" th:errors="*{prodName}" class="help-block text-danger"></span>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('prodDesc')} ? 'has-error'">
    <label for="prodDesc">Product Description</label>
    <textarea class="form-control" name="prodDesc" cols="60" rows="3" th:field="*{prodDesc}"></textarea>
    <span th:if="${#fields.hasErrors('prodDesc')}" th:errors="*{prodDesc}" class="help-block text-danger"></span>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('prodPrice')} ? 'has-error'">
    <label for="prodPrice">Product Price</label>
    <input type="number" class="form-control" name="prodPrice" th:field="*{prodPrice}" />
    <span th:if="${#fields.hasErrors('prodPrice')}" th:errors="*{prodPrice}" class="help-block text-danger"></span>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('prodImage')} ? 'has-error'">
    <label for="prodImage">Product Image URL:</label>
    <input type="url" class="form-control" name="prodImage" th:field="*{prodImage}" />
    <span th:if="${#fields.hasErrors('prodImage')}" th:errors="*{prodImage}" class="help-block text-danger"></span>
</div>

注意

  • th:field="*{prodName}" 是Thymeleaf的表单绑定语法,它会自动设置name、id和value属性。
  • th:classappend="${#fields.hasErrors('prodName')} ? 'has-error'" 会在字段有错误时添加has-error类,通常用于样式高亮。
  • th:errors="*{prodName}" 会显示该字段的错误消息。
  • th:if="${#fields.hasErrors('prodName')}" 用于条件性地显示错误消息。
  • 为了使th:field正常工作,form标签需要使用th:object="${product}"来指定绑定的对象。

修改create.html和edit.html的form标签如下:

<!-- create.html -->
<form action="/s*e" method="post" th:object="${product}">
    <!-- ... form fields ... -->
</form>

<!-- edit.html -->
<form action="/update" method="post" th:object="${product}">
    <!-- ... form fields ... -->
    <input type="hidden" name="id" th:field="*{id}" />
</form>

三、客户端校验:使用HTML5 required属性

客户端校验可以在用户提交表单之前提供即时反馈,提升用户体验并减轻服务器压力。HTML5提供了required属性以及各种input类型(如type="number"、type="url")来实现基本的客户端校验。

1. 使用 required 属性

在需要必填的input、textarea或select元素上添加required属性。

<!-- create.html 和 edit.html -->
<div class="form-group">
    <label for="prodName">Product Name:</label>
    <input type="text" class="form-control" name="prodName" th:field="*{prodName}" required />
</div>
<div class="form-group">
    <label for="prodDesc">Product Description</label>
    <textarea class="form-control" name="prodDesc" cols="60" rows="3" th:field="*{prodDesc}" required></textarea>
</div>
<div class="form-group">
    <label for="prodPrice">Product Price</label>
    <input type="number" class="form-control" name="prodPrice" th:field="*{prodPrice}" required />
</div>
<div class="form-group">
    <label for="prodImage">Product Image URL:</label>
    <input type="url" class="form-control" name="prodImage" th:field="*{prodImage}" />
</div>

注意

  • required属性是布尔属性,只需存在即生效。
  • type="number"会限制用户只能输入数字,并且浏览器会提供步进器(如果支持)。
  • type="url"会要求用户输入符合URL格式的字符串。
  • label的for属性应与input的id属性对应,以提高可访问性。为了避免冲突,建议将label的for属性值修改为与name属性值一致(或使用th:field自动生成的id)。

四、结合使用客户端与服务器端校验

最佳实践是同时使用客户端和服务器端校验:

  • 客户端校验:提供即时、友好的用户反馈,减少不必要的服务器请求。
  • 服务器端校验:作为最终防线,确保数据的完整性和安全性,因为客户端校验容易被绕过。

当客户端校验通过后,数据提交到服务器,服务器端会再次进行校验。如果服务器端校验失败,则将错误信息返回给客户端,由客户端页面显示。

五、总结

通过本教程,我们学习了如何在Spring Boot应用中实现表单字段的必填校验。核心步骤包括:

  1. 添加spring-boot-starter-validation依赖
  2. 在POJO模型中使用JSR 303/380校验注解(如@NotBlank, @Min)。
  3. 在控制器方法中使用@Valid和@ModelAttribute触发校验,并利用BindingResult处理校验结果。
  4. 在Thymeleaf模板中显示校验错误信息,并使用th:field进行表单绑定。
  5. 在HTML表单中使用required属性和合适的input类型进行客户端校验,提升用户体验。

结合使用这两种校验方法,能够有效地保障应用程序的数据质量,提高系统的健壮性和用户满意度。

以上就是在Spring Boot中实现表单字段校验的教程的详细内容,更多请关注其它相关文章!


# 观澜整合营销网络推广  # 绑定  # 为空  # 如何在  # 必填  # 能为  # 推荐使用  # 推特网站推广运营  # 淄博市关键词排名本地推投放  # 错误信息  # 武汉会计网站建设ppt  # 蓟州区网络营销推广  # 安义一站式网站建设低价  # 青岛网站建设公司哪家  # 双流seo优化员  # 盐城搜索引擎营销推广  # 肇庆seo做排名  # html  # 适用于  # 客户端  # 表单  # red  # 表单提交  # html表单  # ai  # 后端  # app  # 浏览器  # mongodb  # html5  # go  # 前端  # js 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: PHP中高效并行检查多链接状态的教程  J*aScript中赋值与自增运算符的复杂交互与执行机制  J*a中实现Go语言select通道多路复用机制  淘宝网网页版登录入口 淘宝官方网页版快捷登录  大象笔记网页版入口 印象笔记网页版登录入口  纯CSS与HTML网格布局的HTML精简策略:SVG与JS方案解析  c++如何实现一个简单的软件渲染器_c++从零开始的3D图形学  KFC套餐升级怎么获取优惠代码_KFC套餐升级活动与优惠代码获取方法  怎样使用“本地安全策略”提升Windows安全性_Secpol.msc配置指南【高手】  TikTok搜索结果不显示如何解决 TikTok搜索刷新优化方法  随机参数递归函数的基准调用次数与时间复杂度探究  Win11网速慢怎么解决 Win11网络设置优化解除限速  黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】  Tailwind CSS line-clamp 布局问题解析与修复指南  Android Studio计算器C键逻辑错误排查与修复:条件判断优化指南  漫蛙漫画网页端入口 漫蛙2官方正版漫画站点  yandex入口引擎手机版 yandex安卓版下载入口  UC浏览器如何安装插件 UC浏览器添加扩展程序详细教程【进阶】  夸克浏览器桌面版同步不了书签怎么处理 夸克浏览器跨设备同步异常解决方案  mcjs网页版流畅运行 mcjs低配电脑畅玩入口  《铁拳8》黑皮辣妹新实机:元气满满的18岁少女!  漫蛙漫画官方首页 漫蛙2漫画在线阅读入口  sublime怎么覆盖插件的默认快捷键_sublime快捷键优先级与设置  构建轻量级网站内部消息系统:Formspree 集成指南  Go语言中动态执行代码字符串的策略与实践  PowerPoint如何制作滚动字幕结尾彩蛋_PowerPoint路径动画实现平滑滚动字幕效果  CSS响应式网页如何实现主次模块比例自适应_flex-grow与flex-shrink调整  单射、满射与双射的关系 一文理清所有逻辑  Steam官网入口直达 Steam注册及登录步骤  2306选座时如何选靠窗位置_12306选座靠窗座位查看方法解析  uc浏览器网页版极速入口 uc网页浏览器网页版流畅体验  汽水音乐车机版横屏版7.1 汽水音乐车机版横屏版下载入口  Python中如何避免重复条件判断:利用数据结构实现动态逻辑  护手霜蹭到袖口上了如何清洗? 怎样避免留下一圈油印?  今日头条怎么同步内容到抖音_今日头条内容同步到抖音教程  知乎APP怎么管理已购盐选内容_知乎APP盐选内容购买记录与查看方法  使用CSS更改登录屏幕输入框中PNG图标颜色的策略与局限性  动漫岛观看全网网 动漫岛在线正版动漫入口  Safari浏览器输入栏卡顿如何解决 Safari搜索建议与缓存清理  php源码怎么看淘宝客系统_看php源码淘宝客系统技巧  NRF24L01数据传输深度解析:解决大载荷接收异常与分包策略  如何将一个大型PHP应用拆分为多个Composer包_微服务与模块化架构的Composer实践  Android Studio计算器C键功能异常排查与修复教程  自定义Bag-of-Words实现:处理带负号的词汇权重  QQ邮箱正确登录入口_QQ邮箱官方网站使用地址  QQ邮箱网页版入口页面 QQ邮箱在线登录入口官网  漫画星球免费下拉式入口 漫画星球免费漫画在线阅读网站  《刺客信条:影》PS5 Pro和Switch 2画面对比  taptap防沉迷怎么解除 taptap解除健康系统限制说明【2025最新】  qq邮箱发邮件给国外发不出去_QQ邮箱国际邮件发送失败原因与解决 

搜索