首页 > 其他分享 >新来的一个同事,把SpringBoot参数校验玩的那叫一个优雅

新来的一个同事,把SpringBoot参数校验玩的那叫一个优雅

时间:2024-01-29 13:34:37浏览次数:31  
标签:SpringBoot 验证 校验 private 新来 注解 message public

介绍

在开发现代应用程序时,数据验证是确保用户输入的正确性和应用程序数据完整性的关键方面。Spring Boot 提供了强大的数据验证机制,使开发者能够轻松地执行验证操作。本文将深入介绍 Spring Boot 中的 Validation,以及如何在应用程序中正确使用它。

为什么使用数据验证?

  • 1.用户输入的正确性:数据验证是确保用户输入的正确性的一种重要手段。通过验证用户输入的数据,可以防止无效或错误的数据进入应用程序,提高数据的质量。例如:系统中的备注字段数据库中对应的长度是256,如果用户输入的备注超过这个长度值,那么就会导致mysql报Data too long

    1. 数据完整性: 数据完整性是指数据在存储和传输过程中的准确性和一致性。数据验证有助于确保数据满足特定的格式、长度、范围等要求,从而提高数据的完整性。
  1. 安全性: 数据验证也是保障应用程序安全性的关键因素。通过验证用户输入,可以防范一些潜在的安全威胁,例如 SQL 注入、跨站脚本攻击等。

  2. 业务规则的执行: 在应用程序中,通常存在一些业务规则,例如某个字段不能为空、日期范围必须在某个特定范围内等。通过数据验证,可以确保这些业务规则在应用程序中得到正确执行。

手动数据校验的痛点

日常开发中,有些写项目可能没有采用Spring Validator,采用的是在代码中手动校验数据。但是手动校验数据会带来代码冗余、错误处理的一致性以及业务规则的维护的一些痛点。

  • 代码冗余的手动校验逻辑,导致代码中大量的if-else
public ResponseEntity<String> registerUser(UserRegistrationRequest request) {
    if (request == null) {
        return ResponseEntity.badRequest().body("Request cannot be null");
    }

    if (StringUtils.isBlank(request.getUsername())) {
        return ResponseEntity.badRequest().body("Username cannot be blank");
    }

    if (StringUtils.length(request.getPassword()) < 6) {
        return ResponseEntity.badRequest().body("Password must be at least 6 characters long");
    }

    // 处理用户注册逻辑
    return ResponseEntity.ok("User registered successfully");
}

  • 缺乏统一的错误处理机制

  • 业务规则维护的困难
    随着业务规则的增加,手动编写的校验逻辑可能变得庞大且难以维护。修改和扩展校验规则可能需要修改多个地方,增加了维护成本。

  • 缺乏验证组的支持
    手动校验通常不支持验证组的概念,难以根据不同场景执行不同的验证规则。

  • 不易于集成前端验证
    手动校验不易与前端验证框架集成,导致前后端验证逻辑可能不一致。

通过引入 Spring Validator,我们能够有效解决这些痛点,提高代码的可读性、可维护性,并确保校验逻辑的一致性。

Spring Boot 中的 Validation 概述

因Springboot的spring-boot-starter-web默认内置了Hibernate-Validator(Spring boot 2.3以前版本),虽然Hibernate-Validator也能做到数据校验,但是考虑到spring-boot-starter-validation 是一个抽象层,使得验证框架的具体实现变得可插拔。这意味着,除了 Hibernate Validator,开发者可以选择其他符合 Bean Validation 规范的实现。所以我们可以手动引入spring-boot-starter-validation实现数据验证。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<dependency>  
	<groupId>org.springframework.boot</groupId>  
	<artifactId>spring-boot-starter-web</artifactId>  
</dependency>

spring-boot-starter-validation 不仅支持 JSR-303(Bean Validation 1.0)规范,还提供了对 JSR-380(Bean Validation 2.0)规范的全面支持。这使得开发者可以利用 Bean Validation 2.0 的新特性,更灵活地定义验证规则,包括对集合、嵌套对象的验证等。

