第六篇:【Spring Cloud】RestTemplate FeignClient使用

  • RestTemplate使用方式

1.創建user項目 pom文件見如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cohesion</groupId>
    <artifactId>spring-cloud-user</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-cloud-user</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <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-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>  
           <groupId>com.alibaba</groupId>  
           <artifactId>fastjson</artifactId>  
           <version>1.2.15</version>  
        </dependency>
        <dependency>
            <groupId>com.github.miemiedev</groupId>
            <artifactId>mybatis-paginator</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.3</version>
        </dependency>
        <dependency>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
            <version>0.9.4</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

 

 

2.標記自己是消費者

package com.cohesion;

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

@SpringBootApplication
@EnableEurekaClient//標記自己是消費者
public class SpringCloudUserApplication {

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

3.修改配置文件 application.yml文件

server:
  port: 8083

spring:
  application:
    name: service-user

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8080/eureka/

service:
  url:
    order: service-order#訂單服務

 

4.創建UserController

package com.cohesion.user.rest;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.cohesion.entity.ResponseModel;
import com.cohesion.util.ApiUtils;
import com.cohesion.util.RemoteLoad;
@RestController
public class UserController extends RemoteLoad{
    
    @Value("${service.url.order}")
    private String serviceOrderUrl;    
 
    @RequestMapping(value="/testRestTemplate")
    public ResponseModel testRestTemplate(HttpServletRequest request){
         HashMap<String, Object> par = new HashMap<String, Object>();
        //request值放到HashMap中
        ApiUtils.setRequestPar(request,par);
        //postRestObject參數說明
        //【0】服務名稱 serviceOrderUrl
        //【1】接口地址 /order/getUserOrderInfo
        //【2】返回類型 ResponseModel.class
        //【3】參數類型 par
          ResponseModel res = postRestObject(serviceOrderUrl, "/order/getUserOrderInfo", ResponseModel.class, par);
        return res;
    }
}

5.創建依賴的工具類

ResponseModel

package com.cohesion.entity;

import java.io.Serializable;

public class ResponseModel implements Serializable{
     private static final long serialVersionUID = 5285476448351872035L;
      private int status;
      private String msg;
      private Object data;
      private Object perm;
      
      public ResponseModel() {}
      
      public ResponseModel(int status, String msg, Object data)
      {
        this.status = status;
        this.msg = msg;
        this.data = data;
      }
      
      public int getStatus()
      {
        return this.status;
      }
      
      public void setStatus(int status)
      {
        this.status = status;
      }
      
      public String getMsg()
      {
        return this.msg;
      }
      
      public void setMsg(String msg)
      {
        this.msg = msg;
      }
      
      public Object getData()
      {
        return this.data;
      }
      
      public void setData(Object data)
      {
        this.data = data;
      }
      
      public Object getPerm()
      {
        return this.perm;
      }
      
      public void setPerm(Object perm)
      {
        this.perm = perm;
      }
}

 

 UserConfig

package com.cohesion.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class UserConfig {
    
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

ApiUtils

package com.cohesion.util;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

public class ApiUtils {
    //把request中的數據放到map中
    public static void setRequestPar(HttpServletRequest request, HashMap<String, Object> par) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (String key : parameterMap.keySet()) {
            if (parameterMap.get(key) != null && parameterMap.get(key).length == 1) {
                par.put(key, parameterMap.get(key)[0]);
            }
        }
    }
}

RemoteLoad

package com.cohesion.util;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import com.google.common.base.Joiner;
@Component
public class RemoteLoad {
 
    @Autowired
    private RestTemplate rest;
 
    public <T> T postRestObject(String serviceName, String url, Class<T> clazz, Map<String, Object> pars) {
        return postRestObjectRetry(serviceName, url, clazz, pars, 0);
    }

