SpringBoot——关于controller参数校验

news2025/1/17 2:50:00

参数校验主要使用两个标签@Validated和@Valid;

@Valid是Hibernate的注解校验,@Validated是spring的,是@Valid的增强;这两个标签也有一些不同之处,@Valid可以标注在成员属性上也可以嵌套校验,而@Validated不行,但是@Validated可以使用分组校验;

maven导入:

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

通常用到的注解基本都在javax.validation.constraints包下,基本都有value(设定值)、message(设置错误消息)、groups(指定分组)属性:

  • @AssertFalse:必须为false,支持boolean和Boolean,null是有效的;
  • @AssertTrue:必须为true,支持boolean和Boolean,null是有效的;
  • @DecimalMax:必须是一个小于或者小于等于设定值的数字,可以用inclusive指定是否包含数字(默认true),并且value是String类型的,支持BigDecimal、BigInteger、CharSequence、byte / short / int / long以及它们的包装类(由于舍入原因不支持double和float),null是有效的;
  • @DecimalMin:必须是一个大于或者大于等于设定值的数字,其他同@DecimalMax;
  • @Digits:设定可接受范围内的数字,必须指定integer(整数位数)和fraction(小数位数),支持BigDecimal、BigInteger、CharSequence、byte / short / int / long以及它们的包装类,null是有效的;
  • @Email:必须是一个正确格式的邮箱,可以使用regexp指定正则表达式(默认是任意字符串),可以使用flags指定正则表达式的选项,null是有效的;
  • @Future:必须是一个未来的瞬间、日期或时间(Now是虚拟机默认的当前时区的时间),支持java.util.Date、java.util.Calendar、java.time.Instant、java.time.LocalDate、java.time.LocalDateTime、java.time.LocalTime、java.time.MonthDay、java.time.OffsetDateTime、java.time.OffsetTime、java.time.Year、java.time.YearMonth、java.time.ZonedDateTime、java.time.chrono.HijrahDate、java.time.chrono.JapaneseDate、java.time.chrono.MinguoDate、java.time.chrono.ThaiBuddhistDate,null是有效的;
  • @FutureOrPresent:必须是现在或未来的瞬间、日期或时间,其他同@Future;
  • @Max:必须是小于等于指定值的数字,value是long类型,支持BigDecimal、BigInteger、byte / short / int / long以及它们的包装类(不支持float和double),null是有效的;
  • @Min:必须是大于等于指定值的数字,其他同@Max;
  • @Negative:必须是一个严格的负数,0为无效值,支持BigDecimal、BigInteger、byte / short / int / long / float / double以及它们的包装类,null是有效的;
  • @NegativeOrZero,必须是负数或者0,其他同@Negative;
  • @NotBlank:不能为null,并且至少包含一个非空白字符,接受CharSequence;
  • @NotEmpty:不能为null或空(集合),支持CharSequence(字符序列长度)、Collection(集合size)、Map(map size)、Array(数组长度);
  • @NotNull:不能为null,支持所有类型;
  • @Null:必须为null,支持所有类型;
  • @Past:必须是一个过去的瞬间、日期或时间,其他同@Future;
  • @PastOrPresent:必须是现在或过去的瞬间、日期或时间,其他同@Future;
  • @Pattern:必须符合指定的正则表达式,必须使用regexp参数指定正则表达式;
  • @Positive:必须是一个严格的正数,0为无效值,其他同@Negative;
  • @PositiveOrZero:必须是正数或者0,其他同@Negative;
  • @Size:指定元素大小必须在指定范围内(包括边界值),使用min指定下边界(默认0),使用max指定上边界(默认Integer.MAX_VALUE),支持CharSequence、Collection、Map、Array,null是有效的;

单参数校验

在controller类上添加@Validated标签,在方法的参数前加验证标签,并且同一个参数可以添加多个标签;

启动类:(使用默认配置,端口8080)

/**
 * 2022年12月2日下午4:00:48
 */
package testspringboot.test6paramvalidation;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author XWF
 *
 */
@SpringBootApplication
public class Test6Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		SpringApplication.run(Test6Main.class, args);
		
	}

}

 controller类:

/**
 * 2022年12月2日下午4:05:34
 */
package testspringboot.test6paramvalidation;

import java.util.List;
import java.util.stream.Collectors;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author XWF
 *
 */
@RestController
@RequestMapping("/test6")
@Validated
public class Test6Controller {
	