通过在实体类的字段上使用标准的 Bean Validation 注解(如 @NotBlank@Size@Email 等),我们能够直观地定义数据的验证规则。这些验证规则会在应用程序的不同层次(如控制器层)生效,确保输入数据的正确性。

基本用法

Spring Boot Validation 提供了一系列注解,用于在实体类中定义验证规则。以下是一些常用的校验相关的注解及其功能以及用法:
1.@NotNull 校验元素值不能为 null。如果元素为null,则验证失败。通常用于字段级别的验证。

@NotNull(message = "Name cannot be null")
private String name;

2.@NotBlank 校验字符串元素值不能为 null 或空字符串。必须包含至少一个非空格字符(即执行trim()之后不为'')。如果元素为null或者‘‘,则验证失败。通常用于String类型的字段校验。

@NotBlank(message = "Username cannot be blank")
private String username;

3.NotEmpty 校验集合元素或数组元素或者字符串是否非空。通常作用于集合字段或数组字段,此时需要集合或者数字的元素个数大于0。也可以作用于字符串,此时校验字符串不能为null或空串(可以是一个空格)。注意与@NotBlank的使用区别。

@NotEmpty(message = "List cannot be empty")
private List<String> items;

4.@Length 校验字符串元素的长度。作用于字符串。注:Hibernate-Validator中注解,等同于spring-boot-starter-validation中的@Size

@Length(min = 5, max = 20, message = "Length must be between 5 and 20 characters")
private String username;

5.@Size 校验集合元素个数或字符串的长度在指定范围内。在集合或字符串字段上添加 @Size 注解。

@Size(min = 1, max = 10, message = "Number of items must be between 1 and 10")
private List<String> items;

@Size(min = 5, max = 20, message = "Length must be between 5 and 20 characters")
private String username;

6.@Min 校验数字元素的最小值。

@Min(value = 18, message = "Age must be at least 18")
private int age;

7.@Max 校验数字元素的最大值。

@Max(value = 100, message = "Age must not exceed 100")
private int age;

9.@DecimalMax 作用于BigDecimal类型字段, 校验字段的最大值,支持比较的值为字符串表示的十进制数。通常搭配它的inclusive()使用,区别边界问题。value 属性表示最大值,inclusive 属性表示是否包含最大值。

@DecimalMax(value = "100.00", inclusive = true, message = "Value must be less than or equal to 100.00")
private BigDecimal amount;

10.@DecimalMin 作用于BigDecimal类型字段, 校验字段的最小值,支持比较的值为字符串表示的十进制数。通常搭配它的inclusive()使用,区别边界问题。value 属性表示最小值,inclusive 属性表示是否包含最小值。

@DecimalMin(value = "0.00", inclusive = false, message = "Value must be greater than 0.00")
private BigDecimal amount;

11.@Email 校验字符串元素是否为有效的电子邮件地址。可以通过regexp自定义邮箱匹配正则。

@Email(message = "Invalid email address")
private String email;

12.@Pattern 根据正则表达式校验字符串元素的格式。

@Pattern(regexp = "[a-zA-Z0-9]+", message = "Only alphanumeric characters are allowed")
private String username;

13.@Digits 校验数字元素的整数部分和小数部分的位数。作用于BigDecimalBigInteger,字符串,以及byte, short,int, long以及它们的包装类型。

@Digits(integer = 5, fraction = 2, message = "Number must have up to 5 integer digits and 2 fraction digits")
private BigDecimal amount;

14.@Past 校验日期或时间元素是否在当前时间之前。即是否是过去时间。作用于Date相关类型的字段。

@Past(message = "Date must be in the past")
private LocalDate startDate;

15.@Future 校验日期或时间元素是否在当前时间之后。即是否是未来时间。作用于Date相关类型的字段。

@Future(message = "Date must be in the future")
private LocalDate endDate;

注:以上只罗列部分注解以及它们的功能,其余他们的字段属性并没有详细说明,其他注解以及详细的说明需要去看源码。

