当前位置: 首页 > news >正文

SpringBoot学习06-[SpringBoot与AOP、SpringBoot自定义starter]

SpringBoot自定义starter

  • SpringBoot与AOP
  • SpringBoot集成Mybatis-整合druid
    • 在不使用启动器的情况下,手动写配置类进行整合
    • 使用启动器的情况下,进行整合
  • SpringBoot启动原理
    • 源码解析
      • 创建SpringApplication
        • 初始化SpringApplication总结
      • 启动
  • SpringBoot自定义Starter
    • 定义父maven项目
    • starter模块
    • autoconfigure模块
      • 定义properties文件用于属性绑定
      • 定义controller用于进行功能展示
      • 定义配置类
      • 新建spring.factories文件
    • 打包
    • 在其他工程进行使用

SpringBoot与AOP

使用AOP实现用户接口访问日志功能

  • 添加AOP场景启动器
   <!--添加AOP场景启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
  • 定义切面类
@Aspect
@Component
public class LogAspect {Logger log= LoggerFactory.getLogger(LogAspect.class);@Around("execution(* com.springboot.controller.*.*(..))&&" +"@annotation(apiOperation)")public Object around(ProceedingJoinPoint joinPoint, ApiOperation apiOperation) throws Throwable {StringBuilder loginfo=new StringBuilder();Class<?> controller = joinPoint.getThis().getClass();Api annotation = controller.getAnnotation(Api.class);if (annotation != null) {loginfo.append(annotation.value());}String value = apiOperation.value();loginfo.append(value);log.info("请求接口相关信息:{}",loginfo.toString());return joinPoint.proceed();}
}
  • 测试
    通过swaager进行测试
    在这里插入图片描述
    可以看到日志信息已经被打印
    在这里插入图片描述

SpringBoot集成Mybatis-整合druid

整合druid的目的是为了引入数据控制台

在不使用启动器的情况下,手动写配置类进行整合

  • 整合druid配置datasouce
  • 引入druid依赖
 <!--sprinboot版本2.6.6--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.6</version></parent><!--sprinboot整合druid--><!--jdbc--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!--mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.3</version></dependency>
  • 配置文件
spring:datasource:username: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/personaltesttype: com.alibaba.druid.pool.DruidDataSource#初始化时运行sql脚本schema: classpath:sql/test.sqlinitialization-mode: always
  • 配置类
    在这里插入图片描述
    在没有启动器的情况下我们需要手动配置配置类,配置DruidDataSource的bean

@ConditionalOnProperty(“spring.datasource.type”):配置文件配置spring.datasource.type属性,配置类才会生效

@ConfigurationProperties(“spring.datasource”)可以放在方法上对bean进行属性注入

@Configuration
@ConditionalOnProperty("spring.datasource")
public class CustomDataSourceConfig {@Bean@ConfigurationProperties("spring.datasource") //会绑定application.yml中所有以spring.datasource开头的配置,绑定到datasourcepublic DataSource dataSource(){return new DruidDataSource();}
}
  • 测试
    看启动的时候,sql脚本是否执行正确执行
    成功执行了脚本插入了两个表
    在这里插入图片描述
  • 整合druid配置监控台
  • 配置类添加监控台sevlet和监控台服务过滤器
@Configuration
@ConditionalOnProperty("spring.datasource.bean")
public class CustomDataSourceConfig {@Bean@ConfigurationProperties("spring.datasource") //会绑定application.yml中所有以spring.datasource开头的配置,绑定到datasourcepublic DataSource dataSource() {return new DruidDataSource();}/*** 监控台servlet*/@Beanpublic ServletRegistrationBean<StatViewServlet> statViewServlet() {ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>();bean.setServlet(new StatViewServlet());bean.addUrlMappings("/druid/*");//添加白名单bean.addInitParameter("allow", "127.0.0.1");//添加黑名单,当白名单和黑名单重复时,黑名单优先级更高bean.addInitParameter("deny","127.0.0.1");//添加控制台管理用户bean.addInitParameter("loginUsername", "admin");bean.addInitParameter("loginPassword", "123456");//是否能够重复数据bean.addInitParameter("resetEnable", "false");return bean;}/*** 监控台filter:服务过滤器*/@Beanpublic FilterRegistrationBean<WebStatFilter> webStatFilter() {FilterRegistrationBean<WebStatFilter> filter = new FilterRegistrationBean<>();filter.setFilter(new WebStatFilter());//添加过滤规则filter.addUrlPatterns("/*");// 忽略过滤格式(这些访问都不会被监控到,会被忽略掉)filter.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,");return filter;}@Beanpublic StatFilter statFilter() {StatFilter statFilter = new StatFilter();//慢sql记录statFilter.setLogSlowSql(true);statFilter.setMergeSql(true);//超过多少时间为慢sqlstatFilter.setSlowSqlMillis(3000);return statFilter;}
}

