java架构之路-(微服务专题)feign的基本使用和nacos的配置中心
上次回归:
上次我们说了ribbon的基本使用,包括里面的内部算法,算法的细粒度配置,还有我们自己如何实现我们自己的算法,主要还是一些基本使用的知识,还不会使用ribbon的小伙伴可以回去看一下上一篇博客。
什么是Feign:
Feign是Netflix开发的声明式、模板化的HTTP客户端,其灵感来自Retrofit、JAXRS2.0以及WebSocket。Feign 可帮助我们更加便捷、优雅地调用HTTP API,为什么我们会选择使用Feign呢?我们上次说到的ribbon也是可以调用远程API的啊,但是你的请求地址参数很多呢?比如这样https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=%E5%B0%8F%E8%8F%9C%E6%8A%80%E6%9C%AF&rsv_pq=c848f94a0022633c&rsv_t=82132w5e6o2pWnrOzzEl1kRwfItDYCuNU7FotoIqlCHTCjD2WiDKjarInW8&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_sug3=13&rsv_sug1=1&rsv_sug7=100&rsv_sug2=0&inputT=1408&rsv_sug4=1408,而且参数还总是变化的(客户每天都在变需求),你每次都需要改写代码,地址太长还容易写错,是不是觉得写起来很吃力的样子,我们这次学习的Feign就是来解决这个问题的。
Feign的常用配置详解:
刚才我们简单的说到了Feign是做什么的,我们来看一下,我们如何使用Feign吧。还是我们的两个服务,一个用户服务,一个订单服务,我们分别来看一下配置。
一、最简单的启动
①.首先加入父依赖包,在启动类加入注解@EnableFeignClients
<!-- 加入Feign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
package com.xiaocaiFeign; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class FeignOrderApplication {
public static void main(String[] args) {
SpringApplication.run(FeignOrderApplication.class, args);
} }
②.创建我们的订单服务,建立一个接口,接口如下,需要加注解@FeignClient(name = "feign-order"),实现类你们自己去完成吧
package com.xiaocaiFeign.controller; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; @FeignClient(name = "feign-order")
public interface OrderController { @RequestMapping("/getOrderData/{orderId}")
String getOrderData(@PathVariable("orderId") String orderId);
}
③.修改我们的订单服务的POM文件,弄成一个jar包即可,不需要可执行的jar包。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
</plugins>
</build>
④.创建我们的用户服务,将我们的订单服务以jar包的形式引入进来。
<dependencies>
<dependency>
<groupId>com</groupId>
<artifactId>feignOrder</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
这里千万注意一个问题,你的订单服务和你的用户服务,包路径一定要相同,不然springboot是扫描不到你的包的,切记~!!!
⑤.编写我们的调用类(用户服务)
package com.xiaocaiFeign.controller; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
public class UserController { @Autowired
private OrderController orderController; @GetMapping("/getOrder")
public String getOrderData() {
System.out.println("准备调用");
String orderData = orderController.getOrderData("1");
System.out.println(orderData);
return orderData;
}
}
运行看结果
是不是超级简单。
二、打印日志级别
首先我们在订单服务加入一个配置,千万别写@Configuration
package com.xiaocaiFeign.config; import feign.Logger;
import org.springframework.context.annotation.Bean; public class FeignLogConfig { @Bean
public Logger.Level level() {
//return Logger.Level.NONE; //(默认)不打印任何日志
return Logger.Level.BASIC;//仅记录请求方法、URL、响应状态代码以及执行时间,生成一般用这个
//return Logger.Level.HEADERS;//在BASIC基础之上还记录了请求和响应的header.
//return Logger.Level.FULL;//记录了请求和响应的header、body和元数据
}
}
然后在我们的接口类下面给予这个配置
package com.xiaocaiFeign.controller; import com.xiaocaiFeign.config.FeignLogConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; @FeignClient(name = "feign-order", configuration = FeignLogConfig.class)
public interface OrderController { @RequestMapping("/getOrderData/{orderId}")
String getOrderData(@PathVariable("orderId") String orderId); }
最后我们在我们的用户服务中开启配置,注意xiaocaiFeign是你的包名。
logging:
level:
com:
xiaocaiFeign: debug
我们来看一下效果,我这只演示一下FULL的吧~!
三、额外我觉得没用的配置,契约配置
反正我是觉得没啥大用,而且还不熟悉的,和我们的日志差不多,加入一个自定义的配置类
package com.xiaocaiFeign.config; import feign.Contract;
import org.springframework.context.annotation.Bean; public class MyFeignConfig {
/**
* 根据SpringBoot自动装配FeignClientsConfiguration 的FeignClient的契约是SpringMvc
* 通过修改契约为默认的Feign的锲约,那么就可以使用默认的注解
* @return
*/
@Bean
public Contract feiContract() {
return new Contract.Default();
}
}
然后通过接口引入,但是这回接口必须要写feign的注解了,我觉得没这个必要,我还是比较习惯用springMVC的注解。
package com.xiaocaiFeign.controller; import com.xiaocaiFeign.config.MyFeignConfig;
import feign.Param;
import feign.RequestLine;
import org.springframework.cloud.openfeign.FeignClient; @FeignClient(name = "feign-order", configuration = MyFeignConfig.class)
public interface OrderController { @RequestLine("GET /getOrderData/{orderId}")
String getOrderData(@Param("orderId") String orderId);
}
这写就可以调用了,里面都别写错了,写错了,用户服务可能会启动失败的。
四、请求头传递
最后一个实例了,假如我们这样的,用户服务调用订单服务,订单服务每次调用需要携带请求头token进行验证,我们又该如何来做呢?我们来看一下代码实现,先弄一个拦截器。
package com.xiaocaiFeign.config; import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; public class MyRequestInterceptor implements RequestInterceptor { @Override
public void apply(RequestTemplate template) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
template.header("token", request.getHeader("token"));
}
}
然后将拦截器配置到Feign下面去。
package com.xiaocaiFeign.controller; import com.xiaocaiFeign.config.FeignLogConfig;
import com.xiaocaiFeign.config.MyFeignConfig;
import com.xiaocaiFeign.config.MyRequestInterceptor;
import feign.Param;
import feign.RequestLine;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; @FeignClient(name = "feign-order",configuration = MyRequestInterceptor.class)
public interface OrderController { @RequestMapping("/getOrderData/{orderId}")
String getOrderData(@PathVariable("orderId") String orderId); // @RequestLine("GET /getOrderData/{orderId}")
// String getOrderData(@Param("orderId") String orderId); @RequestMapping("/getOrderToken")
String getOrderToken();
}
自己去测试一下调用结果吧,我弄这个弄了好久,保证没问题的,我就不上图了。
Feign的优化配置:
我们的Feign底层还是使用Ribbon来调用的,第一次很多时候会调用的慢,我可以改为HTTPClient调用方式。
feign:
client:
config:
connectTimeout: 5000 #连接超时时间(毫秒)
readTimeout: 5000 # 读取超时时间(毫秒)
product-center:
loggerLevel: full # 日志级别
contract: feign.Contract.Default #指定默认契约
httpclient:
enabled: true # 开启httpClient
max-connections: 200 # 最大连接数
max-connections-per-route: 50 # 为每个url请求设置最大连接数
nacos配置中心详解:
nacos里面还有一个配置中心还没有去说,我们现在的项目很多都是微服务的,也知道微服务会拆分成很多个小的服务,加入你拆分的不多,10个服务,本地开发环境,公共开发环境,测试环境,生产环境,那么你就意味着你需要弄40个配置文件,而且你会暴露你的数据库地址给开发,那么我们这次就用nacos来看看配置中心是如何做的吧。我们先弄一个最简单的测试类。
package com.nacosConfig.controller; import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
public class ConfigCenterController { @Value("${config.center.name}")
private String name; @GetMapping("/")
public String getData() {
System.out.println(name);
return name;
}
}
server:
port: 8080 config:
center:
name: "张三"
先不用nacos配置中心,我们来测试一下。
我们来看一下nacos是怎么来配置的
①.加入依赖包。
<!-- 引入nacos配置依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-config</artifactId>
</dependency>
②.新建一个叫做bootstrap.yml的配置,这个配置会优先于springboot自带的application.yml配置。
spring:
application:
name: nacos
profiles:
active: config
cloud:
nacos:
config:
server-addr: 192.168.138.119:8848
namespace: 83cbe7a9-7713-4d5c-b052-a42ba1df9e84
file-extension: yml
来解释一下我们的配置,第一个spring.application.name=nacos是我们的文件名字,spring.profiles.active=config还是我们的文件名字,spring.cloud.nacos.config.file-extension=yml是文件后缀,就是说,我们会去拿名字为nacos-config.yml这个文件。连接和命令空间这里就不说了,在nacos的注册中心讲的已经很详细了。
③.登录nacos页面,点击配置列表,选择对应的命名空间,点击“+”进行新增。
就这样,一个简单的配置中心就完成了(启动会报错,是因为你的注册中心没有注册成功报错的)。而且还可以查看历史版本,用起来还是不错的,你可以在application.yml写入你的注册配置,如下所示
spring:
application:
name: nacos-config
cloud:
nacos:
discovery:
server-addr: 192.168.138.119:8848
这时项目启动的时候会自动拉取nacos-config.yml配置文件。这样写是什么意思呢?就是你一个shoppingServer,你有不同的环境,我们写一个通用的配置shoppingServer.yml,然后通过你的shoppingServer-dev.yml、shoppingServer-st.yml,等文件来细化咱们的不同环境的配置。
还有一个配置是这样的。
spring:
application:
name: nacos-config
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 192.168.138.119:8848
file-extension: yml
shared-dataids: config1.yml,config2.yml
就是说我们还有加载config1.yml和config2.yml配置文件。现在我们说到四个配置文件了,那么他们的顺序又是什么呢?config1.yml<<<config2.yml<<<nacos-config.yml<<<nacos-config-dev.yml,越是在后面加载的,权利越大,就是后面的配置可以覆盖掉前面的配置。这里的shared-dataids: config1.yml,config2.yml一般用于不同系统中的通用配置,比如我们在用户系统和订单系统有通用配置,我们可以通过shared-dataids的方式来引入配置。
还可以这样来写
spring:
application:
name: nacos-config
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 192.168.138.119:8848
file-extension: yml
shared-dataids: config1.yml,config2.yml
refreshable-dataids: config1.yml,config2.yml
ext-config:
- data-id: config3.yml
group: DEFAULT_GROUP
refresh: true
- data-id: config4.yml
group: DEFAULT_GROUP
refresh: true
这回又多了一些文件,顺序是什么样子的呢?我再来写一下config1.yml<<<config2.yml<<<config3.yml<<<config4.yml<<<nacos-config.yml<<<nacos-config-dev.yml。
spring:
application:
name: nacos-config
profiles:
active: dev
cloud:
refresh:
enabled: true # 默认是true
nacos:
config:
server-addr: 192.168.138.119:8848
file-extension: yml
shared-dataids: config1.yml,config2.yml
refreshable-dataids: config1.yml,config2.yml
ext-config:
- data-id: config3.yml
group: DEFAULT_GROUP
refresh: true
- data-id: config4.yml
group: DEFAULT_GROUP
refresh: false
其中标红的那个几个值是控制是否可以动态刷新的,就是说我们改了配置中心的配置,不用重启服务,配置就可以生效的,需要在类上面加入@RefreshScope注解。
最后一个问题,nacos改密码和添加账户,我们集群的时候连接一个mysql数据库对吧,单机的比较头疼,我们设置单机的内部是用一个Derby这个数据库来连接的,我这里只能用IDEA改本地的Derby然后拷贝到linux上去,暂时没啥别的好办法,用页面也能改,但是无法添加用户,而我们的集群是用的mysql,我们可以自己操作啦,来一个添加用户的操作,打开我们的mysql的nacos库,找到users表,添加用户,然后我们用下面的方法来手动生成密码。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
<version>1.2.2.RELEASE</version>
</dependency>
public static void main(String[] args) {
String nacos = new BCryptPasswordEncoder().encode("nacos");
System.out.println("nacos = " + nacos);
}
然后把我们的密码自己弄到mysql数据库内就可以啦
总结:
这次主要说了feign的基本使用,日志级别的选择,还有我们的请求头如何传递,然后就是我们的Nacos的配置中心是如何去做的,我们配置文件的加载顺序,最后是我们的nacos如何添加用户和修改密码(页面就可以改)。
最进弄了一个公众号,小菜技术,欢迎大家的加入
java架构之路-(微服务专题)feign的基本使用和nacos的配置中心的更多相关文章
- java架构之路-(Redis专题)redis面试助力满分+
1.Redis支持的数据类型? 答:五种,在第一节redis相关的博客我就说过,String,Hash,List,Set,zSet,也就是我们的字符串,哈希,列表,集合,有序集合五种.结构图如下. 2 ...
- java架构之路-(dubbo专题)dubbo的基本使用
今天我们来说一下dubbo的基本使用,没有什么高阶的知识,真的超级简单易懂. Dubbo核心功能解释 dubbo 阿里开源的一个SOA服务治理框架,从目前来看把它称作是一个RPC远程调用框架更为贴切. ...
- java架构之路-(Redis专题)Redis的主从、哨兵和集群
我们使用的redis,单机的绝对做不到高可用的,万一单机的redis宕机了,就没有备用的了,我们可以采用集群的方式来保证我们的高可用操作. 主从架构 大致就是这样的,一个主节点,两个从节点(一般两个就 ...
- java架构之路-(Redis专题)SpringBoot连接Redis超简单
上次我们搭建了Redis的主从架构,哨兵架构以及我们的集群架构,但是我们一直还未投入到实战中去,这次我们用jedis和springboot两种方式来操作一下我们的redis 主从架构 如何配置我上次已 ...
- java架构之路-(Redis专题)聊聊大厂那些redis
上几次说了redis的主从,哨兵,集群配置,但是内部的选举一直没说,先来简单说一下选举吧. 集群选举 redis cluster节点间采取gossip协议进行通信,也就是说,在每一个节点间,无论主节点 ...
- java架构之路-(MQ专题)RabbitMQ安装和基本使用
RabbitMQ安装 我这里安装是使用阿里云的CentOS7.5来安装的,使用CentOS版本低于7的可能会报错. 1.安装rabbitmq所需要的依赖包 输入$ yum install build- ...
- java架构之路-(MQ专题)RocketMQ从入坑到集群详解
这次我们来说说我们的RocketMQ的安装和参数配置,先来看一下我们RocketMQ的提出和应用场景吧. 早在2009年,阿里巴巴的淘宝第一次提出了双11购物狂欢节,但是在2009年,服务器无法承受到 ...
- java架构之路(MQ专题)kafka集群配置和简单使用
前面我们说了RabbitMQ和RocketMQ的安装和简单的使用,这次我们说一下Kafka的安装配置,后面我会用几个真实案例来说一下MQ的真实使用场景.天冷了,不愿意伸手,最近没怎么写博客了,还请见谅 ...
- java架构之路-(netty专题)初步认识BIO、NIO、AIO
本次我们主要来说一下我们的IO阻塞模型,只是不多,但是一定要理解,对于后面理解netty很重要的 IO模型精讲 IO模型就是说用什么样的通道进行数据的发送和接收,Java共支持3种网络编程IO模式: ...
随机推荐
- 【原创】Android adb错误“'adb' 不是内部或外部命令,也不是可运行的程序或批处理文件。”处理方法
才刚刚接触Android没多久,现在使用adb命令的时候出现错误“'adb' 不是内部或外部命令,也不是可运行的程序或批处理文件.”,如下图所示: 这个问题一般有两种可能: 1.就是没有配置环境变量, ...
- Scala实践14
1.Scala的future 创建future import scala.concurrent._ import ExecutionContext.Implicits.global object Fu ...
- Golang最强大的访问控制框架casbin全解析
Golang最强大的访问控制框架casbin全解析 Casbin是一个强大的.高效的开源访问控制框架,其权限管理机制支持多种访问控制模型.目前这个框架的生态已经发展的越来越好了.提供了各种语言的类库, ...
- ASP.Net MVC 引用动态 js 脚本
希望可以动态生成 js 发送给客户端使用. layout页引用: <script type="text/javascript" src="@Url.Action( ...
- python中类的输出或类的实例输出为何是<__main__类名 object at xxxx>这种形式?
原因: __str__()这个特殊方法将对象转换为字符串的结果 效果图: 代码: # 定义一个Person类 class Person(object): """人类&qu ...
- 两个关于 Java 面试的 Github 项目
哈喽,大家好.相信大家都知道金九银十,在人才市场上是指每年的 9 月和 10 月是企业的招聘高峰期.这个时候企业往往有大量招聘需求,求职者在这个时候就找工作无疑是最适合的.需求大,谈工资什么的就更容易 ...
- 测试工具Fiddler(一)—— 基础知识
Fiddler基础知识 一.Fiddler是什么? Fiddler是一个http协议调试代理工具,它能够记录客户端和服务器之间的所有 HTTP请求,可以针对特定的HTTP请求,分析请求数据.设置断点. ...
- margin和 padding 以及 float :left和float :right的介绍
1.margin和padding的介绍 margin是外边距,padding是内边距,用CSS时首先要做的就是把所有标签的margin和padding清空.这样更容易控制布局和兼容浏览器. p li等 ...
- 如何配置好Selenium2Library的环境
1.首先是下载如下文件 1,ActivePython-其自带了pip工具,很方便,记得选择activepython是2.7x版本的python: 2.依次安装wxpython,Robotframewo ...
- Java入门 - 高级教程 - 08.Applet
原文地址:http://www.work100.net/training/java-applet.html 更多教程:光束云 - 免费课程 Applet 序号 文内章节 视频 1 概述 2 Apple ...