Spring Boot组件化与参数校验

Spring Boot组件化与参数校验

Spring Boot版本选择

  1. 2.3.x版本

  2. 2.6.x版本

Spring Boot核心思想

约定大于配置,简化繁琐的配置

Spring Boot自动配置原理

  • @SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot需要运行这个类的main方法来启动SpringBoot应用;

  • SpringBootApplication

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = {
          @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
          @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
    
  • @SpringBootConfiguration:Spring Boot的配置类; 标注在某个类上,表示这是一个Spring Boot的配置类;

  • @Configuration:配置类上来标注这个注解; 配置类 ----- 配置文件;配置类也是容器中的一个组件;本质上是@Component

  • @EnableAutoConfiguration:开启自动配置功能; 以前我们需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置,会帮我们自动去加载 自动配置类

  • @ComponentScan : 扫描包 相当于在spring.xml 配置中context:component-scan 但是并没有指定basepackage,如果没有指定spring底层会自动扫描当前配置类所有在的包。TypeExcludeFilter:springboot对外提供的扩展类, 可以供我们去按照我们的方式进行排除,去找到所有自定义的TypeExcludeFilter的bean调用match方法,满足一个则排除。AutoConfigurationExcludeFilter:排除当前类路径下所有@Configuration修饰的类并且是自动配置的类(spring.factories中EnableAutoConfiguration配置了就是自动配置类)

  • @EnableAutoConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    // 略
}
  • @AutoConfigurationPackage 将当前配置类所在包保存在BasePackages的Bean中。供Spring内部使用。

  • @Import(AutoConfigurationImportSelector.class) 关键点! 可以看到,在@EnableAutoConfiguration注解内使用到了@import注解来完成导入配置的功能,而AutoConfigurationImportSelector实现了DeferredImportSelector,Spring延迟到项目beanDefinition已经全被扫描完,才去执行selectImports,内部在解析@Import注解时会调用getAutoConfigurationEntry方法。 下面是2.3.5.RELEASE实现源码:getAutoConfigurationEntry方法进行扫描具有META-INF/spring.factories文件的jar包。

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
   }
   AnnotationAttributes attributes = getAttributes(annotationMetadata);
   // 从META-INF/spring.factories中获得候选的自动配置类
   List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
   // 排重
   configurations = removeDuplicates(configurations);
   //根据EnableAutoConfiguration注解中属性,获取不需要自动装配的类名单
   // 根据:@EnableAutoConfiguration.exclude
   // @EnableAutoConfiguration.excludeName
   // spring.autoconfigure.exclude  进行排除
   Set<String> exclusions = getExclusions(annotationMetadata, attributes); 
   // 检查如果exclusions排除的类不在自动配置类configurations里,抛出异常
   checkExcludedClasses(configurations, exclusions);
   // exclusions 也排除
   configurations.removeAll(exclusions);
   // 通过读取spring.factories 中AutoConfigurationImportFilter的配置类OnBeanCondition\OnClassCondition\OnWebApplicationCondition实例化进行过滤
   configurations = getConfigurationClassFilter().filter(configurations);
   // 通过读取spring.factories 中的AutoConfigurationImportListener类实例化(可以支持)处理AutoConfigurationImportEvent的事件
   // 分别把候选的配置名单,和排除的配置名单传进去做扩展
   fireAutoConfigurationImportEvents(configurations, exclusions);
   return new AutoConfigurationEntry(configurations, exclusions);
}

@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

@Conditional扩展注解作用(判断是否满足当前指定条件)
@ConditionalOnJava系统的java版本是否符合要求
@ConditionalOnBean容器中存在指定Bean;
@ConditionalOnMissingBean容器中不存在指定Bean;
@ConditionalOnExpression满足SpEL表达式指定
@ConditionalOnClass系统中有指定的类
@ConditionalOnMissingClass系统中没有指定的类
@ConditionalOnSingleCandidate容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty系统中指定的属性是否有指定的值
@ConditionalOnResource类路径下是否存在指定资源文件
@ConditionalOnWebApplication当前是web环境
@ConditionalOnNotWebApplication当前不是web环境
@ConditionalOnJndiJNDI存在指定项

