微服务的spring cloud远程调用,消费端和服务端公用接口的坑

spring cloud 远程调用接口是微服务常用架构。
我这次要将 消费者服务端公用接口来实现。
为什么要通过实现接口,来对应远程服务:
1.如果实现的controller不写@RequestMapping去重新定义路径,就不会有路径出错问题。
2.接口在是谁实现的也可以轻易的找到。阅读代码和调试都要容易的多。

版本:spring boot:2.45,spring-cloud 2020.0.0

服务端

错误1:请求的自己本身的地址

2021-06-23 22:24:55.061 INFO [DiscoveryClient-CacheRefreshExecutor-0] [RedirectingEurekaHttpClient.execute:93] 93 - Request execution error. endpoint=DefaultEndpoint{ serviceUrl='http://localhost:10000/eureka/} exception=I/O error on GET request for "http://localhost:10000/eureka/apps/": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect stacktrace=org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:10000/eureka/apps/": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785)

错误2:重复注册错误

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'com.zb.rpc.IGameToGateway' method 
com.zb.rpc.IGameToGateway#getServerBase(Integer)
to { [/rpcReq/getServerBase/{id}]}: There is already 'configController' bean method
com.zb.gateway.controller.ConfigController#getServerBase(Integer) mapped.

这两个错误属于一个问题。
我们使用了公共的接口:com.zb.rpc.IGameToGateway。而服务端的实现controller继承了IGameToGateway

接口代码:

@FeignClient(name = "gateway")
@RequestMapping(value = "/rpcReq")
public interface IGameToGateway {

	@RequestMapping(value = "/say/{id}")
	String say(@PathVariable("id") Integer id);
}

继承实现的Controller:

@Controller
// 这里可以不继承接口,继承只是为了好找实现在哪。判定去哪主要是@RequestMapping(value = "")value值一样即可
public class ConfigController implements IGameToGateway {

	//这里会默认继承接口的注解,不要再自己写了
	@ResponseBody
	public String say(Integer id) {
		String str = "say:" + id;
		System.out.println(str);
		return str;
	}
}

因为服务端本身会加载实现类。而接口@FeignClient注解会再创造一个远程代理。就会导致报错。因为代码并不认识这个代理其实是我本身实现的。我自己就不用再实现了,他会在创建一个,那么路径必然相同报错。

主要解决思路为:项目启动时,服务端不再为这个接口创建远程代理即可。

解决方式为:接口所在的包,不会被主启动类自动加载。即@SpringBootApplication注解所在的类下的子包不含有IGameToGateway 接口。

*注意点:*不能用@SpringBootApplication注解带的exclude字段,那样实现的conctroller类也不能用了。

消费端

因为如果共用接口是在本包目录下。那么就会可以加载到,但是因为接口是公用的。这么写会比较混乱。
解决方式为:@EnableFeignClients(basePackages = { "com.zb.rpc" }),这样即使不在当前包的范围也能引用到。可以比较完美的解决。

例子

服务端的包以及启动类注解
com.zb.gateway

	@SpringBootApplication
	@EnableFeignClients
	@EnableDiscoveryClient
	@EnableEurekaClient

消费端的包。
com.zb.game

	@EnableFeignClients(basePackages = { "com.zb.rpc" })
	@EnableDiscoveryClient
	@SpringBootApplication

共享项目的包。
com.zb.rpc
无启动类:接口写在这个包下。

这里主要记录遇到的坑以及解决。代码实现会在其他文章发布。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值