Spring:从零开始的Cloud生活(零)——Eureka 服务治理

2023-11-12

 

目录

Spring:从零开始的Cloud生活(零)——Eureka 服务治理

1.Netfilx Eurake

2.搭建服务注册中心

3.服务提供者

4.高可用注册中心

5.服务发现和消费


之前对于SpringCloud都是一知半解的状态,现在开始系统学习,边学边记,参考来源于《Spring Cloud微服务实战》,由于版本差异,通过各大论坛查漏补缺。

SpringCloud是一系列技术的集合,它像我们买台式电脑中的品牌机一样,模式化地整合了一系列技术供我们使用,高手可以自己选择、替换、配置电脑的组件,但是制式品牌机才是应用最为广泛的。

服务治理的主要功能就是用来实现微服务实例的自动化注册与发现,当服务之间互相调用的时候被调用方都需要一个具体的实例清单来告知调用方有哪些实例可供调用,如果系统功能比较简单,微服务模块的数量较少,还可以通过手工维护的方式来静态配置实例清单,但如果服务超过一定规模,集群的大小、服务的位置、服务命名等都有可能发生改变,再使用手工维护的方式极易发生命名冲突和各种调用错误,即使无错也会消耗大量的人力。

这里就涉及了两个概念:

  • 服务注册:通常情况下,微服务的使用都会伴随一个技术——注册中心,每个服务单元都会在注册中心中注册自己的服务,将IP与端口号、版本号、通信协议等附加信息告知注册中心,注册中心会按服务名分类组织服务清单。服务中心会以监听心跳的方式去观察清单中的服务是否可用,若不可用就会剔除该服务,借此来排除故障。
  • 服务发现:在服务治理框架中,两个服务之间的调用再通过指定实例地址来实现,所以调用方并不知道被调用方的具体实例地址,因此调用方需要向注册中心发起请求,获取所有服务的实例清单来完成对具体事例的访问。不过在实际使用中,由于诸多因素的限制,不会每次都向注册中心请求获得被调用方的实例地址,在不同场景中会采用不同的缓存及服务剔除机制

举个小例子,现在有服务提供者A和B,A服务的进程运行在实例192.168.0.1:8200和192.168.0.2:8200上,B服务的进程运行在192.168.0.1:9200、192.168.0.2:9200和192.168.0.3:9200上,假设实例都在启动状态下,并向注册中心注册了自己的服务,那么注册中心就会维护下面这个清单:

服务名

位置

A

192.168.0.1:8200  192.168.0.2:8200

B

192.168.0.1:9200  192.168.0.2:9200  192.168.0.3:9200

假如服务C此时想调用服务A,就先向注册中心打报告,注册中心告诉服务C,服务A的可用实例地址为 192.168.0.1:8200  192.168.0.2:8200,然后服务C通过设置好的轮询规则选取一个来调用。

 


1.Netfilx Eurake

Netfilx Eurake是作为SpringCloud中的一部分来实现注册于发现,它既包含了客户端组件,也包含了服务端组件,同时二者都是使用Java语言编写,当然,Eurake提供了完备的RestfulAPI,其他语言也可兼容。

目前自己了解到的注册中心为zookeeper、consul、eurake,除此之外还有阿里的nacos,在选用配置中心的时候可以根据项目选择,这四者的主要区别如下表格:

表格来源:https://blog.csdn.net/fly910905/article/details/100023415

 

  Nacos Eureka Consul Zookeeper
一致性协议 CP+AP AP CP CP
健康检查 TCP/HTTP/MYSQL/Client Beat Client Beat TCP/HTTP/gRPC/Cmd Keep Alive
负载均衡策略 权重/
metadata/Selector
Ribbon Fabio
雪崩保护
自动注销实例 支持 支持 支持 支持
访问协议 HTTP/DNS HTTP HTTP/DNS TCP
监听支持 支持 支持 支持 支持
多数据中心 支持 支持 支持 不支持
跨注册中心同步 支持 不支持 支持 不支持
SpringCloud集成 支持 支持 支持 支持
Dubbo集成 支持 不支持 支持 支持
K8S集成 支持 不支持 支持 不支持

 

