程序员的资源宝库

网站首页 > gitee 正文

feign简单使用(feign.)

sanyeah 2024-04-04 11:07:17 gitee 4 ℃ 0 评论

在调用服务的时候,我们常用是RestTemplate,但是这种方式调用时需要凭借url,如果服务的地址或者端口号有变化,我们需要跟着做变动,给开发工作带来不必要的麻烦,

这里引入Feign调用服务接口,这是微服务之间经常使用的调用关联方服务的一种,和Dubbo类似,后期调用就类似于本地方法调用同样的道理

需要的依赖

 <!--引入feign依赖-->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-openfeign</artifactId>
		</dependency>

  

<!--客户端-->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>

  列出我使用的springboot版本和springcloud版本

<dependencyManagement>

		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Hoxton.SR3</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>

			<dependency>
				<groupId>com.alibaba.cloud</groupId>
				<artifactId>spring-cloud-alibaba-dependencies</artifactId>
				<version>2.1.0.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>



		</dependencies>
	</dependencyManagement>

  

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.1.RELEASE</version>
		<relativePath/>
	</parent>

  启动类中需要的注解

@SpringBootApplication
//开启定时任务支持
@EnableAsync()
//设置redis共享
@EnableRedisHttpSession
//开启事务支持
@EnableTransactionManagement
//开启服务发现
@EnableDiscoveryClient
// 开启Feign
@EnableFeignClients

  方法声明

package com.java.api;

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

/**
 * @author yourheart
 * @Description
 * @create 2022-09-07 23:33
 */
@FeignClient(name="ip-service")
public interface QueryIpClient {


    @RequestMapping("/queryIpCity/{ip}")
    @ResponseBody
    public String queryIpCity(@PathVariable String ip);
}

  如何使用

package com.java.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.java.api.QueryIpClient;
import com.java.bean.Paramter;
import com.java.service.ParamterService;
import com.java.service.QueryIp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;

/**
 * @author yourheart
 * @Description
 * @create 2021-06-07 0:05
 */
@Service
public class QueryIpServiceImpl implements QueryIp {

    private static final Logger logger= LoggerFactory.getLogger(QueryIpServiceImpl.class);

    @Autowired
    private ParamterService paramterService;

    @Autowired
    private QueryIpClient queryIpClient;

    /**
     * 判断ip
     *
     * @param model
     * @param remoteHost
     * @param localAddr
     */
    @Override
    public void judgeIp(Model model, String remoteHost, String localAddr) {
        logger.info("remoteHost:{}",remoteHost);
        Paramter paramter=new Paramter();
        paramter.setParamterType("IpAddress");
        paramter.setParamterCode(remoteHost);
        String queryByCode = paramterService.queryByCode(paramter);
        model.addAttribute("icp", queryByCode);
    }


    /**
     * 查询ip地址详细信息
     * @param ip
     * @return
     */
    @Override
    public String queryCityByIp(String ip) {
        logger.info("【Feign方式调用】【查询ip地址详细信息】入参:{}",ip);
        String forObject = null;
        try {
            forObject =queryIpClient.queryIpCity(ip);
            logger.info("【Feign方式调用】【查询ip地址详细信息】返回参数:{}",forObject);
        } catch (Exception e) {
            logger.error("【Feign方式调用】【调用获取ip信息接口异常】");
            return "中国上海上海市";
        }
        JSONObject jsonObject = JSON.parseObject(forObject);
        String city=jsonObject.getString("address");
        logger.info("【Feign方式调用】【查询ip地址详细信息】返回参数:{}",city);
        return city;
    }
}

  application.properties文件配置

spring.application.name=pingan-service
#注册到eureka注册中心,如果是注册到集群就用逗号连接多个,单实例写上一个就好
eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka

  当然你要确保调用的服务是使用了springcloud的形式,或者包装了springcloud的形式

下面给出我调用的服务中配置情况

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.ip</groupId>
    <artifactId>ip-service</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
        <skipTests>true</skipTests>
    </properties>

    <dependencyManagement>

        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>



        </dependencies>
    </dependencyManagement>


    <dependencies>

        <!--客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--tomcat容器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--添加fastjson依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.7</version>
        </dependency>
        <!--lombok依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>

        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--springboot整合mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
        <!-- 热部署模块 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
        </dependency>
        <!--java爬虫需要的jar包-->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.12.2</version>
        </dependency>
        <!--判断空的用法  -->
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.10.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.lionsoul</groupId>
            <artifactId>ip2region</artifactId>
            <version>1.7.2</version>
        </dependency>
         <!--RateLimiter的底层是基于令牌桶算法来实现的,来自谷歌的Guava包中-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.0-jre</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>


            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!--编译插件定义编译细节-->
