初识Spring Cloud 之 五大神兽
一览无遗
- 初识Spring Cloud 之 五大神兽
- 一、简介
- 二、我所了解的五大神兽
- 三、我所理解的五大神兽
- ①、Spring Cloud Eureka(注册中心)
- 原理图解
- 代码步骤
- 代码实现
- ②、Spring Cloud Ribbon(客户端负载均衡)
- 什么是Ribbon?
- 代码步骤
- 代码实现
- ③、Spring Cloud Hystrix(熔断器)
- 雪崩机制详解
- 熔断器状态机有3个状态:
- 熔断器的核心:线程隔离和服务降级。
- 代码实现
- ④、Spring Cloud Feign (伪装)
- 概念
- 特性
- 代码实现
- ⑤、Spring Cloud Gateway(网关)
- 概念
- 核心
- 四、Spring Cloud 小结
初识Spring Cloud 之 五大神兽
一、简介
Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发。
如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 Spring Boot 的开发风格做到一键启动和部署。
二、我所了解的五大神兽
- 服务发现——Netflix Eureka- 客服端负载均衡——Netflix Ribbon- 断路器——Netflix Hystrix- 服务网关——Netflix Zuul- 分布式配置——Spring Cloud Config
三、我所理解的五大神兽
①、Spring Cloud Eureka(注册中心)
1. Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址2. 服务提供者:启动后向Eureka注册自己的信息(地址,提供什么服务)3. 服务消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新4. 心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态
原理图解
代码步骤
- 第一步、创建注册服务工程- 第二步、创建服务提供者--注册服务- 第三步、创建服务消费者--发现服务
代码实现
第一步、创建注册服务工程
- 创建maven工程,引入jar包
<!--父工程-->
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.2.RELEASE</version>
</parent><!--SpringCloud包依赖管理-->
<dependencyManagement><dependencies><!--spring cloud Hoxton.SR1--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR1</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>//以上代码,都可以放在父工程里面,这样就不需要在每个微服务端里都加上了<!--依赖包--><dependencies><!--eureka-server依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency></dependencies>
- 创建 application.yml 文件
server:port: 7001 #端口号
spring:application:name: eureka-server # 应用名称,会在Eureka中作为服务的id标识(serviceId)
eureka:client:register-with-eureka: false #是否将自己注册到Eureka中fetch-registry: false #是否从eureka中获取服务信息service-url:defaultZone: http://localhost:7001/eureka # EurekaServer的地址
- 启动类
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class,args);}
}
启动成功后,直接访问:http://localhost:7001/
第二步、创建服务提供者–注册服务
- 创建maven工程,引入jar包
<dependencies><!--eureka客户端--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--JPA包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!--web起步包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--MySQL驱动包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency></dependencies>//这里是基于父工程已经创建的状态,所以父工程依赖包并没有导入。
- 创建 application.yml 文件
server:port: 18081
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driver
//这里有个小问题,高版本的 MySQL驱动会有时区问题,百度解决username: rootpassword: rooturl: jdbc:mysql://127.0.0.1:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCapplication:name: user-provider #服务的名字,不同的应用,名字不同,如果是集群,名字需要相同
#指定eureka服务地址
eureka:client:service-url:# EurekaServer的地址defaultZone: http://localhost:7001/eureka
- 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class UserProviderApplication {public static void main(String[] args) {SpringApplication.run(UserProviderApplication.class,args);}
}@EnableEurekaClient 和 @EnableDiscoveryClient 两者都可以,只是前者只适用于 Eureka 注册中心
第三步、创建服务消费者–发现服务
- 创建maven工程,引入jar包
<dependencies><!--eureka客户端--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--web起步依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>
- 创建 application.yml 文件
server:port: 18082
spring:application:name: user-consumer #服务名字
#指定eureka服务地址
eureka:client:service-url:# EurekaServer的地址defaultZone: http://localhost:7001/eureka
- 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class UserConsumerApplication {public static void main(String[] args) {SpringApplication.run(UserConsumerApplication.class,args);}
}
到此,就完成了Eureka 注册中心的配置,以及将 服务提供者 和 服务消费者 部署到 Eureka Server 上。
②、Spring Cloud Ribbon(客户端负载均衡)
Spring Cloud Ribbon是一个基于Http和TCP的客户端负载均衡工具 ,
Ribbon主要 解决集群服务中,多个服务高效率访问的问题。
负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容。
因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。
什么是Ribbon?
Ribbon是Netflix发布的负载均衡器,有助于控制HTTP客户端行为。为Ribbon配置服务提供者地址列表后,Ribbon就可基于负载均衡算法,自动帮助服务消费者请求。
Ribbon默认提供的负载均衡算法:轮询(默认),随机,重试法,加权。当然,我们可用自己定义负载均衡算法
Ribbon负载均衡的流程图:
代码步骤
- 第一步、创建注册服务工程- 第二步、创建服务提供者--注册服务1- 第三步、创建服务提供者--注册服务2- 第四步、创建服务消费者--发现服务
代码实现
搭建父工程
<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version>
</properties><!--父工程-->
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.2.RELEASE</version>
</parent><!--SpringCloud包依赖管理-->
<dependencyManagement><dependencies><!--spring cloud Hoxton.SR1--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR1</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
第一步、创建注册服务工程
- 创建maven工程,引入jar包
<!--依赖包-->
<dependencies><!--eureka-server依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency>
</dependencies>
- 创建 application.yml 文件
server:port: 7001 #端口号
spring:application:name: eureka-server # 应用名称,会在Eureka中作为服务的id标识(serviceId
eureka:client:register-with-eureka: false #是否将自己注册到Eureka中fetch-registry: false #是否从eureka中获取服务信息service-url:defaultZone: http://localhost:7001/eureka # EurekaServer的地址
- 启动类
/*** @EnableEurekaServer 注释的类,为开启Eureka服务*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class,args);}
}
第二步、创建服务提供者–注册服务1
- 创建maven工程,引入jar包
<!--依赖包-->
<dependencies><!--JPA包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!--web起步包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--MySQL驱动包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--eureka-client依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies>
- 创建 application.yml 文件
server:port: 18081
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rooturl: jdbc:mysql://127.0.0.1:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCapplication:name: user-provider #服务的名字,不同的应用,名字不同,如果是集群,名字需要相同#指定eureka服务地址
eureka:client:service-url:# EurekaServer的地址defaultZone: http://localhost:7001/eureka
- 启动类
@SpringBootApplication
@EnableEurekaClient //标注为 Client 类或者 @EnableDiscoveryClient
//(兼容性更好 @EnableDiscoveryClient)
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class,args);}
}
- Controller中作出区分
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/find/{id}")public User findOneById(@PathVariable(value = "id")Integer id){User user = userService.findOneById(id);user.setName("user-provider");return user;}
}
第三步、创建服务提供者–注册服务2
- 创建maven工程,引入jar包
<!--依赖包-->
<dependencies><!--JPA包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!--web起步包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--MySQL驱动包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--eureka-client依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies>
- 创建 application.yml 文件
server:port: 18083
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rooturl: jdbc:mysql://127.0.0.1:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCapplication:name: user-provider #服务的名字,不同的应用,名字不同,如果是集群,名字需要相同#指定eureka服务地址
eureka:client:service-url:# EurekaServer的地址defaultZone: http://localhost:7001/eureka
- 启动类
@SpringBootApplication
@EnableEurekaClient //标注为 Client 类或者 @EnableDiscoveryClient
//(兼容性更好 @EnableDiscoveryClient)
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class,args);}
}
- Controller中作出区分
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/find/{id}")public User findOneById(@PathVariable(value = "id")Integer id){User user = userService.findOneById(id);user.setName("user-provider-demo01");//区分两个服务器return user;}
}
第四步、创建服务消费者–发现服务
- 创建maven工程,引入jar包
!--依赖包-->
<dependencies><!--web起步依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--eureka-client依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>
</dependencies>
- 创建 application.yml 文件
server:port: 18082
spring:application:name: user-consumer #服务名字
#指定eureka服务地址
eureka:client:service-url:# EurekaServer的地址defaultZone: http://localhost:7001/eureka
- 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}/*** 开启负载均衡* @return*/@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}
}
- Controller
@RestController
@RequestMapping("/consumer")
public class ConsumerController {@Autowiredprivate RestTemplate restTemplate;@GetMapping(value = "/{id}")public User queryById(@PathVariable(value = "id")Integer id){String url = "http://user-provider/user/find/"+id;return restTemplate.getForObject(url,User.class);}
}
测试
启动并访问测试 http://localhost:18082/consumer/1 ,可以发现,数据会在2个服务之间轮询切换。
③、Spring Cloud Hystrix(熔断器)
雪崩机制详解
什么是雪崩效应?
分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务。
对大部分电商和快递公司来说,每年年底(Q4季度)由于双11等大促活动的存在,将面对大量的用户流量,尤其是属于大促的那几天,无论是用户的商品订单还是物流订单,都将是平时的3倍以上。
如果这个时候,单个服务出现问题,调用这个服务就出现线程阻塞,此时若有大量的请求涌入,容器的线程资源就会被消耗完毕导致服务瘫痪。
如下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商品服务资源耗尽,无法继续对外提供服务。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成不可估量的严重后果,这就是常说的服务故障的“雪崩效应”。
熔断器状态机有3个状态:
熔断器有三个状态 CLOSED、 OPEN、HALF_OPEN 熔断器默认关闭状态,当触发熔断后状态变更为 OPEN,在等待到指定的时间,Hystrix会放请求检测服务是否开启,这期间熔断器会变为HALF_OPEN 半开启状态,熔断探测服务可用则继续变更为 CLOSED关闭熔断器。
① Closed:关闭状态,所有请求正常访问② Open:打开状态,所有请求都会被降级。
Hystrix会对请求情况计数,当一定时间失败请求百分比达到阈值(极限值),则触发熔断,断路器完全关闭,默认失败比例的阈值是50%,请求次数最低不少于20次③ Half Open:半开状态
Open状态不是永久的,打开一会后会进入休眠时间(默认5秒)。休眠时间过后会进入半开状态。
半开状态:熔断器会判断下一次请求的返回状况,如果成功,熔断器切回closed状态。如果失败,熔断器切回open状态。
熔断 三种 状态 流程图:
熔断器的核心:线程隔离和服务降级。
1.线程隔离:是指 Hystrix 为每个依赖服务调用一个小的线程池,如果线程池用尽,调用立即被拒绝,默认不采用排队。2.服务降级(兜底方法):优先保证核心服务,而非核心服务不可用或弱可用。触发 Hystrix 服务降级的情况:线程池已满、请求超时。
代码实现
- pom.xml文件中添加 Hystrix 需要的 jar 包
<!--熔断器-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- Controller 中的配置及实现
/**
1、在类前添加注释 @DefaultProperties
2、编写全局服务降级处理方法
*/
@DefaultProperties(defaultFallback = "defaultFallback")
public User defaultFallback(){User user = new User();user.setUsername("Default---服务降级,默认处理");return user;
}3、将 @HystrixCommand 加在需要熔断的方法上。
④、Spring Cloud Feign (伪装)
概念
Feign可以把HTTP 的请求进行隐藏,伪装成类似 SpringMVC 的 Controller一样。你不用再自己拼接 url,拼接参数等等操作,一切都交给 Feign 去做。
特性
Ⅰ、集成Ribbon的负载均衡功能Ⅱ、集成了Hystrix的熔断器功能Ⅲ、支持请求压缩Ⅳ、大大简化了远程调用的代码,同时功能还增强啦Ⅴ、Feign以更加优雅的方式编写远程调用代码,并简化重复代码
代码实现
(1)导入依赖
在user-consumer中添加依赖
<!--配置feign-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
(2)创建Feign客户端
//@FeignClient(value = "要调用微服务的名字")
@FeignClient(value = "user-provider")
public interface UserClient {/**** 根据ID查询用户信息* @param id* @return*/@RequestMapping(value = "/user/find/{id}")User findById(@PathVariable(value = "id") Integer id);
}
解释:
Feign会通过动态代理,帮我们生成实现类。注解@FeignClient声明Feign的客户端,注解value指明服务名称接口定义的方法,采用SpringMVC的注解。Feign会根据注解帮我们生成URL地址注解@RequestMapping中的/user,不要忘记。因为Feign需要拼接可访问地址
(3)控制层
@RestController
@RequestMapping(value = "/feign")
public class ConsumerFeignController {@Autowiredprivate UserClient userClient;@RequestMapping(value = "/{id}")public User queryById(@PathVariable(value = "id")Integer id){return userClient.findById(id);}
}
(4)开启Feign:
启动类中加入注解 --@EnableFeignClients(basePackages = {"com.atguigu.feign"})
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.atguigu.feign"})
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}/*** 开启负载均衡* @return*/@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}}
(5) 测试
请求http://localhost:18082/feign/2,效果如下:
Feign内置的ribbon默认设置了请求超时时长,默认是1000,可以修改
ribbon内部有重试机制,一旦超时,会自动重新发起请求。如果不希望重试可以关闭配置:
# 修改服务地址轮询策略,默认是轮询,配置之后变随机
user-provider:ribbon:#轮询NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRuleConnectTimeout: 1000 # 连接超时时间 没有连接上ReadTimeout: 2000 # 数据读取超时时间 连接上了,连上之后开始计时,但读取数据需要花费很长时间MaxAutoRetries: 1 # 最大重试次数(第一个服务)在第一次连接超时之后,在重新连接一次MaxAutoRetriesNextServer: 0 # 最大重试下一个服务次数(集群的情况才会用到)OkToRetryOnAllOperations: false # 是否所有操作都进行重试
⑤、Spring Cloud Gateway(网关)
概念
Spring Cloud Gateway 作为SpringCloud生态系统中的网关,目标是替代Netflix Zuul。Gateway不仅提供统一路由方式,并且基于Filter链的方式提供网关的基本功能。
核心
Ⅰ、Route(路由):路由是网关的基本单元,由ID、URI、一组Predicate、一组Filter组成,根据Predicate进行匹配转发。Ⅱ、Predicate(谓语、断言):路由转发的判断条件Ⅲ、Filter(过滤器):过滤器是路由转发请求时所经过的过滤逻辑,可用于修改请求、响应内容。
四、Spring Cloud 小结
1、Spring Cloud Eureka :服务发现
将各个微服务注册到 Eureka Server 上,通过心跳检测、客户端缓存等机制,确保了系统的高可用性、灵活性和可维护性。
2、Spring Cloud Ribbon :客户端的负载均衡
提供负载均衡机制,Ribbon可以基于某种均衡算法(轮询、加权响应时间、随机和区域感知轮询等)自动帮助服务消费者请求。
3、Spring Cloud Hystrix :熔断器
实现服务熔断降级处理,保护微服务,防止雪崩效应发生。
4、Spring Cloud Feign :伪装
不再使用拼接URL的方式实现远程调用,以接口调用的方式实现远程调用,简化了远程调用的实现方式,增强了远程调用功能。
5、Spring Cloud Geteway :网关
为微服务架构提供一种简单有效统一的API路由管理方式,可以在网关中实现微服务鉴权、安全控制、请求监控、限流等。
初识Spring Cloud 之 五大神兽相关推荐
- Spring Cloud 架构 五大神兽的功能
什么是微服务 微服务的概念源于2014年3月Martin Fowler所写的一篇文章"Microservices". 微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服 ...
- Spring Cloud中五大神兽总结(Eureka/Ribbon/Feign/Hystrix/zuul)
一.常用的模块 1.Eureka Eureka是Netflix的一个子模块,也是核心模块之一.Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移.服务注册与发现对于 ...
- Spring Cloud Netflix五大组件简介
微服务与微服务架构 微服务的优缺点 优点 缺点 Dubbo与Spring Cloud Spring Cloud Netflix Eureka Eureka的自我保护机制 Eureka和ZooKeepe ...
- springcloud的简单使用_微服务架构:初识Spring Cloud
现在无论大小公司,都会讲究微服务设计,无论应用大小,都会进行微服务架构,面试的时候,也会把微服务当成必谈的知识点.那么什么是微服务呢? "微服务"一词源于Martin Fowler ...
- Spring Cloud文档阅读笔记-初识Spring Cloud(对Spring Cloud初步了解)
首先要知道的是Spring Cloud是微服务架构. 微服务架构是一种架构模式,它将单一的应用程序划分成一组很小的服务,服务之间相互协调.互相配合.每个服务都运行在独立的进程中,服务与服务间采用轻量级 ...
- 手把手,嘴对嘴教你Spring Cloud 微服务实战 -- 初识Spring Cloud
Spring Cloud 简介 摘自百度百科: Spring Cloud是一系列框架的有序集合.它利用SpringBoot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册.配置中心.消 ...
- 系统架构演变到Spring Cloud
目录 1. 系统架构演变 1.1. 集中式架构 1.2. 垂直拆分 1.3. 分布式服务 1.4. 面向服务架构(SOA) 1.5. 微服务架构 2. 服务调用方式 2.1. RPC和HTTP 2.2 ...
- 轻松搞定 Spring Cloud 2.x 微服务全家桶
研究了一段时间 Spring Boot 了准备向 Spring Cloud 进发,公司架构和项目也全面拥抱了 Spring Cloud.在使用了一段时间后发现 Spring Cloud 从技术架构上降 ...
- 手把手,嘴对嘴教你Spring Cloud 微服务实战 -- 前言
Spring Cloud 总结 博主接触到Spring Cloud 大概已经一年多了,当时Spring Cloud微服务框架已经是潮流了,不会一点都不好意思出去面试.并且主流技术基本上都在谈论微服务, ...
最新文章
- Linq之延迟加载特性
- (0006) iOS 开发之JavaScriptCore 实现UIWebView和HTML的交互
- Linux之ping命令使用详解—网络故障定位(六)
- optee3.14中MMU页表查询的所需配置--深入解读
- 【星球知识卡片】换脸算法和人脸驱动都有哪些核心技术,如何对其长期深入学习...
- 选择将正确答案的序号填在括号里_小学四年级数学第五单元训练题,答案非常详细,见过的都保存了...
- 《网易编程题》计算糖果
- [Yii Framework] 数据库查询
- linux好用的编译器,推荐几款Linux下比Notepad++好的编辑器软件
- Yii 2 美化 url
- 混淆 php,开发简单的PHP混淆器与解混淆器
- 微信开发者工具整个是个浏览器
- wpsppt放映时间_wps演示怎么调整放映速度?
- 高等数学——微分方程
- 怎么同时给多个 Word 文档批量添加自定义的文字和图片水印
- meta标签详解(name、http-equiv、scheme、charset、各浏览器常用meta标签、常见移动端meta标签)、viewport详解
- java chmod 777_尽管使用chmod 777,但java.io.FileNotFoundException(权限被拒绝)
- JavaMail实现发送邮件程序
- JavaScript里面的“类”
- c语言visit_数据结构(c语言)——入门数据结构的世界:顺序线性表(一)
热门文章
- 【新华三网络工程师】H3C如何配置三层组网技术
- 框架模式MVC与MVP在Android中的应用
- 2021-03-17T23:47:55.978+08:00 UTC时间转换
- 【Java基础】基础概念与常识
- 远程访问MySql数据库
- MAC下搭建Hexo博客
- FastDFS,Redis,Solr,ActiveMQ核心技术整合二(1)
- MySQL事务及实现原理
- 全网最全持续集成接口自动化-jmeter+ant+jenkins
- Android adb启动错误,使用adb shell启动Android应用程序时出现错误“活动类不存在”...