我们这里只有一台服务器,所以我们先仿集群搭建。

完整demo项目代码:https://github.com/wades2/EurekaDemo2

在这之前我们先分析分析Eureka相比其他注册中心的好处。在一般的应用过程中,如果注册中心service出现了问题,然而没有备用的节点去替代这个主节点去分发服务,就会造成相关注册服务的瘫痪,因此我们在分布式架构中,都会有备用节点。

我们先看看Doubel,在doubel中,zookeeper(以下简称zk)是作为服务注册中心的,在集群配置中,会有一个主从关系节点。如果Master挂了, zk就会启动节点推举,而在节点推举的过程中,整个服务是不能使用的。但是zk强调的是CAP理论中的CP强调高的一致性,【注:什么是CAP理论:Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得】,在实际上线的站点或者网站中,30~60s的选举过程导致站点不可用,损失是很大。

而我们再看看Eureka(如上图),Eureka是去中心化的,每个Eureka server都是平级的。Eureka取CAP中的AP,注重可用性,Eureka内置了心跳服务(用于淘汰一些“濒死”的服务器),即使当你的应用服务某个server挂掉了,其他的服务是可以立即顶上去,保证客户端向其发起请求有响应。

两者的对比我们先大致分析到这里。具体的分析可以看我转的一篇博客:

https://blog.csdn.net/asd529735325/article/details/85049662

接下来我们尝试自己搭建一个分布式的包含:Eureka Server,Application Service,Application Client的Eureka注册中心。

通过上面这张图我们可以看到,一个Eureka有三个角色:

1、Eureka Server(通过Register, Get,Renew等接口提供注册和发现)
     2、Application Service(服务提供方,把自身服务实例注册到Eureka Server):
     3、Application Client(Service Consumer):服务调用方,通过Eureka Server获取服务实例,并调用Application Service

他们主要进行的活动如下:

每个Region有一个Eureka Cluster, Region中的每个Zone都至少有一个Eureka Server。
Service作为一个Eureka Client,通过register注册到Eureka Server,并且通过发送心跳的方式更新租约(renew leases)。如果Eureka Client到期没有更新租约,那么过一段时间后,Eureka Server就会移除该Service实例。
当一个Eureka Server的数据改变以后,会把自己的数据同步到其他Eureka Server。
Application Client也作为一个Eureka Client通过Get接口从Eureka Server中获取Service实例信息,然后直接调用Service实例。
Application Client调用Service实例时,可以跨可用区调用。(【引】)

