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

SpringCloud(二)

Spring Cloud


文章目录

    • Spring Cloud
      • 任务三:Spring Cloud与微服务架构
        • 1.Spring Cloud课程内容介绍
        • 2.单体应用架构
          • 2.1 互联网应用架构演进
            • 2.2 单体应用架构
        • 3.垂直应用架构
        • 4.SOA应用架构
        • 5.微服务应用架构介绍
        • 6.微服务架构核心思想及优缺点
        • 7.微服务架构的核心概念
        • 8.Spring Cloud 是什么
        • 9.Spring Cloud解决什么问题
        • 10.Spring Cloud核心组件
        • 11.Spring Cloud体系结构
        • 12.Spring Cloud对比Dubbo
        • 13.自测
      • 任务四: Spring Cloud核心组件及实战
        • 1.案例需求及流程分析
        • 2.商品表与工程架构说明
        • 3.项目父工程创建
        • 4.公共组件微服务搭建
        • 5.商品微服务搭建
        • 6.页面静态化微服务搭建
        • 7.案例代码问题分析
        • 8.第一代Spring Cloud核心组件
        • 9.注册中心实现原理
        • 10.主流的服务注册中心
        • 11.Eureka 基础架构及交互原理
        • 12.搭建Eureka Server
        • 13.将微服务注册到Eureka
        • 14.搭建Eureka Server高可用集群
        • 15.改造服务消费者调用服务提供者

任务三:Spring Cloud与微服务架构

1.Spring Cloud课程内容介绍
第⼀部分:微服务架构互联网应用架构演进微服务架构的体现思想及优缺点微服务架构的核心概念
第⼆部分: SpringCloud概述Sping Cloud 是什么Sping Cloud 解决什么问题Sping Cloud 架构
第三部分:案例准备
第四部分:第⼀代 Spring Cloud 核⼼组件 (Spring Cloud Netflix)Eureka服务注册中心Ribbon负载均衡Hystrix熔断器Feign远程调用组件GateWay网关组件Config 分布式配置中心
第五部分:第⼆代 Spring Cloud 核⼼组件(Spring Cloud Alibaba)Nacos 服务注册和配置中心 Sentinel 分布式系统的流量防卫兵
2.单体应用架构
2.1 互联网应用架构演进

​ 随着互联网的发展,用户群体逐渐扩大,网站的流量成倍增长,常规的单体架构已无法满足请求压力和业务的快速迭代,架构的变化势在必行。下面我们以拉勾网的架构演进为例,从最开始的单体架构分析,一步步的到现在的微服务架构。

​ 淘宝:LAMP (Linux,Apache,MySQL,PHP)

2.2 单体应用架构

​ 在诞生之初,拉钩的用户量、数据规模都比较小,项目所有的功能模块都放在了一个工程中编码,编译,打包并且部署在一个tomcat容器中的架构模式就是单体应用架构,这样的架构模式即简单实用,便于维护,成本有低,成为那个时代的主流架构方式。

image-20240113210445125

image-20240113210504172

3.垂直应用架构

为了避免上面提到的那些问题,开始做模块的垂直划分,做垂直划分的原则是基于拉钩现有的特性来做,核心目标:第一个为了业务之间相互不影响,第二个是在研发团队的壮大后为了提高效率,减少组件之间的依赖。

image-20240114103547366

4.SOA应用架构

Service-Oriented Architecture:服务-面向 体系结构

In the service-oriented architecture ( SOA) of Web services, there are three distinct actors: the Provider, the Requestor, and the Broker.

在Web服务的面向服务体系(SOA)中,有三个截然不同的角色:提供者、请求者和中介者

在做了垂直划分之后,模块随之增多,维护的成本也在变高,一些通用的业务和模块重复的越来越多,为了解决上面提到的接口协议不统一,服务无法监控,服务的负载均衡,引入了阿里巴巴开源的Dubbo,一款高性能、轻量级的开源java RPC框架,可以和Spring框架无缝集成。它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

SOA(Service-Oriented Architecture),即面向服务的架构,根据实际业务,把系统分成合适的独立部署的模块,模块之间相互独立(通过Webservice/Dubbo等技术进行通信)

优点:分布式、松耦合、扩展灵活、可重用

缺点:服务抽取粒度大、服务调用方和提供方耦合度较高(接口耦合度 )

image-20240114120404675
5.微服务应用架构介绍
image-20240114132158888
6.微服务架构核心思想及优缺点

微服务架构设计的核心思想就是微,拆分的粒度较小,这样的话单一职责、开发的耦合度就会降低、微小的功能可以独立部署扩展、灵活性强,升级改造影响范围小