用法示例

1.定义接口入参请求参数
/**  
* @version 1.0  
* @description: <p></p >  
* @author: 码农Academy  
* @create: 2024/1/8 16:46  
*/  
@Data  
public class UserCreateRequestVO {  
  
	@NotBlank(message = "请输入用户名")  
	@Size(max = 128, message = "用户名长度最大为128个字符")  
	private String userName;  
	  
	@Email(message = "请填写正确的邮箱地址")  
	private String email;  
	  
	@Min(value = 18, message = "用户年龄必须大于18岁")  
	@Max(value = 60, message = "用户年龄必须小于60岁")  
	private Integer age;  
	  
	@NotEmpty(message = "请输入你的兴趣爱好")  
	@Size(max = 5, message = "兴趣爱好最多可以输入5个")  
	private List<String> hobbies;  
	  
	@DecimalMin(value = "50", inclusive = false, message = "体重必须大于50KG")  
	private BigDecimal weight;  

	@Validated
	@NotNull(message = "请输入地址信息")  
	private UserAddressRequestVO address;  
}
2.定义请求接口
@RestController  
@RequestMapping("user")  
@Validated  
@Slf4j  
public class UserController {  
  
	/**  
	* 创建用户  
	* @param requestVO  
	* @return  
	*/  
	@PostMapping("create")  
	public ResultResponse<Void> createUser(@Validated @RequestBody UserCreateRequestVO requestVO){  
	return ResultResponse.success(null);  
	}  

	/**  
	* 校验用户邮箱是否合法  
	* @param email  
	* @return  
	*/  
	@GetMapping("email")  
	public ResultResponse<Void> validUserEmail(@Email(message = "邮箱格式不正确") String email){  
	return ResultResponse.success(null);  
	}
}
3.测试
  • 创建用户校验,Json请求体校验
    image.png

我们需要捕获一下MethodArgumentNotValidException。该部分内容请参考文章:SpringBoot统一异常处理

  • 校验邮箱,单参数校验
    image.png

注:单参数校验时我们需要,在方法的类上加上@Validated注解,否则校验不生效。

嵌套对象的校验

UserCreateRequestVO中增加一个address的校验,即需要对嵌套对象进行校验

/**  
* @version 1.0  
* @description: <p></p >  
* @author: 码农Academy  
* @create: 2024/1/8 19:45  
*/  
@Data  
public class UserAddressRequestVO {  
	@Size(max = 16, message = "地址信息中国家长度不能超过16个字符")  
	@NotBlank(message = "地址信息国家不能为空")  
	private String country;  
	  
	private String city;  
	  
	@Size(max = 128, message = "详细地址长度不能超过128个字符")  
	private String address1;  
}

UserAddressRequestVO中增加address属性

@Data  
public class UserCreateRequestVO {
	@NotNull(message = "请输入地址信息")  
	private UserAddressRequestVO address;
}

解决办法,要在嵌套对象上使用 @Valid 注解

@Data  
public class UserCreateRequestVO {

	@NotNull(message = "请输入地址信息")  
	@Valid  
	private UserAddressRequestVO address;
}

image.png

试了一些其他的方式,好像都不行,有知道其他方式的,欢迎评论区留言探讨

自定义验证注解

在项目开发中,我们也可以自定义注解去完成我们的字段校验,比如某些枚举值的传递,需要校验枚举值是否合法。在创建自定义注解之前,我们需要了解一下ConstraintValidator以及实现自定义验证注解的原理

1.ConstraintValidator 接口

ConstraintValidator 是 Java Bean Validation (JSR 380) 规范中用于自定义验证逻辑的接口。它允许你定义针对特定自定义注解的验证规则。它是一个泛型接口,需要提供两个类型参数:

  • A:是你的自定义注解的类型。
  • T:是被验证的元素类型,通常是字段类型。
public interface ConstraintValidator<A extends Annotation, T> {

    void initialize(A constraintAnnotation);

    boolean isValid(T value, ConstraintValidatorContext context);
}