此时访问:http://localhost:8080/druid/可以进入控制台(正常情况下可以,但是这儿不行始终404,考虑是springboot和druid版本不匹配问题)
这儿就用配置的方式了解一下整合数据控制台需要什么,需要一个StatViewServlet的bean和WebStatFilter的bean帮助理解,druid自动配置类整合的时候如何整合。
在这里插入图片描述

使用启动器的情况下,进行整合

在使用启动器的情况下只需要添加启动依赖就可以了,配置文件不变,配置文件也是上面的不变

  • 引入依赖
    <!--连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.3</version></dependency>

再次访问还是404,由上述手动配置可知需要两个bean,我们看druid的自动配置类
在这里插入图片描述
它导入了DruidStatViewServletConfiguration和DruidWebStatFilterConfiguration两个配置类分别对应手动配置的两个bean,这两个配置类会分别配置两个bean。我们在看DruidStatViewServletConfiguration配置类
``
在这里插入图片描述
里面加了@ConditionalOnProperty( name = {"spring.datasource.druid.stat-view-servlet.enabled"}, havingValue = "true" )注解,要让这个配置生效,配置文件必须有spring.datasource.druid.stat-view-servlet.enabled属性,并且值必须为true

  • 配置文件配置
    druid:stat-view-servlet:enabled: true

再次访问:http://localhost:8080/druid/index.html
成功进入监控台
在这里插入图片描述

SpringBoot启动原理

SpingBoot在启动的时候使用了ServletWebServerApplicationContext

在这里插入图片描述
在这里插入图片描述
接下来源码分析:主要看准备准备工作阶段
在这里插入图片描述

源码解析

在这里插入图片描述
1、调用SpringApplication.run启动SpringBoot

 SpringApplication.run(MyApplication.class,args);

2、使用自定义SpringApplication进行启动

    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return (new SpringApplication(primarySources)).run(args);}

启动的时候有两步:

  • 创建SpringApplication
  • 启动

创建SpringApplication

调用构造方法

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.sources = new LinkedHashSet();this.bannerMode = Banner.Mode.CONSOLE;this.logStartupInfo = true;this.addCommandLineProperties = true;this.addConversionService = true;this.headless = true;this.registerShutdownHook = true;this.additionalProfiles = Collections.emptySet();this.isCustomEnvironment = false;this.lazyInitialization = false;this.applicationContextFactory = ApplicationContextFactory.DEFAULT;this.applicationStartup = ApplicationStartup.DEFAULT;this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");//将启动类放入primarySourcesthis.primarySources = new LinkedHashSet(Arrays.asList(primarySources));//根据classpath下的类,推算当前web应用类型(wbflux、servlet)this.webApplicationType = WebApplicationType.deduceFromClasspath();this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class));//就是去spring.factories 中去获取所有key:org.springframework.context.ApplicationContextInitializer的valuethis.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));//就是去spring.factories 中去获取所有key:org.springframework.context.ApplicationListener的valuethis.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));//根据main方法推算粗mainApplicationClassthis.mainApplicationClass = this.deduceMainApplicationClass();}

ApplicationContextInitializer
在这里插入图片描述
ApplicationListener
在这里插入图片描述
推算出的启动类
在这里插入图片描述

初始化SpringApplication总结

总结:

  • 获取启动类
  • 获取应用类型
  • 读取了对外扩展的ApplicationContextInitializer和ApplicationListener(从factories文件读取)
  • 根据main方法推断启动类
    就是去初始化了一些信息

