SpringCloud2模块系列:Feign(服务间调用)

1 Feign

1.0 功能

服务间接口调用.

1.2 调用过程

  • 场景
    服务A调用服务B的接口.
  • 实现过程
    在服务A中使用Feign配置服务B的应用及路径属性.
  • 一句话
    在发起调用的服务中,配置被调用服务的信息.

1.3 流程图

图1 服务间调用示意图

1.4 OpenFeign

SpringCloud与OpenFeign匹配,否则出现如下错误:
Could not find class [org.springframework.cloud.client.loadbalancer.reactive.OnNoRibbonDefaultCondition]

  • SpringCloud
<dependencyManagement>
      <dependencies>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-dependencies</artifactId>
              <version>Hoxton.SR5</version>
              <type>pom</type>
              <scope>import</scope>
          </dependency>
      </dependencies>
</dependencyManagement>
  • OpenFeign
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
	<version>2.2.6.RELEASE</version>
</dependency>

2 Usage

2.1 服务A-工单服务

2.1.0 启动类

启动类中添加注解@EnableFeignClients,打开Feign,服务间进行Http调用.

package com.personal.microspersonalworkorder;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @author xdq
 * @description Service Start.
 * @since 2020/6/18
 */
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class MicrospersonalWorkorderApplication {
	static Logger logger = LoggerFactory.getLogger(MicrospersonalWorkorderApplication.class);
	
	public static void main(String[] args) {
		SpringApplication.run(MicrospersonalWorkorderApplication.class, args);
		logger.info("WORKORDER启动");
	}
}

2.1.2 接口类

在发起调用的服务A中,配置被调用服务的应用和URI,发起调用的服务接口如下:
参数属性如下表:
@FeignClient(value,path)

序号属性描述
1value被调用的服务B应用名称,即配置文件中(*.yml)的application:name:micros-user
2path被调用的服务B的servlet路径,即配置文件中(*.yml)的servlet: context-path: /user,如没有配置,则省略参数path

@RequestMapping(value)
value为服务B的完整URI.
方法中的参数前添加@RequestBody或@RequestParam,与被调用的服务B中接口完全一致.

package com.personal.microspersonalworkorder.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.Map;

/**
 * @author xdq
 * @description Call user service
 * @since 2020/6/18
 */
@FeignClient(value="micros-user",path="user")
public interface MicrospersonalUser {
    @RequestMapping("/api/page/user/query")
    Map queryFromUser(@RequestBody Map params);
}

2.1.3 服务类

package com.personal.microspersonalworkorder.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
import com.personal.microspersonalworkorder.feign.MicrospersonalUser;

/**
 * @author xdq
 * @description Service funciton.
 * @since 2020/6/18
 */
@Service
@Transactional
public class UserInfosService {
    @Autowired
    private MicrospersonalUser microspersonalUser;

    public Map getUserInfos(Map params){
        return microspersonalUser.queryFromUser(params);
    }
}

2.2 服务B-人员信息服务

2.2.1 配置文件

配置信息摘要,调用服务B的其他服务需要进行配置的:

序号属性描述
1application:name:micros-user服务应用名称
2servlet:context-path:/user服务B全局路径
spring:
  devtools: 
    restart: 
      enabled: true
  profiles: dev
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/data_repository?useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource
  application: 
    name: micros-user

server:
  port: 8091
  servlet:
    session:
      timeout: PT10S
    context-path: /user
eureka: 
  client: 
    service-url: 
      defaultZone: http://localhost:8090/eureka/eureka

logging: 
  level: 
    root: INFO
  
pagehelper: 
  helperDialect: mysql 
  reasonable: true 
  supportMethodsArguments: true
  params: count=countSql

2.2.1 启动类

package com.personal.microspersonaluser;

import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @author xdq
 * @description Service Start.
 * @since 2020/6/18
 */
