插件
Translation
idea的翻译插件
安装:Plugins直接搜索
使用:
选中文本,右键翻译即可
选中文本,
Ctrl+Shift+y
调试
Stream流调试
在Stream流代码处上打断点
Debug模式启动调试代码,让代码运行到断点处停止
点击流按钮
- 默认为split模式,点击左下角,Flat Mpde,切换模式,即可看到Stream流内的所有执行流程
参数校验
validator
作用:省去繁琐的if-else参数校验
引入依赖
<!-- Spring Boot2.3版本以上 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
插件自带注解
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式
使用示例
创建实体类
package com.example.share.entity;
import lombok.Data;
import javax.validation.constraints.*;
import java.io.Serializable;
/**
* 用户实体类
*/
@Data
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户主键
*/
@NotNull(message = "用户主键不能为Null")
private Long id;
/**
* 用户名称
*/
@NotBlank(message = "用户名不能为空")
private String name;
/**
* 邮箱
*/
@NotNull(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
private String email;
}
创建返回对象
package com.example.share.response;
import lombok.Data;
import java.util.List;
/**
* 自定义返回实体
*/
@Data
public class MyResponse {
/**
* 状态码
*/
private Integer code;
/**
* 返回信息
*/
private String message;
/**
* 多条错误信息
*/
private List<String> errorMessageList;
public MyResponse(){}
public MyResponse(Integer code) {
this.code = code;
}
}
创建控制器
package com.example.share.controller;
import com.example.share.annotation.group.Create;
import com.example.share.annotation.group.Update;
import com.example.share.entity.UserEntity;
import com.example.share.response.MyResponse;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 参数校验测试控制器
*/
@RestController()
@RequestMapping("/paramVerification")
public class ParameterVerificationController {
/**
* 使用@Validated声明需要检查参数
* @param userEntity
*/
@PostMapping("/user")
public MyResponse verifyUserEntity(@RequestBody @Validated UserEntity userEntity){
System.out.println("--------------校验用户实体类--------------");
return new MyResponse(0);
}
}
使用postman请求接口,如果服务器接收到的参数与实体类上注解规则不一致,则服务器内部抛出
MethodArgumentNotValidException
异常,为统一返回数据,故创建一全局的异常处理类,如下
自定义全局异常处理类
package com.example.share.handler;
import com.example.share.response.MyResponse;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.List;
import java.util.stream.Collectors;
/**
* 自定义Controller的异常全局处理类
* 对Controller的增强
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public MyResponse parameterVerificationHandler(MethodArgumentNotValidException exception){
List<FieldError> fieldErrorList = exception.getBindingResult().getFieldErrors();
List<String> errorMessageList = fieldErrorList.stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.toList());
MyResponse response = new MyResponse();
response.setCode(-1);
response.setErrorMessageList(errorMessageList);
return response;
}
}
如此,即可完成参数校验,如果插件自带注解无法满足要求,可自定义注解来满足需求,见下文
自定义注解校验参数
自定义注解
package com.example.share.annotation;
import com.example.share.annotation.group.Update;
import com.example.share.validator.IdentityCardNumberValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
/**
* 自定义注解
*/
// 生成javadoc的时候就会把@Documented注解给显示出来
@Documented
// 对属性生效
@Target({ElementType.PARAMETER, ElementType.FIELD})
// 保留多久
@Retention(RetentionPolicy.RUNTIME)
// 代表处理逻辑是IdentityCardNumberValidator类
@Constraint(validatedBy = IdentityCardNumberValidator.class)
public @interface IdentityCardNumber {
// 定制化提示信息
String message() default "身份证号码不合法";
String text() default "text";
// 将validator进行分类,不同的group中执行不同的操作
// Class<?>[] groups() default {Update.class};
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
/**
* @Target(ElementType.TYPE)——接口、类、枚举、注解
* @Target(ElementType.FIELD)——字段、枚举的常量
* @Target(ElementType.METHOD)——方法
* @Target(ElementType.PARAMETER)——方法参数
* @Target(ElementType.CONSTRUCTOR) ——构造函数
* @Target(ElementType.LOCAL_VARIABLE)——局部变量
* @Target(ElementType.ANNOTATION_TYPE)——注解
* @Target(ElementType.PACKAGE)——包
* ————————————————
* 版权声明:本文为CSDN博主「fengcai0123」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
* 原文链接:https://blog.csdn.net/fengcai0123/article/details/90544338
*
* @Retention作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中.
*
* 从注释上看:
* source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略
* class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
* runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
*/
实现自定义注解的验证逻辑
package com.example.share.validator;
import com.example.share.annotation.IdentityCardNumber;
import com.example.share.util.IDUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* 验证逻辑实现
*/
public class IdentityCardNumberValidator implements ConstraintValidator<IdentityCardNumber, Object> {
@Override
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
return IDUtils.isIDNumber(o.toString());
}
@Override
public void initialize(IdentityCardNumber identityCardNumber){
}
}
测试同上,该不赘述
分组校验参数
将不同的校验规则分给不同的组,在使用时,指定不同的校验规则
创建分组
package com.example.share.annotation.group;
import javax.validation.groups.Default;
/**
* 自定义分组Create
*/
public interface Create extends Default {
}
package com.example.share.annotation.group;
import javax.validation.groups.Default;
/**
* 自定义分组Update
*/
public interface Update extends Default {
}
分组使用
package com.example.share.entity;
import com.example.share.annotation.group.Create;
import com.example.share.annotation.group.Update;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.io.Serializable;
/**
* 自定义实体类
*/
@Data
public class UserEntityWithGroup implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户主键
*/
@NotNull(message = "更新时,用户主键不能为Null", groups = Update.class)
@Null(message = "创建时,用户主键必须为Null", groups = Create.class)
private Long id;
@NotNull(message = "创建的时候名称不能为空", groups = Create.class)
private String name;
@Override
public String toString() {
return "UserEntityWithGroup{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
控制器中需要设置@Validated(groups属性)的Groups属性来决定需要启用的校验分组规则
package com.example.share.controller;
import com.example.share.annotation.group.Create;
import com.example.share.annotation.group.Update;
import com.example.share.entity.UserEntity;
import com.example.share.entity.UserEntityWithGroup;
import com.example.share.response.MyResponse;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
/**
* 参数校验测试控制器
*/
@RestController()
@RequestMapping("/paramVerification")
public class ParameterVerificationController {
/**
* 使用分组的方式校验
* @param userEntityWithGroup
* @return
*/
@PostMapping("/user/group/update")
public MyResponse verifyUserEntityWithGroupUpdate(@RequestBody @Validated(Update.class) UserEntityWithGroup userEntityWithGroup){
System.out.println(userEntityWithGroup);
System.out.println("--------------校验用户实体类--------------");
return new MyResponse(0);
}
/**
* 使用分组的方式校验
* @param userEntityWithGroup
* @return
*/
@PostMapping("/user/group/create")
public MyResponse verifyUserEntityWithGroupCreate(@RequestBody @Validated(Create.class) UserEntityWithGroup userEntityWithGroup){
System.out.println(userEntityWithGroup);
System.out.println("--------------校验用户实体类--------------");
return new MyResponse(0);
}
}