Spring validate参数校验

目录

Spring validate 是什么?

Spring validate能干什么?

Spring validate在项目中怎么使用


Spring validate 是什么?

Spring Validate 是 Spring 框架提供的一个用于数据校验的模块。它提供了一种方便的方式来验证应用程序中的数据,例如用户输入、请求参数等。通过使用 Spring Validate,您可以定义验证规则,并在数据不符合这些规则时抛出异常,从而确保数据的完整性和准确性。

Spring Validate 提供了以下功能:

  1. 注解验证:使用注解来定义验证规则,例如 @NotNull、@Size 等。这些注解可以应用于类、字段或方法上,以便在运行时进行验证。
  2. 自定义验证器:您可以使用自定义验证器来定义自己的验证规则。自定义验证器可以扩展 Spring 的 Validator 接口,并实现 validate() 方法来执行自定义的验证逻辑。
  3. 校验分组:您可以根据不同的需求将校验规则分组,并在运行时选择要应用的组。这对于在不同场景下使用不同的校验规则非常有用。
  4. 错误处理:如果数据不符合验证规则,Spring Validate 将抛出 ConstraintViolationException 异常。您可以使用 @ControllerAdvice 注解和 @ExceptionHandler 方法来处理这些异常,并返回适当的错误消息给用户。

总的来说,Spring Validate 是一个强大的工具,可以帮助您在 Spring 应用程序中确保数据的完整性和准确性。通过使用注解和自定义验证器,您可以轻松地定义验证规则,并在运行时执行这些规则来确保数据的正确性。

Spring validate能干什么?

Spring Validate主要功能包括但不限于:

  1. 参数校验:Spring Validate可以用于对Controller层中接收的参数进行校验,包括请求参数、用户输入等。通过注解的方式,可以方便地定义验证规则,例如非空验证、长度验证等。
  2. 数据完整性验证:在数据传输和存储过程中,可能会遇到数据被篡改或损坏的情况。通过Spring Validate对数据进行校验,可以确保数据的完整性和准确性。
  3. 自定义校验规则:如果默认的验证规则不能满足需求,Spring Validate允许自定义校验规则。用户可以扩展验证器接口,实现自定义的验证逻辑。
  4. 错误处理:当数据不符合验证规则时,Spring Validate会抛出异常。通过捕获并处理这些异常,可以在前端页面上展示错误信息,或者在日志中记录错误信息。
  5. 校验分组:可以将校验规则分组,并在运行时选择要应用的组。这可以帮助在不同的场景下使用不同的校验规则。

Spring validate在项目中怎么使用

首先导入依赖

<dependency>

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

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

<version>2.3.12.RELEASE</version>

</dependency>

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

<version>1.18.10</version>

</dependency>

义: boot-2.3.x开始,spring-boot-starter-web不再引入 spring-boot-starter-validation,因此我们额外引入validation依赖,而 2.3之前的版本只需要引入 web 依赖。

<dependency>

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

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

<version>2.3.12.RELEASE</version>

</dependency> 

<dependency>

<groupId>org.hibernate.validator</groupId>

<artifactId>hibernate-validator</artifactId>

<version>6.0.18.Final</version>

<scope>compile</scope>

^ 以上两个依赖都是可以实现功能的

对象参数的使用(实体类)

package org.example.entity.po;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.example.expleImport.ExcelExport;
import org.example.expleImport.ExcelImport;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("xinbo_celebrity")
public class XinboCelebrity {
    @ExcelExport("编号")
    @TableId(type = IdType.AUTO)
    private Integer cid;
    @ExcelExport("姓名")
    private String name;
    @ExcelExport("省")
    private String province;
    @ExcelExport("市")
    private String city;
    @ExcelExport("区")
    private String district;
    @ExcelExport("地址")
    private String fullAddress;
    @ExcelExport("类型")
    private Integer type;
    @ExcelExport("租金")
    private Integer deposit;
    @ExcelExport("押金")
    private Integer rent;
    @ExcelExport("备注")
    private String remk;
    @ExcelExport("第一张图片")
    private String firstImage;
    @ExcelExport("第二章图片")
    private String secondImage;
    @ExcelExport("第三张图片")
    private String hirdImage;
    @ExcelExport("创建人")
    private String createdby;
    @ExcelExport("修改人")
    private String modifiedby;
    @ExcelExport("创建时间")
    private Date creationtime;
    @ExcelExport("修改时间")
    private Date modifytime;


//    业务字段 (图片的数组)
    @TableField(exist = false)
    private String[] images;

//    日志的类型
    @TableField(exist = false)
    private Integer logstatus;

//  日志的操作时间
    @TableField(exist = false)
    private Date logdate;
}

我们有以上的一个实体类

可以在某一个变量上加 @NotBlank(message = "name为必传参数")  传参不能为空

@NotBlank(message = "name为必传参数") 

private String name;

加了注解就会执行对应的操作 

在需要校验的对象前面加 @RequestBody注解以及@Validated或者@Valid注解,如果校验失败,会抛出MethodArgumentNotValidException异常

@RestController
public class XinboCelredayController{