微服务架构的优点:微服务架构和微服务

  • 微服务很小,便于特定业务功能的聚焦

  • 微服务很小,每个微服务都可以被一个小团队单独实施(开发、测试、部署上线、运维),团队合作一定程度解耦,便于实施敏捷开发

  • 微服务很小,便于重用和模块之间的组装

  • 微服务很独立,那么不同的微服务可以使用不同的语言开发,松耦合(可以用python进行爬虫的开发,用C#进行底层的开发)

  • 微服务架构下,我们更容易引入新技术(微服务之间独立,影响小,使用新技术的影响也小)

微服务架构的缺点:

  • 微服务架构下,分布式复杂难以管理,当服务数量增加,管理将越来越复杂

  • 微服务架构下,分布式链路跟踪难等;

7.微服务架构的核心概念
  • 服务注册与服务发现

    ​ 例如:职位搜索 ————> 简历服务

​ 服务提供者:简历服务 ( 做了集群,有3 台服务器,这个时候服务消费者-职位搜索调用服务提供者-简历服务要调用哪一个呢?我是采用轮询呢?还是随机?

​ 服务消费者:职位搜索

服务注册:服务提供者将所有提供服务的信息(服务器IP和端口、服务访问协议等) 注册/登记到注册中心

服务发现:服务消费者能够从注册中心获取到较为实时的服务列表,然后根据一个策略选择一个服务访问

​ 细节:服务的消费者也要把自己注册到服务注册中心, 注册完成之后,如果你要调用别的服务,这个时候,可以从服务注册中心去拉取服务提供者的列表,然后根据需求进行调用

image-20240114135801711
  • 负载均衡

​ 负载均衡即将请求压力分配到多个服务器(应用服务器,数据库服务器),以此来提高服务的性能、可靠性。多台服务器部署的是同一份代码(这才叫集群嘛)

image-20240114143215110
  • 熔断

​ 熔断即断路保护。微服务架构中,如果下游服务因访问压力过大而响应变慢失败上游服务为了保护系统的可用性,可以暂时切断下游服务的调用。这种牺牲局部,保 全整体的措施就叫熔断

image-20240114144140049

服务B调用服务C,这个时候服务C宕机了,(C已经死了,自己再调,也会跟着死)服务B可以进行熔断,不去调用服务C,然后进行服务降级,返回服务C的默认数据给到服务A

  • 链路追踪

​ 微服务架构越发流行,一个项目往往拆分成很多个服务,那么一次请求就需要设计很多个服务。不同的微服务可能是由不同的团队开发、可能使用不同的语言开发,整个项目也可能部 署在了很多个服务器上(甚至百台、千台)横跨多个不同的数据中心。所谓链路追踪,就是对一次请求设计的很多个服务链路进行日志记录、性能监控。(其实就是分析你的轨迹,然后进 行日志记录,通过分析日志我们就会得出很多信息

那么这个日志记录有用吗?

​ 非常有用,你这个请求经过了谁,延迟有多久,我们就可以大致的推算出来,我服务的瓶颈是在哪个微服务上,哪个微服务需要进行优化,比如说你这个请求中断了,没有成功调 用,那我们通过日志,是不是就能够得出,你死在了哪个位置。比如说,你死在了微服务B,那为什么死了?所以说我们就可以做重点的监控,OK,这个就非常 nice 了。

image-20240114151120773
  • API网关

    • IOT:所有的物联网设备,只要能够联网的设备豆角IOT 客户端
    • Mobile:手机 客户端
    • Browser:浏览器 客户端

    ​ 客户端访问某些数据可以访问我们的微服务,比如,看一下拉钩最近发布了哪些活动,我们每一个微服务都需要单独的调用,而且,你这么多微服务,所对应的地址我是不是都要记住,太难了(臣妾做不到 QAQ),所以得话,我们需要统一的入口(我不找你们,我就找它),什么叫统一的入口呢,比如说,马上十一了,你要去故宫去玩,你不能直接翻墙过去吧,你应该从大门,凭票进入(有票请进,没票滚蛋-鉴权),有票是吧,那行,你要去太和殿,那我给你指路,你要去后宫,那行,在那边,我给你指路。什么?你偷过东西,你也敢来?赶紧滚蛋(黑白名单)。这就是我们网关的作用,就等同于给了你一个统一的入口。

    image-20240114153246182

    微服务架构下,不同的微服务往往会有不同的访问地址,客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信可能出现:

    (1)客户端需要调用不同的URL地址,增加了维护调用的难度 (url 得写死,万一某个URL宕掉了,维护起来比较麻烦)

    (2)在一定的场景下,也存在跨域请求的问题(前后端分离就会碰到跨域问题,原本我们在后端采用Cors就能解决,现在利用网关,那么就放在网关这层做就好了

    (3)每一个微服务都需要进行单独的身份认证 (每调一个微服务都认证一次,太麻烦了,用户体验也太不友好了 | 服务A ——> (认证一次)服务B——>(认证一次)服务C

​ 那么,API网关就可以较好的统计处理上述问题,API请求调用统一接入API网关层,由网关转发请求。API网关更专注在安全、路由、流量等问题的处理上(微服务团队专注于处理业务 逻辑即可),它的功能比如:

​ 1)统一接入(路由)

​ 2)安全防护(统一鉴权,负责网关访问身份认证验证,与 访问认证中心通信,实际认证业务逻辑交移访问认证中心处理)

​ 3)黑白名单(实现通过ID地址控制禁止访问网关功能,控制访问)

​ 4)协议适配(实现通信协议校验、适配转换的功能)

​ 5)流量管控(限流-平滑这个请求,削峰)

​ 6)长短链接支持

​ 7)容错能力(负载均衡)

8.Spring Cloud 是什么

Spring Cloud是一系列框架的有序集合(Spring Cloud是一个规范)

Spring Cloud其实是一套规范,是一套用于构建微服务架构的规范,而不是一个拿来即用的框架(所谓规范就是应该有哪些功能组件,然后组件之间怎么配合,共同完成什么事情)。在这个规范之下第三方的Netflix公司开发了一些组件、Spring官方开发了一些框架/组件,包括第三方的阿里巴巴开发了一套框架/组件集合 Spring Cloud Alibaba,这些才是Spring Cloud规范的实现。

  • Netflix搞了一套,简称SCN

  • Spring Cloud 吸收了Netflix公司的产品基础之上,自己也搞了几个组件

  • 阿里巴巴在之前的基础上搞出了一堆微服务组件,Spring Cloud Alibaba(SCA)

9.Spring Cloud解决什么问题

Spring Cloud 规范及实现意图要解决的问题其实就是微服务架构实施过程中存在的一些问题,比如

微服务架构中的服务注册发现问题、网络问题(比如熔断场景)、统一认证安全授权问题、负载均衡问

题、链路追踪等问题。

  • Distributed/versioned configuration (分布式/版本化配置)
  • Service registration and discovery (服务注册和发现)
  • Routing (智能路由)
  • Service-to-service calls (服务调用)
  • Load balancing (负载均衡)
  • Circuit Breakers (熔断器)
  • Global locks (全局锁)
  • Leadership election and cluster state (
  • 选举与集群状态管理)
  • Distributed messaging (分布式消息传递平台)
10.Spring Cloud核心组件
image-20240114190213146
11.Spring Cloud体系结构
image-20240114191222538
12.Spring Cloud对比Dubbo
image-20240114191721055

dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,基于RPC调用(底层用的协议是TCP协议,但是也可以选择HTTP,默认是TCP),对于目前使用率较高的Spring Cloud Netflix来说,他是基于HTTP的(Spring Cloud Feign基于HTTP协议进行调用),所以效率上没有Dubbo高,但问题在于Dubbo体系的组件不全,不能够提供一站式解决方案,比如服务注册与发现需要借助与Zookeeper等实现,而Spring Cloud Netflix 则是真正的提供了一站式服务化解决方案,且有Spring大家族背景。

前些年,Dubbo使用率高于SpringCloud,但目前SpringCloud在服务化/微服务解决方案中已经有了非常好的发展趋势。

OSI模型主要协议单位TCP/IP
应用层telnet、ftp、HTTP、snmp等数据流应用层
表示层css、gif、html、json、xml、数据流应用层
会话层ftp、ssh、tls、http(s)、sql数据流应用层
传输层tcp、udp传输层传输层
网络层IP(IPV4、IPV6) ICMP数据包网际层
数据链路层802.2,802.3ATM、HDLC网路接口层
物理层v.35、EIA/TIA-232比特流网路接口层
13.自测

阶段九模块一任务三: Spring Cloud与微服务架构

共3道,答对1题

35外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

总分100分

  • 1. 多选题以下哪些选项是单体架构的不足之处(多选) [多选题] *(35分)

    • A可靠性差
    • B复杂性高
    • C扩展能力受限
    • D服务监控不到位

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传D 选项 回答错误, 正确答案为 ABC

    答案解析

    解析:服务监控不到位是垂直应用架构及部分设计不合理的分布式架构存在的问题

  • 2. 单选题以下关于微服务架构的选项,描述错误的是[单选题] *(30分)

    • A微服务架构可以说是SOA架构的一种拓展,这种架构模式下它拆分粒度更小、服务更独立。
    • B微服务架构强调的⼀个重点是业务需要彻底的组件化和服务化
    • C各个微服务很独立,那么不同的微服务可以使用不同的语言开发,松耦合
    • D微服务架构下,各个微服务数据交互的效率要远远高于单体应用架构

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传B 选项 回答错误, 正确答案为 D

    答案解析

    解析:微服务下各个微服务通讯需要借助于http、tcp等通讯协议进行网络通讯,涉及的网络延迟、处理时间相比于单体架构的直接new,效率要低很多。

  • 3. 单选题以下哪个选项是针对微服务架构概念中网关的描述[单选题] *(35分)

    • AA.网关负责对API请求调用统一接入,由该统一服务转发请求。
    • BB.网关负责对一次请求涉及的很多个服务链路进行日志记录、性能监控
    • CC.微服务架构中,如果下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做网关。
    • DD.网关负责即将请求压力分配到多个服务器(应用服务器、数据库服务器等),以此来提高服务的性能、可靠性

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传回答正确 +35分

    答案解析

    解析:B描述的链路追踪,C描述的熔断,D描述的是负载均衡