Eruka作为SpringCloud默认的注册中心,它更偏向于高可用配置,依托强一致性提供良好的服务实例可用性,其中包括自我保护模式、故障分片容灾处理等。比如Netfilx推荐每个可用区域运行一个Eurake服务端,以此形成集群,不同区域的注册中心通过异步来相互复制各自的状态,这就意味着每个不同时间点每个实例中关于所有服务的状态都是有细微差别的。

 


2.搭建服务注册中心

Eureka客户端通过注解和参数配置的方式嵌入于项目中,在项目运行期间,Eureka客户端在注册中心注册自身提供的服务并通过周期性地向注册中心发送心跳的方式来更新服务租约,同时它也能从服务端查询当前注册的服务信息并把信息缓存到本地且周期性地刷新服务状态

我们先搭建一个简单的服务注册中心,首先创建好基础的SpringBoot的工程,并在pom.xml中引入必要依赖,需要注意的是,springboot和springcloud二者的版本一定要对应,不然会发生许多莫名其妙的错误,版本的大致对应关系如下,加粗为目前项目使用的版本:

spring-boot-starter-parent(Spring Boot) spring-cloud-dependencie
1.2.x Angel版本
1.3.x Brixton版本
1.4.x Camden版本
1.5.2.RELEASE Dalston.RC1
1.5.2.RELEASE Dalston.RC1
1.5.16/20.RELEASE Edgware.RELEASE
>=2.0.0.M3 and <2.0.0.M5 Finchley.M2
pring Boot >=2.0.0.M5 and <=2.0.0.M5 Finchley.M3
Spring Boot >=2.0.0.M6 and <=2.0.0.M6 Finchley.M4
Spring Boot >=2.0.0.M7 and <=2.0.0.M7 Finchley.M5
Spring Boot >=2.0.0.RC1 and <=2.0.0.RC1 Finchley.M6
Spring Boot >=2.0.0.RC2 and <=2.0.0.RC2 Finchley.M7
Spring Boot >=2.0.0.RELEASE and <=2.0.0.RELEASE Finchley.M9
Spring Boot >=2.0.1.RELEASE and <2.0.2.RELEASE Finchley.RC1
Spring Boot >=2.0.2.RELEASE and <2.0.3.RELEASE Finchley.RC2
Spring Boot >=2.0.3.RELEASE and <2.0.999.BUILD-SNAPSHOT Finchley.SR4
Spring Boot >=2.0.999.BUILD-SNAPSHOT and <2.1.0.M3 Finchley.BUILD-SNAPSHOT
Spring Boot >=2.1.0.M3 and <2.1.0.RELEASE Greenwich.M1
Spring Boot >=2.1.0.RELEASE and <2.1.9.BUILD-SNAPSHOT Greenwich.SR2
Spring Boot >=2.1.9.BUILD-SNAPSHOT and <2.2.0.M4 Greenwich.BUILD-SNAPSHOT
Spring Boot >=2.2.0.M4 and <=2.2.0.M5 Hoxton.M2
Spring Boot >=2.2.0.BUILD-SNAPSHOT Hoxton.BUILD-SNAPSHOT

通过上图可知当前引用依赖为:

</dependencies> 
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Finchley.SR4</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>
</dependencies> 

配置文件配置完毕,还需要在启动类上添加@EnableEurekaClient注解或者@EnableDiscoveryClient注解,这两个注解中@EnableEurekaClient只适用于Eureka注册中心,后者却可以适用于所有注册中心,可以根据具体环境选择。代码如下:

@EnableEurekaServer  //开启eurake服务注册功能
@SpringBootApplication
public class EurekaDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaDemoApplication.class, args);
    }

}

