Table of Contents
使用传统方式的弊端
引入依赖
注解说明
一、对实体类进行校验
1、entity
3、controller
3、编写全局统一异常处理
二、针对单个参数进行校验
三、分组校验
四、自定义分组校验
2、CustomSequenceProvider
五、自定义校验
1、定义校验注解
2、实现注解
六、嵌套校验
七、快速失败
注意事项
Home Java javaTutorial How to verify SpringBoot parameters

How to verify SpringBoot parameters

May 14, 2023 pm 10:04 PM
springboot

    使用传统方式的弊端

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    public String addUser(User user) {

         if (user == null || user.getId() == null || user.getAccount() == null || user.getPassword() == null || user.getEmail() == null) {

             return "对象或者对象字段不能为空";

         }

         if (StringUtils.isEmpty(user.getAccount()) || StringUtils.isEmpty(user.getPassword()) || StringUtils.isEmpty(user.getEmail())) {

             return "不能输入空字符串";

         }

         if (user.getAccount().length() < 6 || user.getAccount().length() > 11) {

             return "账号长度必须是6-11个字符";

         }

         if (user.getPassword().length() < 6 || user.getPassword().length() > 16) {

             return "密码长度必须是6-16个字符";

         }

         if (!Pattern.matches("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", user.getEmail())) {

             return "邮箱格式不正确";

         }

         // 参数校验完毕后这里就写上业务逻辑

         return "success";

     }

    Copy after login

    这样做确实没有什么问题,而且排版也工整,但代码太繁琐了,如果有几十个字段要校验,那这个方法里面将会变得非常臃肿,实在不够优雅。下面我们就来讲讲如何使用最优雅的方式来解决。

    引入依赖

    1

    2

    3

    4

    <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-validation</artifactId>

    </dependency>

    Copy after login

    注解说明

    注解说明
    @AssertFalse被注解的元素必须为 false
    @AssertTrue被注解的元素必须为 true
    @DecimalMax(value)被注解的元素必须是一个数字,其值必须小于等于指定的最大值
    @DecimalMin(value)被注解的元素必须是一个数字,其值必须大于等于指定的最小值
    @Digits (integer, fraction)被注解的元素必须是一个数字,其值必须在可接受的范围内
    @Null被注解的元素必须为空
    @NotNull被注解的元素必须不为空
    @Min(value)被注解的元素必须是一个数字,其值必须大于等于指定的最大值
    @Max(value)被注解的元素必须是一个数字,其值必须小于等于指定的最大值
    @Size(max, min)被注解的元素的长度必须在指定的范围内
    @Past被注解的元素必须是一个过去的日期
    @Future被注解的元素必须是一个未来的日期
    @Pattern(value)被注解的元素必须符合指定的正则表达式

    下面我们以此来在业务中实现

    一、对实体类进行校验

    1、entity

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    @Data

    public class User {

        @NotNull(message = "用户id不能为空")

        private Long id;

        @NotNull(message = "用户账号不能为空")

        @Size(min = 6, max = 11, message = "账号长度必须是6-11个字符")

        private String account;

        @NotNull(message = "用户密码不能为空")

        @Size(min = 6, max = 11, message = "密码长度必须是6-16个字符")

        private String password;

        @NotNull(message = "用户邮箱不能为空")

        @Email(message = "邮箱格式不正确")

        private String email;

    }

    Copy after login

    2、controller

    1

    2

    3

    4

    5

    6

    7

    @RestController

    public class UserController {

        @PostMapping("/addUser")

        public void addUser(@RequestBody @Valid User user) {

            //业务

        }

    }

    Copy after login

    3、编写全局统一异常处理

    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

    import org.springframework.validation.ObjectError;

    import org.springframework.web.bind.MethodArgumentNotValidException;

    import org.springframework.web.bind.annotation.ExceptionHandler;

    import org.springframework.web.bind.annotation.RestControllerAdvice;

    import javax.validation.ConstraintViolation;

    import javax.validation.ConstraintViolationException;

    import java.util.stream.Collectors;

    /**

     * 全局异常处理

     *

     * @author master

     */

    @RestControllerAdvice

    public class ExceptionConfig {

        /**

         * 参数为实体类

         * @param e

         * @return

         */

        @ExceptionHandler(value = MethodArgumentNotValidException.class)

        public String handleValidException(MethodArgumentNotValidException e) {

            // 从异常对象中拿到ObjectError对象

            ObjectError objectError = e.getBindingResult().getAllErrors().get(0);

            // 然后提取错误提示信息进行返回

            return objectError.getDefaultMessage();

        }

        /**

         * 参数为单个参数或多个参数

         * @param e

         * @return

         */

        @ExceptionHandler(value = ConstraintViolationException.class)

        public String handleConstraintViolationException(ConstraintViolationException e) {

            // 从异常对象中拿到ObjectError对象

            return e.getConstraintViolations()

                    .stream()

                    .map(ConstraintViolation::getMessage)

                    .collect(Collectors.toList()).get(0);

        }

    }

    Copy after login

    然后我们使用apipost测试

    How to verify SpringBoot parameters

    二、针对单个参数进行校验

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    import org.springframework.validation.annotation.Validated;

    import org.springframework.web.bind.annotation.GetMapping;

    import org.springframework.web.bind.annotation.PostMapping;

    import org.springframework.web.bind.annotation.RestController;

    import javax.validation.constraints.NotNull;

    @RestController

    @Validated

    public class TestController {

        @GetMapping("/test")

        public void test(@NotNull(message = "id不能为空") Integer id) {

        }

    }

    Copy after login

    然后我们使用apipost测试

    How to verify SpringBoot parameters

    三、分组校验

    场景:在新增时我们需要id为空,但修改时我们又需要id不为空,总不可能搞两个类吧,这时候分组校验的用处就来了

    1、entity

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    import lombok.Data;

    import javax.validation.constraints.Email;

    import javax.validation.constraints.NotNull;

    import javax.validation.constraints.Size;

    @Data

    public class User {

        public interface Insert{

        }

        public interface Update{

        }

        @NotNull(message = "用户id不能为空",groups = Update.class)

        @Null(message = "用户id必须为空",groups = Integer.class)

        private Long id;

        private String account;

        private String password;

        private String email;

    }

    Copy after login

    2、controller

    1

    2

    3

    @PostMapping("/add")

    public void add(@RequestBody @Validated(User.Insert.class) User user) {

    }

    Copy after login

    添加时就用User.Insert.class,修改时就用User.Update.class

    四、自定义分组校验

    场景:当type为1时,需要参数a不为空,当type为2时,需要参数b不为空。

    1、entity

    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

    import com.example.demo.provider.CustomSequenceProvider;

    import lombok.Data;

    import org.hibernate.validator.group.GroupSequenceProvider;

    import javax.validation.constraints.NotEmpty;

    import javax.validation.constraints.Pattern;

    @Data

    @GroupSequenceProvider(value = CustomSequenceProvider.class)

    public class CustomGroup {

        /**

         * 类型

         */

        @Pattern(regexp = "[A|B]" , message = "类型不必须为 A|B")

        private String type;

        /**

         * 参数A

         */

        @NotEmpty(message = "参数A不能为空" , groups = {WhenTypeIsA.class})

        private String paramA;

        /**

         * 参数B

         */

        @NotEmpty(message = "参数B不能为空", groups = {WhenTypeIsB.class})

        private String paramB;

        /**

         * 分组A

         */

        public interface WhenTypeIsA {

        }

        /**

         * 分组B

         */

        public interface WhenTypeIsB {

        }

    }

    Copy after login

    2、CustomSequenceProvider

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    import com.example.demo.controller.CustomGroup;

    import org.hibernate.validator.spi.group.DefaultGroupSequenceProvider;

    import java.util.ArrayList;

    import java.util.List;

    public class CustomSequenceProvider implements DefaultGroupSequenceProvider<CustomGroup> {

        @Override

        public List<Class<?>> getValidationGroups(CustomGroup form) {

            List<Class<?>> defaultGroupSequence = new ArrayList<>();

            defaultGroupSequence.add(CustomGroup.class);

            if (form != null && "A".equals(form.getType())) {

                defaultGroupSequence.add(CustomGroup.WhenTypeIsA.class);

            }

            if (form != null && "B".equals(form.getType())) {

                defaultGroupSequence.add(CustomGroup.WhenTypeIsB.class);

            }

            return defaultGroupSequence;

        }

    }

    Copy after login

    3、controller

    1

    2

    3

    @PostMapping("/add")

    public void add(@RequestBody @Validated CustomGroup user) {

    }

    Copy after login

    五、自定义校验

    虽然官方提供的校验注解已经满足很多情况了,但还是无法满足我们业务的所有需求,比如校验手机号码,下面我就以校验手机号码来做一个示例。

    1、定义校验注解

    1

    2

    3

    4

    5

    6

    7

    8

    @Target({ElementType.FIELD})

    @Retention(RetentionPolicy.RUNTIME)

    @Constraint(validatedBy = PhoneValidator.class)

    public @interface Phone {

        String message() default "手机号码格式有误";

        Class<?>[] groups() default {};

        Class<? extends Payload>[] payload() default {};

    }

    Copy after login

    注:groups和payload是必须要写的,Constraint是使用哪个类来进行校验。

    2、实现注解

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    import javax.validation.ConstraintValidator;

    import javax.validation.ConstraintValidatorContext;

    import java.util.regex.Pattern;

    /**

     * @author master

     */

    public class PhoneValidator implements ConstraintValidator<Phone, Object> {

        @Override

        public boolean isValid(Object telephone, ConstraintValidatorContext constraintValidatorContext) {

            String pattern = "^1[3|4|5|6|7|8|9]\\d{9}$";

            return Pattern.matches(pattern, telephone.toString());

        }

    }

    Copy after login

    最后直接用到参数前面或者实体类变量上面即可。

    六、嵌套校验

    当某个对象中还包含了对象需要进行校验,这个时候我们需要用嵌套校验。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    @Data

    public class TestAA {

        @NotEmpty(message = "id不能为空")

        private String id;

        @NotNull

        @Valid

        private Job job;

        @Data

        public class Job {

            @NotEmpty(message = "content不能为空")

            private String content;

        }

    }

    Copy after login

    七、快速失败

    Spring Validation默认会校验完所有字段,然后才抛出异常。可以通过配置,开启Fali Fast模式,一旦校验失败就立即返回。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    import org.hibernate.validator.HibernateValidator;

    import org.springframework.context.annotation.Bean;

    import org.springframework.context.annotation.Configuration;

    import javax.validation.Validation;

    import javax.validation.Validator;

    import javax.validation.ValidatorFactory;

    @Configuration

    public class FailFastConfig {

        @Bean

        public Validator validator() {

            ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)

                    .configure()

                    // 快速失败模式

                    .failFast(true)

                    .buildValidatorFactory();

            return validatorFactory.getValidator();

        }

    }

    Copy after login

    注意事项

    SpringBoot 2.3.x 移除了validation依赖需要手动引入依赖。

    The above is the detailed content of How to verify SpringBoot parameters. For more information, please follow other related articles on the PHP Chinese website!

    Statement of this Website
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

    Hot AI Tools

    Undresser.AI Undress

    Undresser.AI Undress

    AI-powered app for creating realistic nude photos

    AI Clothes Remover

    AI Clothes Remover

    Online AI tool for removing clothes from photos.

    Undress AI Tool

    Undress AI Tool

    Undress images for free

    Clothoff.io

    Clothoff.io

    AI clothes remover

    AI Hentai Generator

    AI Hentai Generator

    Generate AI Hentai for free.

    Hot Article

    R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
    3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O. Best Graphic Settings
    3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O. How to Fix Audio if You Can't Hear Anyone
    3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
    WWE 2K25: How To Unlock Everything In MyRise
    1 months ago By 尊渡假赌尊渡假赌尊渡假赌

    Hot Tools

    Notepad++7.3.1

    Notepad++7.3.1

    Easy-to-use and free code editor

    SublimeText3 Chinese version

    SublimeText3 Chinese version

    Chinese version, very easy to use

    Zend Studio 13.0.1

    Zend Studio 13.0.1

    Powerful PHP integrated development environment

    Dreamweaver CS6

    Dreamweaver CS6

    Visual web development tools

    SublimeText3 Mac version

    SublimeText3 Mac version

    God-level code editing software (SublimeText3)

    How Springboot integrates Jasypt to implement configuration file encryption How Springboot integrates Jasypt to implement configuration file encryption Jun 01, 2023 am 08:55 AM

    Introduction to Jasypt Jasypt is a java library that allows a developer to add basic encryption functionality to his/her project with minimal effort and does not require a deep understanding of how encryption works. High security for one-way and two-way encryption. , standards-based encryption technology. Encrypt passwords, text, numbers, binaries... Suitable for integration into Spring-based applications, open API, for use with any JCE provider... Add the following dependency: com.github.ulisesbocchiojasypt-spring-boot-starter2. 1.1Jasypt benefits protect our system security. Even if the code is leaked, the data source can be guaranteed.

    How SpringBoot integrates Redisson to implement delay queue How SpringBoot integrates Redisson to implement delay queue May 30, 2023 pm 02:40 PM

    Usage scenario 1. The order was placed successfully but the payment was not made within 30 minutes. The payment timed out and the order was automatically canceled. 2. The order was signed and no evaluation was conducted for 7 days after signing. If the order times out and is not evaluated, the system defaults to a positive rating. 3. The order is placed successfully. If the merchant does not receive the order for 5 minutes, the order is cancelled. 4. The delivery times out, and push SMS reminder... For scenarios with long delays and low real-time performance, we can Use task scheduling to perform regular polling processing. For example: xxl-job Today we will pick

    How to use Redis to implement distributed locks in SpringBoot How to use Redis to implement distributed locks in SpringBoot Jun 03, 2023 am 08:16 AM

    1. Redis implements distributed lock principle and why distributed locks are needed. Before talking about distributed locks, it is necessary to explain why distributed locks are needed. The opposite of distributed locks is stand-alone locks. When we write multi-threaded programs, we avoid data problems caused by operating a shared variable at the same time. We usually use a lock to mutually exclude the shared variables to ensure the correctness of the shared variables. Its scope of use is in the same process. If there are multiple processes that need to operate a shared resource at the same time, how can they be mutually exclusive? Today's business applications are usually microservice architecture, which also means that one application will deploy multiple processes. If multiple processes need to modify the same row of records in MySQL, in order to avoid dirty data caused by out-of-order operations, distribution needs to be introduced at this time. The style is locked. Want to achieve points

    How to solve the problem that springboot cannot access the file after reading it into a jar package How to solve the problem that springboot cannot access the file after reading it into a jar package Jun 03, 2023 pm 04:38 PM

    Springboot reads the file, but cannot access the latest development after packaging it into a jar package. There is a situation where springboot cannot read the file after packaging it into a jar package. The reason is that after packaging, the virtual path of the file is invalid and can only be accessed through the stream. Read. The file is under resources publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

    How to implement Springboot+Mybatis-plus without using SQL statements to add multiple tables How to implement Springboot+Mybatis-plus without using SQL statements to add multiple tables Jun 02, 2023 am 11:07 AM

    When Springboot+Mybatis-plus does not use SQL statements to perform multi-table adding operations, the problems I encountered are decomposed by simulating thinking in the test environment: Create a BrandDTO object with parameters to simulate passing parameters to the background. We all know that it is extremely difficult to perform multi-table operations in Mybatis-plus. If you do not use tools such as Mybatis-plus-join, you can only configure the corresponding Mapper.xml file and configure The smelly and long ResultMap, and then write the corresponding sql statement. Although this method seems cumbersome, it is highly flexible and allows us to

    Comparison and difference analysis between SpringBoot and SpringMVC Comparison and difference analysis between SpringBoot and SpringMVC Dec 29, 2023 am 11:02 AM

    SpringBoot and SpringMVC are both commonly used frameworks in Java development, but there are some obvious differences between them. This article will explore the features and uses of these two frameworks and compare their differences. First, let's learn about SpringBoot. SpringBoot was developed by the Pivotal team to simplify the creation and deployment of applications based on the Spring framework. It provides a fast, lightweight way to build stand-alone, executable

    How SpringBoot customizes Redis to implement cache serialization How SpringBoot customizes Redis to implement cache serialization Jun 03, 2023 am 11:32 AM

    1. Customize RedisTemplate1.1, RedisAPI default serialization mechanism. The API-based Redis cache implementation uses the RedisTemplate template for data caching operations. Here, open the RedisTemplate class and view the source code information of the class. publicclassRedisTemplateextendsRedisAccessorimplementsRedisOperations, BeanClassLoaderAware{//Declare key, Various serialization methods of value, the initial value is empty @NullableprivateRedisSe

    How to get the value in application.yml in springboot How to get the value in application.yml in springboot Jun 03, 2023 pm 06:43 PM

    In projects, some configuration information is often needed. This information may have different configurations in the test environment and the production environment, and may need to be modified later based on actual business conditions. We cannot hard-code these configurations in the code. It is best to write them in the configuration file. For example, you can write this information in the application.yml file. So, how to get or use this address in the code? There are 2 methods. Method 1: We can get the value corresponding to the key in the configuration file (application.yml) through the ${key} annotated with @Value. This method is suitable for situations where there are relatively few microservices. Method 2: In actual projects, When business is complicated, logic

    See all articles