任务四: Spring Cloud核心组件及实战

1.案例需求及流程分析
image-20240114195828869 image-20240114200202537
2.商品表与工程架构说明
  • 创建商品信息表
CREATE TABLE products( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(50), #商品名称 price DOUBLE, flag VARCHAR(2), #上架状态 goods_desc VARCHAR(100), #商品描述 images VARCHAR(400), #商品图片 goods_stock INT, #商品库存 goods_type VARCHAR(20) #商品类型 
);
  • 案例工程的准备
image-20240114200949925
3.项目父工程创建
  • 父工程 pom 文件配置
<?xml version="1.0" encoding="UTF-8"?>
<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>com.aifeng</groupId><artifactId>aifeng-parent</artifactId><version>1.0-SNAPSHOT</version><!--父工程打包方式--><packaging>pom</packaging><!--spring boot 父启动器依赖--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version>  <!--2.4 以上版本没有 RELEASE--></parent> <dependencies> <!--web依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--日志依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <!--测试依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--lombok工具--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> <scope>provided</scope> </dependency> <!-- Actuator可以帮助你监控和管理Spring Boot应用--> <dependency><groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <!--编译插件--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>21</source> <target>21</target> <encoding>utf-8</encoding> </configuration> </plugin> <!--打包插件--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId><executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
</project>
4.公共组件微服务搭建
<?xml version="1.0" encoding="UTF-8"?>
<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><parent><groupId>com.aifeng</groupId><artifactId>aifeng-parent</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>aifeng-service-common</artifactId><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--引入mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.3.2</version></dependency><!--pojo持久化使用--><!-- https://mvnrepository.com/artifact/javax.el/javax.el-api --><!--<dependency><groupId>javax.el</groupId><artifactId>javax.el-api</artifactId><version>2.2.2</version></dependency>--><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId><version>3.2.1</version></dependency><dependency><groupId>javax.persistence</groupId><artifactId>javax.persistence-api</artifactId><version>2.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.13</version><scope>runtime</scope><!--<scope>runtime</scope>--></dependency></dependencies>
</project>

编译报错: ‘dependencies.dependency.version’ for mysql:mysql-connector-java:jar is missing. @ com.aifeng:aifeng-service-common:[unknown-version]

[INFO] Scanning for projects...
[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[ERROR] 'dependencies.dependency.version' for mysql:mysql-connector-java:jar is missing. @ com.aifeng:aifeng-service-common:[unknown-version], D:\workspace\springclouddemo2\aifeng-parent\aifeng-service-common\pom.xml, line 32, column 21@ 
[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]   
[ERROR]   The project com.aifeng:aifeng-service-common:1.0-SNAPSHOT (D:\workspace\springclouddemo2\aifeng-parent\aifeng-service-common\pom.xml) has 1 error
[ERROR]     'dependencies.dependency.version' for mysql:mysql-connector-java:jar is missing. @ com.aifeng:aifeng-service-common:[unknown-version], D:\workspace\springclouddemo2\aifeng-parent\aifeng-service-common\pom.xml, line 32, column 21
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingExceptionProcess finished with exit code 1

解决方法:加上版本号 8.0.13

      <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.13</version><scope>runtime</scope><!--<scope>runtime</scope>--></dependency>
<dependency><groupId>javax.el</groupId><artifactId>javax.el-api</artifactId><version>2.2.4</version>
</dependency>
  • 生成数据库实体类
image-20240117230608759

使用lombok注解,去掉生成的getter 和 setter 方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

报错:JPS incremental annotation processing is disabled

Executing pre-compile tasks...
Cleaning output directories…
Running 'before' tasks
Checking sources
Copying resources... [aifeng-service-product]
Copying resources... [aifeng-service-common]
Parsing java… [aifeng-service-common]
java: JPS incremental annotation processing is disabled. Compilation results on partial recompilation may be inaccurate. Use build process "jps.track.ap.dependencies" VM flag to enable/disable incremental annotation processing environment.
java: 由于在类路径中发现了一个或多个处理程序,因此启用了批注处理。未来发行版的 javac 可能会禁用批注处理,除非至少按名称指定了一个处理程序 (-processor),或指定了搜索路径 (--processor-path, --processor-module-path),或显式启用了批注处理 (-proc:only, -proc:full)。可使用 -Xlint:-options 隐藏此消息。可使用 -proc:none 禁用批注处理。
java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.sun.tools.javac.tree.JCTree qualid'
java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.sun.tools.javac.tree.JCTree qualid'
Checking dependencies… [aifeng-service-common]
Dependency analysis found 0 affected files
Errors occurred while compiling module 'aifeng-service-common'
javac 21.0.1 was used to compile java sources
Finished, saving caches…
Executing post-compile tasks...
Finished, saving caches…
Synchronizing output directories...
2024/1/16 22:12 - Build completed with 2 errors and 1 warning in 2 sec, 697 ms
java: JPS incremental annotation processing is disabled. Compilation results on partial recompilation may be inaccurate. Use build process "jps.track.ap.dependencies" VM flag to enable/disable incremental annotation processing environment.java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.sun.tools.javac.tree.JCTree qualid'java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.sun.tools.javac.tree.JCTree qualid'

解决方法:提升lombok 版本为:1.18.30

image-20240117210409476

报错: Failed to read candidate component class

有提示信息:Failure to find org.springframework.boot:spring-boot-starter-parent:pom:3.2.1.RELEASE in http://mave


Failure to find org.springframework.boot:spring-boot-starter-parent:pom:3.2.1.RELEASE in http://mave2024-01-16 22:20:54.607 ERROR 3772 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failedorg.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [D:\workspace\springclouddemo\aifeng-parent\aifeng-service-product\target\classes\com\aifeng\product\ProductApplication.class]; nested exception is org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet: file [D:\workspace\springclouddemo\aifeng-parent\aifeng-service-product\target\classes\com\aifeng\product\ProductApplication.class]; nested exception is java.lang.IllegalArgumentException: Unsupported class file major version 65at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(ClassPathScanningCandidateComponentProvider.java:454) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:316) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:275) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:287) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:242) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:199) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:167) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:315) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]at com.aifeng.product.ProductApplication.main(ProductApplication.java:13) ~[classes/:na]at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.1.6.RELEASE.jar:2.1.6.RELEASE]
Caused by: org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet: file [D:\workspace\springclouddemo\aifeng-parent\aifeng-service-product\target\classes\com\aifeng\product\ProductApplication.class]; nested exception is java.lang.IllegalArgumentException: Unsupported class file major version 65at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:57) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.core.type.classreading.CachingMetadataReaderFactory.getMetadataReader(CachingMetadataReaderFactory.java:123) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(ClassPathScanningCandidateComponentProvider.java:430) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]... 23 common frames omitted
Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 65at org.springframework.asm.ClassReader.<init>(ClassReader.java:184) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.asm.ClassReader.<init>(ClassReader.java:166) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.asm.ClassReader.<init>(ClassReader.java:152) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.asm.ClassReader.<init>(ClassReader.java:273) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:54) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]... 26 common frames omittedProcess finished with exit code 0