    private <T> T postRestObjectRetry(String serviceName, String url, Class<T> clazz, Map<String, Object> pars,
            Integer retryTime) {
        try {
            T data = rest.postForObject(Joiner.on("").join("http://",serviceName, url), convertPar(pars), clazz);
            return data;
        } catch (Exception e) {
            // TODO: handle exception
            if (retryTime < 3) {
                return postRestObjectRetry(serviceName, url, clazz, pars, retryTime + 1);
            }
            e.printStackTrace();
            return null;
        }
    }
    //把map放到MultiValueMap中 用來傳值
    private MultiValueMap<String, Object> convertPar(Map<String, Object> par) {
        MultiValueMap<String, Object> result = new LinkedMultiValueMap<String, Object>();
        if (par == null) {
            return result;
        }
        for(String key:par.keySet()) {
            result.add(key, par.get(key));
        }
        return result;
    }
    
}

6.驗證

6.1直接方式user服務

現在服務和服務之間調用和傳參已經ok了,我們來看下結果。

這個是直接調用8083 【user】服務的,可以看到我們傳什麼值過去,order服務就返回什麼值回來,表示傳真和服務之間是沒問題的。

 

6.2 通過zuul訪問【user】服務

zuul的配置文件我這邊多了一個user服務,只要是user開頭的請求,都會轉到user服務

server:
  port: 9000

spring:
  application:
    name: service-zuul

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8080/eureka/
   
zuul:
  routes:
    order:
      path: /order/**
      service-id: SERVICE-ORDER
    user:
      path: /user/**
      service-id: SERVICE-USER

 

 

  • FeignClient使用方式

 7.FeignClient

【pom】文件新增一個屬性

<dependency>
            <groupId>org.springframework.cloud</groupId>
</dependency>

8.新增接口文件

FeignClientTest

package com.cohesion.remote;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.cohesion.entity.ResponseModel;

@FeignClient(name = "SERVICE-ORDER")
public interface FeignClientTest {
    
    @GetMapping("/testFeignClient")//這裏是order項目中的接口地址 和接口參數
    ResponseModel productBrandPage(
    @RequestParam(value = "pageIndex", required = false, defaultValue = "1") Integer pageIndex);
}

9.修改userController類 增加對接口的實現

package com.cohesion.user.rest;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.cohesion.entity.ResponseModel;
import com.cohesion.remote.FeignClientTest;
import com.cohesion.util.ApiUtils;
import com.cohesion.util.RemoteLoad;
@RestController
public class UserController extends RemoteLoad{
    
    @Value("${service.url.order}")
    private  String serviceOrderUrl;    
    
    @Autowired
    private FeignClientTest feignClientTest;
    
    @RequestMapping(value="/testRestTemplate")
    public ResponseModel testRestTemplate(HttpServletRequest request){
         HashMap<String, Object> par = new HashMap<String, Object>();
        //request值放到HashMap中
        ApiUtils.setRequestPar(request,par);
        //postRestObject參數說明
        //【0】服務名稱 serviceOrderUrl
        //【1】接口地址 /order/getUserOrderInfo
        //【2】返回類型 ResponseModel.class
        //【3】參數類型 par
          ResponseModel res = postRestObject(serviceOrderUrl, "/order/getUserOrderInfo", ResponseModel.class, par);
        return res;
    }
    
    @RequestMapping(value="/testFeignClient")
    public ResponseModel testFeignClient(HttpServletRequest request){
        Integer pageIndex = Integer.parseInt(request.getParameter("pageIndex"));
        ResponseModel res = feignClientTest.productBrandPage(pageIndex);
        return res;
    }
}

10.修改【order】服務代碼

package com.cohesion.rest;

import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import com.cohesion.entity.ResponseModel;
import com.cohesion.utils.SystemUtils;
 
@RestController
public class OrderController {
    @Value("${server.port}")
    private String port;
    
    @Value("${spring.application.name}")
    private String serviceName;
    
    @RequestMapping(value="/order/helloWord")
    public String helloWord() {
         String returnStr = "您訪問的是:【"+serviceName+"】服務,【端口號】"+port;
        return returnStr;
    }
    
    @RequestMapping(value="/order/getUserOrderInfo")
    public ResponseModel getUserOrderInfo(HttpServletRequest request) {
        ResponseModel responseModel = new ResponseModel(200,"成功",null);
        HashMap<String, Object> par = new HashMap<String, Object>();
        //把request中的參數放到HashMap中
        SystemUtils.setRequestParamater(par, request);
        System.out.println(par.get("id")+request.getParameter("id"));
        //傳怎什麼值過來 就返回怎麼值 檢測服務之間通信是否暢通
        responseModel.setData(par);
        return responseModel;
    }
    
    @RequestMapping(value = "/testFeignClient")
    public ResponseModel testFeignClient(HttpServletRequest request) {
        ResponseModel responseModel = new ResponseModel(200,"成功",null);
        HashMap<String, Object> par = new HashMap<String, Object>();
        //把request中的參數放到HashMap中
        SystemUtils.setRequestParamater(par, request);
         //傳怎什麼值過來 就返回怎麼值 檢測服務之間通信是否暢通
        responseModel.setData(par);
        return responseModel;
    }
    

}

11.驗證

11.1直接訪問user項目 測試Feign

11.2直接訪問ZUUL項目 測試Feign

 

 

可以看到 數據從user傳到order 又把參數帶回來了,表示通信正常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章