我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SpringBoot参数验证的技巧有哪些

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SpringBoot参数验证的技巧有哪些

这篇文章主要介绍“SpringBoot参数验证的技巧有哪些”,在日常操作中,相信很多人在SpringBoot参数验证的技巧有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot参数验证的技巧有哪些”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

1.使用验证注解

Spring Boot 提供了内置的验证注解,可以帮助简单、快速地对输入字段进行验证,例如检查 null 或空字段、强制执行长度限制、使用正则表达式验证模式以及验证电子邮件地址。

一些最常用的验证注释包括:

  • @NotNull:指定字段不能为空。

  • @NotEmpty:指定列表字段不能为空。

  • @NotBlank:指定字符串字段不得为空或仅包含空格。

  • @Min@Max:指定数字字段的最小值和最大值。

  • @Pattern:指定字符串字段必须匹配的正则表达式模式。

  • @Email:指定字符串字段必须是有效的电子邮件地址。

具体用法参考下面例子:

public class User {    @NotNull    private Long id;    @NotBlank    @Size(min = 2, max = 50)    private String firstName;    @NotBlank    @Size(min = 2, max = 50)    private String lastName;    @Email    private String email;    @NotNull    @Min(18)    @Max(99)    private Integer age;    @NotEmpty    private List<String> hobbies;    @Pattern(regexp = "[A-Z]{2}\d{4}")    private String employeeId;

2.使用自定义验证注解

虽然 Spring Boot 的内置验证注释很有用,但它们可能无法涵盖所有情况。如果有特殊参数验证的场景,可以使用 Spring 的 JSR 303 验证框架创建自定义验证注释。自定义注解可以让你的的验证逻辑更具可重用性和可维护性。

假设我们有一个应用程序,用户可以在其中创建帖子。每个帖子都应该有一个标题和一个正文,并且标题在所有帖子中应该是唯一的。虽然 Spring Boot 提供了用于检查字段是否为空的内置验证注释,但它没有提供用于检查唯一性的内置验证注释。在这种情况下,我们可以创建一个自定义验证注解来处理这种情况。

首先,我们创建自定义约束注解UniqueTitle

@Target({ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = UniqueTitleValidator.class)public @interface UniqueTitle {    String message() default "Title must be unique";    Class<?>[] groups() default {};    Class<? extends Payload>[] payload() default {};}

接下来,我们创建一个PostRepository接口,目的是从数据库中检索帖子:

public interface PostRepository extends JpaRepository<Post, Long> {    Post findByTitle(String title);}

然后我们需要定义验证器类 UniqueTitleValidator,如下所示:

@Componentpublic class UniqueTitleValidator implements ConstraintValidator<UniqueTitle, String> {    @Autowired    private PostRepository postRepository;    @Override    public boolean isValid(String title, ConstraintValidatorContext context) {        if (title == null) {            return true;        }        return Objects.isNull(postRepository.findByTitle(title));    }}

UniqueTitleValidator实现了ConstraintValidator接口,它有两个泛型类型:第一个是自定义注解UniqueTitle,第二个是正在验证的字段类型(在本例中为String). 我们还自动装配了PostRepository 类以从数据库中检索帖子。

isValid()方法通过查询 PostRepository 来检查 title 是否为 null 或者它是否是唯一的。如果 title 为 null 或唯一,则验证成功,并返回 true。

定义了自定义验证注释和验证器类后,我们现在可以使用它来验证 Spring Boot 应用程序中的帖子标题:

public class Post {    @UniqueTitle    private String title;    @NotNull    private String body;}

我们已将 @UniqueTitle 注释应用于 Post 类中的 title 变量。验证此字段时,这将触发 UniqueTitleValidator 类中定义的验证逻辑。

3.在服务器端验证

除了前端或者客户端做了验证意外,服务器端验证输入是至关重要的。它可以确保在处理或存储任何恶意或格式错误的数据之前将其捕获,这对于应用程序的安全性和稳定性至关重要。

假设我们有一个允许用户创建新帐户的 REST 端点。端点需要一个包含用户用户名和密码的 JSON 请求体。为确保输入有效,我们可以创建一个 DTO(数据传输对象)类并将验证注释应用于其字段:

public class UserDTO {    @NotBlank    private String username;    @NotBlank    private String password;}

我们使用@NotBlank注解来确保usernamepassword字段不为空或 null。

接下来,我们可以创建一个控制器方法来处理 HTTP POST 请求并在创建新用户之前验证输入:

@RestController@RequestMapping("/users")@Validatedpublic class UserController {    @Autowired    private UserService userService;    @PostMapping    public ResponseEntity<String> createUser(@Valid @RequestBody UserDTO userDto) {        userService.createUser(userDto);        return ResponseEntity.status(HttpStatus.CREATED).body("User created successfully");    }}

我们使用 Spring 的@Validated注解来启用方法级验证,我们还将 @Valid 注释应用于 userDto 参数以触发验证过程。

4.提供有意义的错误信息

当验证失败时,必须提供清晰简洁的错误消息来描述出了什么问题以及如何修复它。

这是一个示例,如果我们有一个允许用户创建新用户的 RESTful API。我们要确保姓名和电子邮件地址字段不为空,年龄在 18 到 99 岁之间,除了这些字段,如果用户尝试使用重复的“用户名”创建帐户,我们还会提供明确的错误消息或“电子邮件”。

为此,我们可以定义一个带有必要验证注释的模型类 User,如下所示:

public class User {    @NotBlank(message = "用户名不能为空")    private String name;    @NotBlank(message = "Email不能为空")    @Email(message = "无效的Emaild地址")    private String email;    @NotNull(message = "年龄不能为空")    @Min(value = 18, message = "年龄必须大于18")    @Max(value = 99, message = "年龄必须小于99")    private Integer age;}

我们使用 message属性为每个验证注释提供了自定义错误消息。

接下来,在我们的 Spring 控制器中,我们可以处理表单提交并使用 @Valid 注释验证用户输入:

@RestController@RequestMapping("/users")public class UserController {    @Autowired    private UserService userService;    @PostMapping    public ResponseEntity<String> createUser(@Valid @RequestBody User user, BindingResult result) {        if (result.hasErrors()) {            List<String> errorMessages = result.getAllErrors().stream()                    .map(DefaultMessageSourceResolvable::getDefaultMessage)                    .collect(Collectors.toList());            return ResponseEntity.badRequest().body(errorMessages.toString());        }        // save the user to the database using UserService        userService.saveUser(user);        return ResponseEntity.status(HttpStatus.CREATED).body("User created successfully");    }}

我们使用 @Valid 注释来触发 User 对象的验证,并使用 BindingResult 对象来捕获任何验证错误。

5.将 i18n 用于错误消息

如果你的应用程序支持多种语言,则必须使用国际化 (i18n) 以用户首选语言显示错误消息。

以下是在 Spring Boot 应用程序中使用 i18n 处理错误消息的示例

首先,在资源目录下创建一个包含默认错误消息的 messages.properties 文件

# messages.propertiesuser.name.required=Name is required.user.email.invalid=Invalid email format.user.age.invalid=Age must be a number between 18 and 99.

接下来,为每种支持的语言创建一个 messages_xx.properties 文件,例如,中文的 messages_zh_CN.properties

user.name.required=名称不能为空.user.email.invalid=无效的email格式.user.age.invalid=年龄必须在18到99岁之间.

然后,更新您的验证注释以使用本地化的错误消息

public class User {    @NotNull(message = "{user.id.required}")    private Long id;    @NotBlank(message = "{user.name.required}")    private String name;    @Email(message = "{user.email.invalid}")    private String email;    @NotNull(message = "{user.age.required}")    @Min(value = 18, message = "{user.age.invalid}")    @Max(value = 99, message = "{user.age.invalid}")    private Integer age;}

最后,在 Spring 配置文件中配置 MessageSource bean 以加载 i18n 消息文件

@Configurationpublic class AppConfig {    @Bean    public MessageSource messageSource() {        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();        messageSource.setBasename("messages");        messageSource.setDefaultEncoding("UTF-8");        return messageSource;    }    @Bean    public LocalValidatorFactoryBean validator() {        LocalValidatorFactoryBean validatorFactoryBean = new LocalValidatorFactoryBean();        validatorFactoryBean.setValidationMessageSource(messageSource());        return validatorFactoryBean;    }}

现在,当发生验证错误时,错误消息将根据随请求发送的“Accept-Language”标头以用户的首选语言显示。

6.使用分组验证

验证组是 Spring Boot 验证框架的一个强大功能,允许您根据其他输入值或应用程序状态应用条件验证规则。

现在有一个包含三个字段的User类的情况下:firstNamelastNameemail。我们要确保如果 email 字段为空,则 firstNamelastName 字段必须非空。否则,所有三个字段都应该正常验证。

为此,我们将定义两个验证组:EmailNotEmptyDefaultEmailNotEmpty 组将包含当 email 字段不为空时的验证规则,而 Default 组将包含所有三个字段的正常验证规则。

创建带有验证组的 User

public class User {    @NotBlank(groups = Default.class)    private String firstName;    @NotBlank(groups = Default.class)    private String lastName;    @Email(groups = EmailNotEmpty.class)    private String email;    // getters and setters omitted for brevity    public interface EmailNotEmpty {}    public interface Default {}}

请注意,我们在User类中定义了两个接口,EmailNotEmptyDefault。这些将作为我们的验证组。

接下来,我们更新Controller使用这些验证组

@RestController@RequestMapping("/users")@Validatedpublic class UserController {    public ResponseEntity<String> createUser(            @Validated({org.example.model.ex6.User.EmailNotEmpty.class}) @RequestBody User userWithEmail,            @Validated({User.Default.class}) @RequestBody User userWithoutEmail)    {        // Create the user and return a success response           }}

我们已将@Validated注释添加到我们的控制器,表明我们想要使用验证组。我们还更新了 createUser 方法,将两个 User 对象作为输入,一个在 email 字段不为空时使用,另一个在它为空时使用。

@Validated 注释用于指定将哪个验证组应用于每个 User 对象。对于 userWithEmail 参数,我们指定了 EmailNotEmpty 组,而对于 userWithoutEmail 参数,我们指定了 Default 组。

进行这些更改后,现在将根据“电子邮件”字段是否为空对“用户”类进行不同的验证。如果为空,则 firstNamelastName 字段必须非空。否则,所有三个字段都将正常验证。

7.对复杂逻辑使用跨域验证

如果需要验证跨多个字段的复杂输入规则,可以使用跨字段验证来保持验证逻辑的组织性和可维护性。跨字段验证可确保所有输入值均有效且彼此一致,从而防止出现意外行为。

假设我们有一个表单,用户可以在其中输入任务的开始日期和结束日期,并且我们希望确保结束日期不早于开始日期。我们可以使用跨域验证来实现这一点。

首先,我们定义一个自定义验证注解EndDateAfterStartDate

@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy = EndDateAfterStartDateValidator.class)public @interface EndDateAfterStartDate {    String message() default "End date must be after start date";    Class<?>[] groups() default {};    Class<? extends Payload>[] payload() default {};}

然后,我们创建验证器EndDateAfterStartDateValidator

public class EndDateAfterStartDateValidator implements ConstraintValidator<EndDateAfterStartDate, TaskForm> {    @Override    public boolean isValid(TaskForm taskForm, ConstraintValidatorContext context) {        if (taskForm.getStartDate() == null || taskForm.getEndDate() == null) {            return true;        }        return taskForm.getEndDate().isAfter(taskForm.getStartDate());    }}

最后,我们将EndDateAfterStartDate注释应用于我们的表单对象TaskForm

@EndDateAfterStartDatepublic class TaskForm {    @NotNull    @DateTimeFormat(pattern = "yyyy-MM-dd")    private LocalDate startDate;    @NotNull    @DateTimeFormat(pattern = "yyyy-MM-dd")    private LocalDate endDate;}

现在,当用户提交表单时,验证框架将自动检查结束日期是否晚于开始日期,如果不是,则提供有意义的错误消息。

8.对验证错误使用异常处理

可以使用异常处理ExceptionHandler来统一捕获和处理验证错误。

以下是如何在 Spring Boot 中使用异常处理来处理验证错误的示例:

@RestControllerAdvicepublic class RestExceptionHandler extends ResponseEntityExceptionHandler {    @ExceptionHandler(MethodArgumentNotValidException.class)    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,                                                                  HttpHeaders headers, HttpStatus status,                                                                  WebRequest request) {        Map<String, Object> body = new LinkedHashMap<>();        body.put("timestamp", LocalDateTime.now());        body.put("status", status.value());        // Get all errors        List<String> errors = ex.getBindingResult()                .getFieldErrors()                .stream()                .map(x -> x.getDefaultMessage())                .collect(Collectors.toList());        body.put("errors", errors);        return new ResponseEntity<>(body, headers, status);    }}

在这里,我们创建了一个用 @RestControllerAdvice 注解的 RestExceptionHandler 类来处理我们的 REST API 抛出的异常。然后我们创建一个用 @ExceptionHandler 注解的方法来处理在验证失败时抛出的 MethodArgumentNotValidException

在处理程序方法中,我们创建了一个 Map 对象来保存错误响应的详细信息,包括时间戳、HTTP 状态代码和错误消息列表。我们使用 MethodArgumentNotValidException 对象的 getBindingResult() 方法获取所有验证错误并将它们添加到错误消息列表中。

最后,我们返回一个包含错误响应详细信息的ResponseEntity对象,包括作为响应主体的错误消息列表、HTTP 标头和 HTTP 状态代码。

有了这个异常处理代码,我们的 REST API 抛出的任何验证错误都将被捕获并以结构化和有意义的格式返回给用户,从而更容易理解和解决问题。

9.测试你的验证逻辑

需要为你的验证逻辑编写单元测试,以帮助确保它正常工作。

@DataJpaTestpublic class UserValidationTest {    @Autowired    private TestEntityManager entityManager;    @Autowired    private Validator validator;    @Test    public void testValidation() {        User user = new User();        user.setFirstName("John");        user.setLastName("Doe");        user.setEmail("invalid email");        Set<ConstraintViolation<User>> violations = validator.validate(user);        assertEquals(1, violations.size());        assertEquals("must be a well-formed email address", violations.iterator().next().getMessage());    }}

我们使用 JUnit 5 编写一个测试来验证具有无效电子邮件地址的“用户”对象。然后我们使用 Validator 接口来验证 User 对象并检查是否返回了预期的验证错误。

10.考虑客户端验证

客户端验证可以通过向用户提供即时反馈并减少对服务器的请求数量来改善用户体验。但是,不应依赖它作为验证输入的唯一方法。客户端验证很容易被绕过或操纵,因此必须在服务器端验证输入,以确保安全性和数据完整性。

到此,关于“SpringBoot参数验证的技巧有哪些”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SpringBoot参数验证的技巧有哪些

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SpringBoot参数验证的技巧有哪些

这篇文章主要介绍“SpringBoot参数验证的技巧有哪些”,在日常操作中,相信很多人在SpringBoot参数验证的技巧有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot参数验证的技巧
2023-07-05

golang validator库参数校验实用技巧有哪些

这篇“golang validator库参数校验实用技巧有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“golang v
2023-06-30

10个SpringBoot参数验证你需要知道的技巧分享

参数验证很重要,是平时开发环节中不可少的一部分,那么在Spring Boot应用中如何做好参数校验工作呢,本文提供了10个小技巧,你知道几个呢
2023-05-14

SpringBoot中参数校验的方法有哪些

这篇文章给大家分享的是有关SpringBoot中参数校验的方法有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、前言在 Web 开发中经常需要对前端传过来的参数进行校验,例如格式校验、非空校验等,基本上每个
2023-06-15

PHP 函数参数验证的最佳实践有哪些?

php 函数参数验证最佳实践包括:明确声明类型和默认值。使用内建验证函数。创建自定义验证类。使用断言。遵循这些实践可确保php 函数收到有效数据,防止意外崩溃或错误结果。PHP 函数参数验证的最佳实践在 PHP 中构建函数时,参数验证至关
PHP 函数参数验证的最佳实践有哪些?
2024-04-28

网页设计经验和技巧有哪些

这篇文章将为大家详细讲解有关网页设计经验和技巧有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。■ 网站主题规划  注意不要让你的网站主题过于分散。因为网站主题越集中,一般情况下网站所有者
2023-06-08

linux的技巧有哪些

本篇内容主要讲解“linux的技巧有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“linux的技巧有哪些”吧!Linux下修改MAC地址  MAC地址是网卡的物理地址,在Windows系统下
2023-06-10

Python的技巧有哪些

本篇内容主要讲解“Python的技巧有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python的技巧有哪些”吧!1、对输入的字符串“消毒”对用户输入的内容“消毒”,这问题几乎适用于你编写的
2023-06-15

JS前端认证授权技巧有哪些

本篇内容介绍了“JS前端认证授权技巧有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!认证认证 (Identification) 是验证当
2023-07-05

写批处理必备的命令参数使用技巧有哪些

小编给大家分享一下写批处理必备的命令参数使用技巧有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧! 首先批处理文件是一个文本文件,这个文件的每一行都是一条DOS
2023-06-09

ASP定义数组的技巧有哪些

ASP定义数组的技巧有以下几种:1. 使用数组直接量:可以使用Array()函数来定义一个数组,并将初始值作为参数传递给该函数。例如:var arr = Array(1, 2, 3);2. 使用数组字面量:可以使用方括号([])来定义一个数
2023-08-09

Linux下爬取登录凭证的技巧有哪些

这篇文章主要介绍了Linux下爬取登录凭证的技巧有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。仅供参考学习01、history记录敏感操作Linux系统会自动把用户的操
2023-06-15

Flex数据绑定的技巧有哪些

这篇文章主要介绍了Flex数据绑定的技巧有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Flex数据绑定技巧有一种简单的方法可以通过选中来激活/禁用控件。举个例子,假设你
2023-06-17

跟踪数据的Python技巧有哪些

这篇文章主要介绍“跟踪数据的Python技巧有哪些”,在日常操作中,相信很多人在跟踪数据的Python技巧有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”跟踪数据的Python技巧有哪些”的疑惑有所帮助!
2023-06-16

有哪些有用的Python技巧

本篇内容介绍了“有哪些有用的Python技巧”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 函数连续调用def add(x): c
2023-06-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录