**解决方法:**去掉release ,而且maven仓库官网也没有在版本之后 加release ,仔细看了下 maven仓库的官网,发现从 2.4 版本之后就没有加 release 了。

image-20240117211729142

image-20240117210008472

image-20240117205855776

与其他springboot的pom文件进行了对比,也是没有release的

image-20240117211153990

repackage报红解决方法

            <plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>3.2.1</version><executions><execution><goals><goal>repackage</goal> <!--repackage 本地mvn仓库没有这个依赖, 查看使用的默认的, 然后改为自建的本地仓库(D:repository | D:\software\apache-maven-			                                                                                                                                             3.3.3\conf\settings.xml)--></goals></execution></executions></plugin>
5.商品微服务搭建
  • 商品微服务,引入公共组件坐标
        <dependency><groupId>com.aifeng</groupId><artifactId>aifeng-service-common</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope></dependency>
  • 在yml文件中配置端口、应用名、数据库连接等信息
server:port: 9000 #微服务的集群环境中,通常会为每一个微服务叠加
spring:application:name: aifeng-service-productdatasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.11.128:3306/springclouddata?useUnicode=true&characterEncoding=utf8&serverTimezone=UTCusername: rootpassword: 123456
  • Mapper接口开发
package com.aifeng.product.mapper;import com.aifeng.common.pojo.Products;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/**** 现在使用的Mybatis-plus组件,该组件是Mybatis的加强版* 能够与SpringBoot进行非常友好的整合,对比Mybatis框架只有使用便捷的改变* 没有具体功能的改变* 具体使用:让具体的Mapper接口继承BaseMapper即可* */
public interface ProductMapper extends BaseMapper<Products> {
}
  • serive层开发

    • ProductService 接口
    package com.aifeng.product.service;import com.aifeng.common.pojo.Products;public interface ProductService {Products queryById(Integer id);
    }
    • ProductServiceImpl 实现类
    package com.aifeng.product.service.imp;import com.aifeng.common.pojo.Products;
    import com.aifeng.product.mapper.ProductMapper;
    import com.aifeng.product.service.ProductService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;@Service
    public class ProductServiceImpl implements ProductService {@Autowiredprivate ProductMapper productMapper;@Overridepublic Products queryById(Integer id) {return productMapper.selectById(id);}
    }
    
  • controller层开发

    • ProductController 类
    package com.aifeng.product.controller;import com.aifeng.common.pojo.Products;
    import com.aifeng.product.service.ProductService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;@RestController
    @RequestMapping("/product")
    public class ProductController {@Autowiredprivate ProductService productService;@GetMapping("/query/{id}")public Products queryById(@PathVariable Integer id){return productService.queryById(id);}
    }
    
  • 启动类

    package com.aifeng.product;import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
    @MapperScan("com.aifeng.product.mapper")// 扫描mapper
    public class ProductApplication {public static void main(String[] args) {SpringApplication.run(ProductApplication.class,args);}
    }
    

启动项目的时候,一直报红,@table注解不可用,依赖坐标没问题,但是就是包没有导入进来,最后把版本重新降回 2.1.6.release,依然还是爆红,已经试了很多方法,也很晚了,就睡了,想着下次,把jdk版本换成11 再试一下卡难看,过了大概有3天吧,这个周末,再重新打开项目,@table注解已经不爆红了,然后查看扩展库里已经依赖包导入。嗯,想着应该是依赖的包没有导入进来,可能是因为缓存和网络的问题,当时依赖的包还没有下载完成,当时IDEA又没有提示,导致我以为是依赖包下载完成(嗯,后续深入分析一下…)

image-20240121185736625 image-20240121185537830

controller层代码写好之后 启动项目还是包 版本错误,果断 jdk版本降为 11 (啊 jdk 21 用不来啊),然后启动项目正常了。

postman测试,报500错误,查看mapper扫描的路径没有配置正确(少了个mapper)

@SpringBootApplication
@MapperScan("com.aifeng.product.mapper")// 扫描mapper
public class ProductApplication {public static void main(String[] args) {SpringApplication.run(ProductApplication.class,args);}
}

项目重新启动,又报错啊,查看是数据库配置错误,mysql下 没有 products 表,表是建在 springclouddata 下的

2024-01-21 20:40:18.141 ERROR 12712 --- [nio-9000-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: 
### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Table 'mysql.products' doesn't exist
### The error may exist in com/aifeng/product/mapper/ProductMapper.java (best guess)
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT id,name,price,flag,goods_desc,images,goods_stock,goods_type FROM products WHERE id=?
### Cause: java.sql.SQLSyntaxErrorException: Table 'mysql.products' doesn't exist
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Table 'mysql.products' doesn't exist] with root cause

果断切换数据库为: springclouddata

postman测试:http://127.0.0.1:9000/product/query/1

image-20240121205131469
{"id": 1,"name": null,"price": 100.0,"flag": "Y","goodsDesc": "2亿像素让你拍照更清晰","images": "url","goodsStock": 1000,"goodsType": "手机"
}
6.页面静态化微服务搭建

报错: java.net.ConnectException: Connection refused: connect

原因:微服务中,我依赖的那个服务没有启动(QAQ !!! 从昨晚开始到现在,我也是对自己无语了,最怕开始遇到坑,结果还是坑了自己)

2024-01-22 20:47:48.705 ERROR 25196 --- [nio-9100-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://127.0.0.1:9000/product/query/1": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect] with root causejava.net.ConnectException: Connection refused: connectat java.base/java.net.PlainSocketImpl.connect0(Native Method) ~[na:na]at java.base/java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:101) ~[na:na]at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:412) ~[na:na]at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:255) ~[na:na]at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:237) ~[na:na]at java.base/java.net.Socket.connect(Socket.java:608) ~[na:na]at java.base/java.net.Socket.connect(Socket.java:557) ~[na:na]at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:182) ~[na:na]at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:508) ~[na:na]at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:603) ~[na:na]at java.base/sun.net.www.http.HttpClient.<init>(HttpClient.java:276) ~[na:na]at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:375) ~[na:na]at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:396) ~[na:na]at java.base/sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1253) ~[na:na]at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1187) ~[na:na]at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1081) ~[na:na]at java.base/sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:1015) ~[na:na]at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:735) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:311) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at com.aifeng.page.controller.PageController.getProduct(PageController.java:23) ~[classes/:na]at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.21.jar:9.0.21]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88) ~[spring-boot-actuator-2.1.6.RELEASE.jar:2.1.6.RELEASE]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114) ~[spring-boot-actuator-2.1.6.RELEASE.jar:2.1.6.RELEASE]at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104) ~[spring-boot-actuator-2.1.6.RELEASE.jar:2.1.6.RELEASE]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.21.jar:9.0.21]at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

postman 测试调用,成功返回

image-20240122214908160
7.案例代码问题分析

我们在页面静态化微服务中使用RestTemplate调用商品微服务的商品状态接口时(Restful API 接

口)。在微服务分布式集群环境下会存在什么问题呢?怎么解决?

存在的问题:

1)在服务消费者中,我们把url地址硬编码到代码中,不方便后期维护。

2)服务提供者只有一个服务,即便服务提供者形成集群,服务消费者还需要自己实现负载均衡。

