上一篇文章中已经讲述 Feign的基本用法,本章主要概述 FeignClient GET/POST/PUT/DELETE restful写法以及 Feign 拦截器,与配置优化方案,关闭HttpClient开启OKHTTP…
- 准备工作
1.启动Consul,所有文章都将以Consul作为服务注册中心
2.创建 battcn-feign-hello,battcn-feign-hi(本文代码基于上篇改造)
3.服务(Hi)-> FeignClient -> 服务(Hello),通过实现 RequestInterceptor 传递 header 信息
- battcn-feign-hello
- pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
|
- BattcnFeignHelloApplication.java
1 2 3 4 5 6 7 8
|
@SpringBootApplication @EnableDiscoveryClient public class BattcnFeignHelloApplication {
public static void main(String[] args) { SpringApplication.run(BattcnFeignHelloApplication.class, args); } }
|
- Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
public class Student {
private Long id; private String name; private String email;
//...get set @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", email='" + email + '\'' + '}'; } public Student(){} public Student(Long id, String name, String email) { this.id = id; this.name = name; this.email = email; } }
|
- HelloController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
@RestController @RequestMapping("/hello") public class HelloController {
@Autowired HttpServletRequest request;
static Logger LOGGER = LoggerFactory.getLogger(HelloController.class);
@ResponseStatus(HttpStatus.OK) @GetMapping public Student findStudentByName(@RequestParam("name") String name,@RequestHeader(name = "token",required = false)) { // TODO:不做具体代码实现,只打印Log LOGGER.info("[查询参数] - [{}]", name); LOGGER.info("[Token] - [{}]",token); LOGGER.info("[Auth] - [{}]",request.getHeader("Auth")); return new Student(1L,"挽歌-GET","1837307557@qq.com"); }
@ResponseStatus(HttpStatus.CREATED) @PostMapping public Student addStudent(@RequestBody Student student) { // TODO:不做具体代码实现,只打印Log LOGGER.info("[添加信息] - [{}]", student.toString()); return new Student(2L,"挽歌-SAVA","1837307557@qq.com"); }
@ResponseStatus(HttpStatus.CREATED) @PutMapping("/{studentId}") public Student editStudent(@RequestBody Student student, @PathVariable("studentId") Long studentId) { // TODO:不做具体代码实现,只打印Log LOGGER.info("[修改信息] - [{}]", student.toString()); return new Student(3L,"挽歌-EDIT","1837307557@qq.com"); }
@ResponseStatus(HttpStatus.NO_CONTENT) @DeleteMapping("/{studentId}") public void deleteStudent(@PathVariable("studentId") Long studentId) { // TODO:不做具体代码实现,只打印Log LOGGER.info("[根据编号删除学生] - [{}]", studentId); } }
|
- bootstrap.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
server: port: 8765
spring: application: name: battcn-feign-hello cloud: consul: host: localhost port: 8500 enabled: true discovery: enabled: true prefer-ip-address: true
|
- 测试
访问:http://localhost:8765/hello?name=Levin
显示:{"id":1,"name":"挽歌-GET","email":"1837307557@qq.com"} 代表我们服务启动成功
- battcn-feign-hi
- pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
<dependencies> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>com.battcn</groupId> <artifactId>battcn-starter-swagger</artifactId> <version>1.0.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
|
- BattcnFeignHiApplication.java
1 2 3 4 5 6 7 8 9 10
|
@EnableDiscoveryClient @EnableFeignClients @SpringBootApplication public class BattcnFeignHiApplication {
public static void main(String[] args) { SpringApplication.run(BattcnFeignHiApplication.class, args); }
}
|
- HiController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
@RestController @RequestMapping("/hi") public class HiController {
static Logger LOGGER = LoggerFactory.getLogger(HiController.class);
@Autowired HelloClient helloClient;
@ResponseStatus(HttpStatus.OK) @GetMapping public Student find(@RequestParam("name") String name,@RequestHeader(name="token",required = false)String token) { // TODO:只是演示Feign调用的方法 LOGGER.info("[Token] - [{}]",token); return helloClient.findStudentByName(name,token); }
@ResponseStatus(HttpStatus.CREATED) @PostMapping public Student add(@RequestBody Student student) { // TODO:只是演示Feign调用的方法 return helloClient.addStudent(student); }
@ResponseStatus(HttpStatus.CREATED) @PutMapping("/{studentId}") public Student edit(@RequestBody Student student, @PathVariable("studentId") Long studentId) { // TODO:只是演示Feign调用的方法 return helloClient.editStudent(student, studentId); }
@ResponseStatus(HttpStatus.NO_CONTENT) @DeleteMapping("/{studentId}") public void delete(@PathVariable("studentId") Long studentId) { // TODO:只是演示Feign调用的方法 helloClient.deleteStudent(studentId); } }
|
- MyFeignInterceptor.java
1 2 3 4 5 6 7 8 9 10 11 12
|
/** * 传递Token * @author Levin * @date 2017-07-29. */ @Configuration public class MyFeignInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate requestTemplate) { requestTemplate.header("Auth","My Name's request header Auth"); } }
|
- HelloClient.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
package com.battcn.client;
import com.battcn.pojo.Student; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*;
/** * 模拟完整的CRUD操作 */ @FeignClient(name = "battcn-feign-hello") public interface HelloClient {
@ResponseStatus(HttpStatus.OK) @GetMapping("/hello") Student findStudentByName(@RequestParam("name") String name,@RequestHeader(name="token",required = false)String token);
@ResponseStatus(HttpStatus.CREATED) @PostMapping("/hello") Student addStudent(@RequestBody Student student);
@ResponseStatus(HttpStatus.CREATED) @PutMapping("/hello/{studentId}") Student editStudent(@RequestBody Student student, @PathVariable("studentId") Long studentId);
@ResponseStatus(HttpStatus.NO_CONTENT) @DeleteMapping("/hello/{studentId}") void deleteStudent(@PathVariable("studentId") Long studentId); }
|
- bootstrap.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
server: port: 8766
spring: application: name: battcn-feign-hi cloud: consul: host: localhost port: 8500 enabled: true discovery: enabled: true prefer-ip-address: true
#Hystrix支持,如果为true,hystrix库必须在classpath中 feign: okhttp: enabled: true #开启OKHTTP支持,依赖 (feign-okhttp)默认HttpClient #请求和响应GZIP压缩支持 compression: request: enabled: true #支持压缩的mime types mime-types: text/xml,application/xml,application/json min-request-size: 2048 response: enabled: true hystrix: enabled=false # 日志支持 logging: level: project.com.battcn.UserClient: DEBUG
#以下就是需要写的配置,注意base-package就可以了 swagger: enable: true #是否开启Swagger api-info: description: ${spring.application.name} license: ${spring.application.name} license-url: http://blog.battcn.com terms-of-service-url: http://blog.battcn.com title: 鏖战八方 version: "@project.version@" contact: email: 1837307557@qq.com name: 挽歌 url: http://blog.battcn.com docket: base-package: com.battcn.controller #扫描路径,建议以Controller的父包为主 group-name: ${spring.application.name}
|
- 测试
访问:http://localhost:8766/swagger-ui.html
使用Swagger做测试
swagger测试
此处只演示GET,PUT,DELETE,POST 示例代码都包括,自行测试即可
日志:
1 2 3
|
2017-07-29 18:21:26.854 INFO 12620 --- [nio-8765-exec-2] com.battcn.controller.HelloController : [查询参数] - [Levin] 2017-07-29 18:21:26.854 INFO 12620 --- [nio-8765-exec-2] com.battcn.controller.HelloController : [Token] - [Token HA] 2017-07-29 18:21:26.854 INFO 12620 --- [nio-8765-exec-2] com.battcn.controller.HelloController : [Auth] - [My Name's request header Auth]
|
如果未实现 RequestInterceptor 那么 LOGGER.info("[Auth] - [{}]",request.getHeader("Auth")); 就无法获取到 request 中的信息
- 流程图
画图工具:https://www.processon.com/
流程图
- SpringCloud学习系列之二 ----- 服务消费者(Feign)和负载均衡(Ribbon)使用详解
前言 本篇主要介绍的是SpringCloud中的服务消费者(Feign)和负载均衡(Ribbon)功能的实现以及使用Feign结合Ribbon实现负载均衡. SpringCloud Feign Fei ...
- SpringCloud-创建服务消费者-Feign方式(附代码下载)
场景 SpringCloud-服务注册与实现-Eureka创建服务注册中心(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...
- Spring Cloud学习笔记【三】服务消费者Feign
Feign 是一个声明式的 Web Service 客户端,它的目的就是让 Web Service 调用更加简单.它整合了 Ribbon 和 Hystrix,从而让我们不再需要显式地使用这两个组件.F ...
- 创建服务消费者(Feign)
概述 Feign 是一个声明式的伪 Http 客户端,它使得写 Http 客户端变得更简单.使用 Feign,只需要创建一个接口并注解.它具有可插拔的注解特性,可使用 Feign 注解和 JAX-RS ...
- Spring Cloud(四)服务提供者 Eureka + 服务消费者 Feign
上一篇文章,讲述了如何通过RestTemplate + Ribbon去消费服务,这篇文章主要讲述如何通过Feign去消费服务. Feign简介 Feign是一个声明式的伪Http客户端,它使得写Htt ...
- 服务消费者Feign和Ribbon的区别
1.Ribbon通过注解@EnableEurekaClient/@EnableDiscoveryClient向服务中心注册: PS:选用的注册中心是eureka,那么就推荐@EnableEure ...
- 一起来学Spring Cloud | 第四章:服务消费者 ( Feign )
上一章节,讲解了SpringCloud如何通过RestTemplate+Ribbon去负载均衡消费服务,本章主要讲述如何通过Feign去消费服务. 一.Feign 简介: Feign是一个便利的res ...
- Spring Cloud (4) 服务消费者-Feign
Spring Cloud Feign Spring Cloud Feign 是一套基于Netflix Feign实现的声明式服务调用客户端.它使得编写Web服务客户端变得更加简单,我们只需要创建接口并 ...
- 8、服务发现&服务消费者Feign
spring cloud的Netflix中提供了两个组件实现软负载均衡调用,分别是Ribbon和Feign.上一篇和大家一起学习了Ribbon. Ribbon :Spring Cloud Ribbon ...
- 玩转SpringCloud(F版本) 二.服务消费者(2)feign
上一篇博客讲解了服务消费者的ribbon+restTemplate模式的搭建,此篇文章将要讲解服务消费者feign模式的搭建,这里是为了普及知识 平时的项目中两种消费模式选择其一即可 本篇博客基于博客 ...
随机推荐
- Java实现 LeetCode 654 最大二叉树(递归)
654. 最大二叉树 给定一个不含重复元素的整数数组.一个以此数组构建的最大二叉树定义如下: 二叉树的根是数组中的最大元素. 左子树是通过数组中最大值左边部分构造出的最大二叉树. 右子树是通过数组中最 ...
- Java实现 蓝桥杯 算法提高 递推求值
算法提高 递推求值 时间限制:1.0s 内存限制:256.0MB 问题描述 已知递推公式: F(n, 1)=F(n-1, 2) + 2F(n-3, 1) + 5, F(n, 2)=F(n-1, 1) ...
- Java实现 LeetCode 110 平衡二叉树
110. 平衡二叉树 给定一个二叉树,判断它是否是高度平衡的二叉树. 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1. 示例 1: 给定二叉树 [3,9 ...
- Java中lang包的常用方法介绍
JAVA API(图片来源:实验楼) 包装类 Integer包装类 方法 返回值 功能描述 byteValue() byte 以 byte 类型返回该 Integer 的值 intValue() in ...
- Java实现 洛谷 P1421 小玉买文具
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = ...
- 【JavaScript】原生js实现:强制保留2位小数(由于toFixed()报错)
function decimal(x) { var f = parseFloat(x); if (isNaN(f)) { alert("请输入数字!"); return; } va ...
- 一个Redis查询案例
1.远程登陆进服务器 使用ssh连接至Linux服务器中 2.接入redis集群 redis-cli -h 10.1.8.12 -p 29000 3.执行查询命令 根据userid查询用户的最近在线时 ...
- 阿里云杨敬宇:边缘计算行业通识与阿里云ENS的技术演进之路
近日,阿里云杨敬宇在CSDN阿里云核心技术竞争力在线峰会上进行了<5G基础设施-阿里云边缘计算的技术演进之路>主题演讲,针对5G时代下,行业和技术的趋势.边缘计算产业通识以及阿里云边缘计算 ...
- OO学习最终总结
0.前言:本次主要是针对第三阶段的三次作业以及整个课程学习的总结,这三次作业主要是针对对程序进行重构使得程序可以对功能进行扩展的训练以及对类的设计,所以在此阐述在练习过程中的问题以及感悟. 1.作业总 ...
- sublime配置C++编译环境
配置C++编译命令 { "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$", "workin ...