其中:

  • initialize 方法:在验证器初始化时被调用,可以用于获取约束注解中的配置信息。
  • isValid 方法:执行实际的验证逻辑,返回 true 表示验证通过,false 表示验证失败。

以下为枚举校验注解的校验规则实现

/**  
* @version 1.0  
* <p> </p>  
* @author: 码农Academy  
* @create: 2024/01/09 3:11 下午  
*/  
public class EnumValidator implements ConstraintValidator<EnumValid, Object> {  
  
	private Class clazz;  
	  
	private String validField;  
	  
	@Override  
	public void initialize(EnumValid constraintAnnotation) {  
		clazz = constraintAnnotation.enumClass();  
		validField = constraintAnnotation.field();  
	}  
	  
	@SneakyThrows  
	@Override  
		public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {  
		if (object == null || "".equals(object)){  
			return true;  
		}  
		  
		if (!clazz.isEnum()){  
			return false;  
		}  
		  
		Class<Enum> enumClass = (Class<Enum>)clazz;  
		//获取所有枚举实例  
		Enum[] enumConstants = enumClass.getEnumConstants();  
		  
		// 需要比对的字段  
		Field field = enumClass.getDeclaredField(validField);  
		field.setAccessible(true);  
		  
		for(Enum constant : enumConstants){  
			// 取值final修饰  
			Object validValue = field.get(constant);  
			if (validValue == null){  
				Method method = enumClass.getMethod(validField);  
				validValue = method.invoke(constant);  
			}  
			  
			if(validValue instanceof Number) {  
				validValue = ((Number)validValue).intValue();  
				object = ((Number) object).intValue();  
			}  
			if (Objects.equals(validValue,object)){  
				return true;  
			}  
		}  
		return false;  
	}  
}

2.创建自定义注解

在 Java Bean Validation 中,约束注解(Constraint Annotation)是通过元注解 @Constraint 来定义的。这个注解包含了以下关键元素:

  • validatedBy: 指定用于执行验证的 ConstraintValidator 实现类。

以校验枚举值的合法行为例,我们创建一个EnumValid约束注解

@Constraint(validatedBy = {EnumValidator.class})  
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })  
@Retention(RUNTIME)  
public @interface EnumValid {  
	  
	/**  
	* 不合法时 抛出异常信息  
	*/  
	String message() default "值不合法";  
	  
	/**  
	* 校验的枚举类  
	* @return  
	*/  
	Class enumClass() default Enum.class;  
	  
	/**  
	* 对应枚举类中需要比对的字段  
	* @return  
	*/  
	String field() default "code";  
	  
	Class<?>[] groups() default { };  
	  
	Class<? extends Payload>[] payload() default { };  
}

3.注册 ConstraintValidator

在大多数情况下,不需要手动注册 ConstraintValidator。当你使用 @Constraint(validatedBy = EnumValidator.class) 注解时,Java Bean Validation 的实现框架会自动发现并注册相应的验证器。但在一些特殊情况下,你可能需要将验证器注册为 Spring 组件或手动配置。比如

  • 需要使用 Spring 管理的组件: 如果你的验证器需要依赖于 Spring 管理的组件(例如,使用 @Autowired 注解注入其他 bean),那么你可能需要将验证器注册为 Spring bean。这确保了验证器能够正确地使用 Spring 的依赖注入机制。

  • 需要通过属性文件进行配置: 如果你的验证器需要配置属性,而这些属性需要从 Spring 的 application.propertiesapplication.yml 文件中获取,那么将验证器注册为 Spring bean 可以更容易地实现这一点。

  • 需要在验证器中使用 Spring AOP: 如果你希望在验证逻辑中使用 Spring AOP 切面,以便添加额外的逻辑或跟踪行为,那么将验证器注册为 Spring bean 可以让你更容易集成这些方面。
    这种方式可以运用到一些业务校验中,比如账户注册时用户名称不能重复。定义一个校验用户唯一的注解@UniqueUser

