[spring]SpringMVC&Thymeleaf(下)

csdn推荐

[spring] Spring MVC & Thymeleaf(下)

上篇笔记讲了一下怎么使用 thymeleaf 作为 HTML 模板,与 Spring MVC 进行沟通,这里主要说一下验证的部分

常用表单验证

一些 Spring MVC 内置的常用验证注解如下:

AnnotationDescription

@NotNull

Ensures the annotated field is not null.

@NotEmpty

Ensures the annotated field is not empty. This applies to Strings, Collections, Maps, and arrays.

@NotBlank

Ensures the annotated string field is not null or empty.

@Size

Validates that the annotated field has a size within the specified bounds.

@Min

Validates that the annotated field has a value no smaller than the specified minimum.

@Max

Validates that the annotated field has a value no larger than the specified maximum.

@Email

Validates that the annotated field is a valid email address.

@Pattern

Validates that the annotated field matches the specified regular expression.

@Past

Validates that the annotated field contains a date in the past.

@Future

Validates that the annotated field contains a date in the future.

@Positive

Validates that the annotated field is a positive number.

@PositiveOrZero

Validates that the annotated field is a positive number or zero.

@Negative

Validates that the annotated field is a negative number.

@NegativeOrZero

Validates that the annotated field is a negative number or zero.

@Digits

Validates that the annotated field is a number within the specified integer and fraction digits.

@DecimalMin

Validates that the annotated field is a decimal number no smaller than the specified minimum.

@DecimalMax

Validates that the annotated field is a decimal number no larger than the specified maximum.

@AssertTrue

Validates that the annotated field is true.

@AssertFalse

Validates that the annotated field is false.

@CreditCardNumber

Validates that the annotated field is a valid credit card number.

这个列表只是做个参考,具体用法大同小异,后面会选几个比较常用的实现一下,以及会实现自定义验证

设置开发环境

依旧从 spring.io 下载,具体配置如下:

和上里的内容比起来,这里多了一个 Validator

必填选项

这里的实现步骤如下:

创建一个 DAO,并添加验证规则

实现代码如下:

package com.example.springdemo.mvc;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Data
public class Customer {
    private String firstName;
    @NotNull(message = "is required")
    @Size(min = 1, message = "is required")
    private String lastName;
}

⚠️:这里的 @NotNull 和 @Size 是从 jakarta.validation.constraints 中导入的。这里的 message 就是验证失败后,会返回的错误信息

:这里其实有一个小问题,就是如果用户提供的数据是空的字符串,那么也是可以通过验证的。空字符串的处理在后面会提到

添加 controller

package com.example.springdemo.mvc;
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class CustomerController {
    @GetMapping("/")
    public String showForm(Model model) {
        model.addAttribute("customer", new Customer());
        return "customer-form";
    }
    @PostMapping("/processForm")
    public String processForm(
            @Valid @ModelAttribute("customer") Customer customer,
            BindingResult bindingResult
    ) {
        if (bindingResult.hasErrors()) {
            return "customer-form";
        }
        return "customer-confirmation";
    }
}

这里其实直接把第 4 步也做了,后面会具体提一下实现的功能

添加 HTML 和验证支持

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>Customer Registration Form</title>
    <style>
      .error {
        color: red;
      }
    </style>
  </head>
  <body>
    <i>Fill out the form</i>
    <br /><br />
    <form
      th:action="@{/processForm}"
      th:object="${customer}"
      method="post"
      autocomplete="off"
    >
      <label>
        First Name:
        <input type="text" th:field="*{firstName}" />
      </label>
      <br /><br />
      <label>
        Last Name (*):
        <input type="text" th:field="*{lastName}" />
      </label>
      
      <span
        th:if="#{fields.hasErrors('lastName')}"
        th:errors="*{lastName}"
        class="error"
      ></span>
      <br /><br />
      <input type="submit" value="Submit" />
    </form>
    <script src="http://localhost:35729/livereload.js"></script>
  </body>
</html>

这里的代码和之前实现的 thymeleaf 没有什么特别大的区别,唯一的差别在于用于显示错误信息的 span 这部分

th:if 的用法之前已经提过,这里不多赘述

#fields 是一个内置的工具对象,可以用来检查哪个属性有错。在这个情况下,它会检查 lastName 是否验证失败

th:errors="*{lastName}" 是一个没见过的 thymeleaf 语法,这里主要就是将报错信息渲染到 DOM 中

