Spring Boot 2 入门基础

学习要求
● 熟悉Spring基础
● 熟悉Maven使用

环境要求
● Java8及以上
● Maven 3.3及以上:https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started-system-requirements

学习资料
● 文档地址: https://www.yuque.com/atguigu/springboot
○ 文档不支持旧版本IE、Edge浏览器,请使用chrome或者firefox
● 视频地址: http://www.gulixueyuan.com/ https://www.bilibili.com/video/BV19K4y1L7MT?p=1
● 源码地址:https://gitee.com/leifengyang/springboot2

01、Spring与SpringBoot

1、Spring能做什么

1.1、Spring的能力

在这里插入图片描述

1.2、Spring的生态

https://spring.io/projects/spring-boot

覆盖了:
web开发
数据访问
安全控制
分布式
消息服务
移动开发
批处理

1.3、Spring5重大升级

1.3.1、响应式编程

在这里插入图片描述

1.3.2、内部源码设计

基于Java8的一些新特性,如:接口默认实现。重新设计源码架构。

2、为什么用SpringBoot

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".
能快速创建出生产级别的Spring应用

2.1、SpringBoot优点

Create stand-alone Spring applications
创建独立Spring应用
Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files)
内嵌web服务器
Provide opinionated 'starter' dependencies to simplify your build configuration
自动starter依赖,简化构建配置
Automatically configure Spring and 3rd party libraries whenever possible
自动配置Spring以及第三方功能
Provide production-ready features such as metrics, health checks, and externalized configuration
提供生产级别的监控、健康检查及外部化配置
Absolutely no code generation and no requirement for XML configuration
无代码生成、无需编写XML
SpringBoot是整合Spring技术栈的一站式框架
SpringBoot是简化Spring技术栈的快速开发脚手架

2.2、SpringBoot缺点

人称版本帝,迭代快,需要时刻关注变化
封装太深,内部原理复杂,不容易精通

3、时代背景

3.1、微服务

James Lewis and Martin Fowler (2014)  提出微服务完整概念。
https://martinfowler.com/microservices/
In short, the microservice architectural style is an approach to developing a single application 
as a suite of small services, each running in its own process and communicating with lightweight mechanisms, 
often an HTTP resource API. These services are built around business capabilities and independently deployable 
by fully automated deployment machinery. 
There is a bare minimum of centralized management of these services, which may be written in different 
programming languages and use different data storage technologies.-- James Lewis and Martin Fowler (2014)
微服务是一种架构风格
一个应用拆分为一组小型服务
每个服务运行在自己的进程内,也就是可独立部署和升级
服务之间使用轻量级HTTP交互
服务围绕业务功能拆分
可以由全自动部署机制独立部署
去中心化,服务自治。服务可以使用不同的语言、不同的存储技术

3.2、分布式

在这里插入图片描述

分布式的困难

  • 远程调用
  • 服务发现
  • 负载均衡
  • 服务容错
  • 配置管理
  • 服务监控
  • 链路追踪
  • 日志管理
  • 任务调度

分布式的解决

  • SpringBoot + SpringCloud

3.3、云原生

原生应用如何上云。 Cloud Native

上云的困难

  • 服务自愈
  • 弹性伸缩
  • 服务隔离
  • 自动化部署
  • 灰度发布
  • 流量治理

上云的解决
在这里插入图片描述

4、如何学习SpringBoot

4.1、官网文档架构

查看版本新特性;
https://github.com/spring-projects/spring-boot/wiki#release-notes

02、SpringBoot2入门

1、Maven设置

<mirrors><mirror><id>nexus-aliyun</id><mirrorOf>central</mirrorOf><name>Nexus aliyun</name><url>http://maven.aliyun.com/nexus/content/groups/public</url></mirror></mirrors><profiles><profile><id>jdk-1.8</id><activation><activeByDefault>true</activeByDefault><jdk>1.8</jdk></activation><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion></properties></profile></profiles>

2、需求:浏览器发送/hello请求,响应Hello,Spring Boot 2!

2.1、创建Maven工程

在这里插入图片描述

2.2、 引入依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId> <!--spring boot 框架--><version>2.3.4.RELEASE</version>
</parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> <!--web服务的依赖,会导入Tomcat等一些列的库--></dependency></dependencies>

2.3、串讲主程序

package com.atguigu.boot;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** 主程序* @SpringBootApplication:这是一个SpringBoot应用*/
@SpringBootApplication
public class MainApplication {public static void main(String[] args) {SpringApplication.run(MainApplication.class, args);}
}