在上面一篇文章中我们已经搭建好了Eureka Server和Application Client,如果不清楚的朋友建议可以先看看这篇博文(https://blog.csdn.net/asd529735325/article/details/84992538,git代码:https://github.com/wades2/EurekaDemo ),再来本篇中一起探讨学习。

为了保护eureka安全性,在上一篇的基础上,我加了service访问密码。因此在client端和集群配置的service都需要加上相互的访问密码。

先看看我个人demo大致架构吧:

其中:EurekaServer模块和Eurekaserver_back是两个相互平级依赖的server,EurekaClient是我们服务提供方,EurekaCaller是我们服务的调用方。大致的调用过程如下图:

基于上一篇的基础,我们从新看看pom文件和相关配置。

首先是Eureka Server(此处我们是集群配置,因此有两个server)

首先修改电脑的hostname,添加:127.0.0.1 localhost server1 server2,作为两个server的相互依赖。

两个server的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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.M3</spring-cloud.version>
</properties> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.3.6.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> <repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories> </project>

相关注意点在上一篇博客有提到,这里就不赘述。

EurekaServer的配置文件:

# 应用程序的名称
spring.application.name=Eureka-server2 security.user.name=user
security.user.password=123456
#修改启动端口
server.port=8083
# 是否将该实例的注册信息注册到Eureka服务器上,在只有一个Eureka服务器的情况下没必要,只是用于实例的发现
eureka.client.register-with-eureka=true # 是否向Eureka服务器获取注册信息,在单实例的Eureka中共没必要
eureka.client.fetch-registry=true
#Eureka Server能够迅速有效地踢出已关停的节点,但是新手由于Eureka自我保护模式,以及心跳周期长的原因,常常会遇到Eureka Server不踢出已关停的节点的问题
# 设为false,关闭自我保护
eureka.server.enable-self-preservation=true
#清理间隔
eureka.server.eviction-interval-timer-in-ms=6000 eureka.client.serviceUrl.defaultZone=http://user:123456@server2:8082/eureka eureka.instance.hostname=server1

EurekaServer_back的配置文件:

# 应用程序的名称
spring.application.name=Eureka-server2 security.user.name=user
security.user.password=123456
#修改启动端口
server.port=8082
# 是否将该实例的注册信息注册到Eureka服务器上,在只有一个Eureka服务器的情况下没必要,只是用于实例的发现
eureka.client.register-with-eureka=true # 是否向Eureka服务器获取注册信息,在单实例的Eureka中共没必要
eureka.client.fetch-registry=true
#Eureka Server能够迅速有效地踢出已关停的节点,但是新手由于Eureka自我保护模式,以及心跳周期长的原因,常常会遇到Eureka Server不踢出已关停的节点的问题
# 设为false,关闭自我保护
eureka.server.enable-self-preservation=true
#清理间隔
eureka.server.eviction-interval-timer-in-ms=60000 eureka.client.serviceUrl.defaultZone=http://user:123456@server1:8083/eureka eureka.instance.hostname=server2

因为我们引入了security的jar包,保证访问server页面的安全性,因此,在client和其他节点配置的时候,都应该加上用户名和密码,把defaultZone改为:http://用户名:密码@hostname:端口号/eureka的形式。

【注意!!!!,这里因为是相互依赖,所以在EurekaServer中defaultZone使用的是EurekaServer_back的用户名,密码和它对应的hostname+端口,同理EurekaSerer_back对应的是EurekaServer的。】

运行类都一样:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication
@EnableEurekaServer
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

然后我们可以启动一个server访问一下:

访问需要用户名密码,就是配置文件里面的security.user.name,和security.user.password,我们可以看到界面如下:

这里我们可以看到因为我们8082端口的server因为没有启动,所以无法依赖到,但是已经注册进去了。我们再启动server_back可以看到界面如下:

这样的界面就是注册成功了。然后我们开始第二部:

Application Service注册到server里面,也就是我们上一篇说的client端,也就是我这个demo的EurekaClient:

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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.M3</spring-cloud.version>
</properties> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <!--<dependency>-->
<!--<groupId>org.springframework.cloud</groupId>-->
<!--<artifactId>spring-cloud-netflix-eureka-client</artifactId>-->
<!--<version>1.3.6.RELEASE</version>-->
<!--</dependency>--> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>1.4.0.M1</version>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.3.6.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> <repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories> </project>

application配置文件:

spring.application.name=Eureka-client

#eureka.client.allow-redirects=false
#修改启动端口
server.port=8084
eureka.client.serviceUrl.defaultZone=http://user:123456@localhost:8083/eureka,http://user:123456@localhost:8082/eureka
#eureka.client.register-with-eureka=true
eureka.instance.ip-address=true

启动类:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan; @SpringBootApplication
@EnableEurekaClient
//@EnableDiscoveryClient
@ComponentScan(basePackages = {"com.example.demo.controller"})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

这里我们设置了扫描controller包下面的java文件,我的demo中contorller如下:

其中UserController放置在controller这个包下,还有一个作为测试的Contrller放置在启动类平级目录(你也可以随便放一个,我们只是做后期实验的)

我们的UserController

package com.example.demo.controller;

import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.converters.Auto;
import com.netflix.discovery.shared.Applications;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController
@RequestMapping("user")
public class UserController {
// private static final Logger logger = LoggerFactory.getLogger(UserController.class); // @Autowired
// private IUserService userService; // @GetMapping("getUser")
// public List<UserEntity> getUser() {
// UserEntity user = new UserEntity();
// return userService.getUser();
// }
@Autowired
private EurekaClient eurekaClients; // @Autowired
// private DiscoveryClient discoveryClient; @GetMapping("getUser")
public String getUser() {
//todo 得到eureka server的服务实例
InstanceInfo info=eurekaClients.getNextServerFromEureka("Eureka-client",false);
// return info.getHomePageUrl();
return "hello one";
} }

我们的Controller:

package com.example.demo;

import com.netflix.appinfo.InstanceInfo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
@RequestMapping("user")
public class Controller {
@GetMapping("getUser2")
public String getUser() {
return "hello tow....";
}
}

然后启动。

我们可以看到如下界面:

这里client已经注册进来了,然后我们可以访问一下http://localhost:8084/user/getUser

访问没问题。

访问http://localhost:8084/user/getUser2,报错,因为我们启动类没有扫描其他的包。

最后一步:Application Client(Service Consumer):服务调用方,通过Eureka Server获取服务实例,并调用Application Service

也就是我们的EurekaCaller:

直接使用Eureka Client还是比较麻烦的,幸运的是,RestTemplate整合了EurekaClient,Ribbon为我们提供了多样的负载均衡的功能,为我们提供了很多便利,我们所需要做的就是在Spring中注册一个RestTemplate,并且添加@LoadBalanced 注解。

加入Ribbon的原因是服务调用者不关心服务提供者有多少个服务实例,它只关注它要调用这个服务ID,因而可能需要一定的负载均衡。

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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.RC1</spring-cloud.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> <repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories> </project>

application配置文件:

spring.application.name=Eureka_caller
server.port=8086
eureka.client.serviceUrl.defaultZone=http://user:123456@localhost:8083/eureka,http://user:123456@localhost:8082/eureka

启动类一样扫描controller:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan; @SpringBootApplication
@ComponentScan({"com.example.demo.controller"})
@EnableEurekaClient
public class DemoApplication { public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
} }

