spring cloud使用过Eureka怎么进行服务间相互访问

2018-12-10  本文已影响84人  毛于晏

上次我们写到spring cloud的服务治理Eureka(如果还未了解spring cloud eureka的请跳转到spring cloud之Eureka--服务治理, 将一个项目的各个模块给分开, 单独分离成一个项目进行开发, 使各功能各家独立; 然后将所有项目注册到Eureka服务中, 进行统一管理;
我们现在已经达到了服务的统一管理, 那么我们该如果调用各个模块呢 ? 有的人肯定会说, java进行网络请求啊URL 然后设置请求头, 设置参数, 拿到请求地址, 发送请求, 取到返回参数,进行处理, 巴拉巴拉一大堆.....;觉得麻烦又封装了一个请求的工具类, 看似好像简单了许多但是又没考虑到你发送的请求地址怎么处理?写死? 我们可是java高级工程师鸭~ 怎么可能进行硬编码鸭, 下面就进行如何优雅的进行服务之间的相互访问;
下面是我github的一个demo仅供参考,后续我会将spring cloud的内容继续完善;
spring_cloud_demo

叨叨了那么多, 下面进入正题;

1.Feign

Feign, 官方的话我就不说了, 具体大家去官网看; 在使用中, 无非是封装了一个发送网络请求的一个工具, 但是他跟Eureka搭配使用起来就可以动态的调用Eureka服务上的某个服务, 只要指定服务的ID和需要调用的接口; 这里注意下, 仅支持RESTful风格的请求;
这么说, 肯定还是迷糊, 下面我们看看如何去使用Feign

1.1添加Fegin依赖

该依赖在spring cloud 基础上添加,如果还不会请看我之前的一篇文章spring cloud之Eureka--服务治理;

 <!--添加feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>

1.2添加启动注解

spring boot启动类上添加注解: @EnableFeignClients

package cn.cooplan.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

@EnableFeignClients    //开启Feign
@EnableEurekaClient //开启Eureka客户端服务
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

1.3编写Feign接口

这里我们编写Feign的接口, 当spring boot扫描掉@FeignClient注解时, 会为该接口生成代理类;

package cn.cooplan.order.feign;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestMapping;
import pojo.Goods;

/**
 * 订单使用, 用来feign调用goods服务
 * @Author MaoLG
 * @Date 2018/12/8  10:53
 */
//@FeignClient 注解, 注解中的参数为调用Eureka中的服务的名称(ID)
@FeignClient("goods")  //请求Eureka中的服务中goods服务
public interface GoodsFeignClient {

    //该请求方式只支持 RESTful请求方式,
    //此处的    @RequestMapping为springmvc的注解, 借用该注解模仿请求,此处不是controller,请不要搞混
    @RequestMapping("/goods/getGoodsById/{goodsId}")
    //@RequestLine("POST /goods/getGoodsById/{goodsId}")//Feign自己的注解与@RequestMapping效果一样
    public Goods getGoodsById(@RequestParam("goodsId") Integer goodsId);
                              //多个参数
                            (@RequestParam Map<Stirng, Object> param);

}

@FeignClient注解参数的由来,该参数可以在yml文件中自己制定,不指定Eureka会给一个默认值

Feign.jpg
如何设置服务名称:这里不区分大小写
设置服务名称.jpg

1.4调用接口

package cn.cooplan.order.service.impl;

import cn.cooplan.order.feign.GoodsFeignClient;
import cn.cooplan.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import dao.OrderDao;
import dao.OrderGoodsDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import pojo.Goods;
import pojo.Order;
import pojo.OrderGoods;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author MaoLG
 * @Date 2018/12/7  14:03
 */
@Service
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private OrderGoodsDao orderGoodsDao;

    //注入上步编写的Feign接口
    @Autowired
    private GoodsFeignClient goodsFeignClient;

    @Override
    public List<Goods> getOrderInGoods(Integer orderId) {
        OrderGoods o = new OrderGoods();
        o.setOrderId(orderId);
        QueryWrapper queryWrapper = new QueryWrapper(o);
        List<OrderGoods> ogs = orderGoodsDao.selectList(queryWrapper);
        List<Goods> goodses = new ArrayList<>();
        for (OrderGoods og: ogs) {
          /*上面为我自己的业务, 下面这行代码才是调用刚才编写的Feign接口
           * 只要在Feign接口指定好访问的服务和访问URL, 参数写好就行了, 注意只支持RESTful请求风格
           *  如果传递多个参数的话, 可以使用Map接收
           */
            Goods goods = goodsFeignClient.getGoodsById(og.getGoodsId());

            goodses.add(goods);
        }
        return goodses;
    }

1.5效果展示

order服务中的controller

package cn.cooplan.order.controller;

import cn.cooplan.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author MaoLG
 * @Date 2018/12/7  14:00
 */
@RestController
@RequestMapping("/order/")
public class OrderController {
    @Autowired
    private OrderService orderService;

    @RequestMapping("getOrderInGoods")
    public Object getOrderInGoods(Integer orderId){
        return orderService.getOrderInGoods(orderId);
    }
}

调取结果

结果.jpg
如果你返回的最后结果是XML形式, 在你的pom.xml中的Eureka依赖中添加
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
            <!--去除返回xml数据, 去掉后改为json数据-->
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.dataformat</groupId>
                    <artifactId>jackson-dataformat-xml</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

去除xml的依赖, 这个地方是默认返回xml, 我们使用json比较方便;

2.总结

Feign的基础用法就是如此, 我个人认为该框架由spring cloud整合进来, 进行了优化, 兼容了springmvc使我们在spring的大环境的背景下减少了我们学习成本, 让我们更加注重于自己业务的开发, 减少了大量重复代码,使我们的代码更有灵活性;(Feign还有负载均衡的效果, 不过后面我会专门介绍一个负载均衡实现的spring cloud中的组件)
下次我会介绍关于,如果我们的一个服务挂掉了,如何不影响其他项目,避免雪崩效应,并进行一些适当的处理;
下面是我github的一个demo仅供参考,后续我会将spring cloud的内容继续完善;
spring_cloud_demo

上一篇下一篇

猜你喜欢

热点阅读