(基础篇20-xxx)SpringCloud Alibaba组件
配置中心(SpringCloud config)
注册中心(SpringCloud netflix eurka)
API网关(SpringCloud netflix zuul)
1、SpringCloud Alibaba简介
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里分布式应用解决方案,通过阿里中间件来迅速搭建分布式应用系统。
SpringCloud Alibaba Github地址
SpringCloud的几大缺点
1.部分组件停止维护和更新给开发带来不便(eurka)
2.部分环境搭建复杂,没有完善的可视化界面,需要大量的二次开发
3.配置复杂难上手部分配置差别较细SpringCloud Alibaba的优点
阿里使用的组件经过实际考验,性能强悍,设计合理,开源成套的产品搭配完善的可视化界面给开发和运维带来极大便利,且搭建简单,学习难度低。结合SpringCloud Alibaba项目的最终的技术搭配方案
spring-cloud-alibaba版本的选择,见
SpringCloud Alibaba Github地址在父项目pom文件中引入一
<!-- dependencyManagement实际不引用依赖只提供版本号与scope信息 --><dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.1.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
1.1.spring Cloud Alibaba Nacos
- 安装 Alibaba Nacos server
1.window:下载Nacous Server并解压(这里为了方便我们放到本地window系统),运行bin/startup.cmd即可启动Nacous Server服务
2.liunx(docker):
(1) 命令创建挂载文件夹
mkdir -p /mydata/nacos/logs/
mkdir -p /mydata/nacos/init.d/
vim /mydata/nacos/init.d/custom.properties
(2)custom.properties配置
server.contextPath=/nacos
server.servlet.contextPath=/nacos
server.port=8848spring.datasource.platform=mysqldb.num=1
db.url.0=jdbc:mysql://192.168.xxx.xxx:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=rootnacos.cmdb.dumpTaskInterval=3600
nacos.cmdb.eventTaskInterval=10
nacos.cmdb.labelTaskInterval=300
nacos.cmdb.loadDataAtStart=falsemanagement.metrics.export.elastic.enabled=falsemanagement.metrics.export.influx.enabled=falseserver.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}inacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/login,/v1/console/health/**,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**,/v1/console/server/**
nacos.naming.distro.taskDispatchThreadCount=1
nacos.naming.distro.taskDispatchPeriod=200
nacos.naming.distro.batchSyncKeyCount=1000
nacos.naming.distro.initDataRatio=0.9
nacos.naming.distro.syncRetryDelay=5000
nacos.naming.data.warmup=true
nacos.naming.expireInstance=true
(3)拉取镜像
docker pull nacos/nacos-server:1.3.2
(4)新建数据库nacos-config并将链接中sql运行nacos-config.sql
(5)创建容器
docker run \
--name nacos -d \
-p 8848:8848 \
--privileged=true \
--restart=always \
-e JVM_XMS=256m \
-e JVM_XMX=256m \
-e MODE=standalone \
-e PREFER_HOST_MODE=hostname \
-v /mydata/nacos/logs:/home/nacos/logs \
-v /mydata/nacos/init.d/custom.properties:/home/nacos/init.d/custom.properties \
nacos/nacos-server:1.3.2
http://192.168.xxx.xxx:8848/nacos访问服务
1.1.1 discovery(注册中心)
- common模块引入依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
- 在应用的配置文件中配置服务名和Nacos Server 地址,
spring:application:name: wwmall-productcloud:nacos:discovery:server-addr: 192.168.xxx.xxx:8848
- 启动类标注@EnableDiscoveryClient即可将服务注册到nacous注册中心
1.1.2Config(配置中心)可以动态加载配置文件不用手动打包在重启服务
1.1.2.1简单示例
- common模块导入依赖,引入 Nacos Config Starter
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
- 在应用的 /src/main/resources/bootstrap.properties 配置文件中配置 Nacos Config 元数据
#该文件会优先于application.yml/application.properties加载
spring.application.name=wwmall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
- 给配置中心默认添加一个数据集(Data Id的规则为:应用名.properties。例如wwmall-coupon.properties)
- 将需要的配置文件写在数据集中并发布,即可动态获取
- 动态获取:使用@RefreshScope(动态获取或刷新配置)标注类和@Value("${配置项的名}")标注对应的属性(获取配置)
@RefreshScope
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {@Autowiredprivate CouponService couponService;
/*---------------------测试代码start----------------------------------------------*/@Value("${coupon.user.name}")private String username;@Value("${coupon.user.age}")private Integer age;@RequestMapping("/test")public R test(){return R.ok().put("username",username).put("age",age);}
注:如果配置中心和当前应用的配置文件中有相同的项,则优先使用配置中心中的配置信息
1.1.2.2 命名空间与配置分组
- 命名空间(Namespace):可用于进行不同环境的配置隔离。一般一个环境划分到一个命名空间
默认的public为保留空间,默认新增的所有配置都在public空间
1.在不同的环境(开发、测试、生产)利用命名空间来做环境隔离可以在bootstrap.properties配置需要使用哪个命名空间下的配置
2.也可以根据微服务为粒度隔离,每个微服务创建自己的命名空间,只加载自己命名空间下的所有配置
#指定使用的命名空间
spring.cloud.nacos.config.namespace=ad0d2241-8cfc-4c30-a83f-1bd2c72eb62d
- 配置分组(Group):配置分组用于将不同的服务可以归类到同一分组。一般将一个项目的配置分到一组
默认所有的配置集都属于DEFAULT_GRUOP
在bootstrap.properties中使用指定命名空间下的指定配置分组:
#指定使用的命名空间
spring.cloud.nacos.config.namespace=ad0d2241-8cfc-4c30-a83f-1bd2c72eb62d
#指定使用的分组
spring.cloud.nacos.config.group=wwmall-coupon
- 配置集(Data ID):在系统中,一个配置文件通常就是一个配置集ID。一般微服务的配置就是一个配置集
本项目采用:每个微服务创建自己的命名空间,使用配置分组区分环境(desv,test,prod)
1.1.2.3加载多配置文件
配置文件不会全写在application.yml中会根据配置项分出多个配置集,我们关心在nacos中如何加载多个配置集
将配置文件拆分成多个datasource.yml,mybatis.yml,other.yml并在配置中心创建对应的配置集
- 在bootstrap.properties说明加载配置中心中指定的配置集组
spring.cloud.nacos.config.extension-configs[0].data-id=datasource.yml
spring.cloud.nacos.config.extension-configs[0].group=dev
#开启动态刷新
spring.cloud.nacos.config.extension-configs[0].refresh=truespring.cloud.nacos.config.extension-configs[1].data-id=mybatis.yml
spring.cloud.nacos.config.extension-configs[1].group=dev
spring.cloud.nacos.config.extension-configs[1].refresh=truespring.cloud.nacos.config.extension-configs[2].data-id=other.yml
spring.cloud.nacos.config.extension-configs[2].group=dev
spring.cloud.nacos.config.extension-configs[2].refresh=true
- @value @configrationProperties等以前在springboot中能从配置文件中获取值的现在也可以使用。
注:配置中心有的优先从配置中心取,没有的话就去项目的application.properties文件中取
1.1.3Nacos持久化
https://www.cnblogs.com/larscheng/p/11422909.html
1.2spring Cloud Alibaba sentinel
1.2.1什么是熔断降级限流
熔断
降级
两者相同点
两者不同点
限流
对打入服务的请求流量进行控制,使服务能承担不超过自己的流量压力
1.2.2sentinel简介
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
官方文档 https://github.com/alibaba/spring-cloud-alibaba/wiki
整合springboot/springcolud https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
Sentinel 分为两个部分:
核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
资源
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
规则
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
控制台
Sentinel 控制台提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能。您只需要对应用进行简单的配置,就可以使用这些功能。
1.2.3spring boot 整合sentinel
引入依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>
下载,启动,配置控制台
下载地址 https://github.com/alibaba/Sentinel/releases 命令java -jar 启动
配置控制台
spring:cloud:sentinel:transport:port: 8719dashboard: localhost:8080
在控制台设置流控设置即可,设置的留空规则是保存在内存中的,重启就会失效
两个问题
- 控制台的实时监控没有数据(使用endpoint支持)?
1.在服务中导入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
2.修改springboot配置
#允许 Endpoints 的访问。
management.endpoints.web.exposure.include=*
- 请求限流的自定义提示,资源控制
@RestController
public class TestController {// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用@SentinelResource(blockHandler = "blockHandlerForGetUser", fallback = "blockHandlerForGetUser")@RequestMapping("/hello")public String hello(String id) {return "Hello Sentinel";}public String blockHandlerForGetUser(String id,BlockException exception) {System.out.println(id+"--------------------");return id+"访问频繁...";}
}
1.2.4流控规则
流控模式:链路 假设现在需要流控的资源名C,设置A为请求入口,有一个请求A调用了B调用了C,那么只有请求只有入口为A落到C的请求才被流控,从其他入口调用C都不会被流控
流控模式:关联 当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。流控资源为C 关联资源为A,当C被流控时也流控A
1.2.5熔断降级
使用sentinel来保护feign远程调用,熔断
调用方的熔断保护
引入依赖spring-cloud-starter-alibaba-sentinel,spring-cloud-starter-openfeign
配置文件配置:feign.sentinel.enabled=true
@FeignClient(name = "service-provider", fallback = EchoServiceFallback.class, configuration = FeignConfiguration.class)
public interface EchoService {@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)String echo(@PathVariable("str") String str);
}class FeignConfiguration {@Beanpublic EchoServiceFallback echoServiceFallback() {return new EchoServiceFallback();}
}class EchoServiceFallback implements EchoService {@Overridepublic String echo(@PathVariable("str") String str) {return "echo fallback";}
}
调用方控制台手动指定远程服务的降级策略,远程服务被降级处理会触发我们的熔断回掉方法
超大流量的时候必须牺牲一下远程服务,在服务的提供方指定降级策略.提供方是在执行方法,但是执行自己的业务逻辑,返回的是默认的降级数据(限流的数据)
1.2.6自定义受保护资源
1.抛出异常的方式定义资源
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
try (Entry entry = SphU.entry("resourceName")) {// 被保护的业务逻辑// do something here...
} catch (BlockException ex) {// 资源访问阻止,被限流或被降级// 在此处进行相应的处理操作
}
2.注解方式定义资源
注意 blockHandler 函数会在原方法被限流/降级/系统保护的时候调用,而 fallback 函数会针对所有类型的异常。请注意 blockHandler 和 fallback 函数的形式要求,https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81
// 原本的业务方法.
@SentinelResource(blockHandler = "blockHandlerForGetUser")
public User getUserById(String id) {throw new RuntimeException("getUserById command failed");
}// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
public User blockHandlerForGetUser(String id, BlockException ex) {return new User("admin");
}
1.2.7网关层控制-不进入服务
引入依赖(sentinel与网关的整合版本与cloud alibaba吻合)-提供了自动配置,官方文档给的依赖还需要编写配置类
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId><version>2.2.1.RELEASE</version></dependency>
可以在配置文件中配置被限流降级的回调信息
使用代码方式编写回调操作
@Configuration
public class SentinelGatewayConfig {public SentinelGatewayConfig(){GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {@Overridepublic Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {Mono<ServerResponse> mono = ServerResponse.ok().body(Mono.just("网关限流降级"), String.class);return mono;}});}
}
1.2.8sentinel持久化
https://www.jianshu.com/p/609961eb6a6e
2.Spring cloud组件
2.1Feign(声明式远程调用)
Feign是声明式的Http客户端,它让微服务之间的调用变得更简单了,Fegin提供了Http请求的模板,通过编写简单的接口和插入注解,就可以定义好Http请求的参数、格式、地址等信息。
Spring Cloud Fegin集成了Ribbon(负载均衡),可在让我们不在显式的使用这个组件。
Spring Cloud openFegin在NetfilxFeign基础上扩展了对SpringMVC注解的支持,在其实现下我们只需要创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口绑定,简化了Spring Cloud Ribbon自行封装服务调用客户端的开发量。
- 引入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
模仿会员(wwmall-member)模块调用优惠券(wwmall-coupon)模块
- 想要远程调用coupon模块的getCouponListByMemberId方法
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {@Autowiredprivate CouponService couponService;@RequestMapping("/member-coupon/couponList")public R getCouponListByMemberId(@RequestParam("name") String name){CouponEntity couponEntity = new CouponEntity();couponEntity.setCouponName("五折优惠.....");return R.ok().put("memberName",memberName).put("couponEntity",Arrays.asList(couponEntity));}
- 在会员模块编写一个接口,使用@FeignClient注解告诉springcloud这个接口需要调用哪个远程服务,声明接口内的每一个方法是调用哪个远程服务的哪个请求
package com.walkwind.wwmall.member.feign;
@FeignClient("wwmall-coupon")
public interface CouponFeignService {@RequestMapping("/coupon/coupon/member-coupon/couponList")public R getCouponListByMemberId(@RequestParam("name") String name);
}
- 测试调用远程接口业务代码
@RestController
@RequestMapping("member/member")
public class MemberController {@Autowiredprivate MemberService memberService;@AutowiredCouponFeignService couponFeignService;@RequestMapping("/getCouponList")public R getCouponList(){R coupon = couponFeignService.getCouponListByMemberId("张三");return coupon;}
- 使用@EnableFeignClients在启动类上注解开启远程调用功能
@SpringBootApplication
@EnableDiscoveryClient
//明确告诉fegin远程调用接口处在哪个包下,不配置的话会自动扫描所有标注了@FeignClient("wwmall-coupon")的接口
@EnableFeignClients(basePackages="com.walkwind.wwmall.member.openfeign")
public class WwmallMemberApplication {public static void main(String[] args) {SpringApplication.run(WwmallMemberApplication.class, args);}
}
- 运行项目测试远程调用功能(需开启Nacos服务)
注:feign远程调用传递参数是以json数据传输,只要属性名对应就可以封装到任意引用类型中使用RequestParam必须指定参数参数名称
Fegin请求头丢失问题
登录后远程调用请求头数据cookie丢失
解决方法:fegin在调用之前要构造请求,调用很多的拦截器,我们可以加上fegin远程调用的拦截器在请求进入后,获取请求头数据,将请求头放入新的requestTemplate中。RequestContextHolder使用ThreadLocal去获取原请求上下文信息
fegin异步情况丢失上下文问题
解决方法
在主方法中获取老请求的请求头数据,在创建的每个子线程类中为请求头放入数据
2.2gateway网关
1.简介
网关作为流量的入口,常用功能包括路由转发、权限校验、限流控制。springcloud gateway作为springcloud官方推出的第二代网关框架,取代了zuul网关。
2.概念:
请求到达网关-网关利用断言来判定是否符合路由规则-符合就按照路由规则路由到经过过滤器链之后到达指定地址;
Route(路由):这是网关的基本构建块。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。
Filter(过滤器):这是org.springframework.cloud.gateway.filter.GatewayFilter的实例,我们可以使用它修改请求和响应。
3.工作原理
客户端向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
4.使用gateway
- 使用spring初始化向导创建wwmall-gateway模块引入gateway组件
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>
- 在pom文件中引入common模块,修改springboot版本与springcould与其他服务一致
注这里应排除common工程中的mybatis依赖不然会报错
<dependency><groupId>com.walkwind.wwmall</groupId><artifactId>wwmall-common</artifactId><version>0.0.1-SNAPSHOT</version><exclusions><exclusion><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></exclusion></exclusions>
</dependency>
- 将wwmall-gateway注册到nacos中
1.开启注册发现服务功能
@EnableDiscoveryClient
2.配置文件中配置,服务注册/发现中心地址
spring:application:name: wwmall-gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8848
3.在nacos中配置命名空间与配置集
4.配置文件中配置,配置中心信息及使用的命名空间信息
bootstrap.properties
spring.application.name=wwmall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=ac252e0f-5dc4-4a9c-9175-08937b6ddcd9
spring.cloud.nacos.config.name=wwmall-gateway.yml
spring.cloud.nacos.config.group=dev
5.配置网关路由信息
spring:cloud:nacos:gateway:routes:#路由规则意为,如果请求中参数url的值为baidu就路由到www.baidu.com- id: baidu_route uri: https://www.baidu.com/predicates:- Query=url,baidu#路由规则意为,如果请求中参数url的值为baidu就路由到www.qq.com- id: qq_routeuri: https://www.qq.compredicates:- Query=url,qq
更多路由配置参考说明文档
2.3sleuth+zipkin服务链路追踪
2.3.1.为什么用
2.3.2.基本术语
官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-sleuth/2.2.2.RELEASE/reference/html/#introduction
2.3.3流程图
服务调用业务
对应的流程
span之间的父子关系
2.3.4整合sleuth
2.3.5整合zipkin可视化观察链路
界面分析
(基础篇20-xxx)SpringCloud Alibaba组件相关推荐
- 谷粒商城微服务分布式基础篇二—— Spring Cloud Alibaba、Nacos注册与发现
文章目录 Spring Cloud Alibaba--微服务开发 Spring Cloud Alibaba是什么? 主要功能 组件 为什么不使用Spring Cloud 使用 Nacos Disc ...
- Python Qt GUI设计:QCalendar日历类和QDateTimeEdit时间类(基础篇—20)
目录 1.QCalendar日历类 2.QDateTimeEdit时间类 1.QCalendar日历类 QCalendar是一个日历控件,它提供了一个基于月份的视图,允许用户通过鼠标或键盘选择日期,默 ...
- cocos2dx基础篇(20) 扩展动作CCGridAction
[3.x] (1)去掉"CC" [CCGridAction] CCGridAction有两个子类:CCGrid3DAction.CCTiledGrid3DAction.而我 ...
- 谷粒商城之分布式基础篇p1-p50
2021年8月11日 准备把谷粒商城这个项目笔记大概记录一下! 2022年7月21日晚上23:30,二刷谷粒商城!!! 当前进度:P17 坚持就是胜利!!! P1-P4 主要是介绍项目使用了哪些技术, ...
- 分布式微服务架构之SpringCloud基础篇
一,微服务相关概念 1.微服务与分布式 微服务理论:一种架构风格,将项目的不同功能拆分成一个个模块,每个模块都能独立运行,彼此间通过远程调用实现功能. 分布式概念:很多建立在网络上的软件系统的集合. ...
- 2022谷粒商城SpringCloud项目环境搭建+项目流程(基础篇)
谷粒商城项目 前言:在真正开始敲代码实现项目功能之前,关于此项目的介绍和环境搭建读者阅读本篇就可以了(笔者自己还记录了一下项目中遇到的小bug以及知识点).后面的功能实现从简考虑没有附上具体的代码(篇 ...
- SpringCloud Alibaba实战--第二篇:NacosⅠ服务注册和配置中心
系列文章目录 微服务新王SpringCloudAlibaba 文章目录 系列文章目录 前言 一.Nacos是什么?能干啥? 二.Nacos下载及安装 1. 下载 2. 安装并运行 3. 对比Eurek ...
- SpringCloud Alibaba微服务实战(一) - 基础环境搭建
说在前面 Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案.此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来 ...
- layui数据表格(一:基础篇,数据展示、分页组件、表格内嵌表单和图片)
表格展示神器之一:layui表格 前言:在写后台管理系统中使用最多的就是表格数据展示了,使用表格组件能提高大量的开发效率,目前主流的数据表格组件有bootstrap table.layui table ...
最新文章
- 在项目中引入领域驱动设计的经验
- Java中的关于static的解释和应用
- (视频) 基于HTML5的服务器远程访问工具
- 2017-8-22 训练日记
- 修改Chrome的UserAgent
- linux下的ppp软件,linux下ppp拨号无线上网(示例代码)
- 小技巧:Chrome开发者工具里的Alt+单击
- 20个软件开发常用设计文档大全下载
- java窗口小程序atm_写一个ATM机小程序(JAVA), 目前老师 讲到了 静态工厂
- java异常网,Java异常实践事项
- 维护2G网络的稳定必须提升到战略高度
- java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException
- matlab相关性分析
- python实现10进制转换2进制(两种方法)
- window本地运行hadoop 测试用例 failed to create symlink
- “社畜”群体的崛起带来了哪些营销新契机?
- 解决远程连接服务器没有远程桌面授权服务器的许可证问题
- 打印可自定义的字母金字塔(python实现)
- 如何利用python进行一次移动平均预测
- 微信支付-----统一下单接口对接