我们这里的controller开始通过Rest客户端映射调用注册的Eureka_client。

package com.example.demo.controller;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; @RestController
@Configuration
public class Controller {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
} @GetMapping("getUser/routine")
public String routine() {
RestTemplate restTemplate = getRestTemplate();
String json = restTemplate.getForObject("http://Eureka-client/user/getUser", String.class);
return json;
} @GetMapping("getUser/routine2")
public String routine2() {
RestTemplate restTemplate = getRestTemplate();
String json = restTemplate.getForObject("http://Eureka-client/user/getUser2", String.class);
return json;
}
}

restTemplate.getForObject方法请求特定的服务url,注意里面使用的Eureka-client正是我们刚才在服务提供者客户端项目中配置的服务名称,它已经被注册到Eureka服务上。

然后我们启动,访问http://localhost:8086/getUser/routine

我们可以看到内容和访问http://localhost:8084/user/getUser一样,但是依旧访问http://localhost:8086/getUser/routine2访问不到,其实要想访问到很简单,在EurekaClient扫描中带上Conrtoller所在的包就可以了!

OK,全文结束,接下来我们讲解,如何充分利用ribbon来动态调用服务消费者。

更多精彩内容,尽在:https://blog.csdn.net/asd529735325

Spring-cloud微服务 Eureka学习教程-分布式搭建EurekaServer、EurekaClient+Ribbon(中级)的更多相关文章

  1. Spring-cloud微服务 Eureka学习教程-分布式搭建EurekaServer、EurekaClient(中级)

    我们这里只有一台服务器,所以我们先仿集群搭建. 完整demo项目代码:https://github.com/wades2/EurekaDemo2 在这之前我们先分析分析Eureka相比其他注册中心的好 ...

  2. Spring Cloud 微服务架构学习笔记与示例

    本文示例基于Spring Boot 1.5.x实现,如对Spring Boot不熟悉,可以先学习我的这一篇:<Spring Boot 1.5.x 基础学习示例>.关于微服务基本概念不了解的 ...

  3. Spring-cloud微服务 Eureka学习教程-单服务器配置之快速搭建EurekaServer、EurekaClient(基础)

    以下实例代码下载地址:https://github.com/wades2/EurekaDemo Eureka是Spring Cloud Netflix的一个子模块,也是核心模块之一.用于云端服务发现, ...

  4. Spring Cloud 微服务:Eureka+Zuul+Ribbon+Hystrix+SpringConfig实现流程图

    相信现在已经有很多小伙伴已经或者准备使用springcloud微服务了,接下来为大家搭建一个微服务框架,后期可以自己进行扩展.会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新 ...

  5. Spring cloud微服务安全实战-7-3prometheus环境搭建

    Prmetheus 主要用来做来Metrics的监控和报警,这张图是官方的架构图. 这是他的核心 它的作用是根据我们的配置去完成数据的采集.服务的发现,以及数据的存储. 这是服务的发现,通过Servi ...

  6. Spring cloud微服务安全实战_汇总

    Spring cloud微服务安全实战 https://coding.imooc.com/class/chapter/379.html#Anchor Spring Cloud微服务安全实战-1-1 课 ...

  7. spring cloud微服务快速教程之(七) Spring Cloud Alibaba--nacos(一)、服务注册发现

    0.前言 什么是Spring Cloud Alibaba? Spring Cloud Alibaba 是阿里开源的,致力于提供微服务开发的一站式解决方案.此项目包含开发分布式应用微服务的必需组件,方便 ...

  8. Spring Cloud微服务学习笔记

    Spring Cloud微服务学习笔记 SOA->Dubbo 微服务架构->Spring Cloud提供了一个一站式的微服务解决方案 第一部分 微服务架构 1 互联网应用架构发展 那些迫使 ...

  9. 如何优化Spring Cloud微服务注册中心架构?

    作者: 石杉的架构笔记 1.再回顾:什么是服务注册中心? 先回顾一下什么叫做服务注册中心? 顾名思义,假设你有一个分布式系统,里面包含了多个服务,部署在不同的机器上,然后这些不同机器上的服务之间要互相 ...