2.4、编写业务代码

package com.atguigu.boot.Controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;//@ResponseBody
//@Controller@RestController
public class HelloControaller {@RequestMapping("/hello")public String handle01() {return "Hello,Spring Boot 2!";}
}

2.5、测试

直接运行main方法,然后在浏览器发起请求,浏览器应显示“Hello,Spring Boot 2!”。
在这里插入图片描述
在这里插入图片描述

2.6、简化配置

配置文件由application.properties统一管理

server.port=8888

2.7、简化部署

以往我们在部署web应用时,会将项目打成war包,再部署到服务器上,现在可以直接将项目打成可以执行的jar包,直接在服务器执行即可。

 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

在这里插入图片描述
在这里插入图片描述

03、自动装配及原理

1、SpringBoot的特点

1.1、依赖管理

  • 父项目做依赖管理
<!--一般父项目都是用来做依赖管理的-->
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.4.RELEASE</version>
</parent><!--spring-boot-starter-parent--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.3.4.RELEASE</version></parent><!--spring-boot-dependencies中几乎声明了所有开发中常用的依赖的版本号,这种机制称为自动版本仲裁机制-->
  • 导入starter场景启动器
<!--
1、见到很多 spring-boot-starter-* : *就某种场景
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的  *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖为spring-boot-starter
-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.3.4.RELEASE</version><scope>compile</scope>
</dependency>
  • 版本冲裁及版本管理

<!--
1、引入依赖默认都可以不写版本
2、引入非版本仲裁的jar,要写版本号。
查看spring-boot-dependencies里面规定当前依赖的版本用的key。
在当前项目里面重写配置。
--><properties><mysql.version>5.1.43</mysql.version></properties>

1.2、自动配置

  • 自动配好Tomcat
    • 引入Tomcat依赖。
    • 配置Tomcat
  • 自动配好SpringMVC
    • 引入SpringMVC全套组件
    • 自动配好SpringMVC常用组件(功能)
  • 自动配好Web常见功能,如:字符编码问题
    • SpringBoot帮我们配置好了所有web开发的常见场景
  • 默认的包结构
    • 主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
    • 无需以前的包扫描配置
    • 想要改变扫描路径,@SpringBootApplication(scanBasePackages=“com.atguigu”)
      • 或者@ComponentScan 指定扫描路径
        @SpringBootApplication
        等同于
        @SpringBootConfiguration
        @EnableAutoConfiguration
        @ComponentScan("com.atguigu.boot")
        
  • 各种配置拥有默认值
    • 默认配置最终都是映射到某个类上,如:MultipartProperties
    • 配置文件的值最终会绑定每个类上,这个类会在容器中创建对象
  • 按需加载所有自动配置项
    • 非常多的starter
    • 引入了哪些场景这个场景的自动配置才会开启
    • SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面

2、容器功能