@Constraint(validatedBy = {UniqueUserValidator.class})  
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })  
@Retention(RUNTIME)  
public @interface UniqueUser {  
	  
	/**  
	* 不合法时 抛出异常信息  
	*/  
	String message() default "值不合法";  
	  
	Class<?>[] groups() default { };  
	  
	Class<? extends Payload>[] payload() default { };  
}

然后定义一个业务的Validator

@Slf4j  
@Component  
public class UniqueUserValidator implements ConstraintValidator<UniqueUser, UserCreateRequestVO> {  
  
	private UserRepository userRepository;  
	  
	@Override  
	public boolean isValid(UserCreateRequestVO value, ConstraintValidatorContext context) {  
		final String userName = value.getUserName();  
		final UserDO userDO = userRepository.selectUserByName(userName);  
		final String userId = value.getUserId();  
		if (StringUtils.isBlank(userId)){  
			return userDO == null;  
		}  
	  
		return userDO == null || Objects.equals(userDO.getUserId(), userId);  
	}  
	  
	@Autowired  
	public void setUserRepository(UserRepository userRepository) {  
		this.userRepository = userRepository;  
	}  
}

在创建用户的接口中使用@UniqueUser

@RestController  
@RequestMapping("user")  
@Validated  
@Slf4j  
public class UserController {  
  
	/**  
	* 创建用户  
	* @param requestVO  
	* @return  
	*/  
	@PostMapping("create")  
	public ResultResponse<Void> createUser(@Validated @UniqueUser(message = "用户名称已存在") @RequestBody UserCreateRequestVO requestVO){  
			return ResultResponse.success(null);  
		}
}

模拟当用户名存在时,校验不通过

image.png

此时会抛出javax.validation.ConstraintViolationException。异常统一处理请参考:SpringBoot统一异常处理

4.自定义校验注解使用

我们创建一个性别的枚举类:

/**  
* @version 1.0  
* @description: <p></p >  
* @author: 码农Academy  
* @create: 2024/1/9 16:07  
*/  
@AllArgsConstructor  
public enum SexEnum {  
  
	MAN(1, "男"),  
	WOMAN(2,"女");  
	  
	public final Integer code;  
	  
	public final String desc;  
  
}

然后我们在入参中增加sex字段,并使用@EmunValid注解

@Data  
public class UserCreateRequestVO {  
  
	@NotBlank(message = "请输入用户名")  
	@Size(max = 128, message = "用户名长度最大为128个字符")  
	private String userName;  
	  
	@Email(message = "请填写正确的邮箱地址")  
	private String email;  
	  
	@Min(value = 18, message = "用户年龄必须大于18岁")  
	@Max(value = 60, message = "用户年龄必须小于60岁")  
	private Integer age;  
	  
	@NotNull(message = "请输入性别")  
	@EnumValid(enumClass = SexEnum.class, message = "输入性别不合法")  
	private Integer sex;  
	  
	@NotEmpty(message = "请输入你的兴趣爱好")  
	@Size(max = 5, message = "兴趣爱好最多可以输入5个")  
	private List<String> hobbies;  
	  
	@DecimalMin(value = "50", inclusive = false, message = "体重必须大于50KG")  
	private BigDecimal weight;  
}

测试结果如下:

image.png

分组验证

在一个应用中,同一个实体类可能会被用于不同的场景,比如用户创建、用户更新、用户删除等。每个场景对于字段的要求可能不同,有些字段在某个场景下需要验证,而在另一个场景下不需要。不同的业务操作可能对同一实体的验证有不同的需求。例如,在用户创建时可能强调用户名和密码的合法性,而在用户更新时可能更关心其他信息的完整性。

开发中我们针对这种情况,在不知道分组校验的知识时,通常采取的都是对应不同的场景或者业务创建不同的入参实体,比如创建用户UserCreateRequestVO,更新用户UserUpdateRequestVO,删除用户UserDeleteRuquestVO,在不同的实体中根据业务场景设置不同的校验规则。这样做虽然也可以,但是会造成类的膨胀,业务的重复实现。