	@RequestMapping("/a")
	public String a(@NotNull(message = "参数s不能为null") String s, @Min(5) @Max(value = 10) long a) {
		System.out.println(s);
		System.out.println(a);
		return String.format("s:%s a:%d", s, a);
	}
	
}

postman测试:

返回的错误msg也可以使用自定义设定,使用@RestControllerAdvice注释一个类,然后在类里定义各种错误msg,就像这样:

package testspringboot.test6paramvalidation;

import java.util.List;
import java.util.stream.Collectors;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class ValidException {

	@ExceptionHandler(value = MethodArgumentNotValidException.class)
    public String handleValidException(MethodArgumentNotValidException e) {
        List<String> msgList = e.getBindingResult().getAllErrors()
        		.stream()
        		.map(ObjectError::getDefaultMessage)
        		.collect(Collectors.toList());
        return "MethodArgumentNotValidException: " + msgList.toString();
    }

    @ExceptionHandler(value = ConstraintViolationException.class)
    public String handleConstraintViolationException(ConstraintViolationException e) {
        List<String> msgList = e.getConstraintViolations()
                .stream()
                .map(ConstraintViolation::getMessage)
            	.collect(Collectors.toList());
        return "ConstraintViolationException: " + msgList.toString();//返回错误描述
    }
    
}

再次测试结果:

默认验证所有参数,即使前面验证不通过也会继续验证,可以设置快速失败,使验证失败立即返回不继续验证;

自定义注入Validator类:

package testspringboot.test6paramvalidation;

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ValidatConfig {

	@Bean
	public Validator validator() {
		ValidatorFactory vfactory = Validation.byProvider(HibernateValidator.class)
				.configure()
				.failFast(true)//开启快速失败
				.buildValidatorFactory();
		return vfactory.getValidator();
		
	}
	
}

再次测试结果,只显示一个错误msg了:

实体类校验

只需要在controller类的方法实体类参数前加@Validated或者@Valid标签,实体类里的属性前加验证标签,controller类上可以不用@Validated标签也行;

实体类:

package testspringboot.test6paramvalidation;

import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;

public class Bparam {

	@NotNull
	public String s;
	
	@Max(value = 10, message = "Bparam的x参数不能超过10")
	public int x;

	public String getS() {
		return s;
	}

	public void setS(String s) {
		this.s = s;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	@Override
	public String toString() {
		return "Bparam [s=" + s + ", x=" + x + "]";
	}
	
}

controller类里的方法:

	@RequestMapping("/b")
	public String b(@Valid Bparam b) {
		return b.toString();
	}

测试:

另外错误消息也可以在controller类的方法参数里接收,参数里使用BindingResult就可以处理:

	@RequestMapping("/b")
	public String b(@Valid Bparam b, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return b.toString();
	}

使用post的消息体接收参数也一样,在参数前多加一个@RequestBody:

	@RequestMapping("/b")
	public String b(@RequestBody @Validated Bparam b, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return b.toString();
	}

分组校验

可以为同一属性设置不同情况下应用不同的注解标签,需要在注解标签里使用groups参数,groups是一个class集合,一个标签可以设置多个group,在controller类里方法的参数前的@Validated标签里使用value指定要使用的group验证(可以指定多个group验证),没有设置groups的标签默认属于Default.class的group,设置group的class通常使用interface,可以写在外面或者直接写到实体类内部;

实体类:

/**
 * 2023年1月13日上午11:08:47
 */
package testspringboot.test6paramvalidation;

import javax.validation.constraints.AssertFalse;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

/**
 * @author XWF
 *
 */
public class Cparam {

	@AssertTrue(message = "b应为true", groups = CparamBTrue.class)
	@AssertFalse(message = "b应为false", groups = CparamBFalse.class)
	public boolean b;
	
	@NotBlank
	@Size(min = 1, max = 5, message = "s的长度1~5")
	public String s;
	
	@Min(20)
	public int i;
	
//	interface CparamBTrue{}
//	interface CparamBFalse{}
}
interface CparamBTrue{}
interface CparamBFalse{}

controller方法:

	@RequestMapping("/c1")
	public String c1(@RequestBody @Validated(CparamBTrue.class) Cparam c, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return "OK";
	}
	