@SpringBootApplication
@MapperScan("com.personal.microspersonaluser.mapper")
@EnableSwagger2 
@EnableCaching 
@EnableEurekaClient
@EnableFeignClients
public class MicrospersonalUserApplication extends SpringBootServletInitializer{
    private static Logger logger = LoggerFactory.getLogger(MicrospersonalUserApplication.class);
    @Override 
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application){
        return application.sources(MicrospersonalUserApplication.class);
    }
    public static void main(String[] args){
        SpringApplication.run(MicrospersonalUserApplication.class, args);
        logger.info("USER服务启动");
    }
}

2.2.2 接口类

package com.personal.microspersonaluser.mapper;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import com.personal.microspersonaluser.po.UserInfos;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author xdq
 * @description Interface.
 * @since 2020/6/6
 */
public interface UserInfosMapper {
    public Integer addUser(UserInfos params);
    public Integer deleteUser(Integer id );
    public Integer editUser(UserInfos params);
    public List<UserInfos> queryUser(Map params);
    public UserInfos queryUserWithId(Integer id);
    public UserInfos loginByEmail(String email);
}

2.2.3 服务类

package com.personal.microspersonaluser.service;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.personal.microspersonaluser.mapper.UserInfosMapper;
import com.personal.microspersonaluser.po.UserInfos;

/**
 * @author xdq
 * @description User service.
 * @since 2020/6/6
 */
@Service
@Transactional
public class UserInfosService {
    @Autowired
    private UserInfosMapper userInfosMapper;

    public Integer addUser(UserInfos params){
        return userInfosMapper.addUser(params);
    }
    public Integer deleteUser(Integer id){
        return userInfosMapper.deleteUser(id);
    }
    public Integer editUser(UserInfos params){
        return userInfosMapper.editUser(params);
    }
    public List queryUser(Map params){
        return userInfosMapper.queryUser(params);
    }

    public UserInfos queryUserWithId(Integer id){
        return userInfosMapper.queryUserWithId(id);
    }
    public UserInfos loginByEmail(String email){
        return userInfosMapper.loginByEmail(email);
    }
}

2.2.4 控制器类

package com.personal.microspersonaluser.controller;

import com.personal.microspersonaluser.po.UserInfos;
import java.util.Map;
import java.util.HashMap;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.stereotype.Controller;
import org.springframework.http.ResponseEntity; 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.personal.microspersonaluser.service.UserInfosService;

/**
 * @author xdq
 * @description 用户信息API及页面加载.
 * @date 2020/6/6
 */

@CrossOrigin(origins="*", maxAge=3600)
@Controller 
@RequestMapping("/api/page")
public class PageController {
    static Logger logger = LoggerFactory.getLogger(PageController.class);
    @Autowired
    private UserInfosService userInfosService;
    
    @RequestMapping(value="/user/query", method=RequestMethod.POST)
    @ResponseBody
    public Map queryUser(@RequestBody Map params){
        Map returnMap = new HashMap();
        List resFlag = userInfosService.queryUser(params);
        returnMap.put("code", 200);
        returnMap.put("msg", "成功添加");
        returnMap.put("datas", resFlag);
        return returnMap;
    }
}

服务A与服务B的函数名称可以不同.

3 Q&A

  • org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.choose
    原因:Eureka中没有loadbalancer
    方案:移除Eureka的ribbon,添加loadbalancer依赖。
<!-- 服务注册和发现、客户端负载均衡、熔断 -->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
	<exclusions>
		<exclusion>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
		</exclusion>
	</exclusions>
	<version>2.2.3.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>

【参考文献】
[1]https://www.cnblogs.com/huangjuncong/p/9053576.html
[2]https://blog.csdn.net/qq_42815754/article/details/93341709
[3]https://blog.csdn.net/qq_29235677/article/details/91994857#feign%E6%96%B9%E5%BC%8F%E5%AE%9E%E7%8E%B0%E6%9C%8D%E5%8A%A1%E9%97%B4%E7%9A%84%E8%B0%83%E7%94%A8
[4]https://www.cnblogs.com/a8457013/p/8290119.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值