我们可以通过设置配置文件中:启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;
在这里插入图片描述

自定义starter

一、简介 SpringBoot 最强大的功能就是把我们常用的场景抽取成了一个个starter(场景启动器),我们通过引入springboot 为我提供的这些场景启动器,我们再进行少量的配置就能使用相应的功能。即使是这样,springboot也不能囊括我们所有的使用场景,往往我们需要自定义starter,来简化我们对springboot的使用。

模式

我们参照 spring-boot-starter 我们发现其中没有代码:
在这里插入图片描述

我们在看它的pom中的依赖中有个 springboot-starter

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

我们再看看 spring-boot-starter 有个 spring-boot-autoconfigure

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

在这里插入图片描述

  • 启动器(starter)是一个空的jar文件,仅仅提供辅助性依赖管理,这些依赖可能用于自动装配或其他类库。
  • 需要专门写一个类似spring-boot-autoconfigure的配置模块
  • 用的时候只需要引入启动器starter,就可以使用自动配置了

命名规范

官方命名空间

  • 前缀:spring-boot-starter-
  • 模式:spring-boot-starter-模块名
  • 举例:spring-boot-starter-web、spring-boot-starter-jdbc

自定义命名空间

  • 后缀:-spring-boot-starter
  • 模式:模块-spring-boot-starter
  • 举例:mybatis-spring-boot-starter

参数校验

  1. 引入依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
	<!--hibernate validator依赖-->
	<dependency>
		<groupId>org.hibernate.validator</groupId>
		<artifactId>hibernate-validator</artifactId>
		<version>6.0.1.Final</version>
	</dependency>
  1. 添加配置
@Bean
public Validator validator(){
    ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
            .configure()

            .failFast(true)
            .buildValidatorFactory();

return validatorFactory.getValidator();
}
  1. 使用

@Length(max = 64, message = “职务名称超长”) 不校验null的字段
@Email 不去检验null和空字符串
@Pattern 可以允许当前字段为null,针对非null做校验
@AssertTrue 不去检验null值

(1)Controller上的参数校验,主要针对于@RequestBody的POJO
(2)Bean的方法参数校验
(3)针对bean的属性做参数校验

@Valid和@Validated区别

区别@Valid@Validated
提供者JSR-303 规范Spring,意味着只能用于POJO之外的地方,比如controller类上、方法、参数上
是否支持分组不支持支持
标注位置METHOD, FIELD, CONSTRUCTOR, PARAMETER, TYPE_USETYPE, METHOD, PARAMETER
嵌套校验支持不支持
  1. 异常处理

需要全局处理MethodArgumentNotValidException、ConstraintViolationException、BindException异常

@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Response<?> exceptionHandler(HttpServletRequest httpServletRequest, MethodArgumentNotValidException e) {
	log.error("字段校验错误!", e);
	String msg = Optional.ofNullable(e.getBindingResult().getFieldError())
			.map(DefaultMessageSourceResolvable::getDefaultMessage).orElse(NETWORK_ERROR_MSG);
	return new Response<>(CommonErrorCode.FIELD_VALIDATE_FAIL.getCode(), msg);
}