默认情况下,负责充当注册中心的客户端也会尝试自己注册自己,所以需要禁用注册中心的客户端注册行为,在application配置文件中增加如下配置:

## 微服务端口号 ##
server:
  port: 1011

## eureka相关配置 ##
eureka:
  instance:
    hostname: localhost #应用实例主机名
  client:
    register-with-eureka: false #是否向服务中心注册自己  默认:true
    fetch-registry: false  #是否从服务中心获取注册信息,默认:true
    service-url:
      #Eureka服务器的地址,类型为HashMap,默认的key为defaultZone;默认的Value为 http://localhost:8761/eureka
      #如果服务注册中心为高可用集群时,多个注册中心地址以逗号分隔。
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

由于当前应用充当注册中心,所以既不用向注册中心注册自己,也不用调用其它服务,所以register-with-eurekafetch-registry两个属性都为false。配置完毕后,启动应用,在浏览器地址栏输入localhost:1011,就可以查看注册中心的信息面板了:

image.png

这里可以看到Instances currently registered with Eureka一行是空的,说明还没有注册服务。


3.服务提供者

服务提供者如其名字那样,就是供其他服务调用的项目。上文已经搭建好了一个注册中心,并可以成功启动,那么首先自然是注册服务提供者的项目到上面,新建项目provider-demo并添加同注册中心一样的依赖。

项目配置文件如下:

## 微服务端口号 ##
server:
  port: 1012

## 微服务名 ##
spring:
  application:
    name: yasuo-service

## eureka相关配置 ##
eureka:
  client:
    service-url:
      defaultZone: http://localhost:1011/eureka/

其中,端口号是较为常规的配置,为了让提供者在注册中心可以更好地被识别,还要设置微服务名。

eureka.client.service-url.defaultZone=http://localhost:1011/eureka/ 则是说明注册中心所在地址,以供提供者注册。

配置文件配置完毕,为了激活Eureka中DiscoveryClient(服务发现客户端),还需要在启动类上添加@EnableEurekaClient注解或者@EnableDiscoveryClient注解,代码如下:

@EnableDiscoveryClient
@SpringBootApplication
public class ProviderDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderDemoApplication.class, args);
    }

}

这些前置条件都完成后,就可以写一个简单的测试控制器来测试服务注册了,控制器代码如下:

@RestController
@Slf4j
public class HelloController {

    @Autowired
    private Registration registration;

    @Autowired
    private DiscoveryClient client;

    @Value("${server.port}")
    private String servicePort;

    @GetMapping("/yasuo")
    public String yasuo(){

        //获取本地实例数据
        ServiceInstance instance = getLocalServiceInstance();
        log.info("/yasuo控制器的端口为{},服务id为{}",instance.getPort(),instance.getServiceId());
        return "且听风吟,御剑于心";

    }

    /**
     * 获取本地实例数据方法
     * @return 本地实例信息对象
     */
    private ServiceInstance getLocalServiceInstance(){

        List<ServiceInstance> instances = client.getInstances(registration.getServiceId());
        for (ServiceInstance instance : instances) {
            if (instance.getPort() == Integer.parseInt(servicePort)) {
               return instance;
            }
        }
        return null;
    }

}

编码完成后,先启动注册中心Eureka-demo,检查运行正常后再启动服务提供者provider-demo,打开localhost:1011,也就是注册中心页面,可以看到:

image.png

这说明我们的服务提供者已经把自己的实例信息注册到了注册中心。直接向服务提供者发起请求,在地址栏中输入localhost:1012/yasuo,可以看到页面和控制台分别有如下输出:

image.png

image.png


4.高可用注册中心

在分布式架构中,容错是十分重要的一个点,所以需要考虑到发生故障的情况,因此需要在生产环境中对各个组件进行高可用部署,eureka从设计的时候就考虑到了这个问题,任何服务都可以既是消费方,也是提供方,注册中心也是如此。