3)在服务消费者中,不清楚服务提供者的状态。

4)服务消费者调用服务提供者时候,如果出现故障能否及时发现不向用户抛出异常页面?

5)RestTemplate这种请求调用方式是否还有优化空间?能不能类似于Dubbo那样玩?

6)这么多的微服务统一认证如何实现?

7)配置文件每次都修改好多个很麻烦!?

8)…

上述分析出的问题,其实就是微服务架构中必然面临的一些问题:

1)服务管理:自动注册与发现、状态监管

2)服务负载均衡

3)熔断

4)远程过程调用

5)网关拦截、路由转发

6)统一认证

7)集中式配置管理,配置信息实时自动更新

这些问题,Spring Cloud 体系都有解决方案,后续我们会逐个学习。

8.第一代Spring Cloud核心组件
image-20240122221406360
9.注册中心实现原理
image-20240122222424147
10.主流的服务注册中心
  1. Zookeeper

    Dubbo + Zookeeper

    Zookeeper它是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决

    分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布

    式应用配置项的管理等。

    简单来说zookeeper本质 = 存储 + 监听通知。

    Zookeeper 用来做服务注册中心,主要是因为它具有节点变更通知功能,只要客户端监听相

    关服务节点,服务节点的所有变更,都能及时的通知到监听客户端,这样作为调用方只要使用

    Zookeeper 的客户端就能实现服务节点的订阅和变更通知功能了,非常方便。另外,Zookeeper

    可用性也可以,因为只要半数以上的选举节点存活,整个集群就是可用的,最少节点数为3。

  2. Eureka

    由Netflix开源,并被Pivatal集成到SpringCloud体系中,它是基于 RestfulAPI 风格开发的服务

    注册与发现组件。

  3. Consul

    Consul是由HashiCorp基于Go语言开发的支持多数据中心分布式高可用的服务发布和注册服

    务软件, 采用Raft算法保证服务的一致性,且支持健康检查。

  4. Nacos

    Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。简单来说

    Nacos 就是 注册中心 + 配置中心的组合,帮助我们解决微服务开发必会涉及到的服务注册 与发

    现,服务配置,服务管理等问题。Nacos 是 Spring Cloud Alibaba 核心组件之一,负责服务注册

    与发现,还有配置。

  5. 对比

11.Eureka 基础架构及交互原理
image-20240123214049115 image-20240123214709349
12.搭建Eureka Server
  1. aifeng-parent 父工程引入Spring Cloud依赖

​ Spring Cloud是一个综合项目,下面有很多子项目,比如eureka子项目

<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> 
</dependencyManagement>
  1. aifeng-cloud-eureka 工程,pom.xml文件引入依赖
<dependencies> <!--Eureka server依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> 
</dependencies>
  1. 父工程:
<!--引入Jaxb,开始--> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.2.11</version> </dependency> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.2.11</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.2.10-b140310.1920</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency>
<!--引入Jaxb,结束-->
  1. 在yml文件中配置Eureka Server服务端口,服务名等信息

    server:port: 9200
    spring:application:name: aifeng-cloud-eureka
    eureka:client: # Eureka Server本身也是eureka的一个客户端,因为在集群下需要与其他eureka server 进行数据的同步service-url: # 客户端与 EurekaServer交互的地址,如果是集群,也需要写其他Server的地址#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/defaultZone: http://localhost:9200/eurekaregister-with-eureka: false  # 自己就是服务不需要注册自己  | 表示是否向Eureka中心注册自己的信息,因为自己就是Eureka Server所以不进行注册,默认微truefetch-registry: false # 自己就是服务不需要从 Eureka Server获取信息,默认微true,置为false | 表示是否查询/拉取Eureka Server服务注册列表,默认微trueinstance:hostname: localhost # 当前eureka实例的主机名
    
  2. 编写启动类,声明当前服务为Eureka注册中心

    package com.aifeng.eureka;import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication
    @EnableEurekaServer //标识当前项目就是一个Eureka Server
    public class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class,args);}
    }
    
  3. 浏览器访问 http://localhost:9200/

image-20240123224540129 image-20240123230539357

image-20240124210418310
  1. yml 配置

    server:port: 9200
    spring:application:name: aifeng-cloud-eureka
    eureka:client: # Eureka Server本身也是eureka的一个客户端,因为在集群下需要与其他eureka server 进行数据的同步service-url: # 客户端与 EurekaServer交互的地址,如果是集群,也需要写其他Server的地址#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/defaultZone: http://localhost:9200/eurekaregister-with-eureka: true  # 自己就是服务不需要注册自己  | 表示是否向Eureka中心注册自己的信息,因为自己就是Eureka Server所以不进行注册,默认微truefetch-registry: true # 自己就是服务不需要从 Eureka Server获取信息,默认微true,置为false | 表示是否查询/拉取Eureka Server服务注册列表,默认微trueinstance:#hostname: localhost # 当前eureka实例的主机名#使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)prefer-ip-address: true #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddressinstance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
    
  2. 浏览器测试

    image-20240124213144726

13.将微服务注册到Eureka
  1. 商品微服务和页面静态化微服务注册到Eureka

    pom文件中添加Eureka Client依赖

            <!--Eureka client--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
    
  2. application.yml 配置Eureka服务端信息

    eureka:client: # Eureka Server本身也是eureka的一个客户端,因为在集群下需要与其他eureka server 进行数据的同步service-url: # 客户端与 EurekaServer交互的地址,如果是集群,也需要写其他Server的地址#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/defaultZone: http://localhost:9200/eurekainstance:#hostname: localhost # 当前eureka实例的主机名#使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)prefer-ip-address: true #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddressinstance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
    
  3. 修改启动类,启用客户端服务

    使用@EnableDiscoveryClient注解 //使用这个注解,更加通用(不管什么的注册中心都可以使用),比如:阿里的 nacos 相比 Eureka来说 内容更加丰富

    
    @SpringBootApplication
    //@EnableEurekaClient //表示: 将当前项目作为 Eureka Client 注册到Eureka Server, 只能在Eureka环境中使用
    @EnableDiscoveryClient //表示:也是将当前项目表示为注册中心的客户端,向注册中心进行注册,可以在所有的注册中心环境下使用
    @MapperScan("com.aifeng.product.mapper")// 扫描mapper
    public class ProductApplication {public static void main(String[] args) {SpringApplication.run(ProductApplication.class,args);}
    }
    
  4. 开起page 和 product 服务,重新刷新浏览器,正常展示

    image-20240124220503654

