zoukankan      html  css  js  c++  java
  • IDEA项目搭建七——使用Feign简化消费者端操作

    一、简介

    我们可以看到上一篇文章的消费者这边调用Service时比较麻烦,所以我们可以使用Feign来简化这部分操作,它底层也是使用Ribbon实现的只是Ribbon支持HTTP和TCP两种通信协议,而Feign只支持HTTP一种,同样支持负载均衡,所以能满足90%以上的需求了。

    二、搭建生产者模块

    其实这部分是通用的,对于消费者这边使用什么Client并没有影响,Eureka还是使用之前搭建好的,生产者模块也用搭建好的,我们新建一个controller用于承接service,这边就算完成了

    import javademo.tyh.model.hotel.BaseInfoModel;
    import javademo.tyh.model.hotel.ResponseModel;
    import javademo.tyh.model.hotel.SearchModel;
    import javademo.tyh.service.hotel.service.HotelService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.List;
    
    @Controller
    @RequestMapping("/api/hotel")
    public class HotelController {
    
        //自动注入请求对象,查看header信息
        @Autowired
        HttpServletRequest request;
    
        @Autowired
        HotelService service;
    
        @ResponseBody
        @RequestMapping("/test")
        public void test() {
            //do something...
        }
    
        @ResponseBody
        @RequestMapping("/get")
        public BaseInfoModel get(@RequestParam(defaultValue = "0") int id) {
            String tyh = request.getHeader("taiyonghai");//获取Header头信息
            System.out.println("参数为:" + id);
            return service.get(id);
        }
        //设置参数为@RequestBody可以自动序列化为对象
        @ResponseBody
        @RequestMapping("/list")
        public ResponseModel<List<BaseInfoModel>> list(@RequestBody SearchModel search) {
            System.out.println("参数为:" + search.getName());
            List<BaseInfoModel> list = service.list();
            ResponseModel<List<BaseInfoModel>> respModel = new ResponseModel<>();
            respModel.setCode("000000");
            respModel.setMsg("操作成功");
            respModel.setData(list);
            return respModel;
        }
    }

    添加通用Model实体,同样不生成get/set方法,自己生成吧

    import com.baomidou.mybatisplus.annotations.TableName;
    import java.time.LocalDateTime;
    
    @TableName("base_info")
    public class BaseInfoModel {
        private int id;
        private String nickname;
        private LocalDateTime updateTime;
    }
    public class SearchModel {
        private int id;
        private String name;
    }
    public class ResponseModel<T> {
        private String code;
        private String msg;
        private T data;
    }

      

     三、搭建消费者模块——Feign

    还是创建一个Maven模块,看一下我的项目结构

      

    1、修改pom.xml文件,增加对spring boot、spring cloud、feign的引用 

        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>2.0.3.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Finchley.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        <dependencies>
            <!-- import spring boot -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!-- import openfeign -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>

      2、新建resources文件夹,新建application.yml配置文件,并修改内容如下

    #设置自己的程序名称
    spring:
      application:
        name: javademo-tyh-web-hotel
      #thymeleaf 配置
      thymeleaf:
        encoding: UTF-8
        prefix: classpath:/templates
        cache: false
    #服务注册中心地址(刚刚搭建的Eureka Server的地址)
    eureka:
      client:
        #是否向服务中心注册自己
        register-with-eureka: false
        #设置eureka服务中心的地址
        service-url:
          defaultZone: http://localhost:11000/eureka
    #设置自己启动的端口
    server:
      port: 13000

     3、修改main()方法的类,增加Feign的注解

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    
    //引入Feign注解
    @EnableFeignClients
    @SpringBootApplication
    public class AppWebHotel {
        public static void main(String[] args) {
            SpringApplication.run(AppWebHotel.class, args);
        }
    }

     4、新建service文件夹,新建HotelService的Interface用来执行Feign向后端服务生产者的调用,指明服务生产者名称,接口方法指明具体的服务路由,这种方式比Ribbon简单很多,而且更直观更像调用后台方法

    import javademo.tyh.model.hotel.BaseInfoModel;
    import javademo.tyh.model.hotel.ResponseModel;
    import javademo.tyh.model.hotel.SearchModel;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.stereotype.Service;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import java.util.List;
    
    @Service
    @FeignClient("javademo-tyh-service-hotel")//指明服务生产者名称
    @RequestMapping("/api/hotel")//此位置的mapping与controller上的mapping是共享全局唯一的,如果这里的名字和controller的路由相同会报错ambiguous mapping
    public interface HotelService {
    //    //无参数无返回值
    //    @RequestMapping("/test")
    //    void test();
        //基础类型参数
        @RequestMapping("/get")
        BaseInfoModel get(@RequestParam("id") int id);
    
        //自定义类型参数以及泛型返回值
        @RequestMapping("/list")
        ResponseModel<List<BaseInfoModel>> list(@RequestBody SearchModel search);
    }

      5、新建controller文件夹,新建HotelController的class用来接收页面调用

    import javademo.tyh.model.hotel.BaseInfoModel;
    import javademo.tyh.model.hotel.ResponseModel;
    import javademo.tyh.model.hotel.SearchModel;
    import javademo.tyh.web.hotel.service.HotelService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import java.util.List;
    
    @Controller
    @RequestMapping("/hotel")
    public class HotelController {
    
        //自动注入Feign接口对象
        @Autowired
        HotelService service;
    
        @RequestMapping("/get")
        public String get(Model model) {
            //像调用方法一样调用即可实现服务生产者端的调用
            model.addAttribute("model",service.get(1));
            return "/hotel/get";
        }
    
        //直接返回json不写页面了
        @ResponseBody
        @RequestMapping("/list")
        public List<BaseInfoModel> list() {
            SearchModel search = new SearchModel();
            search.setId(1);
            search.setName("taiyonghai");
            ResponseModel<List<BaseInfoModel>> result = service.list(search);
            return result.getData();
        }
    }

     6、在resources文件夹下建立templates及hotel文件夹,新建get.html页面,用来渲染数据

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>this is /hotel/get</h1>
    
    <label th:text="${model.Id}">id</label>
    <label th:text="${model.Nickname}">Nickname</label>
    <label th:text="${model.UpdateTime}">UpdateTime</label>
    
    </body>
    </html>

     OK,现在启动Eureka注册中心、启动服务生产者、启动服务消费者访问http://localhost:13000/hotel/get就可以看到从service取到的结果了

    本应该在这里就完成了,但有时候我们需要在Header头信息中增加些公共内容,在Feign中就可以使用如下方式实现

    在消费者这边的service文件夹下新建FeignInterceptor实现RequestInterceptor接口

    import feign.RequestInterceptor;
    import feign.RequestTemplate;
    import org.springframework.stereotype.Component;
    
    //使用拦截器添加Header头信息
    @Component
    public class FeignInterceptor implements RequestInterceptor {
        @Override
        public void apply(RequestTemplate requestTemplate) {
            System.out.println("调用了FeignInterceptor");
            requestTemplate.header("taiyonghai", "1111111111111");
        }
    }

     Feign的简单使用就OK了

  • 相关阅读:
    long和Long的区别
    C语言的变量的内存分配
    Java蓝桥杯 算法提高 九宫格
    Java实现 蓝桥杯算法提高金明的预算方案
    Java实现 蓝桥杯 算法提高 新建Microsoft world文档
    Java实现 蓝桥杯 算法提高 快乐司机
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
  • 原文地址:https://www.cnblogs.com/taiyonghai/p/9306244.html
Copyright © 2011-2022 走看看