2.1、组件添加

  • @Configuration
    基本使用

    • Full模式,配置类组件之间有依赖关系,方法会被调用得到之前的单实力组件。
    • Lite模式,配置类组件之间无依赖关系,用Lite模式加速器启动过程,减少判断。
    //#############################Configuration使用示例######################################################
    /*** 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的* 2、配置类本身也是组件* 3、proxyBeanMethods:代理bean的方法*      Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】*      Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】*      组件依赖必须使用Full模式默认。其他默认是否Lite模式****/
    @Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
    public class MyConfig {/*** Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象* @return*/@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例public User user01(){User zhangsan = new User("zhangsan", 18);//user组件依赖了Pet组件zhangsan.setPet(tomcatPet());return zhangsan;}@Bean("tom")public Pet tomcatPet(){return new Pet("tomcat");}
    }//################################@Configuration测试代码如下########################################
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan("com.atguigu.boot")
    public class MainApplication {public static void main(String[] args) {//1、返回我们IOC容器ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);//2、查看容器里面的组件String[] names = run.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}//3、从容器中获取组件Pet tom01 = run.getBean("tom", Pet.class);Pet tom02 = run.getBean("tom", Pet.class);System.out.println("组件:"+(tom01 == tom02));//4、com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca@1654a892MyConfig bean = run.getBean(MyConfig.class);System.out.println(bean);//如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。//保持组件单实例User user = bean.user01();User user1 = bean.user01();System.out.println(user == user1);User user01 = run.getBean("user01", User.class);Pet tom = run.getBean("tom", Pet.class);System.out.println("用户的宠物:"+(user01.getPet() == tom));}
    }
    
  • @Bean-用于将一个方法标记为Spring容器中的一个Bean。具体来说,@Bean注解可以用于方法上,该方法返回一个对象,该对象将被Spring容器管理和提供给其他程序组件使用,让IOC容器知道这个组件存在。(相当于创建对象);@Component-注解表明一个类会作为组件类,并告知Spring要为这个类创建bean,使用 @Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。(相当于创建对象)、@Controller-代表是一个控制器;@Service-代表是一个业务逻辑组件;@Repository-代表是一个数据库层组件

  • @ComponentScan-包扫描、@Import-为容器添加组件

    /** 4、@Import({User.class, DBHelper.class})*      给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名****/@Import({User.class, DBHelper.class})
    @Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
    public class MyConfig {
    }
    

    @Import 高级用法: https://www.bilibili.com/video/BV1gW411W7wy?p=8
    注解的解释及用法:http://t.csdnimg.cn/ASzxy

  • @Conditional-条件装配:满足Conditional指定的条件,则进行组件注入
    在这里插入图片描述

    //=====================测试条件装配==========================
    @Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
    //@ConditionalOnBean(name = "tom") //当容器中有组件tom组件时,则生成对应组件(myconfig、user01、tom22)
    @ConditionalOnMissingBean(name = "tom") //当容器中没有tmo组件时,则生成对应组件(myconfig、user01、tom22)
    // 组件的位置决定了会生成哪些组件,如果@ConditionalOnMissingBean位置在tomcatPet方法上,则只生成tom22
    public class MyConfig {/*** Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象* @return*/@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例public User user01(){User zhangsan = new User("zhangsan", 18);//user组件依赖了Pet组件zhangsan.setPet(tomcatPet());return zhangsan;}@Bean("tom22")public Pet tomcatPet(){return new Pet("tomcat");}
    }public static void main(String[] args) {//1、返回我们IOC容器ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);//2、查看容器里面的组件String[] names = run.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}boolean tom = run.containsBean("tom");System.out.println("容器中Tom组件:"+tom);boolean user01 = run.containsBean("user01");System.out.println("容器中user01组件:"+user01);boolean tom22 = run.containsBean("tom22");System.out.println("容器中tom22组件:"+tom22);}
    

2.2、 原生配置文件引入

  • @ImportResource 导入资源文件中配置的组件
    <!--======================beans.xml=========================-->
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><bean id="haha" class="com.atguigu.boot.bean.User"><property name="name" value="zhangsan"></property><property name="age" value="18"></property></bean><bean id="hehe" class="com.atguigu.boot.bean.Pet"><property name="name" value="tomcat"></property></bean>
    </beans>
    
    @ImportResource("classpath:beans.xml")
    public class MyConfig {}//======================测试=================boolean haha = run.containsBean("haha");boolean hehe = run.containsBean("hehe");System.out.println("haha:"+haha);//trueSystem.out.println("hehe:"+hehe);//true
    

2.3、配置绑定

  • 使用Java读取到properties文件中的内容,并且把它封装到JavaBean中,以供随时使用;
    例子:

    public class getProperties {public static void main(String[] args) throws FileNotFoundException, IOException {Properties pps = new Properties();pps.load(new FileInputStream("a.properties"));Enumeration enum1 = pps.propertyNames();//得到配置文件的名字while(enum1.hasMoreElements()) {String strKey = (String) enum1.nextElement();String strValue = pps.getProperty(strKey);System.out.println(strKey + "=" + strValue);//封装到JavaBean。}}}
    
  • @Component + @ConfigurationProperties

    /*** 只有在容器中的组件,才会拥有SpringBoot提供的强大功能*/
    @Component
    @ConfigurationProperties(prefix = "mycar")
    public class Car {private String brand;private Integer price;public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public Integer getPrice() {return price;}public void setPrice(Integer price) {this.price = price;}@Overridepublic String toString() {return "Car{" +"brand='" + brand + '\'' +", price=" + price +'}';}
    }
    
    @RestController
    public class Hello {@AutowiredCar car;@RequestMapping("/car")public Car car() {return car;}@RequestMapping("/hello")public String handle01() {return "Hello,Spring boot 2!";}
    }
    

    application.properties

    mycar.brand=BYD
    mycar.price=100000
    

    在这里插入图片描述

    使用@Component注解,将组件注册到容器中,使用@ConfigurationProperties(prefix = “mycar”)注解,读取application.properties以mycar开头的配置项

  • @EnableConfigurationProperties + @ConfigurationProperties

    package com.atguigu.boot.bean;import org.springframework.boot.context.properties.ConfigurationProperties;//@Component
    @ConfigurationProperties(prefix = "mycar")
    public class Car {private String brand;private Integer price;public Car() {}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public Integer getPrice() {return price;}public void setPrice(Integer price) {this.price = price;}public Car(String brand, Integer price) {this.brand = brand;this.price = price;}@Overridepublic String toString() {return "Car{" +"brand='" + brand + '\'' +", price=" + price +'}';}
    }
    
    package com.atguigu.boot.config;import com.atguigu.boot.bean.Car;
    import com.atguigu.boot.bean.Pet;
    import com.atguigu.boot.bean.User;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;@ConditionalOnMissingBean(name = "tmo")
    @Configuration(proxyBeanMethods = false)
    @EnableConfigurationProperties(Car.class)
    public class Myconfig {@Bean(name = "UserZS")public User user00() {return new User("zhangsan",5,new Pet("tom"));}@Bean(name = "TomCat")public Pet pet00() {return new Pet("tom");}@Beanpublic Pet Pet01() {return new Pet("jerry");}
    }
    

    在这里插入图片描述

    如果要注入的JavaBean是第三方或者无法添加注解@Component,则可以在控制类中使用@EnableConfigurationProperties注解来实现配置绑定

3、自动配置原理入门

3.1、引导加载自动配置类

@SpringBootApplication注解相当于下面三个注解的集合

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication{}    
  • @SpringBootConfiguration
    @Configuration。代表当前是一个配置类
  • @ComponentScan
    指定扫描哪些,Spring注解;
  • @EnableAutoConfiguration
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {}
    
    • @AutoConfigurationPackage
      自动配置包?指定了默认的包规则

      @Import(AutoConfigurationPackages.Registrar.class)  //给容器中导入一个组件
      public @interface AutoConfigurationPackage {}//利用Registrar给容器中导入一系列组件
      //将指定的一个包下的所有组件导入进来?MainApplication 所在包下。
      

      在这里插入图片描述
      在这里插入图片描述

    • @Import(AutoConfigurationImportSelector.class)

      1、利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
      2、调用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)获取到所有需要导入到容器中的配置类
      3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的组件
      4、从META-INF/spring.factories位置来加载一个文件。默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories
      

      在这里插入图片描述

C:\Users\Untifa.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.6.10\spring-boot-autoconfigure-2.6.10.jar!\META-INF\spring.factories 文件里列出了spring-boot一启动就要加载到容器中的所有类,一共133个类,与debug时的数量一致

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
...
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

3.2、按需开启自动配置项

虽然我们133个场景的所有自动配置启动的时候默认全部加载。xxxxAutoConfiguration
按照条件装配规则(@Conditional),最终会按需配置。

3.3、修改默认配置

@Bean
@ConditionalOnBean(MultipartResolver.class)  //容器中有这个类型组件
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中没有这个名字 multipartResolver 的组件
public MultipartResolver multipartResolver(MultipartResolver resolver) {//给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找。//SpringMVC multipartResolver。防止有些用户配置的文件上传解析器不符合规范// Detect if the user has created a MultipartResolver but named it incorrectlyreturn resolver;
}
//给容器中加入了文件上传解析器;

SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先
在这里插入图片描述

@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {}

总结:

  • SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
  • 生效的配置类就会给容器中装配很多组件
  • 只要容器中有这些组件,相当于这些功能就有了
  • 定制化配置
    • 用户直接自己@Bean替换底层的组件
    • 用户去看这个组件是获取的配置文件什么值就去修改。

xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面取值 ----> application.properties

3.4、最佳实践

  • 引入场景依赖
    • https://docs.spring.io/spring-boot/reference/using/build-systems.html
  • 查看自动配置了哪些(选做)
    • 自己分析,引入场景对应的自动配置一般都生效了
    • 配置文件中debug=true开启自动配置报告。Negative(不生效)\Positive(生效)
  • 是否需要修改
    • 参照文档修改配置项
      https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties
      自己分析。xxxxProperties绑定了配置文件的哪些。
    • 自定义加入或者替换组件
      @Bean、@Component。。。
      自定义器 XXXXXCustomizer;

4、开发小技巧

4.1、Lombok

简化JavaBean开发

<!--1.首先引入依赖--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
<!--2.idea中搜索安装lombok插件并安装 -->

在这里插入图片描述

package com.atguigu.boot.bean;import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;//@Component
@Data // 生成getter、setter方法
@ToString // 生成ToString方法
@AllArgsConstructor // 生成全参构造方法
@NoArgsConstructor // 生成无参构造方法
@EqualsAndHashCode // 生成hash值和equal方法
@Slf4j // 注入日志
@ConfigurationProperties(prefix = "mycar")
public class Car {private String brand;private Integer price;
}

4.2、dev-tools

	<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency>

Ctrl+F9来重新编译项目

4.3、Spring Initailizr(项目初始化向导)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

剞劂application.properties文件中文乱码问题

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android SDK下载安装(_指定版本)

安装完sdk&#xff0c;就可以直接使用adb命令了&#xff0c;如果想做app相关自动化测试&#xff0c;也是需要sdk环境依赖的 一、SDK下载 A&#xff1a;官网下载&#xff1a; 管内镜像网站(推荐)&#xff1a;https://www.androiddevtools.cn/index.html 官网&#xff1a;htt…

老师如何对付挑事儿的家长?

身为老师&#xff0c;你有没有遇到过这样的家长&#xff1a;孩子在学校里闹点小矛盾&#xff0c;或者作业分数有点争议&#xff0c;他们就气势汹汹地来找你&#xff0c;说你偏心&#xff0c;甚至在其他家长面前说三道四&#xff1f;面对这种爱“挑事”的家长&#xff0c;老师们…

图片转excel表格工具的工具,分享3个专业的识别软件!

在数字化时代&#xff0c;我们时常面临将图片中的表格数据转换为可编辑的Excel表格的需求。无论是工作中的数据整理&#xff0c;还是学习中的资料汇总&#xff0c;这一需求都显得尤为迫切。幸运的是&#xff0c;市面上已经涌现出众多优秀的图片转Excel表格工具&#xff0c;它们…

OLED显示一张图片

1.思路: void Oled_Show_Image(unsigned char *image) // { unsigned char i; //-128 ~ 127位 unsigned int j; //j要重新定义&#xff0c;因为要到达图片的最后一位 //行 i没有问题&#xff0c;j有问题 i为1时&am…

JAVA云HIS医院管理系统源码 云HIS系统源码 云HIS的优势 云HIS的发展

JAVA云HIS医院管理系统源码 云HIS系统源码 云HIS的优势 云HIS的发展 HIS系统&#xff0c;即医院信息系统&#xff08;Hospital Information System&#xff09;&#xff0c;在医院的运营和管理中扮演着至关重要的角色。关于HIS系统的溯源&#xff0c;简单从以下几个方面进行讲…

应用上架后的关键!苹果商店(AppStore)运营策略与技巧指南

1、运营期&#xff1a;怎么能活得好&#xff1f; ▍封号和下架问题 14天 在收到苹果封号通知&#xff08;我们将会在14天后封你的账号&#xff09;如果觉得冤枉可以在14天内进行申诉。14天并不是一个严格准确的时间&#xff0c;有可能会在第15天或者在第20天&#xff0c;甚至…

故障诊断 | 基于KAN故障诊断模型

效果一览 文章概述 故障诊断 | 基于 KAN故障诊断模型。KAN是一种全新的神经网络架构&#xff0c;它与传统的MLP架构不同&#xff0c;能够用更少的参数量在Science领域取得惊人的表现&#xff0c;并且具备可解释性&#xff0c;有望成为深度学习模型发展的一个重要方向。运用KAN&…

探索数组处理:奇数的筛选与替换

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、数组中的奇数筛选 二、将奇数替换为负一 总结 一、数组中的奇数筛选 在处理数组数据时…

Redis 中 Set 数据结构详解

用法 Redis 中的 Set 是一个无序&#xff0c;不重复集合&#xff08;里面的元素为字符串&#xff09;&#xff0c;支持常用的集合操作。 常见命令 1. 增 添加一个或多个元素到 set 中 SADD key member [ member ... ] 返回值&#xff1a; 添加成功的元素个数 将一个元素移到…

Plesk面板上网站无法访问如何查看日志

近期我的网站出现无法访问的问题&#xff0c;这边想要查询为什么出现无法访问的原因&#xff0c;但不知道如何在主机上面进行检查&#xff0c;由于我使用的Hostease的Windows虚拟主机产品默认带普通用户权限的Plesk面板&#xff0c;因此联系Hostease的咨询了Hostease技术支持&a…

Gartner发布评估威胁情报计划有效性指南:评估威胁情报有效性的四个步骤

许多组织都在努力实施 TI 并评估其价值。安全和风险管理领导者必须使用优先情报要求来评估其 TI 计划的有效性&#xff0c;并根据其组织战略完善该计划。 主要发现 尽管许多组织已将威胁情报 (TI) 纳入其安全计划&#xff0c;但他们很难评估其性能、成熟度以及在相关产品和服务…

1比1万地形图符号库分享

我们在《1:2.5万、1:5万、1:10万军用地形图图式》一文中&#xff0c;为大家分享过军用地形图式。 还在《超实用三调符号库分享下载》一文中&#xff0c;为大家分享过三调符号库。 现在再为你分享一个&#xff11;比&#xff11;万的地形图符号库&#xff0c;请在文末查看符号…

2023年西安交通大学校赛(E-雪中楼)

E.雪中楼 如果算出按南北的序列&#xff0c;再转成从低到高的编号序列&#xff0c;岂不是太麻烦了&#xff0c;幸好&#xff0c;没有在这方面费长时间&#xff0c;而是意识到&#xff0c;本质就是要从低到高的编号序列&#xff0c;所以我就按样例模拟了一下&#xff0c;当a[i]0…

AI生成四季变化解决方案,四季之美,一图尽揽

随着AI技术已经渗透到我们生活的方方面面&#xff0c;在这个充满变化的时代&#xff0c;美摄科技以其前沿的AI生成技术&#xff0c;为企业带来了全新的视觉体验——AI生成四季变化解决方案。这一方案不仅能够让车辆实拍的照片焕发不同季节的风采&#xff0c;更能在不改变原图构…

中国企业出海,哪些业务需要负载均衡?

国内企业出海的进程正在加速。中国的出海企业剑指跨境电商、社交、游戏、短剧等市场&#xff0c;其中尤其以跨境电商的数据最为突出。据官方数据&#xff0c;2023年我国跨境电商进出口总额达到2.38万亿元&#xff0c;比2016年增长近50倍&#xff0c;占货物贸易总规模的5.7%。 …

一行命令将已克隆的本地Git仓库推送到内网服务器

一、需求背景 我们公司用gitea搭建了一个git服务器&#xff0c;其中支持win7的最高版本是v1.20.6。 我们公司的电脑在任何时候都不能连接外网&#xff0c;但是希望将一些开源的仓库移植到内网的服务器来。一是有相关代码使用的需求&#xff0c;二是可以建设一个内网能够查阅的…

【Java】HOT100+代码随想录:动态规划(下)

目录 三、打家劫舍 LeetCode198&#xff1a;打家劫舍 LeetCode213&#xff1a;打家劫舍ii LeetCode337&#xff1a;打家劫舍iii&#xff08;树形&#xff09; 四、股票问题 时间不多了&#xff0c;其他的先不写了 LeetCode121&#xff1a;买卖股票的最佳时机 五、子序列…

【Python】 如何在Python中表示枚举类型(Enum)

枚举&#xff08;Enum&#xff09;是一种特殊的数据类型&#xff0c;它允许我们为一组固定的常量赋予更易读的名字。在Python中&#xff0c;枚举类型可以通过enum模块来实现&#xff0c;这个模块在Python 3.4及以后的版本中被引入。枚举类型不仅可以使代码更加清晰&#xff0c;…

汇编原理(三)编程

源程序&#xff1a; 汇编指令&#xff1a;有对应的机器码与其对应 伪指令&#xff1a;无对应的机器码&#xff0c;是由编译器来执行的指令&#xff0c;编译器根据伪指令来进行相关的编译工作。 ex1:XXX segment、XXX ends这两个是一对成对使用的伪指令&#xff0c;且必须会被用…

蓝桥杯Web开发【大学组:国赛】2022年真题

1.分一分 如果给你一个数组&#xff0c;你能很快将它分割成指定长度的若干份吗&#xff1f; 1.1 题目问题 请在 js/index.js 文件中补全函数 splitArray 中的代码&#xff0c;最终返回按指定长度分割的数组。 具体要求如下&#xff1a; 将待分割的&#xff08;一维&#x…