@ExceptionHandler(value = ConstraintViolationException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Response<?> exceptionHandler(HttpServletRequest httpServletRequest, ConstraintViolationException e) {
	log.error("字段校验错误!", e);
	ConstraintViolation<?> constraintViolation = null;
	Iterator<ConstraintViolation<?>> iterator = e.getConstraintViolations().iterator();
	if (iterator.hasNext()) {
		constraintViolation = iterator.next();
	}
	String msg = Optional.ofNullable(constraintViolation).map(ConstraintViolation::getMessage)
			.orElse(NETWORK_ERROR_MSG);
	return new Response<>(CommonErrorCode.FIELD_VALIDATE_FAIL.getCode(), msg);
}

@ExceptionHandler(value = BindException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Response<?> exceptionHandler(HttpServletRequest httpServletRequest, BindException e) {
	log.error("字段校验错误!", e);
	String msg = Optional.ofNullable(e.getBindingResult().getFieldError())
			.map(DefaultMessageSourceResolvable::getDefaultMessage).orElse(NETWORK_ERROR_MSG);
	return new Response<>(CommonErrorCode.FIELD_VALIDATE_FAIL.getCode(), msg);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3学习日记(day5)

接下来我们继续探讨文档 event对象 在Vue.js中&#xff0c;$event变量或箭头函数中的event参数用于捕获原始的DOM事件对象。这个对象包含了所有与特定事件相关的信息&#xff0c;比如鼠标点击的位置、键盘按键的键码、触摸事件的触摸点等。 当你在事件处理器中需要做一些基于…

前端时钟页面(JSP语言)

前端时钟页面(JSP语言) 一、效果图 二、介绍 1.目前市面上很多时钟组件&#xff0c;像电子时钟&#xff0c;3D时钟&#xff0c;Echarts画的时钟 2.这款时钟&#xff0c;是本人多年前寻找并修改的&#xff0c;感觉效果还不错 3.目前这是jsp写的&#xff0c;后面有时间会用Vue写…

口罩佩戴智能监测摄像机

智能监测摄像机在现代城市安全管理中扮演着关键角色&#xff0c;尤其是像口罩佩戴智能监测摄像机这样的设备&#xff0c;其应用正在日益扩展&#xff0c;对于公共卫生和安全至关重要。 这类摄像机利用先进的图像识别技术&#xff0c;能够实时监测人群中是否佩戴口罩。通过高精度…

CVPR2023论文速览Scenes相关49篇

CVPR2023论文速览Scenes Paper1 CLIP2Scene: Towards Label-Efficient 3D Scene Understanding by CLIP 摘要原文: Contrastive Language-Image Pre-training (CLIP) achieves promising results in 2D zero-shot and few-shot learning. Despite the impressive performance …

05. Java多线程 join 方法

1. 前言 本节对 join 方法进行深入的剖析&#xff0c;主要内容点如下&#xff1a; 了解 join 方法的作用&#xff0c;初步的理解 join 方法的使用带来的效果是学习本节内容的基础&#xff1b;了解 join 方法异常处理&#xff0c;我们在使用 join 方法是&#xff0c;需要对 jo…

【odoo】常用的字符转义:“>“,“<“,““,“/“等

概要 字符转义是指在编写代码或处理文本数据时&#xff0c;将特殊字符转换为另一种形式&#xff0c;以便在特定的上下文中正确解析和处理这些字符。 内容 特殊字符描述XML转义表示法&和符号&amp;<小于符号<>大于符号>"双引号&quot;单引号&ap…

优惠卷秒杀(并发问题)

Redis实战篇 | Kyles Blog (cyborg2077.github.io) 目录 一、Redis实现全局唯一id 二、添加优惠卷 三、实现秒杀下单 四、解决超卖问题&#xff08;库存为负&#xff09; 乐观锁解决超卖问题&#xff08;CAS法&#xff09; 五、实现一人一单 ​编辑 悲观锁解决一人一单问题…

C++ 教程 - 05 构建编译

文章目录 构建工具cmake安装与使用CMakeLists.txt编写使用案例 构建工具 cmake, Cross Platform Make&#xff0c; &#xff08;对C&#xff09;跨平台编译工具&#xff0c;将CMakeLists.txt 文件编译为对应的文件&#xff0c;如linux下的 Makefile&#xff0c;然后使用make命…

这几个都秒懂的都是资深程序猿/媛了吧?

放松第三期下&#xff0c;不讲编程技术&#xff0c;来看看几个冷笑话&#xff0c;最后一个最近还真的遇到了T_T ......想知道有多少人是秒懂的&#xff0c;欢迎大家在评论区交流讨论分享自己身边的搞笑趣事。 大家身边还有什么搞笑趣事呢&#xff1f;欢迎评论区留言交流分享&am…

收银系统源码推荐,线下线上一体化收银系统

1.收银系统源码开发语言 核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后台管理网站: HTML5vue2.0element-uicssjs收银端【安卓/PC收银】: Dart3&#xff0c;框架&#xff1a;Flutter 3.11.0-6.0.pre.27商家小程序助手端: uniapp线上商城: uniapp 2.功能介绍 支持测试体验…

SARscape——Refined Lee滤波

目录 一、算法原理1、概述2、参考文献 二、软件操作三、结果展示1、原始图像2、滤波结果 一、算法原理 1、概述 精致Lee滤波通过定义8种非正方形局部窗口&#xff0c;将均匀区域像素值等于其平均值&#xff0c;将非均匀区域近似于局部窗口中心像素值。 精致 Lee 滤波 8 种模板…

C#调用OpenCvSharp和SkiaSharp绘制图像直方图

最近在B站上学习OpenCv教程&#xff0c;学到图像直方图&#xff0c;后者描述的是不同色彩在整幅图像中所占的比例&#xff08;统计不同色彩在图像中的出现次数&#xff09;&#xff0c;可以对灰度图、彩色图等计算并绘制图像直方图。本文学习OpenCvSharp中与计算直方图相关的函…

全志 Android 11:实现响应全局按键

一、篇头 最近实现热键想功能&#xff0c;简单总结了下全志平台Android 11 的响应全局热键的方法。 二、需求 实现全局热键&#xff0c;响应F-、AF、F三个按键&#xff0c;AF只用于启动调焦界面&#xff0c;F-和F除了可以启动调焦界面外&#xff0c;还用于调整镜头的焦距&…

锂电池寿命预测 | Matlab基于ARIMA的锂电池寿命预测

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 锂电池寿命预测 | Matlab基于ARIMA的锂电池寿命预测 NASA数据集&#xff0c;B0005号电池&#xff0c;选择前110个数据训练&#xff0c;后58个数据测试预测。程序包含去趋势线、差分、平稳化及AIC准则判定p和q。命令窗…

幂集000

题目链接 幂集 题目描述 注意点 集合中不包含重复的元素 解答思路 可以使用深度优先遍历的思想按顺序将相应的元素添加到子集中&#xff0c;并将每个子集添加到结果集 代码 class Solution {public List<List<Integer>> subsets(int[] nums) {List<List&…

openGauss安装流程2024

openGauss安装流程2024 报错解决&#xff1a;https://blog.csdn.net/weixin_47115107/article/details/139844012?spm1001.2014.3001.5501 openGauss安装 之后安装过程中openGauss用户互信&#xff0c;openEuler服务器需要用到Python-3.7.x命令&#xff0c;但是默认Python版…

GNSS边坡监测站

TH-WY1随着科技的飞速发展&#xff0c;各种先进的监测技术不断涌现&#xff0c;为边坡安全监测提供了有力保障。其中&#xff0c;GNSS边坡监测站以其高精度、实时性强的特点&#xff0c;受到了广泛关注。 GNSS边坡监测站&#xff0c;全称为全球导航卫星系统边坡监测站&#xf…

掌握心理学知识成为产品经理一门必修课?

文章目录 心理学与产品设计的关联关系产品经理需要学习哪些心理学知识产品心理学的学习对象包含哪些 谈及心理学&#xff0c;往往认为它是一门研究人类心理现象及其影响下的精神功能和行为活动的科学&#xff0c;很多情况下&#xff0c;我们的直观印象是把心理学与医学领域进行…

代码随想录刷题复习day01

day01 数组-二分查找 class Solution {public int search(int[] nums, int target) {// 左闭右闭int left 0;int right nums.length - 1;int mid 0;while (right > left) {mid left (right - left) / 2;if (nums[mid] > target)right mid - 1;else if (nums[mid]…

HoVer-Net复现:手把手带你实现细胞核的分割与分类,并输出叠加图像|24-06-21

小罗碎碎念 先说一下&#xff0c;只要你跟着我一步一步走&#xff0c;你能实现的效果——对细胞核进行分割和分类&#xff0c;并在原始图像上以颜色叠加的方式直观地展示这些结果。 昨天我在交流群里进行了一下预热&#xff0c;并且提供了一些前期的教程&#xff0c;反响还不…