之前在配置文件中配置了注册中心不注册自己:

eureka:
  client:
    register-with-eureka: false #是否向服务中心注册自己  默认:true
    fetch-registry: false  #是否从服务中心获取注册信息,默认:true

为了实现高可用,注册中心就需要向其他注册中心注册自己,同时也需要获取相关注册信息,这两个配置就保持默认的true了。复制一份同样的注册中心eureka-demo2,eureka-demo和eureka-demo2的配置文件如下:

eureka-demo:

### 注册中心eureka-demo ###
## 微服务端口号 ##
server:
  port: 1011

#服务名
spring:
  application:
    name: eureka-server1

## eureka相关配置 ##
eureka:
  instance:
    hostname: NO1 #应用实例主机名
  client:
    service-url:
      #Eureka服务器的地址,类型为HashMap,默认的key为defaultZone;默认的Value为 http://localhost:8761/eureka
      #如果服务注册中心为高可用集群时,多个注册中心地址以逗号分隔。
      defaultZone:  http://localhost:1021/eureka/

eureka-demo2:

### 注册中心eureka-demo2 ###
## 微服务端口号 ##
server:
  port: 1021

#服务名
spring:
  application:
    name: eureka-server2

## eureka相关配置 ##
eureka:
  instance:
    hostname: NO2 #应用实例主机名
  client:
    service-url:
      #Eureka服务器的地址,类型为HashMap,默认的key为defaultZone;默认的Value为 http://localhost:8761/eureka
      #如果服务注册中心为高可用集群时,多个注册中心地址以逗号分隔。
      defaultZone:  http://localhost:1011/eureka/

然后修改服务提供者的配置文件,让服务提供者注册到两个注册中心上:

### 服务提供者 ###
## 微服务端口号 ##
server:
  port: 1012

## 微服务名 ##
spring:
  application:
    name: yasuo-service

## eureka相关配置 ##
eureka:
  client:
    service-url:
      defaultZone: http://localhost:1011/eureka/,http://localhost:1021/eureka/

这两个注册中心相互进行注册来实现服务清单的互相同步,来实现高可用的效果。假如需要搭建eureka集群的话,那么eureka.instance.hostname不能重复,否则集群失败,所以不能为localhost或者ip地址。在测试中我刚开始使用的是localhost去进行集群发现失败了。所以我们需要修改一下本地的hosts文件,位置在C:\Windows\System32\drivers\etc\hosts。

#eureka
127.0.0.1 NO1
127.0.0.1 NO2

将两个注册中心启动,启动有先后间隔,先启动的注册中心会报错,因为无法找到要注册的另一个注册中心,等待第二个注册中心启动后在周期内发出心跳就可以了,无需理会。启动完毕后再启动服务提供者并分别访问两个注册中心的主页。

image.png

image.png

当前三个服务都已经注册,且正常运行(处于UP状态),这样,当其中某个注册中心发生故障的时候,服务消费者依然可以从其他节点获取生产者的地址。如果提供者的配置文件中只注册了一个注册中心,那么其他注册中心也可以获取到提供者的地址,但仅限于提供者注册的注册中心正常运行的情况下

 


5.服务发现和消费

前面说了注册中心的高可用模式和单节点模式,也通过修改配置让服务提供者注册到注册中心上,下面就要编码一个消费者来消费提供者的服务。消费者需要完成两个目标,服务发现与服务消费,服务发现通过Eureka的客户端完成,服务消费需要通过Ribbon来完成。

Ribbon其实是一个基于HTTP和TCP的负载均衡器,它可以通过在客户端配置的ribbonServerList(ribbon服务列表)进行轮询访问以达到负载均衡的作用。二者联合使用时,RibbonServerList会被DiscoveryEnableNIWSServerList重写,拓展成从Eureka注册中心获取服务列表,同时会使用NIWSDiscoveryPing替代IPing,Ribbon职责推给了Eureka来确定服务端是否启动,有关ribbon后面会继续详细学习,目前只需要知道Ribbon通过负载均衡策略在Eureka的基础上选择服务,从而实现消费服务。