启动

  • run
  • 启动springboot最核心的逻辑
    public ConfigurableApplicationContext run(String... args) {//记录应用启动时间long startTime = System.nanoTime();DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();//它是任何spring上下文的接口,所以可以接收任何applicationtext实现ConfigurableApplicationContext context = null;//开启了Headless模式(了解即可)this.configureHeadlessProperty();//又去spring.factories中读取了 SpringApplicationRunListener类型的组件,就是用来进行发布事件或者说运行监听器(发布事件和运行监听器是一个意思,发布事件,监听器就会运行)SpringApplicationRunListeners listeners = this.getRunListeners(args);//开始运行监听器,发布1、ApplicationStartingEvent事件,在运行时发送listeners.starting(bootstrapContext, this.mainApplicationClass);try {//根据命令行参数 实例化一个ApplicationArgumentsApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//预初始化环境,读取环境变量,读取配置文件信息(基于监听器)ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);//忽略beaninfo的beanthis.configureIgnoreBeanInfo(environment);//打印banner横条Banner printedBanner = this.printBanner(environment);//创建spring上下文context = this.createApplicationContext();context.setApplicationStartup(this.applicationStartup);//预初始化contextthis.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);//加载spring ioc容器,启动servlet容器 ** 相当重要 由于是使用AnnotationConfigServletWebServerApplicationContext 启动的Spring容器,// 所以springboot对它进行了扩展:加载自动配置类:invokeBeanFactoryPostProcessors;创建servlet容器:onRefreshthis.refreshContext(context);this.afterRefresh(context, applicationArguments);Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);if (this.logStartupInfo) {(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);}//发布ApplicationStartedEvent事件listeners.started(context, timeTakenToStartup);this.callRunners(context, applicationArguments);} catch (Throwable var12) {this.handleRunFailure(context, var12, listeners);throw new IllegalStateException(var12);}try {Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);//发布了ApplicationReadyEvent事件listeners.ready(context, timeTakenToReady);return context;} catch (Throwable var11) {this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);throw new IllegalStateException(var11);}}

在启动第一步会发布ApplicationStartingEvent事件

  public void starting(ConfigurableBootstrapContext bootstrapContext) {this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));}