	@RequestMapping("/c2")
	public String c2(@RequestBody @Validated(value = {CparamBFalse.class, Default.class}) Cparam c, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return "OK";
	}

分组测试:

c1只验证了group是CparamBTrue的成员b,c2除了验证了group是CparamBFalse的成员b,也验证了没有设置groups的s和i;

另外也可以设置动态组校验,根据某些条件和情况设置验证的groups,需要在实体类上添加@GroupSequenceProvider标签指定实现了DefaultGroupSequenceProvider接口并实现接口里getValidationGroups方法的class,getValidationGroups方法返回List<Class<?>>,即为当前请求需要使用的groups(返回值相当于controller类方法参数前@Validated标签里的value的作用);

例如根据实体类内boolean值指定int值使用正负数:

实体类:

/**
 * 2023年1月13日下午3:03:56
 */
package testspringboot.test6paramvalidation;

import javax.validation.constraints.Negative;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;

import org.hibernate.validator.group.GroupSequenceProvider;

/**
 * @author XWF
 *
 */
@GroupSequenceProvider(value = C3paramGroupProvider.class)
public class C3param {

	@NotNull(message = "b不能为null")
	public boolean b;
	
	@NotNull
	@Positive(message = "b为true时i应大于0", groups = BTrue.class)
	@Negative(message = "b为false时i应小于0", groups = BFalse.class)
	public int i;
	
	@Override
	public String toString() {
		return "C3param [b=" + b + ", i=" + i + "]";
	}
	interface BTrue{}
	interface BFalse{}
	
}

GroupProvider:

/**
 * 2023年1月13日下午3:10:32
 */
package testspringboot.test6paramvalidation;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.validator.spi.group.DefaultGroupSequenceProvider;

/**
 * @author XWF
 *
 */
public class C3paramGroupProvider implements DefaultGroupSequenceProvider<C3param> {

	@Override
	public List<Class<?>> getValidationGroups(C3param object) {
		System.out.println("obj:" + object);
		List<Class<?>> groupList = new ArrayList<>();
		groupList.add(C3param.class);//实体类需要加入
		if (object != null) {//该方法会调用多次,object可能为null
			//b为true时使用BTrue.class组,b为false时使用BFalse.class组
			groupList.add(object.b ? C3param.BTrue.class : C3param.BFalse.class);
		}
		return groupList;
	}

}

controller方法:

	@RequestMapping("/c3")
	public String c3(@RequestBody @Validated C3param c3, BindingResult result) {
		System.out.println("param:" + c3);
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return "OK";
	}

测试:

嵌套校验

实体类成员为另一个级联的类时,需要在成员前使用@Valid标签(支持嵌套),并且提供该级联的成员属性的get方法,另外级联类内部也需要提供需要验证的成员属性的get方法(不验证的成员不用get方法)

第一层实体类:

/**
 * 2023年1月13日下午3:27:12
 */
package testspringboot.test6paramvalidation;

import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;

/**
 * @author XWF
 *
 */
public class D1param {

	@AssertTrue(message = "D1param.b必须为true")
	public boolean b;
	
	@Valid
	public D2param d2;
	
	public D2param getD2() {//级联对象需要get方法
		return d2;
	}
	
}

第二层实体类:

/**
 * 2023年1月13日下午3:27:28
 */
package testspringboot.test6paramvalidation;

import javax.validation.Valid;
import javax.validation.constraints.Positive;

/**
 * @author XWF
 *
 */
public class D2param {

	@Positive(message = "D2param.i必须为正数")
	public int i;
	
	public String s;//不验证,不需get方法
	
	@Valid
	public D3param d3;
	
	public int getI() {//成员需要get方法
		return i;
	}

	public D3param getD3() {//级联对象需要get方法
		return d3;
	}

}

第三层实体类:

/**
 * 2023年1月13日下午3:37:33
 */
package testspringboot.test6paramvalidation;

import javax.validation.constraints.NotNull;

/**
 * @author XWF
 *
 */
public class D3param {

	@NotNull(message = "D3param.s不能为null")
	public String s;

	public String getS() {//成员需要get方法
		return s;
	}
	
}

controller方法:

	@RequestMapping("/d")
	public String d(@RequestBody @Validated D1param d1, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return "OK";
	}

测试:

自定义注解

定义一个注解,使用@Retention、@Target、@Constraint标签注释,并携带三个方法message()、groups()、payload(),并在@Constraint标签里使用validatedBy属性指定自定义验证类,自定义验证类实现ConstraintValidator<A extends Annotation, T>接口的boolean isValid(T value, ConstraintValidatorContext context)方法,判断验证是否通过;

自定义注解:(功能:验证是偶数)

/**
 * 2023年1月13日下午4:24:06
 */
package testspringboot.test6paramvalidation;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Retention(RUNTIME)
@Target(FIELD)
@Constraint(validatedBy = EValidator.class)
/**
 * @author XWF
 *
 */
public @interface EAnnotation {