    @PostMapping("queryCelready")
    public void queryCelready(@RequestBody @Validated Celready cel){}
}

不使用@RequestBody的情况

@Validated注解或者@Valid注解,如果校验失败,会抛出BindException异常

@RestController
public class XinboCelredayController{

    @PostMapping("queryCelready")
    public void queryCelready(@Validated Celready cel){}
}

基本类型使用

其实也就是路径传参,在参数前面加上相对应的校验注解,还必须在Controller类上加 @Validated注解。如果校验失败,会抛出ConstraintViolationException异常

在传单个参数的形式添加 

@RestController
public class XinboCelredayController{

    @PostMapping("queryCelready")
    public void queryCelready(@NotBlank(message="name")String name,@NotBlank(message="age")String age){}
}

全局异常处理 

如果参数校验失败,三种使用场景会抛出三种异常或者警告,分别是MethodArgumentNotValidExceptionConstraintViolationExceptionBindException异常,每种异常的响应格式不一致。所以在实际项目开发中,通常会使用统一异常处理来返回一个统一格式的信息来友好的提示。

@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * @RequestBody 上校验失败后抛出的异常是 MethodArgumentNotValidException 异常。
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        String messages = bindingResult.getAllErrors()
                .stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.joining(";"));
        return messages;
    }
    /**
     * 不加 @RequestBody注解,校验失败抛出的则是 BindException
     */
    @ExceptionHandler(value = BindException.class)
    public String exceptionHandler(BindException e){
        String messages = e.getBindingResult().getAllErrors()
                .stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.joining(";"));
        return messages;
    }

    /**
     *  @RequestParam 上校验失败后抛出的异常是 ConstraintViolationException
     */
    @ExceptionHandler({ConstraintViolationException.class})
    public String methodArgumentNotValid(ConstraintViolationException exception) {
        String message = exception.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";"));
        return message;
    }
}

它是将校验完才抛出的异常,能不能只要检测到一个不通过就抛出异常?

@Configuration
public class ParamValidatorConfig {

    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                //failFast:只要出现校验失败的情况,就立即结束校验,不再进行后续的校验。
                .failFast(true)
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
        return methodValidationPostProcessor;
    }

}

MethodValidationPostProcessorSpring提供的来实现基于方法MethodJSR校验的核心处理器,最终会由 MethodValidationInterceptor进行校验拦截。

校验注解合集o:

注解备注适用类型示例
@AssertFalse被注释的元素必须为 false,null 值是有效的。boolean 和 Boolean@AssertFalse(message = "该参数必须为 false")
@AssertTrue被注释的元素必须为 true,null 值是有效的。boolean 和 Boolean@AssertTrue(message = "该参数必须为 true")
@DecimalMax被注释的元素必须是一个数字,其值必须小于或等于指定的最大值,null 值是有效的。BigDecimal、BigInteger、CharSequence、byte、short、int、long以及包装类型@DecimalMax(value = "100",message = "该参数不能大于 100")
@DecimalMin被注释的元素必须是一个数字,其值必须大于或等于指定的最小值,null 值是有效的。BigDecimal、BigInteger、CharSequence、byte、short、int、long以及包装类型@DecimalMin(value = "0",message = "该参数不能小于 0")
@Digits被注释的元素必须是可接受范围内的数字,null 值是有效的。BigDecimal、BigInteger、CharSequence、byte、short、int、long以及包装类型@Digits(integer = 3,fraction = 2,message = "该参数整数位数不能超出3位,小数位数不能超过2位")
@Max被注释的元素必须是一个数字,其值必须小于或等于指定的最大值,null 值是有效BigDecimal、BigInteger、byte、short、int、long以及包装类型@Max(value = 200,message = "最大金额不能超过 200")
@Min被注释的元素必须是一个数字,其值必须大于或等于指定的最小值,null 值是有效的。BigDecimal、BigInteger、byte、short、int、long以及包装类型@Min(value = 0,message = "最小金额不能小于 0")
@Negative被注释的元素必须是负数,null 值是有效BigDecimal、BigInteger、byte、short、int、long、float、double 以及包装类型@Negative(message = "必须是负数")
@NegativeOrZero被注释的元素必须是负数或 0,null 值是有效的。BigDecimal、BigInteger、byte、short、int、long、float、double 以及包装类型@NegativeOrZero(message = "必须是负数或者为0")
@Positive被注释的元素必须是正数,null 值是有效的。BigDecimal、BigInteger、byte、short、int、long、float、double 以及包装类型@Positive(message = "必须是正数")
@PositiveOrZero被注释的元素必须是正数或0,null 值是有效的。BigDecimal、BigInteger、byte、short、int、long、float、double 以及包装类型@PositiveOrZero(message = "必须是正数或者为0")
@Future被注释的元素必须是未来的日期(年月日),null 值是有效的。基本所有的时间类型都支持。常用的:Date、LocalDate、LocalDateTime、LocalTime、Instant@Future(message = "预约日期要大于当前日期")
@FutureOrPresent被注释的元素必须是现在或者未来的日期(年月日),null 值是有效的。基本所有的时间类型都支持。常用的:Date、LocalDate、LocalDateTime、LocalTime、Instant@FutureOrPresent(message = "预约日要大于当前日期")
@Past被注释的元素必须是过去的日期,null 值是有效的。基本所有的时间类型都支持。常用的:Date、LocalDate、LocalDateTime、LocalTime、Instant@Past(message = "出生日期要小于当前日期")
@PastOrPresent被注释的元素必须是过去或者现在的日期,null 值是有效的基本所有的时间类型都支持。常用的:Date、LocalDate、LocalDateTime、LocalTime、Instant@PastOrPresent(message = "出生时间要小于当前时间")
@NotBlank被注释的元素不能为空,并且必须至少包含一个非空白字符CharSequence@NotBlank(message = "name为必传参数")
@NotEmpty被注释的元素不能为 null 也不能为空CharSequence、Collection、Map、Array@NotEmpty(message = "不能为null或者为空")
@NotNull被注释的元素不能为null任意类型@NotNull(message = "不能为null")
@Null被注释的元素必须为null任意类型@Null(message = "必须为null")
@Email被注释的元素必须是格式正确的电子邮件地址,null 值是有效的CharSequence@Email(message = "email格式错误,请重新填写")
@Pattern被注释的元素必须匹配指定的正则表达式,null 值是有效的CharSequence@Pattern(regexp = "^1[3456789]\d{9}$",message = "手机号格式不正确")
@Size被注释的元素大小必须在指定范围内,null 值是有效的CharSequence、Collection、Map、Array@Size(min = 5,max = 20,message = "字符长度在 5 -20 之间")