ApplicationStartingEvent事件对应的监听器,当事件发布后,监听器就会运行
在这里插入图片描述
环境准备prepareEnvironment

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {//根据webapplicationType, 创建Environment 创建就会读取 java环境变量和系统环境变量ConfigurableEnvironment environment = this.getOrCreateEnvironment();//将命令行参数读取到环境变量中,供应用使用this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());//将@PropertySource()的配置信息,放在第一位,因为读取配置文件@PropertySource()优先级最低ConfigurationPropertySources.attach((Environment)environment);//在创建上下文之前,会发布ApplicationEnvironmentPreparedEvent事件 目的就是读取springboot全局配置文件listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);DefaultPropertiesPropertySource.moveToEnd((ConfigurableEnvironment)environment);Assert.state(!((ConfigurableEnvironment)environment).containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties.");//将所有spring.main 开头的配置信息绑定到SpringApplication类this.bindToSpringApplication((ConfigurableEnvironment)environment);if (!this.isCustomEnvironment) {environment = this.convertEnvironment((ConfigurableEnvironment)environment);}//更新PropertySourceConfigurationPropertySources.attach((Environment)environment);return (ConfigurableEnvironment)environment;}

预处理context:prepareContext方法

    private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {context.setEnvironment(environment);this.postProcessApplicationContext(context);//拿到我们之前读取到的所有ApplicationContextInitializer类型的组件,循环调用它们的initialize方法this.applyInitializers(context);//发布ApplicationContextInitializedEvent 事件listeners.contextPrepared(context);bootstrapContext.close(context);if (this.logStartupInfo) {this.logStartupInfo(context.getParent() == null);this.logStartupProfileInfo(context);}//获取当前spring上下文 beanFactory(用来创建bean)ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {((AbstractAutowireCapableBeanFactory)beanFactory).setAllowCircularReferences(this.allowCircularReferences);//在spring下 如果出现两个重名的bean,后读取到的会覆盖前面的,但是在boot中设置了不允许覆盖,如果重复会报错if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}}//设置当前spring容器是不是要将所有的bean设置为懒加载,true为懒加载,false不懒加载if (this.lazyInitialization) {context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}Set<Object> sources = this.getAllSources();Assert.notEmpty(sources, "Sources must not be empty");//读取主启动类(因为后续要根据配置类去解析配置的所有bean)this.load(context, sources.toArray(new Object[0]));//读取完配置类后发送ApplicationPreparedEvent事件listeners.contextLoaded(context);}

重要:加载spring ioc容器:refreshContext

加载spring ioc容器,启动servlet容器 ** 相当重要 由于是使用AnnotationConfigServletWebServerApplicationContext 启动的Spring容器,
所以springboot对它进行了扩展:加载自动配置类:invokeBeanFactoryPostProcessors;创建servlet容器:onRefresh

    public void refresh() throws BeansException, IllegalStateException {synchronized(this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");this.prepareRefresh();ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();this.prepareBeanFactory(beanFactory);try {this.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");//调用BeanFactoryPostProcess,扫描class为beanDefinitiointhis.invokeBeanFactoryPostProcessors(beanFactory);this.registerBeanPostProcessors(beanFactory);beanPostProcess.end();this.initMessageSource();this.initApplicationEventMulticaster();//创建servlet容器,启动servlet容器this.onRefresh();this.registerListeners();this.finishBeanFactoryInitialization(beanFactory);this.finishRefresh();} catch (BeansException var10) {if (this.logger.isWarnEnabled()) {this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);}this.destroyBeans();this.cancelRefresh(var10);throw var10;} finally {this.resetCommonCaches();contextRefresh.end();}}}

总结:SpringBoot启动的时候会解析配置文件、解析环境变量,创建spring上下文context,执行refresh方法,加载ioc容器,启动servlet容器,在refresh中做了一些扩展,加载自动配置类、创建servlet容器。在启动过程中还会发布一些事件,启动相应的监听器来进行扩展和解耦。
在这里插入图片描述

SpringBoot自定义Starter

自定义一个Starter给web应用添加首页

Sringbootstarter分三个部分:父工程、starter模块、auconfiration模块

定义父maven项目

springboot_custome_starter

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>springboot_custome_starter</artifactId><version>1.0-SNAPSHOT</version><modules><module>tulingxueyuan-spring-boot-starter</module><module>tulingxueyuan-spring-boot-autoconfigure</module></modules><packaging>pom</packaging><name>springboot_custome_starter</name><url>http://maven.apache.org</url><description>SpringBoot自定义Starter</description><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.6</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency></dependencies><!--打包好
帮我们把所有依赖的jar 统统放到jar文件里面的BOOT-INF\lib中
--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

starter模块

定义tulingxueyuan-spring-boot-starter

只需要引入autoconfiratioin即可,其他项目引用的时候,只需要引入starter即可

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springboot_custome_starter</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>tulingxueyuan-spring-boot-starter</artifactId><packaging>jar</packaging><description>启动器(starter)是一个空的jar文件,仅仅提供辅助性依赖管理,这些依赖需要自动装配或其他类库。</description><name>tulingxueyuan-spring-boot-starter</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--引入autoconfigure--><dependency><groupId>org.example</groupId><artifactId>tulingxueyuan-spring-boot-autoconfigure</artifactId><version>1.0-SNAPSHOT</version></dependency><!--如果当前starter还需要其他类库 就在这里进行引用--></dependencies>
</project>

autoconfigure模块

定义tulingxueyuan-spring-boot-autoconfigure模块

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springboot_custome_starter</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>tulingxueyuan-spring-boot-autoconfigure</artifactId><packaging>jar</packaging><name>tulingxueyuan-spring-boot-autoconfigure</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></dependency></dependencies>
</project>

定义properties文件用于属性绑定

@ConfigurationProperties(prefix = "tuling.hello")
public class HelloProperties {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}
}

定义controller用于进行功能展示

@RestController
public class HelloController {private HelloProperties properties;public HelloController(HelloProperties properties) {this.properties = properties;}@RequestMapping("/")public String index(){return properties.getName()+"欢迎你";}
}

定义配置类

@Configuration
@ConditionalOnProperty("tuling.hello.name") //配置文件必须有tuling.hello.name属性配置类才会生效
@EnableConfigurationProperties(HelloProperties.class) //开启配置属性类,让属性类可以和配置文件进行属性绑定,并且将属性类注入到spring容器
public class HelloAutoConfigration {@Autowiredprivate HelloProperties properties;@Beanpublic HelloController helloController(){return new HelloController(properties);}
}

新建spring.factories文件

在classpath/META-INF下新建spring.factories文件,让springboot可以扫描到我们的配置类
在这里插入图片描述
key:org.springframework.boot.autoconfigure.EnableAutoConfiguration

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.starter.tulingxueyuan.HelloAutoConfigration

打包

打包的时候注意:先打包父工厂,在打包configration,最后打包stater,不然会打包失败,因为autoconfigration和starter依赖父工程,starter又依赖autuconfigration
在这里插入图片描述

在这里插入图片描述

  • 打包后的机构
    在这里插入图片描述

在其他工程进行使用

只需要引入starter模块就可以了

    <!--引入自定义starter--><dependency><groupId>org.example</groupId><artifactId>tulingxueyuan-spring-boot-starter</artifactId><version>1.0-SNAPSHOT</version></dependency>
  • 配置文件配置,让配置类生效
tuling:hello:name: ddd
  • 测试
    直接启动项目就可以了
    在这里插入图片描述

相关文章:

SpringBoot学习06-[SpringBoot与AOP、SpringBoot自定义starter]

SpringBoot自定义starter SpringBoot与AOPSpringBoot集成Mybatis-整合druid在不使用启动器的情况下&#xff0c;手动写配置类进行整合使用启动器的情况下,进行整合 SpringBoot启动原理源码解析创建SpringApplication初始化SpringApplication总结 启动 SpringBoot自定义Starter定…...

Maven - 在没有网络的情况下强制使用本地jar包

文章目录 问题解决思路解决办法删除 _remote.repositories 文件代码手动操作步骤验证 问题 非互联网环境&#xff0c;无法从中央仓库or镜像里拉取jar包。 服务器上搭建了一套Nexus私服。 Nexus私服故障&#xff0c;无法连接。 工程里新增了一个Jar的依赖&#xff0c; 本地仓…...

JAVA--JSON转换工具类

JSON转换工具类 import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackso…...

每日复盘-20240705

今日关注&#xff1a; 20240705 六日涨幅最大: ------1--------300391--------- 长药控股 五日涨幅最大: ------1--------300391--------- 长药控股 四日涨幅最大: ------1--------300391--------- 长药控股 三日涨幅最大: ------1--------300391--------- 长药控股 二日涨幅最…...

MySQL 一些用来做比较的函数

目录 IF&#xff1a;根据不同条件返回不同的值 CASE&#xff1a;多条件判断&#xff0c;类似于Switch函数 IFNULL&#xff1a;用于检查一个值是否为NULL&#xff0c;如果是&#xff0c;则用指定值代替 NULLIF&#xff1a;比较两个值&#xff0c;如果相等则返回NULL&#xff…...

一个使用率超高的大数据实验室是如何练成的?

厦门大学嘉庚学院“大数据应用实训中心”&#xff08;以下简称“实训中心”&#xff09;自2022年建成以来&#xff0c;已经成为支撑“大数据专业”复合型人才培养的重要支撑&#xff0c;目前实训中心在专业课程实验教学、项目实训、数据分析类双创比赛、毕业设计等方面都有深入…...

Chiasmodon:一款针对域名安全的公开资源情报OSINT工具

关于Chiasmodon Chiasmodon是一款针对域名安全的公开资源情报OSINT工具&#xff0c;该工具可以帮助广大研究人员从各种来源收集目标域名的相关信息&#xff0c;并根据域名、Google Play应用程序、电子邮件地址、IP地址、组织和URL等信息进行有针对性的数据收集。 该工具可以提…...

如何在Java中实现PDF生成

如何在Java中实现PDF生成 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在软件开发和企业应用中&#xff0c;生成PDF文档是一项常见的需求。Java作为一种强大…...

Redis 的缓存淘汰策略

Redis 作为一个高性能的内存数据库&#xff0c;提供了多种缓存淘汰策略&#xff08;也称为过期策略或驱逐策略&#xff09;&#xff0c;用于管理内存使用。当 Redis 达到其内存限制时&#xff0c;系统会根据配置的策略删除一些数据&#xff0c;以释放内存空间。以下是 Redis 支…...

音乐播放器

目录 一、设计目标二、实现流程1. 数据库操作2. 后端功能实现3. 前端UI界面实现4. 程序入口 三、项目收获 一、设计目标 1. 模拟网易云音乐&#xff0c;实现本地音乐盒。 2. 功能分析&#xff1a; 登录功能窗口显示加载本地音乐建立播放列表播放音乐删除播放列表音乐 3.设计思…...

三星组件新的HBM开发团队加速HBM研发

为应对人工智能(AI)市场扩张带来的对高性能存储解决方案需求的增长&#xff0c;三星电子在其设备解决方案(DS)部门内部成立了全新的“HBM开发团队”&#xff0c;旨在提升其在高带宽存储器(HBM)领域的竞争力。根据Business Korea的最新报告&#xff0c;该团队将专注于推进HBM3、…...

图书馆数据仓库

目录 1.数据仓库的数据来源为业务数据库&#xff08;mysql&#xff09; 初始化脚本 init_book_result.sql 2.通过sqoop将mysql中的业务数据导入到大数据平台&#xff08;hive&#xff09; 导入mysql数据到hive中 3.通过hive进行数据计算和数据分析 形成数据报表 4.再通过sq…...

基于uniapp(vue3)H5附件上传组件,可限制文件大小

代码&#xff1a; <template><view class"upload-file"><text>最多上传5份附件&#xff0c;需小于50M</text><view class"" click"selectFile">上传</view></view><view class"list" v…...

Phoenix Omid Timestamp Oracle 组件实现原理

Omid Timestamp Oracle 组件实现原理 作用 生成全局单调递增的时间戳&#xff0c;支持获取操作和崩溃恢复。 功能 1.生成全局单调递增的时间戳(支持崩溃恢复)apinext返回下一个时间戳getLast返回最后一个分配的时间戳(当前时间戳)实现方式TimestampOracleImpl单调递增的时间…...

Lex Fridman Podcast with Andrej Karpathy

我不太喜欢Lex Fridman的声音&#xff0c;总觉得那让人昏昏欲睡&#xff0c; 但无奈他采访的人都太大牌了&#xff0c;只能去听。但是听着听着&#xff0c;就会觉得有深度的采访这些人&#xff0c;似乎也只有他这种由研究员背景的人能干&#xff0c; 另&#xff0c;他提的问题确…...

力扣1895.最大的幻方

力扣1895.最大的幻方 求前缀和暴力枚举幻方边长 求行列前缀和 class Solution {public:int largestMagicSquare(vector<vector<int>>& grid) {int n grid.size() , m grid[0].size();vector<vector<int>> rowsum(n,vector<int>(m));for…...

【C++】 解决 C++ 语言报错:Segmentation Fault

文章目录 引言 段错误&#xff08;Segmentation Fault&#xff09;是 C 编程中常见且令人头疼的错误之一。段错误通常发生在程序试图访问未被允许的内存区域时&#xff0c;导致程序崩溃。本文将深入探讨段错误的产生原因、检测方法及其预防和解决方案&#xff0c;帮助开发者在…...

【linuxC语言】手撕Http协议之程序框架

文章目录 前言提示基本框架主函数一个小问题代码概况多线程版本单线程版本总结前言 在现代网络编程中,HTTP协议无疑是最常用的协议之一。它是互联网上应用最为广泛的一种网络协议。理解HTTP协议并能够手动实现它,对于深入理解网络编程和提高编程技能都有着重要的意义。本文将…...

溶解氧(DO)理论指南(1)

转载自梅特勒官网资料&#xff0c;仅用于学习交流&#xff0c;侵权则删&#xff01; 溶解氧理论指南 1 溶解氧(DO)原理1.1 溶解氧和分压1.2 氧气在水中的溶解度1.3 溶解氧对生物的重要性1.4 溶解氧对工业的重要性 1 溶解氧(DO)原理 氧是宇宙中第三大常见元素&#xff0c;也是…...

Mysql中常用函数的使用示例

场景 基础知识回顾&#xff1a;mysql中常用函数的使用示例。 注&#xff1a; 博客&#xff1a;霸道流氓气质-CSDN博客 实现 数学函数 -- ABS(x)返回x的绝对值 SELECT ABS(-1),ABS(2); -- PI()返回圆周率 SELECT PI(); -- SQRT(x)返回非负数x的二次方根 SELECT SQRT(4); -…...

开源205W桌面充电器,140W+65W升降压PD3.1快充模块(2C+1A口),IP6557+IP6538

开源一个基于IP6557和IP6538芯片的205W升降压快充模块&#xff08;140W65W&#xff09;&#xff0c;其中一路C口支持PD3.1协议&#xff0c;最高输出28V5A&#xff0c;另一路是A口C口&#xff0c;最高输出65W&#xff08;20V3.25A&#xff09;&#xff0c;可搭配一个24V10A的开关…...

Java中的内存数据库与缓存技术

Java中的内存数据库与缓存技术 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 1. 内存数据库的概念与优势 1.1 什么是内存数据库&#xff1f; 内存数据库是…...

GUKE万能工具箱(附带源码)

GUKE万能工具箱&#xff08;附带源码&#xff09; 效果图部分源码领取完整源码下期更新 效果图 部分源码 <!DOCTYPE html> <html><head><meta charset"utf-8" name"viewport" content"widthdevice-width, initial-scale1"…...

FFmpeg开发笔记(四十二)使用ZLMediaKit开启SRT视频直播服务

《FFmpeg开发实战&#xff1a;从零基础到短视频上线》一书在第10章介绍了轻量级流媒体服务器MediaMTX&#xff0c;通过该工具可以测试RTSP/RTMP等流媒体协议的推拉流。不过MediaMTX的功能实在是太简单了&#xff0c;无法应用于真实直播的生产环境&#xff0c;真正能用于生产环境…...

spring-boot-starter-data-redis是否支持reactive响应式编程

开源项目SDK&#xff1a;https://github.com/mingyang66/spring-parent 个人文档&#xff1a;https://mingyang66.github.io/raccoon-docs/#/ spring-boot-starter-data-redis&#xff1a; 使用传统的基于阻塞的I/O编程模型&#xff0c;这意味着当你调用Redis操作时&#xff0…...

Java后端每日面试题(day3)

目录 Spring中Bean的作用域有哪些&#xff1f;Spring中Bean的生命周期Bean 是线程安全的吗&#xff1f;了解Spring Boot中的日志组件吗&#xff1f; Spring中Bean的作用域有哪些&#xff1f; Bean的作用域&#xff1a; singleton&#xff1a;单例&#xff0c;Spring中的bean默…...

[单master节点k8s部署]18.监控系统构建(三)Grafana安装

Grafana是一个跨平台的开源的度量分析和可视化工具。支持多种数据源&#xff0c;比如OpenTSDB&#xff0c;Prometheus&#xff0c;ElasticResearch&#xff0c;Cloudwatch等。 Grafana安装 通过yaml配置grafana的pod和service&#xff0c;grafana工作在kube-system的命名空间…...

【JavaScript脚本宇宙】优化你的Web色彩:精选JavaScript颜色工具对比

万能色彩助手&#xff1a;详解最受欢迎的JavaScript颜色库 前言 在现代Web开发中&#xff0c;颜色处理和转换是一个不可忽视的环节。无论是网站设计、数据可视化还是用户界面开发&#xff0c;都离不开对颜色的精确控制和转换。为了满足这一需求&#xff0c;众多JavaScript库应…...

用html+css设计一个列表清单小卡片

目录 简介: 效果图: 源代码: 可能的问题: 简介: 这个HTML代码片段是一个简单的列表清单设计。它包含一个卡片元素(class为"card"),内部包含一个无序列表(ul),列表项(li)前面有一个特殊的符号(△)。整个卡片元素设计成300px宽,150px高,具有圆角边…...

day11_homework_need2submit

Homework 编写—个将ts或mp4中视频文件解码到yuv的程序 yuv数据可以使用如下命令播放: ffplay -i output yuv-pix_fmt yuv420p-s 1024x436 要求: ffmpeg解析到avpacket并打印出pts和dts字段完成解码到avframe并打印任意字段完成yuv数据保存 // teminal orders on bash cd ex…...

昇思MindSpore学习总结九——FCN语义分割

1、语义分割 图像语义分割&#xff08;semantic segmentation&#xff09;是图像处理和机器视觉技术中关于图像理解的重要一环&#xff0c;AI领域中一个重要分支&#xff0c;常被应用于人脸识别、物体检测、医学影像、卫星图像分析、自动驾驶感知等领域。 语义分割的目的是对图…...

js数据库多级分类按树形结构打印

可以使用 JavaScript 来按层级打印 categories 数组。首先&#xff0c;需要将这个数组转换成一个树形结构&#xff0c;然后再进行递归或者迭代来打印每个层级的内容。 以下是一个示例代码&#xff0c;用来实现这个功能&#xff1a; const categories [{ id: 2, name: "…...

centos下编译安装redis最新稳定版

一、目标 编译安装最新版的redis 二、安装步骤 1、redis官方下载页面 Downloads - Redis 2、下载最新版的redis源码包 注&#xff1a;此时的最新稳定版是 redis 7.2.5 wget https://download.redis.io/redis-stable.tar.gz 3、安装编译环境 yum install -y gcc gcc-c …...

如何让自动化测试更加灵活简洁?

简化的架构对于自动化测试和主代码一样重要。冗余和不灵活性可能会导致一些问题&#xff1a;比如 UI 中的任何更改都需要更新多个文件&#xff0c;测试可能在功能上相互重复&#xff0c;并且支持新功能可能会变成一项耗时且有挑战性的工作来适应现有测试。 页面对象模式如何理…...

linux 下载依赖慢和访问github代码慢

1 pip install 下载依赖慢&#xff0c;添加清华镜像源 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 2 git 出现错误 Could not resolve host: github.com 原来是因为github.com没有被主机给解析&#xff0c; 第一步 先 ping 看一下主机地址 …...

奥比中光astra_pro相机使用记录

一、信息获取 1、官网 用于了解产品信息 http://www.orbbec.com.cn/sys/37.html 2、开发者社区 咨询问题下载开发部https://developer.orbbec.com.cn/ 二 、windowvs19 1、相机型号 orbbec_astro_pro 根据对应的型号找到需要的包工具 踩坑1&#xff0c;因为这个相机型号…...

【MindSpore学习打卡】应用实践-计算机视觉-深入解析 Vision Transformer(ViT):从原理到实践

在近年来的深度学习领域&#xff0c;Transformer模型凭借其在自然语言处理&#xff08;NLP&#xff09;中的卓越表现&#xff0c;迅速成为研究热点。尤其是基于自注意力&#xff08;Self-Attention&#xff09;机制的模型&#xff0c;更是推动了NLP的飞速发展。然而&#xff0c…...

Debezium系列之:支持在一个数据库connector采集中过滤某些表的删除事件

Debezium系列之:支持在一个数据库connector采集中过滤某些表的删除事件 一、需求二、相关技术三、参数设置四、消费数据一、需求 在一个数据库的connector中采集了多张表,部分表存在数据归档的业务场景,会定期从表中删除历史数据,希望能过滤掉存在数据归档这些表的删除事件…...

SQL Server端口配置指南:最佳实践与技巧

1. 引言 SQL Server通常使用默认端口1433进行通信。为了提高安全性和性能&#xff0c;正确配置SQL Server的端口非常重要。本指南将帮助您了解如何配置和优化SQL Server的端口设置&#xff0c;以满足不同环境和需求。 2. 端口配置基础 2.1 默认端口 SQL Server的默认端口是…...

FastGPT 报错:undefined 该令牌无权使用模型:gpt-3.5-turbo (request id: xxx)

目录 一、FastGPT 报错 二、解决方法 一、FastGPT 报错 进行对话时 FastGPT 报错如下所示。 [Error] 2024-07-01 09:25:23 sse error: undefined 该令牌无权使用模型:gpt-3.5-turbo (request id: xxxxx) {message: 403 该令牌无权使用模型:gpt-3.5-turbo (request id: x…...

springboot系列八: springboot静态资源访问,Rest风格请求处理, 接收参数相关注解

文章目录 WEB开发-静态资源访问官方文档基本介绍快速入门注意事项和细节 Rest风格请求处理基本介绍应用实例注意事项和细节思考题 接收参数相关注解基本介绍应用实例PathVariableRequestHeaderRequestParamCookieValueRequestBodyRequestAttributeSessionAttribute ⬅️ 上一篇…...

# 职场生活之道:善于团结

在职场这个大舞台上&#xff0c;每个人都是演员&#xff0c;也是观众。要想在这个舞台上站稳脚跟&#xff0c;除了专业技能&#xff0c;更要学会如何与人相处&#xff0c;如何团结他人。团结&#xff0c;是职场生存的重要法则之一。 1. 主动团结&#xff1a;多一个朋友&#x…...

go sync包(五) WaitGroup

WaitGroup sync.WaitGroup 可以等待一组 Goroutine 的返回&#xff0c;一个比较常见的使用场景是批量发出 RPC 或者 HTTP 请求&#xff1a; requests : []*Request{...} wg : &sync.WaitGroup{} wg.Add(len(requests))for _, request : range requests {go func(r *Reque…...

基于深度学习的相机内参标定

基于深度学习的相机内参标定 相机内参标定&#xff08;Camera Intrinsic Calibration&#xff09;是计算机视觉中的关键步骤&#xff0c;用于确定相机的内部参数&#xff08;如焦距、主点位置、畸变系数等&#xff09;。传统的标定方法依赖于已知尺寸的标定板&#xff0c;通常…...

适合金融行业的国产传输软件应该是怎样的?

对于金融行业来说&#xff0c;正常业务开展离不开文件传输场景&#xff0c;一般来说&#xff0c;金融行业常用的文件传输工具有IM通讯、邮件、自建文件传输系统、FTP应用、U盘等&#xff0c;这些传输工具可以基础实现金融机构的文件传输需求&#xff0c;但也存在如下问题&#…...

昇思25天学习打卡营第9天|MindSpore使用静态图加速(基于context的开启方式)

在Graph模式下&#xff0c;Python代码并不是由Python解释器去执行&#xff0c;而是将代码编译成静态计算图&#xff0c;然后执行静态计算图。 在静态图模式下&#xff0c;MindSpore通过源码转换的方式&#xff0c;将Python的源码转换成中间表达IR&#xff08;Intermediate Repr…...

class类和style内联样式的绑定

这里的绑定其实就是v-bind的绑定&#xff0c;如代码所示&#xff0c;div后面的引号就是v-bind绑定&#xff0c;然后大括号将整个对象括起来&#xff0c;对象内先是属性&#xff0c;属性后接的是变量&#xff0c;这个变量是定义在script中的&#xff0c;后通过这个变量&#xff…...

3033.力扣每日一题7/5 Java

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;算法练习关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 目录 思路 解题方法 时间复杂度 空间复杂度 Code 思路 首先创建一个与…...

GPT-5:下一代AI如何彻底改变我们的未来

GPT-5 发布前瞻&#xff1a;技术突破与未来展望 随着科技的飞速发展&#xff0c;人工智能领域不断迎来新的突破。根据最新消息&#xff0c;OpenAI 的首席技术官米拉穆拉蒂在一次采访中确认&#xff0c;GPT-5 将在一年半后发布&#xff0c;并描述了其从 GPT-4 到 GPT-5 的飞跃如…...

重载一元运算符

自增运算符 #include<iostream> using namespace std; class CGirl { public:string name;int ranking;CGirl() { name "zhongge"; ranking 5; }void show() const{ cout << "name : "<<name << " , ranking : " <…...