而实际上用分组校验可以让你根据场景以及业务的差异性,有选择地执行特定组的验证规则。

1.定义验证分组接口

我们定义两个分组接口CreateUserGroup(用户创建组),UpdateUserGroup(用户更新组),分别继承javax.validation.groups.Default,标识不同的业务场景。

public interface CreateUserGroup extends Default {  
}

public interface UpdateUserGroup extends Default {  
}

2.分组校验的使用

在 Bean Validation 中,分组校验是通过在验证注解上指定 groups 属性来实现的。这个属性允许你为验证规则分配一个或多个验证组。我们设定用户创建时不传递用户ID,其余的参数必传,用户更新接口必须传递用户ID,可以不传递用户名,其他参数必须传递。

@Data  
public class UserCreateRequestVO {  
  
	@NotBlank(message = "请选择用户", groups = UpdateUserGroup.class)  
	private String userId;  
	  
	@NotBlank(message = "请输入用户名", groups = CreateUserGroup.class)  
	@Size(max = 128, message = "用户名长度最大为128个字符")  
	private String userName;  
	  
	@Email(message = "请填写正确的邮箱地址")  
	private String email;  
	  
	@Min(value = 18, message = "用户年龄必须大于18岁")  
	@Max(value = 60, message = "用户年龄必须小于60岁")  
	private Integer age;  
	  
	@NotNull(message = "请输入性别")  
	@EnumValid(enumClass = SexEnum.class, message = "输入性别不合法")  
	private Integer sex;  
	  
	@NotEmpty(message = "请输入你的兴趣爱好")  
	@Size(max = 5, message = "兴趣爱好最多可以输入5个")  
	private List<String> hobbies;  
	  
	@DecimalMin(value = "50", inclusive = false, message = "体重必须大于50KG")  
	private BigDecimal weight;  
}

指定了分组的校验规则,分别在对应的分组校验中生效,没有指定分组使用默认分组Default,即对所有的校验都生效。

3.在接口中使用分组

使用 @Validated 注解,并指定要执行的验证组。

@RestController  
@RequestMapping("user")  
@Validated  
@Slf4j  
public class UserController {  
  
	/**  
	* 创建用户  
	* @param requestVO  
	* @return  
	*/  
	@PostMapping("create")  
	public ResultResponse<Void> createUser(@Validated(value = CreateUserGroup.class) @RequestBody UserCreateRequestVO requestVO){  
		return ResultResponse.success(null);  
	}  
	  
	/**  
	* 更新用户  
	* @param requestVO  
	* @return  
	*/  
	@PostMapping("update")  
	public ResultResponse<Void> updateUser(@Validated(value = UpdateUserGroup.class) @RequestBody UserCreateRequestVO requestVO){  
		return ResultResponse.success(null);  
	}
}

我们指定create接口指定CreateUserGroup分组,update接口指定UpdateUserGroup

测试接口如下:

  • 创建用户create接口
    因为userId可以不传递,接口可以校验通过
    image.png

  • 更新用户update接口
    因为必须传递userId, 我们不传时校验不通过,提示选择用户
    image.png

传递userId,不传递userName时,校验通过
image.png

处理验证错误

由上述测试结果中,可以看出接口抛出的一场结果并不是很友好,我们需要统一的处理一下异常以及返回结果,给予用户友好提示。具体实现,在这里不再赘述,可以移步:SpringBoot统一异常处理

总结

Spring Boot Validation通过简化验证流程、集成Bean Validation规范、支持分组验证以及提供友好的错误处理,为Java应用开发者提供了强大而灵活的数据验证机制。最佳实践包括在控制器层使用@Validated注解、合理利用各种验证注解、使用自定义验证注解解决特定业务需求,确保代码清晰简洁、符合规范,并提高系统的可维护性和用户体验。

本文已收录于我的个人博客:码农Academy,专注分享Java技术干货,包括Java基础、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中间件、架构设计、面试题、程序员攻略等