	String message() default "应该是偶数";
	
	Class<?>[] groups() default {};
	
	Class<? extends Payload>[] payload() default {};
	
}

对应的验证类:

/**
 * 2023年1月13日下午4:25:39
 */
package testspringboot.test6paramvalidation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * @author XWF
 *
 */
public class EValidator implements ConstraintValidator<EAnnotation, Integer> {

	@Override
	public boolean isValid(Integer value, ConstraintValidatorContext context) {
		return value % 2 == 0;
	}

}

实体类:

/**
 * 2023年1月13日下午3:52:20
 */
package testspringboot.test6paramvalidation;

/**
 * @author XWF
 *
 */
public class Eparam {

	@EAnnotation
	public int i;
	
}

controller方法:

	@RequestMapping("/e")
	public String e(@RequestBody @Validated Eparam e, BindingResult result) {
		if (result.hasErrors()) {
			List<String> errors = result.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.toList());
			return "BindingResult Errors: " + errors.toString();
		}
		return "OK";
	}

测试:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/162082.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Node.js 操作MySQL数据库

在讲Node.js中引入mysql模块之前先讲一下关于MySQL数据库&#xff0c;首先是关于MySQL数据库的安装和mysql服务以及对mysql命令和可视化工具的一个基本使用&#xff1b;那么在这里已经准备好了关于MySQL数据库的内容了&#xff1a; MySQL 数据库安装详细 &#xff1a; MySQL数…

redis主从复制,一主多仆启动流程

文章目录一、安装redis二、复制修改配置文件三、添加conf配置文件四、开启主从复制五、薪火相传六、反客为主7、哨兵模式一、安装redis redis安装笔记 https://blog.csdn.net/G_GUi/article/details/128361131 二、复制修改配置文件 把redis.conf复制到一个新建文件夹里面&a…

安卓手机还有这么多神仙玩法,关键只有少数人知道

随着“智能手机”的快速更新迭代&#xff0c;手机系统逐渐融入了许多实用功能&#xff1b;今年Android手机市场竞争相当激烈&#xff0c;各大手机品牌都争先恐后地向消费者展示自己的新机型。今天我就来给大家分享几个只有安卓手机才有的隐藏黑科技功能&#xff0c;每个功能都非…

cocos creator新手教程:第003节3D模型的基本概念

3.1 计算机如何制作一个3D模型 讲述这个问题之前&#xff0c;我们先来看下现实生活中我们要做一个模型&#xff0c;应该如何做呢&#xff1f;首先我们要把模型的形状给雕刻构建出来&#xff0c;现实生活中的物体都是由分子组成的连续的表面&#xff0c;计算机是离散的无法做到这…

【jQuery】常用API——尺寸、位置操作

一、jQuery 尺寸 以上参数为空&#xff0c;则是获取相应值&#xff0c;返回的是数字型。如果参数为数字&#xff0c;则是修改相应值。参数可以不必写单位。 <style>div {width: 200px;height: 200px;background-color: pink;padding: 10px;border: 15px solid red;margin…

在Windows中安装Mysql数据库(shawn安装成功记录)

一、下载安装包 首先去官网下载mysql安装包 下载网址:https://dev.mysql.com/downloads/mysql/ 下载Windows系统版本,如下图 注意版本必须是8.xx, 5开头的版本不适合本教程   点击下载,选择自己的文件路径,C盘非C盘都可以(我没有放C盘),路径中不要出现中文…

【蓝桥杯简单篇】Python组刷题日寄Part08

刷题日记&#xff1f;刷题日寄&#xff01; 萌新备战蓝桥杯python组 &#x1f339; 发现有需要纠正的地方&#xff0c;烦请指正&#xff01; &#x1f680; 欢迎小伙伴们的三连关注&#xff01; 往期系列&#xff1a; 【蓝桥杯简单篇】Python组刷题日寄Part01 【蓝桥杯简单篇】…

SCRM开源营销平台MarketGo-创建员工活码

一、背景介绍 客户需求&#xff1a;企业在做营销活动的时候&#xff0c;会有大量的客户需要添加企业微信的联系方式。这样就有两个问题&#xff1a; 一个企业微信账号添加太多会受到企业微信的限制&#xff1b;如果有多个企业微信的账号&#xff0c;添加的客户的数量也不平均…

如何给PPT文件添加水印?