新建一个消费者项目eureka-consumer,在提供者依赖的基础上新增ribbon相关依赖:

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

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--Eureka依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <!--Ribbon 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <!--Cloud依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.SR4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>

在启动类上添加@EnableDiscoveryClient注解开启服务发现功能,并添加名为RestTemplate的Bean实例,添加@LoadBalanced注解开启负载均衡功能。

@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerDemoApplication {
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(ConsumerDemoApplication.class, args);
    }

}

构建一个消费者控制器并实现/ruiwen接口用于调用提供者控制器的/yasuo接口,同时配置项目端口、注册中心地址、项目名等信息:

//消费者控制器
@RestController
public class ConsumerController {

    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/ruiwen")
    public String ruiwen(){

        return restTemplate.getForEntity("http://yasuo-service/yasuo",String.class)
                .getBody();
    }

}
### 消费者配置文件 ###
## 微服务端口号 ##
server:
  port: 1014

## 微服务名 ##
spring:
  application:
    name: ruiwen-service

## eureka相关配置 ##
eureka:
  client:
    service-url:
      defaultZone: http://localhost:1011/eureka/

依次启动注册中心->两个提供者(笔记中端口号为1012、1013,为了测试负载均衡,服务名都为yasuo-service)->消费者,观察Eureka主页的变化:

image.png

提供者yasuo-service(两个)和消费者ruiwen-service都注册到注册中心了,访问一下localhost:1014/ruiwen发起多次请求,观察页面和控制台输出:

image.png

image.png

访问了六次,发现被调用方yasuo-service的两个服务各调用三次,说明ribbon当前是按照轮询调用提供者服务的。而消费者控制台也会输出调用信息(以调用提供者1013端口为例):

