2022-02-17 分享

插件

Translation

idea的翻译插件

安装:Plugins直接搜索

使用:

  1. 选中文本,右键翻译即可

  2. 选中文本,Ctrl+Shift+y

调试

Stream流调试

  1. 在Stream流代码处上打断点

  2. Debug模式启动调试代码,让代码运行到断点处停止

  3. 点击流按钮

1645104780426.png
  1. 默认为split模式,点击左下角,Flat Mpde,切换模式,即可看到Stream流内的所有执行流程
1645104826950.png

参数校验

validator

作用:省去繁琐的if-else参数校验

引入依赖
<!-- Spring Boot2.3版本以上 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

插件自带注解

  1. @Null 被注释的元素必须为 null
  2. @NotNull 被注释的元素必须不为 null
  3. @AssertTrue 被注释的元素必须为 true
  4. @AssertFalse 被注释的元素必须为 false
  5. @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
  6. @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
  7. @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
  8. @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
  9. @Size(max, min) 被注释的元素的大小必须在指定的范围内
  10. @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
  11. @Past 被注释的元素必须是一个过去的日期
  12. @Future 被注释的元素必须是一个将来的日期
  13. @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);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容