随机推荐

  1. chrome插件-YSlow 一个使用的web性能测试插件

    本文为转载是文章,如作者发现后不愿意,请联系我进行删除 原文链接:http://www.cnblogs.com/wajika/p/6278825.html YSlow的安装: 1.安装 firebug ...

  2. Tarjan+树形DP【洛谷P2515】[HAOI2010]软件安装

    [洛谷P2515][HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得 ...

  3. kuangbin专题十六 KMP&&扩展KMP HDU3336 Count the string

    It is well known that AekdyCoin is good at string problems as well as number theory problems. When g ...

  4. mongoDB3.4安装

    添加官方yum源——mongodb3.4vim /etc/yum.repos.d/mongodb-org-3.4.repo [mongodb-org-3.4] name=MongoDB Reposit ...

  5. spring mvc 自定义handler不拦截静态资源

    处理静态资源的handler和处理Controller请求中的handler不同,对应的Interceptor也不同 查找对应handler是在DispatcherServlet中 因此一些自定义的I ...

  6. eclipse+pydev 安装和配置过程

    安装 PyDev 在安装 PyDev 之前,要保证您已经安装了 Java 1.4 或更高版本.Eclipse 以及 Python.接下来,开始安装 PyDev 插件. 启动 Eclipse,利用 Ec ...

  7. Django易混淆问题

    1.Django本身提供了runserver 为什么不能用来 部署 runserver 方法是调试 Django 时经常用到的运行方式,它使用 Django 自带的  WSGI Server 运行,主 ...

  8. 利用vue-cli搭建vue项目

    手把手教你用vue-cli搭建vue项目 本篇主要是利用vue-cli来搭建vue项目,其中前提是node和npm已经安装好,文章结尾将会简单提到一个简单的例子.使用vue-cli搭建项目最开始我也是 ...

  9. spring mvc源码分析

    1.传统xml配置方式 web.xml里面配置:org.springframework.web.servlet.DispatcherServlet,处理项目的spring配置文件:classpath* ...

  10. 2019.03.21 读书笔记 枚举ENUM

    其实没必要为枚举显式赋值,如果赋值了,就一定要全部赋值,否则默认在上一个元素的基础上+1,如果不给枚举变量赋值,就算枚举中没有0元素,也会显示为0,而超出枚举范围的整型数据,也会显示值本身,而不是异常 ...