DynamicServerListLoadBalancer for client yasuo-service initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=yasuo-service,current list of Servers=[11.205.243.215:1013, 11.205.243.215:1012],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone; Instance count:2;   Active connections count: 0;    Circuit breaker tripped count: 0;   Active connections per server: 0.0;]
},Server stats: [[Server:11.205.243.215:1012;   Zone:defaultZone;   Total Requests:0;   Successive connection failure:0;    Total blackout seconds:0;   Last connection made:Thu Jan 01 08:00:00 CST 1970;  First connection made: Thu Jan 01 08:00:00 CST 1970;    Active Connections:0;   total failure count in last (1000) msecs:0; average resp time:0.0;  90 percentile resp time:0.0;    95 percentile resp time:0.0;    min resp time:0.0;  max resp time:0.0;  stddev resp time:0.0]
, [Server:11.205.243.215:1013;  Zone:defaultZone;   Total Requests:0;   Successive connection failure:0;    Total blackout seconds:0;   Last connection made:Thu Jan 01 08:00:00 CST 1970;  First connection made: Thu Jan 01 08:00:00 CST 1970;    Active Connections:0;   total failure count in last (1000) msecs:0; average resp time:0.0;  90 percentile resp time:0.0;    95 percentile resp time:0.0;    min resp time:0.0;  max resp time:0.0;  stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@54cd75b0

这些信息是ribbon进行输出的,其中包含了实例位置,对各实例的请求总数量,第一次连接信息,上一次连接信息,总请求失败次数等。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring:从零开始的Cloud生活(零)——Eureka 服务治理 的相关文章

  • 为 JSP 创建注销链接?

    当用户登录我的应用程序时 他提交一个要通过 Servlet 处理的表单 servlet 为用户创建一个会话 我如何创建一个链接以便用户可以注销 我似乎无法直接链接到 Servlet 如何删除会话并链接回主页 HttpSession sess
  • Javadoc 链接到其他类中的方法

    目前我正在使用以下 Javadoc 语法引用其他类中的方法 see link com my package Class method 据我从文档中了解到 这是执行此操作的正确方法 但现在到了有趣的部分 或者说令人沮丧的部分 当我生成这个 j
  • 如何注入“运行时”依赖项,例如登录用户,该依赖项在应用程序启动时不可用?

    我只是不明白这个 我在我的 java GWT 应用程序中使用 Gin 来进行 DI 登录屏幕集成到完整的应用程序窗口中 用户登录后 我想将用户对象注入到我创建的其他类 例如 GUI Presenters 中 因此我相信存在某种运行时依赖性
  • Google API - 重定向 URI 不匹配错误

    我正在我的网络应用程序上实现 google 登录 我通过参考this尝试过link https developers google com web signin server side flow 我的 google 登录按钮如下 div s
  • 从 Windows Batch (cmd.exe) 中的文件读取环境变量

    我正在尝试从批处理文件中读取变量 以便稍后在批处理脚本 Java 启动器 中使用 理想情况下 我希望所有平台 Unix Windows 上的设置文件都具有相同的格式 并且也是有效的 Java 属性文件 也就是说 它应该看起来像这样 sett
  • .NET 世界有 Maven 替代方案或端口吗?

    NET 世界有 Maven 替代方案或端口吗 我很想使用 Java 世界拥有的良好依赖管理系统 但我没有找到任何可与 NET 项目相媲美的系统 NMaven http incubator apache org nmaven 是第一个 官方努
  • 如何增加使用 SAX 解析 XML 文件的entityExpansionLimit

    我正在尝试使用 Java 中的 SAX 解析器解析一个 1 23 GB 的 XML 文件 我使用的是 Mac 操作系统和 JDK 1 7 0 51 不幸的是 我收到以下错误 The pasrser has encountered more
  • JAVA 签名对象 - 没有安装的提供程序支持此密钥:sun.security.rsa.RSAPrivateCrtKeyImpl

    我想使用密钥工具和以下命令创建的一对 RSA 密钥对我创建的文件进行签名 keytool genkeypair alias key keyalg RSA keysize 2048 sigalg SHA256withRSA validity
  • Runtime.getRuntime().exec(cmd) 挂起

    我正在执行一个命令 该命令返回文件的修订号 文件名 但如果执行命令时出现问题 应用程序就会挂起 我可以做什么来避免这种情况 请在下面找到我的代码 String cmd cmd C si viewhistory fields revision
  • 使用 PowerMock 和 TestNG 模拟单个静态方法

    class StaticClass public static String a return a public static String ab return a b 我想嘲笑StaticClass a以便它返回 x 并致电StaticC
  • 具有多个字符串的列表视图

    我正在尝试创建一个包含多个字符串的列表视图 现在我有一个可以实现的功能 while i lt 10 GETS DATA FROM WEBPAGE ETC a DATAFROMWEBPAGE1 b DATAFROMWEBPAGE2 c DAT
  • CompletableFuture SupplyAsync

    我刚刚开始探索 Java 8 的一些并发特性 让我有点困惑的一件事是这两个静态方法 CompletableFuture
  • 在Linux中执行jar文件[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我创建了一个可执行的 Java jar 文件 也就是说 我将 java 程序正确打包到 jar 文件中 包括 META INF MANIFEST 文件
  • 使用会话空闲超时进行轮询

    我对 Tomcat 中的所有应用程序使用单点登录 我的要求是 我必须轮询应从后端获取的事务状态 但它也不应该影响会话的空闲超时 有人可以建议是否可以做点什么吗 Thanx 我不知道是否有标准方法可以做到这一点 如果没有 你可以写一个过滤器
  • 尝试用Java实现基于文本的Hangman游戏

    我需要检查用户输入的字母以及他们猜测的空格是否位于隐藏单词的特定位置 变量one等于用户猜测的空间索引 而letterGuess是他们猜测的字母 我的代码怎么错了 示例 秘密词是你好 hidden word is 用户猜测h 0 1 2 3
  • 如何根据受保护的 String doInBackground 方法中 AsyncTask 的结果调用 Toast.makeText() ?

    我从 AsyncTask 中的数据库中获取数据 如果它为空 我想吐司一个警告文本 我在 AsyncTask 中尝试过 但我了解到它不是在工作线程中调用的 这是我的 doInBackground 方法 protected String doI
  • 如何在不下载子项的情况下从 Firebase 获取子项密钥?

    我有一个 Firebase 数据库 其中的节点 items 有很多子项 我想导入子项键的列表 由于每个子项都包含相当多我对此不感兴趣的数据 因此我想仅下载子项密钥 以最大程度地减少传输的数据量 为了便于说明 假设我有以下数据结构 然后我想获
  • 如何将 printStackTrace() 中的异常写入 Java 中的文本文件?

    我需要用 Java 捕获文本文件中的异常 例如 try File f new File catch FileNotFoundException f f printStackTrace instead of printing into con
  • 确保 MAVEN_HOME 设置正确

    这里是 Java 和 Maven 菜鸟 使用 OSX 10 8 并使用 HomeBrew 安装 Maven 1 如果我说which mvn我会得到这个 usr local bin mvn 2 如果我说echo MAVEN HOME我不会得到
  • Java编程编译jar

    我有一个文本文件中的java源代码 必须在源代码中输入一些自定义的硬编码变量 然后将其转换为 jar 这是可行的 但是当我运行 jar 时 找不到 Main 类 当我用 WinRAR 解压 jar 文件时 我似乎找不到错误 当我通过 cmd

随机推荐

  • 由于找不到xinput1_3.dll,无法继续执行代码的解决方法都有哪些?

    关于由于找不到xinput1 3 dll 无法继续执行代码这个问题 其实在网上经常看别人提及 要解决这个问题 还是不难的 今天小编就来给大家详细的说说关于这个问题的解决方法吧 本文会介绍多种的修复方法 下面一起来看看 一 xinput1 3
  • ubuntu 安装Nginx 以及简单配置

    Nginx使用的地方特别多 很久以前就知道Nginx使用范围很广 却并不知道Nginx具体可以做什么 怎么使用 最近读了几篇关于Nginx的文章 对Nginx有了大致的了解 只看不练无法解决真正的问题 此处主要是Nginx的安装以及 Ngi
  • 常见异常汇总

    目录 登录异常 org apache ibatis binding BindingException Invalid bound statement not found com jt mapper UserMapper findUserBy
  • MyBatis<if>标签判断字符串相等写法

    mybatis 映射文件中 if标签判断字符串相等 两种方式 因为mybatis映射文件 是使用的ognl表达式 所以在判断字符串sex变量是否是字符串Y的时候 1
  • 【数据结构】栈的代码实现

    个人博客 www hellocode top 所有文章均在上方博客首发 其他平台同步更新 本文专栏 数据结构与算法 如有问题 欢迎指正 一起学习 文章参考整理自小码哥的 恋上数据结构和算法 课程 图片转载自课程PPT 如有侵权 请联系删除
  • shell命令

    1 系统信息 arch 显示机器的处理器架构 1 uname m 显示机器的处理器架构 2 uname r 显示正在使用的内核版本 dmidecode q 显示硬件系统部件 SMBIOS DMI hdparm i dev hda 罗列一个磁
  • JAVA代码添加License

    在开源代码的时候 我们经常会在代码顶部添加License信息 每个文件复制粘贴显然是比较麻烦的 我们可以在工具中进行配置 在创建新的类的时候自动为我们添加相关信息 以eclipse为例 进入Preference gt Java gt Cod
  • SQL笔记(一)

    1 初识MySQL JavaEE 企业级Java开发 Web 前端 页面 展示 数据 后台 连接点 连接数据库JDBC 链接前端 控制 控制视图跳转 和给前端传递数据 数据库 存数据 ITxt Excel word 只会写代码 学好数据库
  • sqli-labs (less-39)

    sqli labs less 39 输入id 1 http 127 0 0 1 sql1 Less 39 id 1 根据错误显示判断为数字型注入 这里我们就不讲使用union注入的方法 前面的关卡讲了很多union注入的方法 我们直接使用堆
  • word:表格中的文字居中

    如 操作 如下图 选择布局 点击2就可以把表格居中了 居中结果
  • 实时ETL解决方案总结

    问题导读1 实时ETL可以选择哪些架构部件 2 实时ETL有哪些实现方法 3 实时ETL有哪些难点 1 简述在架构实时ETL时的可以选择的架构部件 答 在建立数据仓库时 ETL通常都采用批处理的方式 一般来说是每天的夜间进行跑批 随着数据仓
  • 【MyBatis】一天之内快速掌握MyBatis的增删改查

    MyBatis 文章介绍 一共不到8000字 一天之内可以快速学会mybatis的增删改查 以及经常使用的操作 不讲废话 只将眼光聚焦到实操上 也可以搭配黑马的视频观看 看完之后 可以自己找个mybatis源码课继续学习 但是一般的业务代码
  • Eclipse的安装与基本操作(详解配图)

    不为失败找理由 只为成功找方法 所有的不甘 都是因为还心存梦想 在你放弃之前 好好拼一把 只怕心老 不怕路长 文章目录 一 简介 二 下载 三 使用Eclipse编写第一个Java程序 四 Eclipse的基本操作 1 背景 2 字体 五
  • Windows10系统MySQL服务器简单安装

    Windows10系统MySQL服务器简单安装 Mysql下载 安装 修改MySQL数据保存地址 修改服务 初始化数据库 修改root密码 新增用户 Mysql下载 MySql官网下载 下载地址 https dev mysql com do
  • 创建M32F103C8T6的工程文件之后编译为什么一堆错误?

    首先先看错误的提示是不是以下的显示 Rebuild started Project STM32F103C8T6 Using Compiler V6 15 folder F keil ARM ARMCLANG Bin Rebuild targ
  • 关于vxe-table全局引入的问题

    主要讲解一下vxe table全局引入然后使用碰到的问题 0 vxe table的官网地址 1 基本环境 1 vue版本为3 x以上 我的是3 2 13 2 依赖库 xe utils 注意 这篇博客的是vue3的脚手架搭建的 如果需要看低版
  • 毕业设计-机器视觉的疲劳驾驶检测系统-python-opencv

    目录 前言 课题背景和意义 实现技术思路 实现效果图样例 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精力 近几年各个学校要求的毕设项目越来越难 有不少课题是研究生级别难度
  • vue-admin-template,连接自己后台,二次开发必看

    第一步 找到 env development文件做如下修改 just a flag ENV development base api VUE APP BASE API api 第二步 找到 vue config js 配置跨域 关闭mock
  • Ubuntu 20版本将动态ip修改为静态ip时,ping 不通网络

    问题描述 在对Ubuntu 20版本将动态ip修改为静态ip时 ping www baidu com ping不通了 火狐浏览器没有了网路 下载不了东西 一直卡在这里不动 问题出在哪里还是配置ip dns 网关的问题 如果我们在当初安装ub
  • Spring:从零开始的Cloud生活(零)——Eureka 服务治理

    目录 Spring 从零开始的Cloud生活 零 Eureka 服务治理 1 Netfilx Eurake 2 搭建服务注册中心 3 服务提供者 4 高可用注册中心 5 服务发现和消费 之前对于SpringCloud都是一知半解的状态 现在