我们在制作PPT的时候&#xff0c;有时候需要在幻灯片上加入logo&#xff0c;或者特定的大小、颜色等一致的文字标题&#xff0c;而幻灯片通常都是很多页数的&#xff0c;如果一张张幻灯片来添加&#xff0c;那就很费功夫。 这种情况&#xff0c;我们就可以选择通过“幻灯片母版…

SSL/TLS协议详解 - https为什么比http更安全

概述 首先纠正一个错误&#xff0c;可能很多初学者都以为HTTPS跟HTTP一样&#xff0c;都属于应用层协议。但其实HTTPS并不是一个单独的协议。HTTPS是安全版本的HTTP&#xff0c;简单理解 HTTPS HTTP SSL/TLS&#xff0c;即HTTPS就是使用SSL/TLS协议对HTTP报文进行了加密处理…

一不小心进入“决赛圈”,没“阳过”的怎么办?

前两天看到一个央视新闻&#xff0c;说河南新冠病毒感染率接近90%&#xff0c;流行毒株是奥密克戎BA.5.2&#xff0c;数字让我挺吃惊的&#xff1a;真有这么多人感染了&#xff1f; 如果是这样&#xff0c;我就属于那幸运的10%了&#xff0c;没有经历过刀片嗓&#xff0c;水泥鼻…

机器学习--模型调参、超参数优化、网络架构搜索

目录 一、模型调参 手动调超参数 多次调参的管理 机器调参与人调参的成本比较 自动调参&#xff08;AutoML&#xff09; 总结 二、超参数优化 在搜索空间中选择超参数 HPO算法有哪些 Black-Box Multi-Fidelity 总结 三、网络架构搜索 Neural Architecture Sear…

【Java AWT 图形界面编程】LayoutManager 布局管理器 ② ( FlowLayout 流式布局 )

文章目录一、FlowLayout 流式布局二、FlowLayout 流式布局 API三、FlowLayout 流式布局代码示例1、FlowLayout 流式布局左对齐代码示例及执行效果2、FlowLayout 流式布局居中对齐代码示例及执行效果2、FlowLayout 流式布局右对齐代码示例及执行效果一、FlowLayout 流式布局 Flo…

上半年要完成的博客60

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

RT-Thread系列--对象容器

一、目的RT-Thread号称小而美&#xff0c;那具体美在哪里呢&#xff1f;下面我们就来说说首先&#xff0c;代码简练逻辑清晰明了&#xff1b;其次是框架设计。其创新性的对象容器系统是我认为最优美的设计亮点&#xff0c;本篇的目的就是给大家介绍一下对象容器的设计以及这样设…

sklearn聚类之谱聚类SpectralClustering

文章目录基本原理sklearn中谱聚类的构造实战基本原理 谱聚类是一种基于图论的聚类方法&#xff0c;所谓图&#xff0c;就是将空间中的所有点连接起来&#xff0c;只要这些连接中出现了一个圈&#xff0c;就可以称之为图。如果把这些连线加上一个权重&#xff0c;就叫做加权图。…

小程序开发经验分享(6)开发流程大全

一、准备的资料 我们在开发微信小程序前,需要准备下相关资料。这个资料主要是后面进行ICP备案,微信小程序认证以及申请支付接口时需要用到。 资料如下: 营业执照【个体经营户或公司都行】银行开户许可证【个体经营户可以用法人个人银行卡】,企业网银【最好开通】。相关类…

车载以太网 - DoIP实体状态信息AliveCheck - 08

我们知道车载以太网的实体在车内一般常见的就是网关和节点,而网关和节点的状态信息对我们的以太网通信尤为重要,我们只有知道节点或者网关所处的状态,才能更好的进行下一步处理或者诊断,今天我们就来详细的了解下DoIP实体的状态信息这部分在ISO 13400中的定义。 DoIP实体状…

多图解析manacher算法原理

什么是manacher算法 用于快速计算一个字符串的最长回文子串 什么是最长回文子串&#xff1f; 例如&#xff1a;abc12321中&#xff0c;最长回文子串为12321&#xff0c;即子字符串中最长&#xff0c;且是回文的那个 怎么用暴力做法找出最长回文子串呢&#xff1f; 长度为奇…

线程等待,线程休眠,线程状态

线程等待:因为线程与线程之间&#xff0c;调度顺序是完全不确定&#xff0c;它取决于操作系统本身调度器的一个实现&#xff0c;但是有时候我们希望这个顺序是可控的&#xff0c;此时的线程等待&#xff0c;就是一种方法&#xff0c;用来控制线程结束的先后顺序&#xff1b; 1)…