<!--            <plugin>-->
<!--                <groupId>org.apache.maven.plugins</groupId>-->
<!--                <artifactId>maven-compiler-plugin</artifactId>-->
<!--                <version>3.1</version>-->
<!--                <configuration>-->
<!--                    <source>1.8</source>-->
<!--                    <target>1.8</target>-->
<!--                    <encoding>utf-8</encoding>-->
<!--                    <!–告诉编译器,编译的时候记录下形参的真实名称–>-->
<!--                    <compilerArgs>-->
<!--                        <arg>-parameters</arg>-->
<!--                    </compilerArgs>-->
<!--                </configuration>-->
<!--            </plugin>-->

        </plugins>
        <finalName>server0825</finalName>
    </build>


</project>

  

package com.ip;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @author yourheart
 * @Description
 * @create 2021-06-06 10:34
 */
@SpringBootApplication
@EnableDiscoveryClient
public class CloudPingAnApplication {
    public static void main(String[] args) {
        SpringApplication.run(CloudPingAnApplication.class,args);
    }
}

  

package com.ip.controller.front;

import com.alibaba.fastjson.JSONObject;
import com.ip.service.QueryIpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author yourheart
 * @Description
 * @create 2021-06-06 10:59
 */
@Controller
@RequestMapping("/queryIp")
@Slf4j
public class QueryIpController {

    @Autowired
    private QueryIpService queryIpService;

    @RequestMapping("/queryIpCity/{ip}")
    @ResponseBody
    public String queryIpCity(@PathVariable String ip){
        long a = System.currentTimeMillis();
        JSONObject ipCityByIp = queryIpService.getIpCityByIp(ip);
        String jsonString = ipCityByIp.toJSONString();
        long b = System.currentTimeMillis();
        log.info("接口调用耗时:{}",(b-a)+"ms");
        return jsonString;
    }
}

  其中

queryIpService.getIpCityByIp(ip);可以自己写实现
同时对于调用方式给出使用测试类方式测试
结果报错
feign.RetryableException: iZuf627hz8vloz1wtzgxzdZ executing GET http://ip-service/queryIpCity/116.230.165.108

	at feign.FeignException.errorExecuting(FeignException.java:249)
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:120)
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:80)
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
	at com.java.ApiTest.test(ApiTest.java:27)
	at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
	at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
Caused by: java.net.UnknownHostException: iZuf627hz8vloz1wtzgxzdZ
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
	at feign.Client$Default.convertResponse(Client.java:78)
	at feign.Client$Default.execute(Client.java:74)
	at org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer.execute(FeignLoadBalancer.java:93)
	at org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer.execute(FeignLoadBalancer.java:56)
	at com.netflix.client.AbstractLoadBalancerAwareClient$1.call(AbstractLoadBalancerAwareClient.java:104)
	at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:303)
	at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:287)
	at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:231)
	at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:228)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:286)
	at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.onNext(OnSubscribeConcatMap.java:144)
	at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:185)
	at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94)
	at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42)
	at rx.Observable.unsafeSubscribe(Observable.java:10327)
	at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1.call(OperatorRetryWithPredicate.java:127)
	at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:73)
	at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.schedule(TrampolineScheduler.java:52)
	at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:79)
	at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:45)
	at rx.internal.util.ScalarSynchronousObservable$WeakSingleProducer.request(ScalarSynchronousObservable.java:276)
	at rx.Subscriber.setProducer(Subscriber.java:209)
	at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:138)
	at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:129)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
	at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
	at rx.Observable.subscribe(Observable.java:10423)
	at rx.Observable.subscribe(Observable.java:10390)
	at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:443)
	at rx.observables.BlockingObservable.single(BlockingObservable.java:340)
	at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:112)
	at org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:83)
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:110)
	... 21 more

  下面给出解决方案,见后续补充地址,其实这里使用Feign调用并没有成功,拿到的事服务器的实例名,并不是服务的信息

下面给Feign添加日志打印

package com.java.config;

import com.java.log.MyFeignLogger;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description:
 * @Author: Yourheart
 * @Create: 2022/9/16 13:30
 */
@Configuration
public class FeignConfig {

    /**
     * NONE【性能最佳,适用于生产】:不记录任何日志(默认值)
     * BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间
     * HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
     * FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数 据
     * @return
     */
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.FULL;
    }


}

  

#设置Feign的日志级别
logging.level.com.java.config.FeignConfig = DEBUG

  报错显示如下

 调整服务提供者的配置文件为

eureka.instance.prefer-ip-address=true
eureka.instance.hostname=127.0.0.1
eureka.instance.instance-id=${eureka.instance.hostname}:${server.port}

 然后记录调用的时候,路径要写完整

@FeignClient(value="ip-service-query")
@RequestMapping("/queryIp")
public interface QueryIpClient {


    @RequestMapping("/queryIpCity/{ip}")
    @ResponseBody
    public String queryIpCity(@PathVariable String ip);
}

  

 

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表