Comment vérifier les paramètres SpringBoot
使用传统方式的弊端
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"; }
这样做确实没有什么问题,而且排版也工整,但代码太繁琐了,如果有几十个字段要校验,那这个方法里面将会变得非常臃肿,实在不够优雅。下面我们就来讲讲如何使用最优雅的方式来解决。
引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
注解说明
注解 | 说明 |
---|---|
@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
@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; }
2、controller
@RestController public class UserController { @PostMapping("/addUser") public void addUser(@RequestBody @Valid User user) { //业务 } }
3、编写全局统一异常处理
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); } }
然后我们使用apipost测试
二、针对单个参数进行校验
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) { } }
然后我们使用apipost测试
三、分组校验
场景:在新增时我们需要id为空,但修改时我们又需要id不为空,总不可能搞两个类吧,这时候分组校验的用处就来了
1、entity
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; }
2、controller
@PostMapping("/add") public void add(@RequestBody @Validated(User.Insert.class) User user) { }
添加时就用User.Insert.class,修改时就用User.Update.class
四、自定义分组校验
场景:当type为1时,需要参数a不为空,当type为2时,需要参数b不为空。
1、entity
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 { } }
2、CustomSequenceProvider
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; } }
3、controller
@PostMapping("/add") public void add(@RequestBody @Validated CustomGroup user) { }
五、自定义校验
虽然官方提供的校验注解已经满足很多情况了,但还是无法满足我们业务的所有需求,比如校验手机号码,下面我就以校验手机号码来做一个示例。
1、定义校验注解
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = PhoneValidator.class) public @interface Phone { String message() default "手机号码格式有误"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
注:groups和payload是必须要写的,Constraint是使用哪个类来进行校验。
2、实现注解
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()); } }
最后直接用到参数前面或者实体类变量上面即可。
六、嵌套校验
当某个对象中还包含了对象需要进行校验,这个时候我们需要用嵌套校验。
@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; } }
七、快速失败
Spring Validation默认会校验完所有字段,然后才抛出异常。可以通过配置,开启Fali Fast模式,一旦校验失败就立即返回。
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(); } }
注意事项
SpringBoot 2.3.x 移除了validation依赖需要手动引入依赖。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Introduction à Jasypt Jasypt est une bibliothèque Java qui permet à un développeur d'ajouter des fonctionnalités de chiffrement de base à son projet avec un minimum d'effort et ne nécessite pas une compréhension approfondie du fonctionnement du chiffrement. Haute sécurité pour le chiffrement unidirectionnel et bidirectionnel. technologie de cryptage basée sur des normes. Cryptez les mots de passe, le texte, les chiffres, les binaires... Convient pour l'intégration dans des applications basées sur Spring, API ouverte, pour une utilisation avec n'importe quel fournisseur JCE... Ajoutez la dépendance suivante : com.github.ulisesbocchiojasypt-spring-boot-starter2 1.1. Les avantages de Jasypt protègent la sécurité de notre système. Même en cas de fuite du code, la source de données peut être garantie.

Scénario d'utilisation 1. La commande a été passée avec succès mais le paiement n'a pas été effectué dans les 30 minutes. Le paiement a expiré et la commande a été automatiquement annulée 2. La commande a été signée et aucune évaluation n'a été effectuée pendant 7 jours après la signature. Si la commande expire et n'est pas évaluée, le système donne par défaut une note positive. 3. La commande est passée avec succès. Si le commerçant ne reçoit pas la commande pendant 5 minutes, la commande est annulée. 4. Le délai de livraison expire et. un rappel par SMS est envoyé... Pour les scénarios avec des délais longs et de faibles performances en temps réel, nous pouvons utiliser la planification des tâches pour effectuer un traitement d'interrogation régulier. Par exemple : xxl-job Aujourd'hui, nous allons choisir

