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了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM