技术标签: 微服务 thtmeleaf SpringBoot 源码解析 springBoot 原理
1:SpringBoot基础入门
1-1:什么是SpringBoot
什么是Spring
Spring是一个开源框架,2003年兴起的一个轻量级的Java开发框架,作者:Rod Johnson。
Spring是为了解决企业级应用开发的复杂性而创建的,简化开发
Spring是如何简化Java开发的
为了降低Java开发的复杂性,Spring采用了以下4种关键策略:
- 1、基于Bean的轻量级和最小侵入性编程;
- 2、通过IOC,依赖注入DI和面向接口实现松耦合;
- 3、基于切面AOP和惯例进行声明式编程;
- 4、通过切面和模板减少样式代码;
什么是SpringBoot
我们从最原始的Servlet结合Tomcat,接着到Struts,后来到SpringMVC,框架从无到有的衍生,这一切都是为何简化开发,提高开发效率,但是慢慢的我们发现,Spring也不满足我们的需求了,因为配置太多,简称配置地狱。而SpringBoot呢,就是一个JavaWeb大的开发框架,和SpringMVC类似,对比其他JavaWeb框架的好处,官方说是简化开发,约定大于配置,you can ‘‘just run’’,能迅速的开发web应用,几行代码开发一个http接口。
我们慢慢的发现了一个规律,所有的技术框架的发展似乎都遵循了一条主线:从一个复杂应用场景衍生一种规范框架,人们只需要进行各种配置而不需要自己实现它,这时候强大的配置功能成了优点;发展到一定程度之后,人们根据实际生产应用情况,选取其中实际功能和设计精华,重构出一些轻量级的框架;之后为了提高开发效率,嫌弃原先的各种配置过于麻烦,于是开始提倡“约定大于配置”,进而衍生出一些一站式的解决方案。
这就是Java企业级应用->J2EE->Spring->SpringBoot的过程
随着Spring不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,违背了最初的理念,甚至人称配置地域。SpringBoot正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用Spring,更容易的集成各种常用的中间件,开源软件;
SpringBoot基于Spring开发,SpringBoot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷的开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。SpringBoot以约定大于配置的核心思想,默认帮我们进行了很多配置,多试SpringBoot应用只需要很少的Spring配置。同时它集成了大量常用的第三方库配置(例如Redis、MongoDB、Jpa、RabbitMQ、Quartz等等),SpringBoot应用中这些第三方库几乎可以零配置的开箱即用。
简单来说就是SpringBoot其实不是什么 新框架,它默认配置了很多框架的使用方式,就像Maven整合了所有的jar包,SpringBoot整合了所有的框架
SpringBoot出生名门,从一来是就站在一个比较高的起点,又经过这几年的发展,生态最有完善,SpringBoot已经当之无愧成为Java领域最热门的技术。SpringBoot的主要特点
- 快速创建独立运行的Spring项目以及与主流程框架集成
- 开箱即用,大量的自动配置,提供各种默认配置来简化项目配置,也可以修改默认值
- 内嵌式容器简化Web项目,使用嵌入式的Servlet容器,应用无需打成war包
- 没有冗余代码生成和XML配置的要求
- starters自动依赖与版本控制
- 准生产环境的运行时应用监控
- 与运计算的天然集成
使用SpringBoot到底有多爽,用下面这幅图来表达
1-2:什么是微服务
什么是微服务
微服务是一种架构风格,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合;可以通过http的方式进行互通。要说微服务架构,先得说说我们过去的单体应用架构。
单体应用架构
所谓单体应用架构(all in one)是指,我们将一个应用的中所有应用服务都封装在一个应用中。
无论是ERP、CRM或是其他什么系统,你都把数据库访问,web访问等等各个功能都放大一个war包内。这样做的好处:
- 易于开发和测试
- 十分方便部署
- 需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
这样做的缺点是:
- 牵一发而动全身,哪怕修改一个非常小的地方,都要停掉整个服务,重新打包、部署这个应用的war包。
- 对于一个大型应用,如果把所有的内容都放在一个应用里面,我们如何维护,如何分工合作都是问题。
微服务架构
所谓微服务架构,就是打破之前all in one的传统架构方式,把每个功能元素单独出来。把独立出来的功能元素进行动态组合,需要的功能元素才拿来组合,需要多一些时可以整合多个功能元素。所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制。
这样做的好处是:
- 节省了调用资源
- 每个 功能元素的服务都是一个可替换换的,可堵路升级的软件代码
下面的连接详细的阐述了什么是微服务
原文里也提供了几种语言的版本
如何构建微服务
一个大型系统的微服务架构,就像是一个复杂交织的神经网络,每一个神经元就是一个功能元素,它们各自完成自己的功能,然后通过http相互请求调用。比如一个电商系统,查缓存,连数据库,浏览页面,结账,支付等服务都是一个个独立的功能服务,都被微化了,他们只为一个个微服务共同构建了一个庞大的系统。如果修改其中的一个功能,只需要更新升级其中一个功能服务单元即可。
但是这种庞大的系统架构给部署和运维带来很大的难度。于是,Spring为我们带来了构建大型分布式微服务的全套、全程产品:
- 构建一个个功能独立的微服务应用单元,可以使用SpringBoot,可以帮我们快速构建一个应用;
- 大型分布式网络服务的调用。这部分有SpringCloud来完成,实现分布式;
- 在分布式中间,进行流式数据计算、批处理,我们有springCloud Data Flow;
- Spring为我们想清楚了整个从开始构建应用到大型分布式应用全流程方案。
1-3:官网搭建SpringBoot项目
拉到最下面
点击进入或者直接进入https://start.spring.io/
填写项目信息
我们要创建web项目,选择Spring Web
信息填完后创建项目
然后会把项目下载下来
把包拷贝到你想要的目录下,然后解压
用idea打开我们的项目
打开项目后先让maven下载依赖包,导入完可以删掉我们不需要的文件
删掉文件后的项目
然后启动项目
访问http://localhost:8080/
到这里整个基础项目就完成,接下来就是自己的业务问题,我们这里写个简单的接口
重启访问接口
1-4:使用Idea快速创建SpringBoot项目
创建项目
填写基本信息
提示Artifact含有非法字符集
是因为我们的Artifact含有大写字母,改为小写就好
SpringBoot项目创建成功,删掉我们不想要的文件
因为我们创建的时候,没有导入Web依赖,所以这个项目不是Web项目,如果想变为Web项目,可以手动Maven导入依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
启动项目
访问http://localhost:8080/
修改端口号
重启
resources文件夹中目录结构
- static:保存所有的静态资源:(js、css、images)
- templates:保存所有的模板页面:(SpringBoot默认jar包使用嵌入式的Tomcat,默认不支持JSP页面),可以使用模板引擎(freemarker、thymeleaf)
- application.properties:SpringBoot应用的配置文件,可以修改一些默认设置
1-5:自定义banner
所谓banner,就是启动项目的时候的这个东西
在项目的resources目录下,新建一个文件叫banner.txt
在这个新建的banner.txt文件下定义你们想要输出的内容即可
更多的banner图,可以来这里找https://www.bootschool.net/ascii-art
我这里搞了一辆车的
_____________________________________________________ | | _______ | | / _____ | | 货拉拉---程序员的好归宿 | / /(__) || | | ________/ / |OO| || | | | |-------|| | | (| | -.|| |_______________________ | | ____ \ ||_________||____________ | ____ ____ | /| / __ \ |______|| / __ \ / __ \ | | / __ \ / __ \ |\ \|| / \ |_______________| / \ |_| / \ |__| |___________| / \ |__| / \|_|/ | () | | () | | () | | () | | () | \__/ \__/ \__/ \__/ \__/
启动项目
1-6:单元测试@SpringBootTest
使用@SpringBootTest要导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
进入spring-boot-starter-test的依赖看,里面集成了SpringBootTest的依赖,sprin的核心springframework依赖以及junit和各种依赖
总体来说比junit强大很多
然后在单元测试的类上方加上@SpringBootTest,在单元测试的方法上方加上@Test,加了@SpringBootTest,那就可以使用Spring的注入了
package com.lingaolu.springbootdemo; import com.lingaolu.springbootdemo.bean.Student; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class SpringbootdemoApplicationTests { @Autowired Student student; @Test void contextLoads() { System.out.println(student); } }
我这里注入了类Student,Student类注入了name属性
package com.lingaolu.springbootdemo.bean; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class Student { @Value("林某") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + '}'; } }
单元测试执行,结果出来
2:SpringBoot的配置
我们在第一章SpringBoot基础入门的第四节使用Idea快速创建SpringBoot项目的时候已经初步接触了SpringBoot的配置,那就是修改端口号,下面我们来介绍SpringBoot的配置
2-1: 配置文件格式
SpringBoot的配置文件,后缀不仅支持.properties,还只会yml和yaml格式,从下图我们可以看出
2-2:YAML语法
百度百科:
YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达数据序列化的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、电子邮件的数据格式(RFC 2822)中获得灵感。Clark Evans在2001年首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。当前已经有数种编程语言或脚本语言支持(或者说解析)这种语言。
YAML是"YAML Ain’t a Markup Language"(YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言),但为了强调这种语言以数据做为中心,而不是以标记语言为重点,而用反向缩略语重命名。
YAML以数据为中心,比json、xml等更适合做位置文件
YAML配置例子
server: port: 666
XML配置例子
<server> <port>666</port> </server>
可见yml太简洁方便,我们验证一下yaml修改端口号
说明我们使用yaml修改端口号成功
2-2-1:基本语法
- k:(空格)v:表示一对键值对,k和v之间的空格必须有,并且冒号:是英文的冒号:
- 以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的
- 属性和值也是大小写敏感
2-2-2:值的写法
字面量:普通的值(数字,字符串,布尔)
k: v(字面直接来写)
- 字符串默认不用加上单引号或者双引号
- “”:双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表达的意思
如:name: “lin\nmou”,输出:lin换行mou- ‘’:单引号,会转义特殊字符,特殊字符最终只是一个普通的字符串数据
如:name: ‘lin\nmo’,输出:lin\nmou对象、map(属性和值)(键值对)
girlFriend: name: 未知 age: 29
行内写法
girlFriend: { name: 未知,age: 29}
数组(List、Set)
用-值表示数组中的第一个元素games: - LOL - CS - WOW
行内写法
games: [LOL,CS,WOW]
2-3:从配置文件中获取值
SpringBoot默认的配置文件全名为application.properties,默认被识别,也就是application开头.(properties/yaml/yml)的配置文件属于SpringBoot的全局配置文件,可以 被默认加载
2-3-1:@ConfigurationProperties(prefix=“配置”)
@ConfigurationProperties可以从配置文件中获取整个对象的配置值,将配置文件中配置的每一个属性的值,通过反射的set方法,映射到这个组件中,我们还是直接举例子
我们有2个实体bean对象
- Girl:含有name和age属性,书写set和get方法
- Programmer:含有name和age以及girl属性,使用lombok
Girl的代码
package com.lingaolu.springbootdemo.bean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; // 只有这个组件是容器的组件,才能使用容器提供的>@ConfigurationProperties功能 @Component // 将配置文件中配置的每一个属性的值,映射到这个组件中 // @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配合文件中相关的配置进行绑定 // prefix="girl",配置文件中哪个页面的所有属性进行--映射 @ConfigurationProperties(prefix="girl") public class Girl { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Girl{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Programmer的代码
package com.lingaolu.springbootdemo.bean; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component // 使用lombok @Data @ConfigurationProperties(prefix="pro") public class Programmer { private String name; private Integer age; private Girl girl; }
Girl的配置,采用properties文件
girl.name=go girl.age=25
Programmer的配置,采用yml文件
pro: name: 林某 age: 25 girl: name: 狗不理 age: 23
单元测试
package com.lingaolu.springbootdemo; import com.lingaolu.springbootdemo.bean.Girl; import com.lingaolu.springbootdemo.bean.Programmer; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class SpringbootdemoApplicationTests { @Autowired Girl girl; @Autowired Programmer programmer; @Test void contextLoads() { System.out.println(girl); System.out.println("------------------"); System.out.println(programmer); } }
运行结果
从结果可以看出,无论是properties文件还是yml文件,都能成功的把配置文件里的属性值映射到我们的实体
properties文件中文乱码问题,从上面的例子看出,我们的yml配置文件使用中文,可能成功的映射,那么我们的properties文件也使用中文,结果乱码了
解决properties文件中文乱码问题,因为我们idea里的properties文件默认的是utf-8编码,而运行时的properties文件是ascii编码,所以我们需设置一下
Apply,OK,接着修改属性的值,我们修改为一场梦幻的爱情,再测试一下,中文乱码解决了
发现没有,无论是Girl类还是Programmer类,上方都会有一个红色的提示,这个不影响我们的代码,就是看起来不舒服
解决上面的问题,我们可以导入配置文件处理器
<!-- 导入配置文件处理器,配置文件进行绑定就会有提示 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
刷新maven,重启一下,那么无论是哪种配置文件,我们配置的时候也会有提示了
2-3-2:@ConfigurationProperties(prefix=“配置”)和@value的区别
我们知道spring原生的注解@value也可以给属性注入值,如我们下列的例子
Programmer类的name属性使用@value,其他的使用@ConfigurationProperties
package com.lingaolu.springbootdemo.bean; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @Data @ConfigurationProperties(prefix="programmer") public class Programmer { @Value("${name}") private String name; private Integer age; private String no; }
配置文件
programmer: age: 25 no: 110 name: 码农
结果,name属性也注入值了
虽然@value也可以注入,但是和@ConfigurationProperties还是有区别的,如下表
比较项 | @ConfigurationProperties | @value |
---|---|---|
决定性 | 非SpEL注入,以@ConfigurationProperties为最终结果 | 以SpEL注入,以@value为最终结果 |
功能 | 批量注入配置文件中的属性 | 一个一个指定 |
SpEL | 不支持 | 支持 |
松散绑定 | 支持 | 不支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
下面我们举例说明
决定性
SpEL
松散绑定
JSR303数据校验
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
要使用数据校验,得maven引入上面的包,然后使用注解@Validated作用在要校验的类上,接着在对应属性的相关类型校验进行注解,比如我们这里进行邮箱校验
复杂类型封装
2-3-3:@PropertySource()加载.properties文件
我们先看一个例子
我们前面说过,SpringBoot默认的配置文件名前缀是application,并且这种前缀的配置文件属于全局配置文件,可以被SpringBoot全局找到,被默认加载,但是我们的配置文件是pro.properties,命名的格式不符合全局配置文件的方式,所以找不到,要想找到,就使用@PropertySource(),加载指定的配置文件
package com.lingaolu.springbootdemo.bean; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; @Data @Component @PropertySource(value = { "classpath:pro.properties"}) @ConfigurationProperties(prefix="pro") public class Programmer { private String name; private Integer age; }
加载了指定的配置文件后,就可以被找到了
2-3-4:@PropertySource()加载.yml或者yaml文件
上一节我们说到了@PropertySource()加载.properties文件,这节我们将说@PropertySource()加载.yml或者yaml文件,那么你可能回想,为何要分开说,既然分开说,那就明他们是有区别的,我们先用.properties文件成功的例子,演示一下.yml文件
发现即使使用了@PropertySource()加载指定的文件,还是没有成功
这是为什么呢?这是因为@PropertySource只对properties文件可以进行加载,但对于yml或者yaml不能支持。
想要解决这个问题,我们需要写一个工厂类,继承DefaultPropertySourceFactory,用来处理yml或者yaml文件,因为@PropertySource有一个工厂属性factory。默认就是DefaultPropertySourceFactory
所以我们写了一个工厂类
package com.lingaolu.springbootdemo.factory; import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.core.env.PropertiesPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.DefaultPropertySourceFactory; import org.springframework.core.io.support.EncodedResource; import java.io.IOException; import java.util.List; import java.util.Properties; // 继承DefaultPropertySourceFactory public class YamlAndPropertySourceFactory extends DefaultPropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { if (resource == null) { return super.createPropertySource(name, resource); } Resource resourceResource = resource.getResource(); if (!resourceResource.exists()) { return new PropertiesPropertySource(null, new Properties()); } else if (resourceResource.getFilename().endsWith(".yml") || resourceResource.getFilename().endsWith(".yaml")) { List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resourceResource.getFilename(), >resourceResource); return sources.get(0); } return super.createPropertySource(name, resource); } }
然后我们的@PropertySource,除了要加载指定的配置文件外,还要指定我们所写的工厂类
package com.lingaolu.springbootdemo.bean; import com.lingaolu.springbootdemo.factory.YamlAndPropertySourceFactory; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; @Data @Component @PropertySource(value = { "classpath:pro.yml"}, factory = YamlAndPropertySourceFactory.class) @ConfigurationProperties(prefix="pro") public class Programmer { private String name; private Integer age; }
结果能成功注入
2-3-5:@ImportResource
@ImportResource的作用就是导入Spring的配置文件,让配置文件里面的内容生效
我们先看一个例子,SpringBoot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别
我们自己写了一个spring的配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring->>beans.xsd"> <bean id="programmer1" class="com.lingaolu.springbootdemo.bean.Programmer"> <property name="name" value="我们缺少的是勇气"/> </bean> </beans>
单元测试
package com.lingaolu.springbootdemo; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; @SpringBootTest class SpringbootdemoApplicationTests { @Autowired ApplicationContext ioc; @Test void contextLoads() { boolean b1 = ioc.containsBean("programmer"); System.out.println(b1); boolean b2 = ioc.containsBean("programmer1"); System.out.println(b2); } }
结果发现IOC容器竟然没有我们注入的bean,因为我们自己写的spring.xml文件没有生效
想要我们自己写的spring.xml生效,这就需要@ImportResource登场了,在我们的SpringBoot的主配置类入口上标注上@ImportResource(locations = {“classpath:spring.xml”})
我们再运行测试一下,成功生效
2-3-6:@Configuration
我们在Spring中知道,xml配置文件可以使用配置类来代替,只需要在配置类中使用注解@Configuration就可以声明这个类是配置类,然后使用@Bean注解说明这个方法相当于配置文件的<bean>标签,SpringBoot提倡使用配置类的方式,代替2-3-5:@ImportResource的配置文件方式
我们定义一个配置类MyConfig
package com.lingaolu.springbootdemo.config; import com.lingaolu.springbootdemo.bean.Programmer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; // @Configuration声明这个类是配置类 @Configuration public class MyConfig { // @Bean相当于配置文件里的<bean>标签,注入到IOC容器中,key为方法名 @Bean public Programmer programmer2(){ return new Programmer(); } }
结果
2-3-7:配置文件占位符
配置文件占位符使用的是${表达式},其中可以使用随机数等等
我们的Programmer类代码
package com.lingaolu.springbootdemo.bean; import com.lingaolu.springbootdemo.factory.YamlAndPropertySourceFactory; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Data @Component @ConfigurationProperties(prefix="pro") public class Programmer { private Integer age; private String name1; private String name2; private String name3; private String name4; }
配置文件代码
pro: age: 24 name1: ${ random.uuid} name2: ${ pro.name1}林 name3: ${ pro.name}林 name4: ${ pro.name:神}林
结果说明
2-4:多配置环境Profile
我们在协作开发的过程中,通常需要多配置环境,比如开发是一套环境,上线又是一套环境,这就需要多环境配置,需要用到什么环境就切换到相应的配置环境即可
2-4-1:多文档快方式
在yml文件中,支持多文档快方式,使用—进行文档快的分割,如下
结果
默认环境
使用激活dev环境
文章浏览阅读237次。test.html<!doctype html><html lang="en"> <head> <meta charset="utf-8"> <title>WebGL Demo</title> <link rel="stylesheet" href="./webgl.css" type="text/css"> <script src="https://cdnjs.cloudfla_webgl 三角形 动画
文章浏览阅读1.6k次。一、mysql查看数据库:SHOW DATABASES;创建数据库:CREATE DATABASE db_name;使用数据库:USE db_name;删除数据库:DROP DATABASE db_name;创建表:CREATE TABLE table_name(id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, --id值,无符号、非空、递增——唯一性,可做..._python数据库查询语句
文章浏览阅读3.5k次,点赞3次,收藏51次。最近在玩儿公主连结,之前也玩儿过阴阳师这样的游戏,这样的游戏都会有个初始号这样的东西,或者说是可以肝的东西。当然,作为一名程序员,肝这种东西完全可以用写代码的方式帮我们自动完成。游戏脚本其实并不高深,最简单的体验方法就是下载一个Airtest了,直接截几个图片,写几层代码,就可以按照自己的逻辑玩儿游戏了。当然,本篇文章不是要讲Airtest这个怎么用,而是用原始的python+opencv来实现上面的操作。_手游刷初始号的脚本怎么写
文章浏览阅读10次。CAD绿色版下载地址百度网盘CAD完全卸载
文章浏览阅读3.9k次。nacos开启鉴权提示unknown user!_nacos.core.auth.enabled=true
文章浏览阅读1.5w次,点赞5次,收藏64次。服务器数据上报查询SQLServer/MySQL数据库查询(SELECT)/上报(INSERT);相关案例PLC查询PC数据库中的数据返回到寄存器MQTT协议JSON/XML发布/订阅;HTTP/FTP协议文件解析、上传下载;专用协议与主站设备双向数据通讯;PLC数据寄存器地址、数据类型可自由配置,支持有线网口/WIFI/4G通讯,无需二次开发。 PLC串口扩展/转..._plc与数据库通讯
文章浏览阅读91次。这个是hibernate的一对多建表实例:一的一端是部门(Department),对的一端是员工(Employee),下面贴上成员源代码:其中@mappedBy是加在@OneToMany一端,并且它的name属性=多的那一端(N端)属性是一的那一端的属性名,mappedBy是定义在Department类中,即Department类不负责维护级联关系.即维护者是Employee类Departme..._java建表一对多注释加在哪儿
文章浏览阅读1.8k次,点赞8次,收藏13次。VS QT VTK 左下角显示同步小坐标轴_qvtkwidget 坐标轴
文章浏览阅读951次。传送门:http://acm.fzu.edu.cn/problem.php?pid=2191题型:数论题意:中文题,不解释。分析:因为要求X = A*A*B且B>A,所以,如果单纯计算X的方法数的话,对A枚举到10^5就可以了。对于区间[a,b],枚举³√b的数k,完美度为b/k² - (a-1)/k²,这里,b/k²≥k,但是(a-1)/k²可能所
文章浏览阅读1.9k次。闪聚支付 第1章 讲义-开发环境搭建_黑马闪聚支付项目配置文件
ElasticSearch 8有新特性并介绍了集群安装方法。要求至少启动两个节点以成功重置密码。
文章浏览阅读116次。2019独角兽企业重金招聘Python工程师标准>>> ..._wochao 第一声