1. Redis implémente le principe du verrouillage distribué et pourquoi les verrous distribués sont nécessaires. Avant de parler de verrous distribués, il est nécessaire d'expliquer pourquoi les verrous distribués sont nécessaires. Le contraire des verrous distribués est le verrouillage autonome. Lorsque nous écrivons des programmes multithreads, nous évitons les problèmes de données causés par l'utilisation d'une variable partagée en même temps. Nous utilisons généralement un verrou pour exclure mutuellement les variables partagées afin de garantir l'exactitude de celles-ci. les variables partagées. Son champ d’utilisation est dans le même processus. S’il existe plusieurs processus qui doivent exploiter une ressource partagée en même temps, comment peuvent-ils s’exclure mutuellement ? Les applications métier d'aujourd'hui sont généralement une architecture de microservices, ce qui signifie également qu'une application déploiera plusieurs processus si plusieurs processus doivent modifier la même ligne d'enregistrements dans MySQL, afin d'éviter les données sales causées par des opérations dans le désordre, les besoins de distribution. à introduire à ce moment-là. Le style est verrouillé. Vous voulez marquer des points

Springboot lit le fichier, mais ne peut pas accéder au dernier développement après l'avoir empaqueté dans un package jar. Il existe une situation dans laquelle Springboot ne peut pas lire le fichier après l'avoir empaqueté dans un package jar. La raison en est qu'après l'empaquetage, le chemin virtuel du fichier. n’est pas valide et n’est accessible que via le flux Read. Le fichier se trouve sous les ressources publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

SpringBoot et SpringMVC sont tous deux des frameworks couramment utilisés dans le développement Java, mais il existe des différences évidentes entre eux. Cet article explorera les fonctionnalités et les utilisations de ces deux frameworks et comparera leurs différences. Tout d’abord, découvrons SpringBoot. SpringBoot a été développé par l'équipe Pivotal pour simplifier la création et le déploiement d'applications basées sur le framework Spring. Il fournit un moyen rapide et léger de créer des fichiers exécutables autonomes.

Lorsque Springboot+Mybatis-plus n'utilise pas d'instructions SQL pour effectuer des opérations d'ajout de plusieurs tables, les problèmes que j'ai rencontrés sont décomposés en simulant la réflexion dans l'environnement de test : Créez un objet BrandDTO avec des paramètres pour simuler le passage des paramètres en arrière-plan. qu'il est extrêmement difficile d'effectuer des opérations multi-tables dans Mybatis-plus. Si vous n'utilisez pas d'outils tels que Mybatis-plus-join, vous pouvez uniquement configurer le fichier Mapper.xml correspondant et configurer le ResultMap malodorant et long, puis. écrivez l'instruction SQL correspondante Bien que cette méthode semble lourde, elle est très flexible et nous permet de

1. Personnalisez RedisTemplate1.1, mécanisme de sérialisation par défaut RedisAPI. L'implémentation du cache Redis basée sur l'API utilise le modèle RedisTemplate pour les opérations de mise en cache des données. Ici, ouvrez la classe RedisTemplate et affichez les informations sur le code source de la classe. Déclarer la clé, diverses méthodes de sérialisation de la valeur, la valeur initiale est vide @NullableprivateRedisSe

Dans les projets, certaines informations de configuration sont souvent nécessaires. Ces informations peuvent avoir des configurations différentes dans l'environnement de test et dans l'environnement de production, et peuvent devoir être modifiées ultérieurement en fonction des conditions commerciales réelles. Nous ne pouvons pas coder en dur ces configurations dans le code. Il est préférable de les écrire dans le fichier de configuration. Par exemple, vous pouvez écrire ces informations dans le fichier application.yml. Alors, comment obtenir ou utiliser cette adresse dans le code ? Il existe 2 méthodes. Méthode 1 : Nous pouvons obtenir la valeur correspondant à la clé dans le fichier de configuration (application.yml) via le ${key} annoté avec @Value. Cette méthode convient aux situations où il y a relativement peu de microservices. Méthode 2 : En réalité. projets, Quand les affaires sont compliquées, la logique