class="error" 用于添加 css

在 controller 中实现验证

@PostMapping("/processForm")
      public String processForm(
              @Valid @ModelAttribute("customer") Customer customer,
              BindingResult bindingResult
      ) {
          if (bindingResult.hasErrors()) {
              return "customer-form";
          }
          return "customer-confirmation";
      }

这里着重讲一下这部分的代码

@Valid 注解代表 customer 对象包含验证需要被执行,这也是在 DAO 层中,在 lastName 上添加的验证

BindingResult bindingResult 也是通过依赖注入获取的,这个对象会绑定所有的验证结果

创建 confirm 页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8" />
    <title>Customer Confirmation</title>
  </head>
  <body>
    The customer is confirmed:
    <span th:text="${customer.firstName + ' ' + customer.lastName}"></span>
    <script src="http://localhost:35729/livereload.js"></script>
  </body>
</html>

这部分没什么特殊的,之前已经写过很多遍了

具体的实现效果如下:

@InitBinder

上面的实现中,如果用户输入空白的字符串,那么也会通过检查。因此这里会使用 @InitBinder 去对数据进行一个自定义处理(预处理)

具体的使用方式如下:

public class CustomerController {
    @InitBinder
    public void initBinder(WebDataBinder dataBinder) {
        StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);
        dataBinder.registerCustomEditor(String.class, stringTrimmerEditor);
    }
}

这部分其实没有什么特别复杂的,WebDataBinder 是一个数据绑定器,传入的参数也是需要处理的数据类型,与处理的方式。如这里的实现就是对所有输入的字符串进行一个处理,处理的方式就是将空格去除

需要注意的就是,这部分的代码需要在 controller 中实现,这里的代码就是在 CustomerController 中实现的

@Min & @Max

@Min & @Max 也是两个常见的对数字进行的验证,实现方法如下:

@Data
public class Customer {
    @Min(value = 0, message = "must be greater than or equals to 0")
    @Max(value = 10, message = "must be smaller than or equals to 10")
    private int freePasses;
}

这里不需要修改 controller,HTML 模板的修改部分如下:

<label>
  Free passes:
  <input type="text" th:field="*{freePasses}" />
</label>

<span
  th:if="#{fields.hasErrors('freePasses')}"
  th:errors="*{freePasses}"
  class="error"
></span>
<br /><br />

实现效果:

regex,正则

验证同样可以接受正则,这里只做一个比较简单的处理方式,即邮政编码的处理,可以包含数字和大小写字母

DAO 修改如下:

    @Pattern(regexp = "^[a-zA-Z0-9]{5}", message = "only 5 chars/digits")
    private String postalCode;

同样不需要修改 controller,只需要更新 HTML 模板:

<label>
  Postal Code
  <input type="text" th:field="*{postalCode}" />
</label>

<span
  th:if="#{fields.hasErrors('postalCode')}"
  th:errors="*{postalCode}"
  class="error"
></span>

这是 confirmation 的修改:

Postal Code: <span th:text="${customer.postalCode}"></span>

显示效果:

数字的一些问题 @NotNull

数字类型使用使用 @NotNull 会造成一点问题,如:

这是因为 Java 的数据类型转换问题,其中一个解决方式可以吧声明的 private int freePasses; 换成 private Integer freePasses;,这样 Integer 这个包装类可以自动实现数据转换的处理

字符串

另一个可能会遇到的问题,就是在处理数字的输入框中输入字符串,如:

这种情况下,Spring 也是没有办法正常转换类型,这里可以解决的方法是在 resource 文件夹下,新建一个 messages.properties 文件

这是一个特殊的 properties 文件,Spring 会自动扫描并读取这个文件,并可以通过这个文件信息进行处理。除了报错信息外,它也经常被用于 i18n 和 l10n

配置方式如下:

typeMismatch.customer.freePasses=Invalid number

实现效果:

⚠️:使用这个配置文件也可以覆盖上面 @NotNull 带来的问题,主要因为空字符串也不是一个合法的数字,所以这个错误也会被 typeMismatch 所捕获

自定义验证

Spring 提供的验证肯定没有办法满足所有的需求,这个情况下就需要开发手动实现自定义验证

具体的实现步骤如下:

后面的步骤,就是更新 HTML 模板的部分就省略了,最终的实现效果如下:

文章来源:https://blog.csdn.net/weixin_42938619/article/details/139895449



微信扫描下方的二维码阅读本文

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容