14.搭建Eureka Server高可用集群
  1. 创建2台 Eureka Server

    修改host文件 windows11: C:\Windows\System32\drivers\etc

    127.0.0.1       AifengCloudEurekaServerB 
    127.0.0.1       AifengCloudEurekaServerA
    
  2. 9200 端口的Eureka服务的 applicaion.yml 文件配置

    server:port: 9200
    spring:application:name: aifeng-cloud-eureka
    eureka:client: # Eureka Server本身也是eureka的一个客户端,因为在集群下需要与其他eureka server 进行数据的同步service-url: # 客户端与 EurekaServer交互的地址,如果是集群,也需要写其他Server的地址 #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/defaultZone: http://AifengCloudEurekaServerB:9201/eurekaregister-with-eureka: true  # 自己就是服务不需要注册自己  | 表示是否向Eureka中心注册自己的信息,因为自己就是Eureka Server所以不进行注册,默认微truefetch-registry: true # 自己就是服务不需要从 Eureka Server获取信息,默认微true,置为false | 表示是否查询/拉取Eureka Server服务注册列表,默认微trueinstance:#hostname: localhost # 当前eureka实例的主机名#使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)prefer-ip-address: true #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddressinstance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
    
  3. 9201 端口的Eureka服务的 application.yml 文件配置

    server:port: 9201
    spring:application:name: aifeng-cloud-eureka
    eureka:client: # Eureka Server本身也是eureka的一个客户端,因为在集群下需要与其他eureka server 进行数据的同步service-url: # 客户端与 EurekaServer交互的地址,如果是集群,也需要写其他Server的地址#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ |集群情况下,defaultZone 设置为其他 Eureka Server的地址, 集群-多个地址逗号隔开即可defaultZone: http://AifengCloudEurekaServerA:9200/eurekaregister-with-eureka: true  # 自己就是服务不需要注册自己  | 表示是否向Eureka中心注册自己的信息,因为自己就是Eureka Server所以不进行注册,默认微truefetch-registry: true # 自己就是服务不需要从 Eureka Server获取信息,默认微true,置为false | 表示是否查询/拉取Eureka Server服务注册列表,默认微trueinstance:#hostname: localhost # 当前eureka实例的主机名#使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)prefer-ip-address: true #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddressinstance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
    
  4. 商品微服务的 application.yml 文件配置

    server:port: 9000 #微服务的集群环境中,通常会为每一个微服务叠加
    spring:application:name: aifeng-service-productdatasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.11.128:3306/springclouddata?useUnicode=true&characterEncoding=utf8&serverTimezone=UTCusername: rootpassword: 123456
    eureka:client: # Eureka Server本身也是eureka的一个客户端,因为在集群下需要与其他eureka server 进行数据的同步service-url: # 客户端与 EurekaServer交互的地址,如果是集群,也需要写其他Server的地址#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/defaultZone: http://AifengCloudEurekaServerA:9200/eureka,http://AifengCloudEurekaServerB:9201/eurekainstance:#hostname: localhost # 当前eureka实例的主机名#使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)prefer-ip-address: true #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddressinstance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
    
  5. 页面静态化微服务

    server:port: 9100 #微服务的集群环境中,通常会为每一个微服务叠加
    spring:application:name: aifeng-service-pagedatasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.11.128:3306/springclouddata?useUnicode=true&characterEncoding=utf8&serverTimezone=UTCusername: rootpassword: 123456eureka:client: # Eureka Server本身也是eureka的一个客户端,因为在集群下需要与其他eureka server 进行数据的同步service-url: # 客户端与 EurekaServer交互的地址,如果是集群,也需要写其他Server的地址#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/defaultZone: http://AifengCloudEurekaServerA:9200/eureka,http://AifengCloudEurekaServerB:9201/eurekainstance:#hostname: localhost # 当前eureka实例的主机名#使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)prefer-ip-address: true #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddressinstance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
    
  6. 查看Eureka Server 的注册服务中心

    http://aifengcloudeurekaservera:9200/

    image-20240125220040273

​ http://aifengcloudeurekaserverb:9201/