标签:SpringBoot,验证,校验,private,新来,注解,message,public
From: https://www.cnblogs.com/coderacademy/p/17994311

相关文章

  • SpringBoot + SpEL,轻松搞定复杂权限控制
    对于在Springboot中,利用自定义注解+切面来实现接口权限的控制这个大家应该都很熟悉,也有大量的博客来介绍整个的实现过程,整体来说思路如下:自定义一个权限校验的注解,包含参数value配置在对应的接口上定义一个切面类,指定切点在切入的方法体里写上权限判断的逻辑乍一看,没毛病,学......
  • springboot中@Repository 和 @Mapper的区别
    在springboot中他们两都是数据访问层的注解(在定义方面)@Repository:@Repository注解通常用于对DAO(DataAccessObject)组件进行标识。它告诉Spring框架,被注解的类是用于数据访问的组件,可以通过Spring的组件扫描机制自动注册为SpringBean,并且可以将底层的数据访问异......
  • SpringBoot日志配置
    1.简介Spring使用spring5及以后commons-logging被spring直接自己写了。支持log4j2,logback是默认使用的。虽然日志框架很多,但是我们不用担心,使用SpringBoot的默认配置就能工作的很好。 SpringBoot怎么把日志默认配置好的1、每个starter场景,都会导入一个核心场景......
  • 如何改Maven Dependencies的源码,如何把springboot组件的源码改造后使用
    由于springboot提供的源码有些地方不太符合预期,所以需要改动改动,这里就会说到,如何改MavenDependencies的源码。如何把springboot组件的源码改造后使用。v修改源码的几种方式直接在自己工程中建同包同类名的类进行替换采用@Primary注解排除需要替换的jar包中的类@Bean......
  • Springboot CRUD简单实现
    SpringBoot对Spring的改善和优化,它基于约定优于配置的思想,提供了大量的默认配置和实现使用SpringBoot之后,程序员只需按照它规定的方式去进行程序代码的开发即可,而无需再去编写一堆复杂的配置SpringBoot的主要功能如下:起步依赖:SpringBoot以功能化的方式将需要的依赖进行组装,并......
  • SpringBoot启动过程中发布的事件
    springboot启动过程中会发布的事件(启动类的run()方法执行时)ApplicationStartingEvent:应用运行开始事件SpringBoot运行run()方法未进行任务操作时先发布此事件ApplicationEnvironmentPreparedEvent:Environment准备完成事件在Environement准备完成且应用上下文context......
  • springboot学习:建立springboot项目及相关注意事项
    一、建立maven项目后引入依赖:以下没有版本号的依赖表示在springboot父依赖中已锁定相应的版本号必需依赖:1.springboot父依赖<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.5</versio......
  • SpringBoot启动项目报错:java.lang.UnsatisfiedLinkError: D:\files\software\jdk-1
    目录问题描述解决方法:问题描述在运行向的时候出现报错:java.lang.UnsatisfiedLinkError:D:\files\software\jdk-15.0.1\jdk-17.0.3.1\bin\tcnative-1.dll:Can'tloadIA32-bit.dllonaAMD64-bitplatform atjava.base/jdk.internal.loader.NativeLibraries.load(Native......
  • SpringBoot简易教程
     SpringBoot简易教程(01):SpringBoot基础入门SpringBoot简易教程(02):SpringBoot配置文件详解SpringBoot简易教程(03):SpringBoot整合ssmSpringBoot简易教程(04):SpringBoot单元测试SpringBoot简易教程(05):SpringBoot开发RestfulAPI及使用jmeter测试SpringBoot简易教程(06):swagger测试Rest......
  • SpringBoot中使用LocalDateTime踩坑记录
    目录前言近日心血来潮想做一个开源项目,目标是做一款可以适配多端、功能完备的模板工程,包含后台管理系统和前台系统,开发者基于此项目进行裁剪和扩展来完成自己的功能开发。本项目基于Java21和SpringBoot3开发,序列化工具使用的是默认的Jackson,使用SpringDataRedis操作Redis缓......