以上注解有几个需要注意一下,因为经常用到,也经常使用错误

  • @NotNull:适用于任何类型,不能为null,但可以是 (",")

  • @NotBlank:只能用于 String,不能为null,而且调用 trim() 后,长度必须大于0,必须要有实际字符。

  • @NotEmpty:用于 String、Collection、Map、Array,不能为null,长度必须大于0。

  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security校验JWT Token的代码可以参考如下: 首先,需要创建JWT Token的验证过滤器类。该类继承自OncePerRequestFilter,并在doFilterInternal()方法中实现了JWT Token的校验逻辑: ```java public class JwtTokenAuthenticationFilter extends OncePerRequestFilter { @Autowired private JwtTokenProvider jwtTokenProvider; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = jwtTokenProvider.resolveToken(request); try { if (token != null && jwtTokenProvider.validateToken(token)) { Authentication auth = jwtTokenProvider.getAuthentication(token); if (auth != null) { SecurityContextHolder.getContext().setAuthentication(auth); } } } catch (JwtException e) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()); return; } filterChain.doFilter(request, response); } } ``` 然后,需要创建JWT Token的提供者类,该类负责创建Token并验证Token: ```java @Component public class JwtTokenProvider { @Value("${jwt.secret}") private String secretKey; @Value("${jwt.token.validity}") private long validityInMilliseconds; private Key getSecretKey() { return Keys.hmacShaKeyFor(secretKey.getBytes()); } public String createToken(String username, List<Role> roles) { Claims claims = Jwts.claims().setSubject(username); claims.put("auth", roles.stream().map(role -> new SimpleGrantedAuthority(role.getAuthority())).filter(Objects::nonNull).collect(Collectors.toList())); Date now = new Date(); Date validity = new Date(now.getTime() + validityInMilliseconds); return Jwts.builder() .setClaims(claims) .setIssuedAt(now) .setExpiration(validity) .signWith(getSecretKey()) .compact(); } public Authentication getAuthentication(String token) { UserDetails userDetails = new User(getUsername(token), "", getAuthorities(token)); return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); } private String getUsername(String token) { return Jwts.parserBuilder().setSigningKey(getSecretKey()).build().parseClaimsJws(token).getBody().getSubject(); } private List<GrantedAuthority> getAuthorities(String token) { Claims claims = Jwts.parserBuilder() .setSigningKey(getSecretKey()) .build() .parseClaimsJws(token) .getBody(); List<LinkedHashMap<String, String>> roles = (List<LinkedHashMap<String, String>>) claims.get("auth"); return roles.stream().map(role -> new SimpleGrantedAuthority(role.get("authority"))).collect(Collectors.toList()); } public boolean validateToken(String token) { try { Jwts.parserBuilder().setSigningKey(getSecretKey()).build().parseClaimsJws(token); return true; } catch (JwtException | IllegalArgumentException e) { e.printStackTrace(); return false; } } public String resolveToken(HttpServletRequest req) { String bearerToken = req.getHeader("Authorization"); if (bearerToken != null && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } return null; } } ``` 最后,需要把上述过滤器类和提供者类添加到Spring Security的配置中: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtTokenProvider jwtTokenProvider; @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/api/v1/auth/login").permitAll() .anyRequest().authenticated() .and() .addFilterBefore(new JwtTokenAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder()); } @Bean public UserDetailsService userDetailsService() { return new UserServiceImpl(); } } ``` 以上代码用来实现Spring Security校验JWT Token的功能,提供了创建Token、校验Token和获取Token中存储的用户和权限信息等相关方法。您可以根据您的实际需求进行修改和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值