image-20240125220142394
15.改造服务消费者调用服务提供者
  1. 使用Eureka 方式调用静态页面微服务

    import org.springframework.cloud.client.discovery.DiscoveryClient; //使用 SpringCloud 官方提供的客户端@RestController
    @RequestMapping("/page")
    public class PageController {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient; //使用 SpringCloud 官方提供的客户端@GetMapping("/getProduct/{id}")public Products getProduct(@PathVariable Integer id){//通过aifeng-service-product在服务注册中心注册的服务列表(因为一般情况下,实例都是集群)List<ServiceInstance> instances = discoveryClient.getInstances("aifeng-service-product");//因为实在实验环境中,获取商品服务列表中的第一个就可以了ServiceInstance instanceInfo = instances.get(0);//获取商品微服务的主机地址String host = instanceInfo.getHost();//获得商品微服务的端口号int port = instanceInfo.getPort();//拼接URLString url = "http://" +host+ ":"+port+"product/query/"+id;//发送HTTP请求给商品微服务,将ID传过去,获取ID所对应的products对象//String url = "http://127.0.0.1:9000/product/query/";Products products = restTemplate.getForObject(url, Products.class);return products;}}
    
  2. 注意使用 Spring Cloud官提供的 Client ,因为在启用客户端的时候,使用的是 Spring cloud 官方提供的 @EnableDiscoveryClient 注解

    所以注入到容器中的 Client 实例对象是 Spring cloud 官方提供的,所以在 @Autowired 注入 的时候也要用 Spring Cloud 下的 DiscoveryClient

    package com.aifeng.page;import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient; //Spring cloud 官方提供的
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;@SpringBootApplication
    //@EnableEurekaClient
    @EnableDiscoveryClient //使用这个注解,更加通用,比如:阿里的 nacos 相比 Eureka来说 内容更加丰富
    public class PageApplication {public static void main(String[] args) {SpringApplication.run(PageApplication.class,args);}//向容器中注入一个RestTemplate,封装了HttpClient@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
    }
    

    注入了 netflix 提供的DiscoveryClient : com.netflix.discovery.DiscoveryClient ,会报错提示:

    2024-01-25 22:36:18.453 ERROR 20756 --- [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter   : ***************************
    APPLICATION FAILED TO START
    ***************************Description:Field discoveryClient in com.aifeng.page.controller.PageController required a bean of type 'com.netflix.discovery.DiscoveryClient' that could not be found.The injection point has the following annotations:- @org.springframework.beans.factory.annotation.Autowired(required=true)Action:Consider defining a bean of type 'com.netflix.discovery.DiscoveryClient' in your configuration.Process finished with exit code 0
    

    使用Spring Cloud官提供的 Client:

    image-20240125224619171
  3. 调用接口正常返回

    image-20240125230952867

/@EnableEurekaClient
@EnableDiscoveryClient //使用这个注解,更加通用,比如:阿里的 nacos 相比 Eureka来说 内容更加丰富
public class PageApplication {

   public static void main(String[] args) {SpringApplication.run(PageApplication.class,args);}//向容器中注入一个RestTemplate,封装了HttpClient@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}

}


注入了 netflix 提供的DiscoveryClient : com.netflix.discovery.DiscoveryClient ,**会报错提示:**```java
2024-01-25 22:36:18.453 ERROR 20756 --- [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter   : ***************************
APPLICATION FAILED TO START
***************************Description:Field discoveryClient in com.aifeng.page.controller.PageController required a bean of type 'com.netflix.discovery.DiscoveryClient' that could not be found.The injection point has the following annotations:- @org.springframework.beans.factory.annotation.Autowired(required=true)Action:Consider defining a bean of type 'com.netflix.discovery.DiscoveryClient' in your configuration.Process finished with exit code 0

使用Spring Cloud官提供的 Client:

image-20240125224619171
  1. 调用接口正常返回

    image-20240125230952867

相关文章:

SpringCloud(二)

Spring Cloud 文章目录 Spring Cloud任务三&#xff1a;Spring Cloud与微服务架构1.Spring Cloud课程内容介绍2.单体应用架构2.1 互联网应用架构演进2.2 单体应用架构 3.垂直应用架构4.SOA应用架构5.微服务应用架构介绍6.微服务架构核心思想及优缺点7.微服务架构的核心概念8.Sp…...

【java】常见的面试问题

目录 一、异常 1、 throw 和 throws 的区别&#xff1f; 2、 final、finally、finalize 有什么区别&#xff1f; 3、try-catch-finally 中哪个部分可以省略&#xff1f; 4、try-catch-finally 中&#xff0c;如果 catch 中 return 了&#xff0c;finally 还会执行吗&#…...

虚幻UE 插件-像素流送实现和优化

本笔记记录了像素流送插件的实现和优化过程。 UE version&#xff1a;5.3 文章目录 一、像素流送二、实现步骤1、开启像素流送插件2、设置参数3、打包程序4、打包后的程序进行像素流参数设置5、下载NodeJS6、下载信令服务器7、对信令服务器进行设置8、启动像素流送 三、优化1、…...

Vue2 props组件通信

一、父组件向子组件传值 1、流程图 2、父组件代码 <template><div class"app"><UserInfo:usernameusername:ageage:isSingleisSingle:carcar:hobbyhobby></UserInfo></div> </template><script> import UserInfo from .…...

重构改善既有代码的设计-学习(三):重新组织数据

1、拆分变量&#xff08;Split Variable&#xff09; 有些变量用于保存一段冗长代码的运算结果&#xff0c;以便稍后使用。这种变量应该只被赋值一次。 如果它们被赋值超过一次&#xff0c;就意味它们在函数中承担了一个以上的责任。如果变量承担多个责任&#xff0c;它就应该被…...

群狼调研(长沙品牌忠诚度测试)|广告效果测评方法

广告效果测评方法可以根据具体的目标和需求而有所差异&#xff0c;以下是一些常见的广告效果测评方法&#xff1a; 1.品牌调研和调查&#xff1a;通过定量或定性的调研和调查方法&#xff0c;评估广告对品牌认知、品牌形象和品牌偏好的影响&#xff0c;包括品牌知名度、品牌关联…...

Gradle学习笔记:Gradle的使用方法

文章目录 1.初始化项目2.构建脚本语言选择3.项目命名4.项目构建过程 1.初始化项目 创建一个test空文件夹&#xff0c;在该文件夹下打开终端&#xff0c;并执行命令&#xff1a;gradle init. 会有一个选项让你选择项目的类型。下面是每个选项的含义和用途&#xff1a; basic&am…...

少儿编程 2023年12月电子学会图形化编程等级考试Scratch二级真题解析(选择题)

2023年12月scratch编程等级考试二级真题 选择题(共25题,每题2分,共50分) 1、在制作推箱子游戏时,地图是用数字形式储存在电脑里的,下图是一个推箱子地图,地图表示如下:第一行( 111111)第二行( 132231) 第三行( 126621) 第四行( ) 第五行( 152321) 第六行( 111111 ) 根…...

基于Java+SpringMvc+vue+element实现上海汽车博物馆平台

基于JavaSpringMvcvueelement实现上海汽车博物馆平台 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统 …...

Sybase PowerDesigner15安装配置

1&#xff0c;软件介绍 ​ Power Designer 是Sybase公司的CASE工具集&#xff0c;使用它可以方便地对管理信息系统进行分析设计&#xff0c;他几乎包括了数据库模型设计的全过程。利用Power Designer可以制作数据流程图、概念数据模型、物理数据模型&#xff0c;还可以为数据仓…...

基于物联网设计的水稻田智能灌溉系统(STM32+华为云IOT)

一、项目介绍 随着科技的不断发展和人们生活水平的提高&#xff0c;农业生产也逐渐向智能化、高效化的方向发展。水稻作为我国主要的粮食作物之一&#xff0c;其生长过程中的灌溉管理尤为重要。传统的灌溉方式往往依赖于人工观察和控制&#xff0c;不仅效率低下&#xff0c;而…...

【数据结构】数据结构初识

前言&#xff1a; 数据结构是计算存储&#xff0c;组织数据的方式。数据结构是指相互间存在一种或多种特定关系的数据元素的集合。通常情况下&#xff0c;精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。 Data Structure Vi…...

java多线程测试websocket demo(使用文件流)

这个demo主要是利用Java多线程来测试WebSocket通信。首先&#xff0c;创建一个WebSocket服务器和客户端&#xff0c;然后使用多线程来模拟多个客户端同时连接服务器进行通信。通过多线程测试&#xff0c;可以验证WebSocket通信的并发性能和稳定性。同时&#xff0c;可以通过多线…...

Tosei 自助网络店铺管理系统network_test.php_RCE漏洞复现

简介 Tosei 自助洗衣机是日本一家公司的产品,在 network_test.php 文件存在命令执行 漏洞复现 FOFA语法: body="tosei_login_check.php" 主要是日本 访问界面如下所示: 验证POC: /cgi-bin/network_test.php 拼接访问url: https://ip:port/cgi-bin/network_tes…...

uni-app 国际化

vue i18n v9的迁移后的$t()无法获取数组、对象 http://t.csdnimg.cn/WkCHy api:vue i18n [intlify] Not found ‘language’ key in ‘zh-Hans’ locale messages. [intlify] Fall back to translate ‘language’ key with ‘zh’ locale. [intlify] Not found ‘languag…...

git:git reset 和 git revert

在使用 git 进行项目开发的过程中&#xff0c;有时会出现错误提交的情况&#xff0c;这时就需要能够撤销错误的提交&#xff0c;将代码恢复到提交之前的样子。根据不同情况&#xff0c;可以使用 git reset 或 git revert 命令。 一. git reset git reset 的原理是修改 HEAD 的…...

LeetCode:670. 最大交换(Java 贪心)

目录 670. 最大交换 题目描述&#xff1a; 实现代码与解析&#xff1b; 贪心 原理思路&#xff1a; 670. 最大交换 题目描述&#xff1a; 给定一个非负整数&#xff0c;你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释…...

【STM32】STM32学习笔记-Unix时间戳(41)

00. 目录 文章目录 00. 目录01. Unix时间戳02. UTC/GMT03. 时间戳转换04. C 标准库 <time.h>05. 时间相关函数示例5.1 time函数5.2 gmtime函数5.3 localtime函数5.4 mktime函数5.5 ctime函数5.6 asctime函数5.7 strftime函数 06. 预留07. 附录 01. Unix时间戳 •Unix 时…...

2016年认证杯SPSSPRO杯数学建模B题(第一阶段)低分辨率下看世界全过程文档及程序

2016年认证杯SPSSPRO杯数学建模 B题 低分辨率下看世界 原题再现&#xff1a; 数码摄像技术被广泛使用于多种场合中。有时由于客观条件的限制&#xff0c;拍摄设备只能在较低的分辨率下成像。为简单起见&#xff0c;我们只考虑单色成像。假设成像的分辨率为 32 64&#xff0c…...

16、Kafka ------ SpringBoot 整合 Kafka (配置 Kafka 属性 及对应的 属性处理类 解析)

目录 配置 Kafka 及对应的 属性处理类配置KafkaKafka配置属性的约定代码演示生产者相关的配置消费者相关的配置 代码&#xff08;配置文件&#xff09;application.properties 配置 Kafka 及对应的 属性处理类 配置Kafka spring.kafka.* 开头的配置属性&#xff0c;这些属性将由…...

【蓝桥杯选拔赛真题61】python偶数平方 第十五届青少年组蓝桥杯python 选拔赛比赛真题解析

目录 python偶数平方 一、题目要求 1、编程实现 2、输入输出...

智能语音识别源码系统+语义理解+对话管理+语音合成 带完整的搭建教程

人工智能技术的不断发展&#xff0c;智能语音识别技术逐渐成为人们日常生活和工作中不可或缺的一部分。然而&#xff0c;目前市场上的智能语音识别产品大多存在一定的局限性&#xff0c;如识别率不高、功能单一等。为了解决这些问题&#xff0c;罗峰给大家分享一款基于智能语音…...

cdh6.3.2的hive配udf

背景 大数据平台的租户要使用udf&#xff0c;他们用beeline连接&#xff0c; 意味着要通过hs2&#xff0c;但如果有多个hs2&#xff0c;各个hs2之间不能共享&#xff0c;需要先把文件传到hdfs&#xff0c;然后手动在各hs2上create function。之后就可以永久使用了&#xff0c;…...

在DevEco开发工具中,使用Previewer预览界面中的UI组件

1、在DevEco工具中&#xff0c;点击并展开PreViewer预览器 2、在PreViewer预览器中&#xff0c;点击Tt按钮&#xff08;Inspector&#xff09;切换至组件查看模式 3、在组件查看模式下选择组件&#xff0c;代码呈现选中状态&#xff0c;右侧呈现组件树&#xff0c;右下方呈现组…...

【蓝桥杯冲冲冲】旅行计划

蓝桥杯备赛 | 洛谷做题打卡day18 文章目录 蓝桥杯备赛 | 洛谷做题打卡day18旅行计划题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示题解代码我的一些话 旅行计划 题目描述 Kira酱要去一个国家旅游。这个国家有 N N N 个城市&#xff0c;编号为 1 1 1 至 N N…...

Ultraleap 3Di配置以及在 Unity 中使用 Ultraleap 3Di手部跟踪

0 开发需求 1、硬件&#xff1a;Ultraleap 手部追踪相机&#xff08;Ultraleap 3Di&#xff09; 2、软件&#xff1a;在计算机上安装Ultraleap Gemini (V5.2) 手部跟踪软件。 3、版本&#xff1a;Unity 2021 LTS 或更高版本 4、Unity XR插件管理&#xff1a;可从软件包管理器窗…...

HarmonyOS鸿蒙学习基础篇 - Text文本组件

该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 Text文本组件是可以显示一段文本的组件。该组件从API Version 7开始支持&#xff0c;从API version 9开始&#xff0c;该接口支持在ArkTS卡片中使用。 子组件 可…...

pytorch学习笔记(十一)

优化器学习 把搭建好的模型拿来训练&#xff0c;得到最优的参数。 import torch.optim import torchvision from torch import nn from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear from torch.utils.data import DataLoaderdataset torchvision.datas…...

【并发编程】 synchronized的普通方法,静态方法,锁对象,锁升级过程,可重入锁,非公平锁

目录 1.普通方法 2.静态方法 3.锁对象 4.锁升级过程 5.可重入的锁 6.不公平锁 非公平锁的 lock 方法&#xff1a; 1.普通方法 将synchronized修饰在普通同步方法&#xff0c;那么该锁的作用域是在当前实例对象范围内,也就是说对于 SyncDemosdnewSyncDemo();这一个实例对象…...

jQuery 删除元素 —— W3school 详解 简单易懂(十四)

通过 jQuery&#xff0c;可以很容易地删除已有的 HTML 元素。 删除元素/内容 如需删除元素和内容&#xff0c;一般可使用以下两个 jQuery 方法&#xff1a; remove() - 删除被选元素&#xff08;及其子元素&#xff09;empty() - 从被选元素中删除子元素 jQuery remove() 方…...

如何电脑安装wordpress/seo优化网站教程百度

数组是VBA中非常好用的功能 下面用代码来演示如何将txt的tab文件转入excel表格的方法 当中利用的转记工具就是数组 会写上一部分注释 Function saveFile()Dim Temp, Temp2, Buf, Target As String, LRow_Output As Long, LCon_Output As Long, InputT, DelFile As StringSet S…...

vs2010可以做动态网站吗/缅甸在线今日新闻

提前半年定的亲 订婚前男方带着女方家人认一下男方的家&#xff0c;之后双方一起去订婚宴&#xff1b; 订婚宴邀请双方父母及近的亲戚&#xff0c;比如叔、婶子、媒人、姑&#xff0c;也可以叫上舅&#xff0c;大概三桌&#xff0c;三十来个人&#xff0c;双方父母及最近的人…...

达人室内设计网官方/广州seo公司如何

在windows上编译apr库apr-util库 环境&#xff1a; win10、VS2015企业版、CMake3.18.2 一、下载apr相关库 1.1&#xff09;expat&#xff1a;expat-2.1.0.tar.gz 1.2&#xff09;apr库&#xff1a;apr-1.6.3.zip 1.3&#xff09;apr-util库&#xff1a;apr-util-1.6.1-win32-…...

外国网站在内地做seo/实时疫情最新消息数据

创建Controller sudo php think make:controller --plain index/ConTest 创建Model sudo php think make:model --plain index/modelTest 创建公共Model 不加路径 直接名字创建 sudo php think make:model Articles 创建Module 模块 sudo php think build --module admin...

长沙网站建设推广/百度云资源搜索

基本输入 Laravel使用一种简单的方式来访问用户提交的信息。 你可以用统一的方式来访问用户提交的信息&#xff0c;而不用为用户提交信息的方式操心。 获取一个用户提交的值 $name Input::get(name); 为用户提交信息指定一个的默认返回值(如果用户未提交) $name Input::…...

网站访客qq获取/在线视频用什么网址

摘要&#xff1a;华为导流测试平台通过对线上流量回放到被测环境中&#xff0c;利用线上真实流量进行充分测试&#xff0c;保证业务系统稳定上线。但是业务在导流测试过程中现网数据库往往难以同步到测试环境&#xff0c;导致现网数据无法正常回放&#xff0c;测试价值降低。由…...