SpringBoot使用Validation校验参数
准备工作
引入相关依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
约束性注解(简单)说明
@AssertFalse | 可以为null,如果不为null的话必须为false |
@AssertTrue | 可以为null,如果不为null的话必须为true |
@DecimalMax | 设置不能超过最大值 |
@DecimalMin | 设置不能超过最小值 |
@Digits | 设置必须是数字且数字整数的位数和小数的位数必须在指定范围内 |
@Future | 日期必须在当前日期的未来 |
@Past | 日期必须在当前日期的过去 |
@Max | 最大不得超过此最大值 |
@Min | 最大不得小于此最小值 |
@NotNull | 不能为null,可以是空 |
@Null | 必须为null |
@Pattern | 必须满足指定的正则表达式 |
@Size | 集合、数组、map等的size()值必须在指定范围内 |
必须是email格式 | |
@Length | 长度必须在指定范围内 |
@NotBlank | 字符串不能为null,字符串trim()后也不能等于“” |
@NotEmpty | 不能为null,集合、数组、map等size()不能为0;字符串trim()后可以等于“” |
@Range | 值必须在指定范围内 |
@URL | 必须是一个URL |
param:
@Data
public class User {@NotNull(message = "Name cannot be null")private String name;@Min(value = 18, message = "Age must be at least 18")private int age;}
test:
@Testvoid test() {ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorFactory.getValidator();User user = new User();user.setName(null); // 故意设置为 nulluser.setAge(15); // 故意设置为小于 18Set<ConstraintViolation<User>> validate = validator.validate(user);for (ConstraintViolation<User> violation : validate) {System.out.println(violation.getMessage());}}
ValidatorFactory
-
ValidatorFactory
是一个工厂类,用于创建Validator
实例。 -
它负责管理验证器的生命周期,并提供默认的验证器配置。
2. Validation.buildDefaultValidatorFactory()
-
Validation
是一个静态类,提供了构建默认ValidatorFactory
的方法。 -
buildDefaultValidatorFactory()
方法会根据默认的配置(如hibernate-validator
或其他实现)创建一个ValidatorFactory
。
3. validatorFactory.getValidator()
-
通过
ValidatorFactory
获取一个Validator
实例。 -
Validator
是实际执行验证操作的接口,用于验证 Java Bean 中的约束(如@NotNull
、@Size
等注解)。
@Validated的使用时机
@Validated的使用位置较多(可详见源码),但其主流的使用位置却是以下两种:
1、在Controller层中,放在模型参数对象前。
当Controller层中参数是一个对象模型时,只有将@Validated直接放在该模型前,该模型内部的字段才会被校验(如果有对该模型的字段进行约束的话)。
2、在Controller层中,放在类上。
当一些约束是直接出现在Controller层中的参数前时,只有将@Validated放在类上时,参数前的约束才会生效
import com.aspire.model.ValidationBeanModel;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.validation.constraints.DecimalMax;/*** Controller层 --- 初步简单测试 @Validated 的使用位置** 对比测试过程:* 方案一 : 不在类上加@Validated注解,访问这六个接口* 方案二 : 在类上加@Validated注解,再次访问这六个接口** 对比方案一和方案二,可初步得出@Validated的使用时机:* 1.当我们是在模型里面对模型字段添加约束注解,在Controller中使用模型接收数* 据时,@Validated要直接放在该模型参数前才有效。 如: "/test/one"* 2.当我们是直接在Controller层中的参数前,使用约束注解时,@Validated要直接放在类上,* 才会有效。如: /test/six*** @author JustryDeng* @date 2019/1/18 22:22*/
@RestController
@Validated
public class JustryDengController {@RequestMapping(value = "/test/one")public String validatioOne(@Validated ValidationBeanModel.AbcDecimalMax myDecimalMax) {System.out.println(myDecimalMax.getMyDecimalMax());return "one pass!";}@RequestMapping(value = "/test/two")@Validatedpublic String validatioTwo(ValidationBeanModel.AbcDecimalMax myDecimalMax) {System.out.println(myDecimalMax.getMyDecimalMax());return "two pass!";}@RequestMapping(value = "/test/three")public String validatioThree(ValidationBeanModel.AbcDecimalMax myDecimalMax) {System.out.println(myDecimalMax.getMyDecimalMax());return "three pass!";}@RequestMapping(value = "/test/four")public String validatioFour(@Validated @DecimalMax(value = "12.3") String myDecimalMax) {System.out.println(myDecimalMax);return "four pass!";}@RequestMapping(value = "/test/five")@Validatedpublic String validatioFive(@DecimalMax(value = "12.3") String myDecimalMax) {System.out.println(myDecimalMax);return "five pass!";}@RequestMapping(value = "/test/six")@Validatedpublic String validatioSix(@DecimalMax(value = "12.3") String myDecimalMax) {System.out.println(myDecimalMax);return "six pass!";}
}
@Validated与@Valid的简单对比说明
@Valid注解与@Validated注解功能大部分类似;两者的不同主要在于:@Valid属于javax下的,而@Validated属于spring下;@Valid支持嵌套校验、而@Validated不支持,@Validated支持分组,而@Valid不支持。笔者这里只简单介绍@Validated的使用时机。
自定义注解
虽然Bean Validation和Hibernate Validator已经提供了非常丰富的校验注解,但是在实际业务中,难免会碰到一些现有注解不足以校验的情况;这时,我们可以考虑自定义Validation注解。
第一步:创建自定义注解
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import javax.validation.Constraint;import static java.lang.annotation.ElementType.FIELD;/*** 自定义校验注解* 提示:* 1、message、contains、payload是必须要写的* 2、还需要什么方法可根据自己的实际业务需求,自行添加定义即可** 注:当没有指定默认值时,那么在使用此注解时,就必须输入对应的属性值** @author JustryDeng* @date 2019/1/15 1:17*/
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
@Documented
// 指定此注解的实现,即:验证器
@Constraint(validatedBy ={MyValidationImpl.class})
public @interface MyValidation {// 当验证不通过时的提示信息String message() default "校验失败";// 根据实际需求定的方法String contains() default "";// 约束注解在验证时所属的组别Class<?>[] groups() default { };// 负载Class<? extends Payload>[] payload() default { };
}
第二步:编写(第一步中的校验器实现类)该注解
import org.hibernate.validator.internal.engine.ValidationContext;
import org.hibernate.validator.internal.engine.ValueContext;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree;import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;/*** ConstraintsJustryDeng注解 校验器 实现* <p>* 注:验证器需要实现ConstraintValidator<U, V>, 其中 U为对应的注解类, V为被该注解标记的字段的类型(或其父类型)** 注: 当项目启动后,会(懒加载)创建ConstraintValidator实例,在创建实例后会初始化调* 用{@link ConstraintValidator#initialize}方法。* 所以, 只有在第一次请求时,会走initialize方法, 后面的请求是不会走initialize方法的。** 注: (懒加载)创建ConstraintValidator实例时, 会走缓存; 如果缓存中有,则直接使用相* 同的ConstraintValidator实例; 如果缓存中没有,那么会创建新的ConstraintValidator实例。* 由于缓存的key是能唯一定位的, 且 ConstraintValidator的实例属性只有在* {@link ConstraintValidator#initialize}方法中才会写;在{@link ConstraintValidator#isValid}* 方法中只是读。* 所以不用担心线程安全问题。** 注: 如何创建ConstraintValidator实例的,可详见源码* @see ConstraintTree#getInitializedConstraintValidator(ValidationContext, ValueContext)** @author JustryDeng* @date 2019/1/15 1:19*/
public class MyValidationImpl implements ConstraintValidator<MyValidation, Object> {/** 错误提示信息 */private String contains;/*** 初始化方法, 在(懒加载)创建一个当前类实例后,会马上执行此方法** 注: 此方法只会执行一次,即:创建实例后马上执行。** @param constraintAnnotation* 注解信息模型,可以从该模型中获取注解类中定义的一些信息,如默认值等* @date 2019/1/19 11:27*/@Overridepublic void initialize(MyValidation constraintAnnotation) {System.out.println(constraintAnnotation.message());this.contains = constraintAnnotation.contains();}/*** 校验方法, 每个需要校验的请求都会走这个方法** 注: 此方法可能会并发执行,需要根据实际情况看否是需要保证线程安全。** @param value* 被校验的对象* @param context* 上下文** @return 校验是否通过*/@Overridepublic boolean isValid(Object value, ConstraintValidatorContext context) {if (value == null) {return false;}if (value instanceof String) {String strMessage = (String) value;return strMessage.contains(contains);} else if (value instanceof Integer) {return contains.contains(String.valueOf(value));}return false;}}
第三步:自定义注解简单使用测试
@Testvoid test2() {ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();Validator validator = validatorFactory.getValidator();User user = new User();user.setName("ddd"); // 故意设置为 nulluser.setAge(15); // 故意设置为小于 18Set<ConstraintViolation<User>> validate = validator.validate(user);for (ConstraintViolation<User> violation : validate) {System.out.println(violation.getMessage());}}
@Data
public class User {@MyValidation(message = "校验测试",contains = "a")private String name;@Min(value = 18, message = "Age must be at least 18")private int age;}
效果:
对注解抛出的异常进行处理
说明:当注解校验不通过时,直接将异常信息返回给前端其实并不友好,我们可以将异常包装一下,返回给前端。
情况一:使用BindingResult类来容纳异常信息,当校验不通过时,不影响正常程
序往下走。我们只需要处理BindingResult中的异常信息即可。
处理前:
参数模型是这样的:
Controller是这样的
使用postman测试,当校验不通过时显示如下:
处理后:
参数模型是这样的(没有变):
Controller是这样的(在@Validated注解的参数后,紧接着加上BindingResult):
再次使用postman测试,当校验不通过时显示如下:
postman中返回了数据,说明虽然参数错误,但是不影响程序的执行。
程序在控制台输出了如下信息:
可见,后台已经获悉了错误,至于怎么处理,这就看伟大的程序员们了。
情况二(推荐):通过SpringMVC全局异常处理器来处理异常。
描述:如果不采用BindingResult来容纳异常信息时,那么异常会被向外抛出。注解校验不通过时,可能抛出的异常有BindException异常、ValidationException异常(或其子类异常)、
MethodArgumentNotValidException异常。
处理前:
示例一:Controller和对应的参数模型是这样的:
使用postman测试,当校验不通过时显示如下:
示例二:Controller是这样的:
使用postman测试,当校验不通过时显示如下:
注:ConstraintViolationException异常是ViolationException异常的子异常。
示例三:Controller是这样的:
注:此处的User模型与情况一里给出的模型是一样的,这里就不再给出了。
使用postman测试,当校验不通过时显示如下:
进行处理:加入全局异常处理器:
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.HashMap;
import java.util.Map;/*** SpringMVC统一异常处理** @author JustryDeng* @date 2019/10/12 16:28*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {/*** 处理Validated校验异常* <p>* 注: 常见的ConstraintViolationException异常, 也属于ValidationException异常** @param e* 捕获到的异常* @return 返回给前端的data*/@ResponseStatus(code = HttpStatus.BAD_REQUEST)@ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})public Map<String, Object> handleParameterVerificationException(Exception e) {log.error(" handleParameterVerificationException has been invoked", e);Map<String, Object> resultMap = new HashMap<>(4);resultMap.put("code", "100001");String msg = null;/// MethodArgumentNotValidExceptionif (e instanceof MethodArgumentNotValidException) {BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();// getFieldError获取的是第一个不合法的参数(P.S.如果有多个参数不合法的话)FieldError fieldError = bindingResult.getFieldError();if (fieldError != null) {msg = fieldError.getDefaultMessage();}/// BindException} else if (e instanceof BindException) {// getFieldError获取的是第一个不合法的参数(P.S.如果有多个参数不合法的话)FieldError fieldError = ((BindException) e).getFieldError();if (fieldError != null) {msg = fieldError.getDefaultMessage();}/// ValidationException 的子类异常ConstraintViolationException} else if (e instanceof ConstraintViolationException) {/** ConstraintViolationException的e.getMessage()形如* {方法名}.{参数名}: {message}* 这里只需要取后面的message即可*/msg = e.getMessage();if (msg != null) {int lastIndex = msg.lastIndexOf(':');if (lastIndex >= 0) {msg = msg.substring(lastIndex + 1).trim();}}/// ValidationException 的其它子类异常} else {msg = "处理参数时异常";}resultMap.put("msg", msg);return resultMap;}}
处理后,使用postman再次进行上述两个请求:
可见,异常处理成功!
经常存在加参数校验后就不加触发注解的情况,前一段公司在做国际化的时候就发现了两个服务一个参数注解都没触发的情况,让人痛心疾首,那么有没有可以不加参数注解就能自动为我们触发参数方法呢?
AOP实现触发参数校验
公司部分服务是这样做的
/**** @Description:参数效验拦截器* Author Version Date Changes* zjf 1.0 2020年11月30日 Created*/
@Aspect
@Component
@Slf4j
public class ValidateParameterAspectAdvice implements Ordered {@Autowiredprivate ParamCheckSpringUtils paramCheckSpringUtils;/*** (non-Javadoc)* @see Ordered#getOrder()*/@Overridepublic int getOrder() {return 1000;}@Before("execution(* com.echronos.iform.feign.*.*(..)) || execution(* com.echronos.iform.controller.*.*(..))")public void before(JoinPoint pjd) {Object[] args = pjd.getArgs();if (args.length > 0) {Object oneParam = args[0];MethodSignature signature = (MethodSignature) pjd.getSignature();Method method = signature.getMethod();Annotation[][] parameterAnnotations = method.getParameterAnnotations();List<Class<?>> list = new ArrayList<>();for (Annotation[] annotations : parameterAnnotations) {for (Annotation annotation : annotations) {if (annotation instanceof ConvertGroup) {list.add(Default.class);ConvertGroup convertGroup = (ConvertGroup) annotation;Class<?> curClass = convertGroup.to();list.add(curClass);}else if (annotation instanceof ConvertGroup.List) {ConvertGroup.List convertGroupList = (ConvertGroup.List) annotation;ConvertGroup[] groups = convertGroupList.value();for (ConvertGroup convertGroup : groups) {Class<?> curClass = convertGroup.to();list.add(curClass);}}}}Class<?> targetClass = method.getDeclaringClass();log.info("{}方法,入参为:{}", targetClass.getName() + "#" + method.getName(), FastJsonUtils.toJSONNoFeatures(oneParam));//异常处理String check = null;if(list.size() > 1){Class[] arrClass = list.toArray(new Class[list.size()]);check = paramCheckSpringUtils.checkParam(oneParam,arrClass);}else{check = paramCheckSpringUtils.checkParam(oneParam);}if (check != null) {throw new ParamsValidateException(CommonResultCode.CommonResultEnum.BAD_REQUEST.getCode(), check);}}}
}
@Component
public class ParamCheckSpringUtils {@Autowiredprivate Validator validator;public ParamCheckSpringUtils() {}public <T> String checkParam(final T obj, final Class<?>... group) {List<String> list = new ArrayList();Set<ConstraintViolation<T>> constraintViolations = this.validator.validate(obj, (Class[])group);StringBuilder strBuilder = new StringBuilder();if (constraintViolations != null && constraintViolations.size() > 0) {Iterator var6 = constraintViolations.iterator();while(var6.hasNext()) {ConstraintViolation<T> cv = (ConstraintViolation)var6.next();if (!list.contains(String.valueOf(cv.getPropertyPath()))) {list.add(String.valueOf(cv.getPropertyPath()));strBuilder.append(cv.getMessage()).append(";");}}return strBuilder.toString();} else {return null;}}public <T> String checkParam(final T obj, final Class<?> group, final String... args) {StringBuilder strBuilder = new StringBuilder("");if (args != null) {String[] var5 = args;int var6 = args.length;for(int var7 = 0; var7 < var6; ++var7) {String param = var5[var7];Set<ConstraintViolation<T>> constraintViolations = this.validator.validateProperty(obj, param, new Class[]{group});if (constraintViolations != null && constraintViolations.size() > 0) {Iterator var10 = constraintViolations.iterator();while(var10.hasNext()) {ConstraintViolation<T> cv = (ConstraintViolation)var10.next();strBuilder.append(cv.getMessage()).append(";");}}}}return strBuilder.toString().equals("") ? null : strBuilder.toString();}
}
相关文章:
SpringBoot使用Validation校验参数
准备工作 引入相关依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency> 约束性注解(简单)说明 AssertFalse可以为null,如果不为null的话必…...
AAAI-2024 | 大语言模型赋能导航决策!NavGPT:基于大模型显式推理的视觉语言导航
作者:Gengze Zhou, Yicong Hong, Qi Wu 单位:阿德莱德大学,澳大利亚国立大学 论文链接: NavGPT: Explicit Reasoning in Vision-and-Language Navigation with Large Language Models (https://ojs.aaai.org/index.p…...
Scala迭代更新
在Scala中,迭代器(Iterator)是一种用于遍历集合(如数组、列表、集合等)的元素而不暴露其底层表示的对象。迭代器提供了一种统一的方法来访问集合中的元素,而无需关心集合的具体实现。 在Scala中,…...
算法练习——位运算
前言:位运算的方法大多比较抽象,很难想到。 一:判断字符是否唯一 题目要求: 解题思路: 法一:使用hash的思想,统计每一个字母出现的次数,再通过一次循环遍历查询是否有超过1的字母&…...
“文件夹管理”与“标签管理”如何合理使用
在现代信息化的工作与生活环境中,文件夹管理与标签管理是两种常见的信息组织方法。合理使用文件夹与标签管理、提高信息检索效率、优化工作流程是实现高效信息管理的关键。其中,提高信息检索效率尤为重要,因为在海量的数据和文件中࿰…...
【学习总结|DAY023】Java高级技术
大家好,今天我们来聊聊 Java 中的几个高级技术:单元测试、反射、注解和动态代理。这些技术在源码、框架和架构师层面发挥着重要作用,掌握它们能让我们更深入地理解 Java 的底层原理,并提升代码质量和开发效率。 单元测试…...
java 对mongodb操作封装工具类
在 Java 中,封装 MongoDB 操作的工具类是非常常见的做法。使用 MongoDB 官方的 Java 驱动程序,结合常用的工具类封装,可以使得与 MongoDB 的交互更加方便和清晰。下面是一个简单的 MongoDB 操作封装工具类的示例代码。 前提 首先࿰…...
Spark-Streaming集成Kafka
Spark Streaming集成Kafka是生产上最多的方式,其中集成Kafka 0.10是较为简单的,即:Kafka分区和Spark分区之间是1:1的对应关系,以及对偏移量和元数据的访问。与高版本的Kafka Consumer API 集成时做了一些调整,下面我们…...
最大似然检测在通信解调中的应用
最大似然检测(Maximum Likelihood Detection,MLD),也称为最大似然序列估计(Maximum Likelihood Sequence Estimation,MLSE),是一种在通信系统中广泛应用的解调方法。其核心思想是在给…...
Bert各种变体——RoBERTA/ALBERT/DistillBert
RoBERTa 会重复一个语句10次,然后每次都mask不同的15%token。丢弃了NSP任务,论文指出NSP任务有时甚至会损害性能。使用了BPE ALBERT 1. 跨层参数共享 可以共享多头注意力层的参数,或者前馈网络层的参数,或者全部共享。 实验结果…...
力扣周赛T2-执行操作后不同元素的最大数量
给你一个整数数组 nums 和一个整数 k。 你可以对数组中的每个元素 最多 执行 一次 以下操作: 将一个在范围 [-k, k] 内的整数加到该元素上。 返回执行这些操作后,nums 中可能拥有的不同元素的 最大 数量。 示例 1: 输入: nums [1…...
uniapp 3分钟集成轮播广告图
先上效果图 顶部广告栏为 移动app常见需求,今天主要演示如何快速实现.这里还是基于 《星云erp-移动版》演示版 (自行下载 导入 Hbuilder, 后端接口可以直接使用我演示接口,不需要修改) 第一步: 组件选择 我们直接使用uni-swipe…...
图像修复和编辑大一统 | 腾讯北大等联合提出BrushEdit:BrushNet进阶版来了
文章链接:https://arxiv.org/pdf/2412.10316 项目链接:https://liyaowei-stu.github.io/project/BrushEdit 亮点直击 提出了BrushEdit,这是先前BrushNet模型的高级迭代版本。BrushEdit通过开创基于修复(inpainting)的图…...
极狐GitLab 17.7正式发布,可从 GitLab 丝滑迁移至极狐GitLab【二】
GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料: 极狐GitLab 官网极狐…...
Python基础知识回顾
数据类型 Python可以区分整数(integers、下文简写为int)、浮点数(float)、字符串(string)和布尔值(Boolean)等数据类型。 1)int是可正可负的整数 2)float包…...
SpringCloud2023集成Nacos2.4.3
基本都是最新版,踩了两天的坑终于集成上了,实现了多环境配置。 使用版本 关键应用版本备注Java21Oracle OpenJDK 21.0.5Spring Boot3.2.4Spring Cloud2023.0.1Spring Cloud Alibaba2023.0.1.3Nacos2.4.3单机模式 nacos安装 我学习过程使用的是windows…...
数势科技指标平台, 让数据产生最大价值
近来,指标体系和指标平台的重要性正被越来越多的业界同仁所认可。作为行业领先的数据智能产品提供商,数势科技最早推出了统一指标开发管理平台这一突破性产品(2021年获得软著),并首家完成了中国信通院数据指标管理平台…...
【玩转MacBook】Maven安装
下载Maven 官网: https://maven.apache.org/download.cgi 下载 Zip 类型的压缩包: 配置环境变量 以管理员身份编辑配置文件。注意,由于 MacBook 上使用了 zsh 命令行,所以需要编辑~/.zshrc文件而不是~/.bash_profile文件&am…...
OpenGL笔记(1)
GLFW的函数说明 GLFW: Window guide 窗口创建提示 在创建窗口和上下文之前,可以设置多个提示。有些提示影响窗口本身,另一些则影响帧缓冲区或上下文。这些提示每次通过 glfwInit 初始化库时都会被重置为默认值。 整数值的提示可以通过 glfwWindowHint …...
前端Python应用指南(二)深入Flask:理解Flask的应用结构与模块化设计
《写给前端的python应用指南》系列: (一)快速构建 Web 服务器 - Flask vs Node.js 对比 书接上文,这一篇将会深入了解下Flask,这个轻量级的Web框架,非常适合用来构建小型应用和快速原型开发。但是&#x…...
前端Python应用指南(三)Django vs Flask:哪种框架适合构建你的下一个Web应用?
《写给前端的python应用指南》系列: (一)快速构建 Web 服务器 - Flask vs Node.js 对比(二)深入Flask:理解Flask的应用结构与模块化设计 在上一篇博文中,我们深入探讨了Flask框架,…...
Unity3D Huatuo技术原理剖析详解
前言 在游戏开发领域,Unity3D凭借其强大的跨平台能力和丰富的功能,成为了众多开发者的首选工具。而在Unity3D的生态系统中,Huatuo作为一款重要的插件,为游戏开发带来了极大的便利。本文将深入剖析Huatuo的技术原理,并…...
复习打卡大数据篇——Hadoop HDFS 03
目录 1. HDFS元数据存储 2. HDFS HA 高可用 1. HDFS元数据存储 HDFS中的元数据按类型可以分为: 文件系统的元数据:包括文件名、目录名、修改信息、block的信息、副本信息等。datanodes的状态信息:比如节点状态、使用率等。 HDFS中的元数…...
宠物行业的出路:在爱与陪伴中寻找增长新机遇
在当下的消费市场中,如果说有什么领域能够逆势而上,宠物行业无疑是一个亮点。当人们越来越注重生活品质和精神寄托时,宠物成为了许多人的重要伴侣。它们不仅仅是家庭的一员,更是情感的寄托和生活的调剂。然而,随着行业…...
使用Turtle库实现,鼠标左键绘制路径,用鼠标右键结束绘制,小海龟并沿路径移动
使用Turtle库实现,鼠标左键绘制路径,用鼠标右键结束绘制,小海龟并沿路径移动 Turtle库是Python标准库的一部分,它提供了一种基于命令的图形绘制方式。Turtle模块通过一个“海龟”(Turtle)对象在屏幕上移动…...
海格通信嵌入式面试题及参考答案
计算电路的最高工作频率如何计算? 计算电路的最高工作频率主要考虑电路中的关键路径延迟。关键路径是指在整个电路中,信号传播延迟最长的路径。电路的最高工作频率的倒数就是时钟周期,而时钟周期必须大于关键路径的延迟时间。 首先要确定电路中各个模块的延迟。比如对于组合…...
3D几何建模引擎Parasolid功能解析
一、什么是Parasolid? Parasolid是由Siemens PLM Software开发的高精度精密几何建模引擎。它全面评估CAD(计算机辅助设计)、CAM(计算机辅助制造)、CAE(计算机辅助工程)、PLM(产品生…...
AI的进阶之路:从机器学习到深度学习的演变(四)
AI的进阶之路:从机器学习到深度学习的演变(三) 五、深度学习的应用领域 深度学习的应用领域广泛,涵盖了计算机视觉、自然语言处理、语音识别和推荐系统等多个方面。以下将详细探讨这些关键应用领域,展示深度学习在不同…...
【ES6复习笔记】rest参数(7)
什么是 rest 参数? rest 参数是 ES6 引入的一个特性,它允许我们将一个不定数量的参数表示为一个数组。使用 rest 参数可以更方便地处理函数的参数,尤其是在参数数量不确定的情况下。 如何使用 rest 参数? 在函数定义中…...
安装MongoDB,环境配置
官网下载地址:MongoDB Shell Download | MongoDB 选择版本 安装 下载完成双击打开 点击mongodb-windows-x86_64-8.0.0-signed 选择安装地址 检查安装地址 安装成功 二.配置MongoDB数据库环境 1.找到安装好MongoDB的bin路径 复制bin路径 打开此电脑 -> 打开高级…...
ubuntu 网络管理
1 查看ip地址 rootu22-tools-20:~# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever…...
flask后端开发(1):第一个Flask项目
目录 一、Helloworddebug、host、port的配置 gitcode地址: https://gitcode.com/qq_43920838/flask_project.git 一、Helloword 一般是会创建两个文件夹和app.py app.py from flask import FlaskappFlask(__name__)app.route(/) def hello_world():return Hello…...
详解下c语言中struct和union的对齐规则
接触过c语言的同学应该都知道字节对齐。有些时候我们很容易弄错字节对齐的方式,特别是涉及到struct(结构体)和union(联合体)时。今天我们通过详细例子来说明下struct和union的对齐规则,以便了解各种struct和…...
虚拟机桥接模式网络连接不上解决方法
可能是桥接模式自动配置网络地址的时候没配好,自己手动配置一下。先看看windows里的wifi的ip 把虚拟机的网络设置打开ipv4把地址、子网掩码、网关输进去,然后再连接...
MySQL用表组织数据
用表组织数据 文章目录 用表组织数据一.四种完整性约束二.数值类型2-1三.数值类型2-2四.字符串.日期类型五.设置1.设置主键2.设置标识列3.设置非空4.设置默认值 六.主外键建立后注意事项 一.四种完整性约束 1.域完整性 列 域完整性约束方法:限制数据类型,检查约束,外键约束,默…...
基于python 微信小程序的医院就诊小程序
标题:基于 Python 微信小程序的医院就诊小程序 内容:1.摘要 基于 Python 微信小程序的医院就诊小程序旨在解决传统医院就诊流程繁琐、排队时间长等问题。通过小程序,患者可以在线预约挂号、查询医生信息、在线支付等,提高就诊效率。本小程序采用 Python…...
VUE3+django接口自动化部署平台部署说明文档(使用说明,需要私信)
网址连接:http://118.25.110.213:5200/#/login 账号/密码:renxiaoyong 1、VUE3部署本地。 1.1本地安装部署node.js 1.2安装vue脚手架 npm install -g vue/cli # 或者 yarn global add vue/cli1.3创建本地项目 vue create my-vue-project1.4安装依赖和插…...
【MySQL】十三,关于MySQL的全文索引
MySQL的全文索引用于搜索文本中的关键字,类似于like查询。 演示 建表 CREATE TABLE demo (id INT(11) NOT NULL,name CHAR(30) NOT NULL,age INT(11) NOT NULL,info VARCHAR(255),primary key(id),fulltext index futxt_idx_info(info) );此表的默认存储引擎为In…...
人工智能学习框架入门教程(一)
人工智能(AI)学习框架是指为开发、训练和部署人工智能模型提供的结构化工具和环境。它们帮助开发者实现AI项目的高效性、可扩展性、可维护性,并提供了优化算法、模型训练、评估、调优等功能。根据任务的不同,人工智能框架可以分为…...
NNDL 作业11 LSTM
习题6-4 推导LSTM网络中参数的梯度, 并分析其避免梯度消失的效果 先来推个实例: 看式子中间,上半部分并未有连乘项,而下半部分有到的连乘项,从这可以看出,LSTM能缓解梯度消失,梯度爆炸只是不易…...
Git 操作全解:从基础命令到高级操作的实用指南
文章目录 1.基本命令1.初始化仓库2.克隆远程仓库3.查看当前仓库状态4.查看提交日志5.添加文件到暂存区6.提交更改7.查看仓库的配置信息 2.分支操作1.查看所有分支2.创建新分支3.切换名称4.创建并切换到新分支5.删除分支6.查看当前分支 3.合并分支1.合并分支2.解决合并冲突 4.远…...
CSS(四)display和float
display display 属性用于控制元素的显示类型,用的 display 值包括: block:块级元素 使元素成为块级元素,占据一整行,前后有换行宽度默认为父容器的 100%,可以设置宽高,支持 margin、padding、…...
python中使用selenium执行组合快捷键ctrl+v不生效问题
在执行ctrlv进行粘贴时,绑定一个页面上的元素对象(无论元素对象是否是引用过期或者是粘贴的目标文本区,但前提需要粘贴的目标文本区获取焦点)执行ctrlv后可以生效。执行粘贴组合快捷键(ctrlv)的示例代码 se…...
数据结构 C/C++(实验五:图)
(大家好,今天分享的是数据结构的相关知识,大家可以在评论区进行互动答疑哦~加油!💕) 目录 提要:实验题目 一、实验目的 二、实验内容及要求 三、源程序及注释 实验1代码 (折半查…...
非零掩码矩阵邻接矩阵
文章目录 1. 举例:2. python 代码3. 邻接矩阵 1. 举例: 在深度学习过程中,我们经常会用到掩码矩阵,比如我们有一个矩阵A表示如下,希望得到矩阵B,在矩阵A的非零位置表示为1,零位置表示为0, A …...
Docker安装
目录 1. 联网安装 Docker 2. 离线安装 Docker 3. 安装 Docker Compose 4. 卸载 Docker 和 Docker Compose 1. 联网安装 Docker 在 CentOS 上通过 yum 安装 Docker: # 安装 Docker yum -y install docker # 启动 Docker systemctl start docker # 查看 D…...
嵌入式驱动开发详解21(网络驱动开发)
文章目录 前言以太网框架ENET 接口简介MAC接口MII \ RMII 接口MDIO 接口RJ45 接口 PHY芯片以太网驱动驱动挂载wifi模块挂载后续 前言 linux驱动主要是字符设备驱动、块设备驱动还有网络设备驱动、字符设备驱动在本专栏前面已经详细将解了,网络设备驱动本文会做简要…...
2024年12月25日Github流行趋势
项目名称:system-design-primer 项目维护者:donnemartin, cclauss, satob, fluency03, linhe0x0项目介绍:学习如何设计大规模系统。为系统设计面试做准备。包括 Anki 卡片。项目star数:282,387项目fork数:47,226 项目…...
6、mysql的MHA故障切换
MHA的含义 MHA:master high availability,建立在主从复制基础上的故障切换的软件系统。 主从复制的单点问题: 当主从复制当中,主服务器发生故障,会自动切换到一台从服务器,然后把从服务器升格成主&…...
#error: WinSock.h has already been included解决方案
原因: 在工程中使用了 Boot 库之后,使用了socket、tcp 相关的头文件,在其他地方还是包括了头文件<windows.h>,该头文件内包含了<winsock.h>。导致遇到报错问题:WinSock.h has already been included 解决…...