【spring cloud】spring cloud zuul 路由网关
GitHub源码地址:https://github.com/AngelSXD/springcloud
版本介绍:
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <java.version>1.8</java.version>
- <spring-boot.version>2.0.4.RELEASE</spring-boot.version>
- <spring-cloud.version>Finchley.SR1</spring-cloud.version>
- <lcn.last.version>4.2.1</lcn.last.version>
- </properties>
====================================================
参考地址:https://www.cnblogs.com/cralor/p/9234697.html
====================================================
一.简单介绍
Zuul作为微服务系统的网关组件,用于构建边界服务,致力于动态路由、过滤、监控、弹性伸缩和安全。
为什么需要Zuul
Zuul、Ribbon以及Eureka结合可以实现智能路由和负载均衡的功能;网关将所有服务的API接口统一聚合,统一对外暴露。外界调用API接口时,不需要知道微服务系统中各服务相互调用的复杂性,保护了内部微服务单元的API接口;网关可以做用户身份认证和权限认证,防止非法请求操作API接口;网关可以实现监控功能,实时日志输出,对请求进行记录;网关可以实现流量监控,在高流量的情况下,对服务降级;API接口从内部服务分离出来,方便做测试。
Zuul通过Servlet来实现,通过自定义的ZuulServlet来对请求进行控制。核心是一系列过滤器,可以在Http请求的发起和响应返回期间执行一系列过滤器。Zuul采取了动态读取、编译和运行这些过滤器。过滤器之间不能直接通信,而是通过RequestContext对象来共享数据,每个请求都会创建一个RequestContext对象。
Zuul生命周期如下图。 当一个客户端Request请求进入Zuul网关服务时,网关先进入”pre filter“,进行一系列的验证、操作或者判断。然后交给”routing filter“进行路由转发,转发到具体的服务实例进行逻辑处理、返回数据。当具体的服务处理完成后,最后由”post filter“进行处理,该类型的处理器处理完成之后,将Request信息返回客户端。
二.配置过程
1.pom依赖
- <!--熔断器 健康检查-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
- </dependency>
- <!--zuul核心依赖-->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
- </dependency>
2.配置application.properties
- spring.application.name=springcloud-ms-gateway
- server.port=8001
- eureka.client.service-url.defaultZone=http://127.0.0.1:8000/eureka/
- #因为parent的pom.xml中 添加了连接数据库的依赖,所以 需要配置数据库连接相关配置
- spring.datasource.continue-on-error=false
- spring.datasource.url=jdbc:mysql://localhost:3306/springcloudtest?useSSL=false&useUnicode=true&characterEncoding=UTF-8
- spring.datasource.driver-class-name=com.mysql.jdbc.Driver
- spring.datasource.username=root
- spring.datasource.password=root
- zuul.host.socket-timeout-millis=10000
- #网关最大超时时间10s
- zuul.host.connect-timeout-millis=10000
- #网关最大连接数 默认200
- zuul.host.max-total-connections=200
- #给要路由的API请求加前缀 可加可不加
- zuul.prefix=/v1
- #需要忽略的服务 ,号分隔 配置后将不会被路由
- zuul.ignored-services=spring-cloud-ms-eureka
- #配置了zuul之后,那么整个分布式系统,对外则只暴露http://zuul-IP:zuul-port/v1/服务自定义地址/具体API请求地址
- #这一组配置后,访问http://localhost:8001/v1/ms-member/member/showMember 即相当于直接访问会员服务http://localhost:9000/member/showMember
- #zuul.routes.xx xx随便写,zuul中唯一即可
- #zuul.routes.xx.serviceId=eureka中注册的服务名 即各个服务配置文件中的spring.application.name
- zuul.routes.member.serviceId=springcloud-ms-member
- #zuul.routes.xx.path=/自定义的地址 /**表示下级也可以访问
- zuul.routes.member.path=/ms-member/**
- #这一组配置后,所有访问积分服务的请求 即可直接访问网关地址http://localhost:8001/v1/ms-integral/具体接口地址 ,由zuul进行路由转发和负载均衡
- zuul.routes.integral.serviceId=springcloud-ms-integral
- zuul.routes.integral.path=/ms-integral/**
- #这一组配置后,所有访问商品服务的请求 即可直接访问网关地址http://localhost:8001/v1/ms-goods/具体接口地址 ,由zuul进行路由转发和负载均衡
- zuul.routes.goods.serviceId=springcloud-ms-goods
- zuul.routes.goods.path=/ms-goods/**
- #txmanager地址 必填
- tm.manager.url=http://127.0.0.1:7000/tx/manager/
3.启动类注解
核心注解@EnableZuulProxy
同时需要添加注解,服务发现,注册eureka
- package com.swapping.springcloud.ms.gateway;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
- import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
- import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
- import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
- import org.springframework.cloud.openfeign.EnableFeignClients;
- @EnableCircuitBreaker //Hystrix Dashboard必须加
- @EnableHystrixDashboard//展示熔断器仪表盘
- @EnableZuulProxy //网关映射 注解
- @EnableFeignClients //feign调用注解
- @EnableDiscoveryClient
- @SpringBootApplication(scanBasePackages = "com.swapping")
- public class SpringcloudMsGatewayApplication {
- public static void main(String[] args) {
- SpringApplication.run(SpringcloudMsGatewayApplication.class, args);
- }
- }
>>>>>>>>>>>>>路由转发
4.启动网关服务
springcloud-ms-gateway 端口8001
启动ms-member服务,端口9000
那么现在访问
- http://localhost:9000/member/showMember
- 即直接访问ms-member服务,的/member/showMember这个API
现在可以访问网关,通过zuul进行动态路由
- http://localhost:8001/v1/ms-member/member/showMember
- 统一访问网关地址,由网关进行统一路由转发
至此,zuul实现路由转发!
>>>>>>>>>>>>>路由拦截
5.使用zuul进行路由拦截
现在既然所有的访问接口都是由zuul网关暴露出去的,那所有的请求都来找网关,这样的话在网关的过滤器中就可以做很多的事情。
Filter是Zuul的核心,用来实现对外服务的控制。Filter的生命周期有4个,分别是“PRE”、“ROUTING”、“POST”、“ERROR”,整个生命周期可以用下图来表示
5.1 Zuul大部分功能都是通过过滤器来实现的,这些过滤器类型对应于请求的典型生命周期。
- PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
- ERROR:在其他阶段发生错误时执行该过滤器。 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
5.2 在zuul中默认已经实现的filter有:
类型 | 顺序 | 过滤器 | 功能 |
---|---|---|---|
pre | -3 | ServletDetectionFilter | 标记处理Servlet的类型 |
pre | -2 | Servlet30WrapperFilter | 包装HttpServletRequest请求 |
pre | -1 | FormBodyWrapperFilter | 包装请求体 |
route | 1 | DebugFilter | 标记调试标志 |
route | 5 | PreDecorationFilter | 处理请求上下文供后续使用 |
route | 10 | RibbonRoutingFilter | serviceId请求转发 |
route | 100 | SimpleHostRoutingFilter | url请求转发 |
route | 500 | SendForwardFilter | forward请求转发 |
post | 0 | SendErrorFilter | 处理有错误的请求响应 |
post | 1000 | SendResponseFilter | 处理正常的请求响应 |
5.3 zuul还提供了一类特殊的过滤器,分别为:StaticResponseFilter和SurgicalDebugFilter
StaticResponseFilter:StaticResponseFilter允许从Zuul本身生成响应,而不是将请求转发到源。
SurgicalDebugFilter:SurgicalDebugFilter允许将特定请求路由到分隔的调试集群或主机
5.4 在zuul中定义自定义的过滤器
例如:自定义一个请求被路由之前的过滤器,用于验证请求中是否携带auth,如果携带安全验证,则成功路由;否则统一终止路由,返回响应
自定义filter需要继承ZuulFilter【注意,自定义Filter需要注入spring 使用注解@Component】
- package com.swapping.springcloud.ms.gateway.filter;
- import com.alibaba.fastjson.JSON;
- import com.netflix.zuul.ZuulFilter;
- import com.netflix.zuul.context.RequestContext;
- import com.netflix.zuul.exception.ZuulException;
- import com.swapping.springcloud.ms.core.response.UniVerResponse;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.stereotype.Component;
- import javax.servlet.http.HttpServletRequest;
- /**
- * 路由拦截
- *
- *
- * >>>>>zuul的filter过滤器的生命周期有一下四个:
- *
- * PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- * ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
- * POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
- * ERROR:在其他阶段发生错误时执行该过滤器。 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
- *
- *
- * Zuul中默认实现了很多Filter,也可以自己自定义过滤器
- *
- * 下面是自己自定义过滤器
- * 实际使用中我们可以结合shiro、oauth2.0等技术去做鉴权、验证
- *
- */
- @Component
- public class AuthFilter extends ZuulFilter{
- @Override
- public String filterType() {
- return "pre";//可以在请求被路由之前调用
- }
- @Override
- public int filterOrder() {
- return 0;//filter执行顺序,通过数字指定 ,优先级为0,数字越大,优先级越低
- }
- @Override
- public boolean shouldFilter() {
- return true;// 是否执行该过滤器,此处为true,说明需要过滤
- }
- /**
- * filter需要执行的具体操作
- *
- * 例如:本filter实际执行的逻辑 是验证所有的访问请求中,是否包含安全信息auth
- * @return
- * @throws ZuulException
- */
- @Override
- public Object run() throws ZuulException {
- RequestContext ctx = RequestContext.getCurrentContext();
- HttpServletRequest request = ctx.getRequest();
- String auth = request.getParameter("auth");
- //TODO 此处可以做日志记录
- System.out.println("zuul拦截--请求前验证---auth:"+auth);
- //成功的情况
- if (StringUtils.isNotBlank(auth)){
- ctx.setSendZuulResponse(true); //对请求进行路由
- ctx.setResponseStatusCode(200);
- ctx.set("isSuccess", true);
- }else {
- //失败的情况
- UniVerResponse res = new UniVerResponse();
- res.beFalse3("zuul拦截--请求前验证---没有auth登录验证",UniVerResponse.ERROR_BUSINESS);
- ctx.setSendZuulResponse(false); //不对请求进行路由
- ctx.setResponseStatusCode(res.getCode());//设置返回状态码
- ctx.setResponseBody(JSON.toJSONString(res));//设置返回响应体
- ctx.set("isSuccess", false);
- ctx.getResponse().setContentType("application/json;charset=UTF-8");//设置返回响应体格式,可能会乱码
- }
- return null;
- }
- }
5.5 测试自定义拦截
启动网关服务 ms-gateway 端口:8001
启动服务注册中心eureka
启动要被路由的服务ms-member 端口:9000
- @RestController
- @RequestMapping("/member")
- public class MemberController {
- @Autowired
- MemberService memberService;
- @RequestMapping(value = "/showMember")
- public String showMember(){
- return "会员服务正常,会员服务是服务消费者,也就是服务调用者,会调用商品服务进行商品购买,减少库存,增加销量;\n\r同时调用积分服务,增加积分";
- }
访问地址:携带auth验证
- http://localhost:8001/v1/ms-member/member/showMember?auth=111
访问地址:不携带auth
5.6 如果你想禁用 zuul中的filter,可以这么做:
如果你想禁用一个,只需设置zuul.<SimpleClassName>.<filterType> .disable = true。按照惯例,过滤器后面的包是Zuul过滤器类型。例如,要禁用org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter 需设置 zuul.SendResponseFilter.post.disable = true
>>>>>>>>>>>>>路由熔断
6.使用zuul进行路由熔断
类似与服务之间的feign调用熔断器设定,网关路由各个服务的请求也可以做路由熔断,在不能成功路由到具体服务上的请求时,进行降级处理,定制返回内容【也就是设置统一响应体】
- 目前路由熔断仅能 支持服务级别的熔断,不支持具体到某个URL进行熔断
自定义熔断类需要实现FallbackProvider接口【注意,自定义熔断类需要注入spring 使用注解@Component】
- package com.swapping.springcloud.ms.gateway.fallback;
- import com.alibaba.fastjson.JSON;
- import com.swapping.springcloud.ms.core.response.UniVerResponse;
- import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
- import org.springframework.http.HttpHeaders;
- import org.springframework.http.HttpStatus;
- import org.springframework.http.MediaType;
- import org.springframework.http.client.ClientHttpResponse;
- import org.springframework.stereotype.Component;
- import java.io.ByteArrayInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- /**
- * 路由熔断
- *
- * 类似与服务之间的feign调用熔断器设定,网关路由各个服务的请求也可以做路由熔断,
- * 在不能成功路由到具体服务上的请求时,进行降级处理,定制返回内容【也就是设置统一响应体】
- *
- * 目前路由熔断仅能 支持服务级别的熔断,不支持具体到某个URL进行熔断
- *
- */
- @Component
- public class UniVerFallback implements FallbackProvider {
- /**
- * 指定 可以熔断拦截 哪些服务
- * @return
- */
- @Override
- public String getRoute() {
- // return "springcloud-ms-member";//指定 可熔断某个服务 服务名是配置文件中配置的各服务的serviceId
- return "*"; //指定 可熔断所有服务
- }
- /**
- * 指定 熔断后返回的定制化内容
- * @param route
- * @param cause
- * @return
- */
- @Override
- public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
- return new ClientHttpResponse() {
- @Override
- public HttpStatus getStatusCode() throws IOException {
- return HttpStatus.OK;
- }
- @Override
- public int getRawStatusCode() throws IOException {
- return 200;
- }
- @Override
- public String getStatusText() throws IOException {
- return "OK";
- }
- @Override
- public void close() {
- }
- /**
- * 设置响应体
- * @return
- * @throws IOException
- */
- @Override
- public InputStream getBody() throws IOException {
- //TODO 此处可以做日志记录
- UniVerResponse uniVerResponse = new UniVerResponse();
- uniVerResponse.beFalse3(route+"服务凉凉了",UniVerResponse.ERROR_BUSINESS);
- return new ByteArrayInputStream(JSON.toJSONString(uniVerResponse).getBytes());
- }
- /**
- * 设置响应头信息
- * @return
- */
- @Override
- public HttpHeaders getHeaders() {
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.APPLICATION_JSON_UTF8);//指定响应体 格式+编码方式
- return headers;
- }
- };
- }
- }
保证eureka启动,
然后重启网关服务ms-gateway,端口:8001
关闭ms-member服务,端口:9000
然后访问地址:来访问ms-member的接口
- http://localhost:8001/v1/ms-member/member/showMember?auth=111
就可以对指定的服务进行熔断!!!
>>>>>>>>>>>>>路由重试
7.使用zuul进行路由重试【慎用】
在服务暂时不可用的情况下,可能是服务重启正被注册中心扫描或者其他原因,我们想要对发起的请求进行重试,zuul结合Spring Retry实现路由重试
7.1 网关服务添加依赖
- <!--路由重试 依赖-->
- <dependency>
- <groupId>org.springframework.retry</groupId>
- <artifactId>spring-retry</artifactId>
- </dependency>
7.2 application.properties添加配置
- #路由重试
- #是否开启路由重试,针对于 查询接口可以使用,但是对于非幂等的新增或更新接口,使用路由重试会出现很大的问题,应该注意
- #是否开启重试功能
- zuul.retryable=true
- #对当前服务的重试次数[不包含首次访问],也就是说实际访问接口的次数是3+1次
- ribbon.MaxAutoRetries=3
- #切换相同Server的次数
- ribbon.MaxAutoRetriesNextServer=0
7.3 重启网关服务,更改一下ms-member的测试接口
- @RequestMapping(value = "/showMember")
- public String showMember(){
- System.out.println("请求到达!!!!");
- try {
- Thread.sleep(10000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return "会员服务正常,会员服务是服务消费者,也就是服务调用者,会调用商品服务进行商品购买,减少库存,增加销量;\n\r同时调用积分服务,增加积分";
- }
可以看到,要访问的接口 休眠10s,而网关配置的超时时间设置为2s
结合上面的重试次数的配置,请求到达的次数应该是3+1次。
启动ms-member服务,访问地址:
- http://localhost:8001/v1/ms-member/member/showMember?auth=111
可以看到,请求总共到达了4次,首次+重试3次
。
请求结果可以看到,最终服务被熔断。
7.4 路由重试注意
- 是否开启路由重试,针对于 查询接口可以使用,但是对于非幂等的新增或更新接口,使用路由重试会出现很大的问题,应该注意
- 开启重试在某些情况下是有问题的,比如当压力过大,一个实例停止响应时,路由将流量转到另一个实例,很有可能导致最终所有的实例全被压垮。说到底,断路器的其中一个作用就是防止故障或者压力扩散。用了retry,断路器就只有在该服务的所有实例都无法运作的情况下才能起作用。这种时候,断路器的形式更像是提供一种友好的错误信息,或者假装服务正常运行的假象给使用者。
- 不用retry,仅使用负载均衡和熔断,就必须考虑到是否能够接受单个服务实例关闭和eureka刷新服务列表之间带来的短时间的熔断。如果可以接受,就无需使用retry。
=============结束================
参考:http://www.ityouknow.com/springcloud/2018/01/20/spring-cloud-zuul.html
参考:https://www.cnblogs.com/cralor/p/9234697.html
【spring cloud】spring cloud zuul 路由网关的更多相关文章
- spring cloud 2.x版本 Zuul路由网关教程
前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server.eureka-client.eureka ...
- 【七】zuul路由网关
一.zuul是什么?zuul 包含以下两个最主要的功能:1.路由功能: 负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础.2.过滤器功能: 则负责对请求的处理过程进行干预,是实现请 ...
- SpringCloud 进阶之Zuul(路由网关)
1. Zuul(路由网关) Zuul 包含了对请求的路由和过滤两个最主要的功能; 路由功能:负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础; 过滤功能:负责对请求的处理过程进行干 ...
- SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理
前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...
- SpringCloud的入门学习之概念理解、Zuul路由网关
1.Zuul路由网关是什么? 答:Zuul包含了对请求的路由和过滤两个最主要的功能,其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进 ...
- SpringCloud学习笔记(八):Zuul路由网关
概述 是什么? Zuul包含了对请求的路由和过滤两个最主要的功能: 其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请 ...
- SpringCloud与微服务Ⅸ --- Zuul路由网关
一.Zool是什么 Zuul包含了对请求路由和过滤两个最主要的功能: 其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现 ...
- zuul路由网关集成ssl,实现http到https的转变
1 前言 最近几天刚开始接触微信小程序的开发,才接触到了https的概念(微信小程序中的请求必须为https请求,不然请求无法成功).https算是对http的安全封装,在http的基础上加了ssl证 ...
- zuul路由网关
zuul作为网关组件,主要用来管理api请求接口(统一对外暴露,负载均衡),身份认证,流量监控等.它是通过servlet来实现的,核心是一系列过滤器,可以在请求的发起跟相应返回阶段进行一系列的处理. ...
随机推荐
- SonarQube的安装、配置与使用(windows)
onarQube是管理代码质量一个开放平台,可以快速的定位代码中潜在的或者明显的错误,下面将会介绍一下这个工具的安装.配置以及使用. 准备工作: 1.jdk(不再介绍) 2.sonarqube:htt ...
- Windbg在应用层调试漏洞时的应用
主要记录一些在应用层调试漏洞的技巧,不会写一些基本的命令,只记录比较有用的平时难以想到的调试方法. 1.!address eax 查看对应内存页的属性,如果poc触发异常之后就可以用这个指令看一下触发 ...
- WDK10+VS2015 驱动环境搭建
其实做驱动或者说底层安全的最大问题就是没有合适的资料去参考,网上很难找到想要的信息.比如搭建驱动环境我以前一直用的都是WDK7.1基于控制台去编译的,之前尝试过搭建WDK10+VS2015的组合环境, ...
- 【LOJ】#2292. 「THUSC 2016」成绩单
题解 神仙dp啊><(也有可能是我菜) 我们发现,想要拿一段区间的话,只和这个区间的最大值和最小值有关系,那么我们考虑,如果一个区间[l,r]我们拿走了一些数后,使它的最小值是a,最大值是 ...
- 关于 eclipse启动卡死的问题 解决方法
关于 eclipse启动卡死的问题(eclipse上一次没有正确关闭,导致启动的时候卡死错误解决方法),自己常用的解决方法: 方案一(推荐使用,如果没有这个文件,就使用方案二): 到<works ...
- LoadRunner中Action的迭代次数的设置和运行场景中设置
LoadRunner中Action的迭代次数的设置和运行场景中设置 LoadRunner是怎么重复迭代和怎么增加并发运行的呢? 另外,在参数化时,对于一次压力测试中均只能用一次的资源应该怎么参数化呢? ...
- oracle配置ODBC
摘自:http://www.cnblogs.com/shelvenn/p/3799849.html 我使用的Windows 10,64位的操作系统. 1.下载驱动包 base包:instantclie ...
- html5+css3 h5页面生成的思路
<!DOCTYPE html><html style="height: 100%;"> <head> <meta charset=&quo ...
- Scala入门2(特质与叠加在一起的特质)
一.介绍 参考http://luchunli.blog.51cto.com/2368057/1705025 我们知道,如果几个类有某些共通的方法或者字段,那么从它们多重继承时,就会出现麻烦.所以Jav ...
- 20169211《Linux内核原理与分析》第六周作业
1.教材内容总结 2.实验报告 3.学习总结 一.教材内容总结 1.系统调用与应用编程接口API的区别 操作系统为用户态进程与硬件设备进行交互提供了一组接口,就是系统调用.它主要有一下三个方面的作用: ...