1.1.背景
当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻。
那么有没有更好的解决方案呢?答案是确定的有,Netflix已经为我们提供了一个框架:Feign。
1.2.Feign概述
Feign是Spring Cloud提供的声明式、模板化的HTTP客户端, 它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。
Spring Cloud集成Feign并对其进行了增强,使Feign支持了Spring MVC注解;Feign默认集成了Ribbon,所以Fegin默认就实现了负载均衡的效果。
1.3.Feign入门
1.3.1.创建服务提供者
1.3.1.1.创建工程
1.3.1.2.application.yml
server:
port: 9091
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.128.131:8848 #nacos服务的地址
application:
name: feign-provider #向注册中心注册的名字
pom文件
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
controller
package com.peng.controller;
import com.peng.pojo.User;
import com.peng.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/provider")
public class ProviderController {
@Autowired
private UserService userService;
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable Integer id){
return userService.getUserById(id);
}
@RequestMapping("/deleteUserById")
public User deleteUserById(@RequestParam("id") Integer id){
return userService.deleteUserById(id);
}
@RequestMapping("/addUser")
public User addUser(@RequestBody User user){
return userService.addUser(user);
}
}
service
package com.peng.service;
import com.peng.pojo.User;
public interface UserService {
User getUserById(Integer id);
User deleteUserById(Integer id);
User addUser(User user);
}
impl
package com.peng.service.impl;
import com.peng.pojo.User;
import com.peng.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Override
public User getUserById(Integer id) {
return new User(id,"张三-01",12);
}
@Override
public User deleteUserById(Integer id) {
return new User(id,"删除了张三-01",12);
}
@Override
public User addUser(User user) {
return new User(22,"新增了张三-01",12);
}
}
启动类
package com.peng;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient //向注册中心注册该服务,并可以获取其他服务的调用地址
public class SpringCloudProviderApp {
public static void main(String[] args) {
SpringApplication.run(SpringCloudProviderApp.class,args);
}
}
1.3.2.创建feign接口
1.3.2.1.创建工程
pom文件
1.3.2.3.feign在接口中使用
1、@RequestMapping表示 拼接请求路径 localhost:80/getUser/1
2、@PathVariable("id") 表示 ?传参 localhost:80/getUser?id=1
3、@RequestBody 对象转JSON传参 localhost:80/getUser?id=1&name=zs 转成JSON
package com.peng.feign;
import com.peng.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient("feign-provider") //调用的服务名
@RequestMapping("/provider") //拼接路径
public interface UserServiceFeign {
@RequestMapping("/getUserById/{id}") //拼接url
User getUserById(@PathVariable("id") Integer id); //restful形式拼接参数
@RequestMapping("/deleteUserById") //拼接url
User deleteUserById(@RequestParam("id") Integer id);//?形式拼接参数
@RequestMapping("/addUser") //拼接url
User addUser(@RequestBody User user); //pojo ==> json 把传过来的参数转成json串
}
1.3.3.创建服务消费者
1.3.3.1.创建工程
1.3.3.2.pom.xml
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
1.3.3.3.application.yml
server:
port: 80
compression:
enabled: true #开启gzip压缩
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.128.131:8848 #向nacos中心注册服务(nacos服务的地址)
application:
name: feign-consumer #给该服务起个名字
1.3.3.4.Controller
package com.peng.controller;
import com.peng.feign.UserServiceFeign;
import com.peng.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
//访问Rest服务的客户端
@Autowired
private UserServiceFeign userServiceFeign; //注入代理类
@RequestMapping("/getUserById/{id}")
public User getUserById(@PathVariable Integer id){
//打印代理类的类型
System.out.println(userServiceFeign.getClass());
return userServiceFeign.getUserById(id);
}
@RequestMapping("/deleteUserById")
public User deleteUserById(@RequestParam("id") Integer id){
//打印代理类的类型
System.out.println(userServiceFeign.getClass());
return userServiceFeign.deleteUserById(id);
}
@RequestMapping("/addUser")
public User addUser(User user){
//打印代理类的类型
System.out.println(userServiceFeign.getClass());
return userServiceFeign.addUser(user);
}
}
配置类
package com.peng.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConfigBean {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
1.3.3.4.app(启动类)
package com.peng;
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
@EnableDiscoveryClient //向Nacos 注册中心注册该服务,并可以获取其他服务的调用地址
@EnableFeignClients //开启feign注解扫描
public class SpringCloudConsumerApp {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConsumerApp.class,args);
}
}
测试:三种方式访问
第一种:对象
第二种:路径传参
第三种:路径拼接传参,key=value
1.4.Feign原理
1.4.1、将feign接口的代理类扫描到Spring容器中: @EnableFeignClients开启feign注解扫描:FeignClientsRegistrar.registerFeignClients()扫描被 @FeignClient标识的接口生成代理类, 并把接口和代理类交给Spring的容器管理。 1.4.2、为接口的方法创建RequestTemplate 当consumer调用feign代理类时,代理类会调用SynchronousMethodHandler.invoke()创建RequestTemplate(url,参数) 1.4.3、发出请求 代理类会通过RequestTemplate创建Request,然后client(URLConnetct、HttpClient、OkHttp)使用Request发送请求
1.5feign优化
1.5.1、开启feign日志
feign: client: config: default: loggerLevel: full logging: level: com.peng.feign: debug
1.5.2、feign超时
1、方式一: ribbon: ConnectTimeout: 5000 #请求连接的超时时间 ReadTimeout: 5000 #请求处理的超时时间 2、方式二: feign: client: config: feign-provider: ConnectTimeout: 5000 #请求连接的超时时间 ReadTimeout: 5000 #请求处理的超时时间
不配置的话默认是一秒,超过一秒就会抛异常,可以配置连接超时时间,当开启日志时,会忽略连接超时
1.5.3、http连接池
1.5.4、gzip压缩
server: compression: enabled: true #开启gzip压缩
文章来源
发表评论