Feign访问外部http请求
大家好,目前接手了一个项目,具体的逻辑并不复杂,主要是一个"中间商"角色, 比如客户端通过我访问高德地图API,就不需要带秘钥,直接带高德API所需的入参和url后缀,就可以访问。
目前遇到这样一个问题,项目架构师要求所有的项目自己写的htttpClintUtils或者其他工具,需要替换到feign的形式来完成调用,但是,目前这个项目访问外部的http接口很多,比如,提供的高德服务就有10多种,一共有大几十类型,这样的话,如果按照以前的方式,一个接口指定一个高德子服务,那岂不是要累死 = =!
累死人的写法:(仅参考)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@FeignClient (value = "test" ,url = "http://ip:port" ) public interface TestFeign { /** * @return 高德服务接口 * @description 访问高德地理编码服务 */ @PostMapping (value = "/Amap/geo" ) Object geo( @RequestBody GeoEntity entity); /** * @return 高德服务接口 * @description 访问高德逆地理编码服务 */ @PostMapping (value = "/Amap/regeo" ) Object regeo( @RequestBody RegeoEntity entity); ......... ........... } |
然后如果我除了高德服务还有其他外部服务,并且其他外部服务下的子接口,不一定就两个,那这样写的话,要头大死,并且这样的写法,在服务的内部,不能做秘钥和权限的动态配置,只能在url上做指定,比较笨拙,所以就需要一种可以灵活访问外部httpClient的Feign接口,只需要我指定一个url,指定下提交的post数据,就可以得到返回结果,岂不是美滋滋?
话不多说,先上pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
< dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-starter-openfeign</ artifactId > < version >2.0.1.RELEASE</ version > </ dependency > < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-starter-netflix-hystrix</ artifactId > < version >2.0.1.RELEASE</ version > </ dependency > <!-- 引入 httpclient --> < dependency > < groupId >org.apache.httpcomponents</ groupId > < artifactId >httpclient</ artifactId > </ dependency > < dependency > < groupId >com.netflix.feign</ groupId > < artifactId >feign-httpclient</ artifactId > < version >8.18.0</ version > </ dependency > |
前两个是feign和服务降级用到的包,后两个是用Apache Http替换原生的feign-http-client用来提供连接池等功能。
bootstap.yml 部分配置
1
2
3
4
5
6
7
8
9
10
11
12
|
feign: httpclient: enabled: true hystrix: enabled: true hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 3000 #降级超时时间,我设置为3秒。 feign.retry默认超时时间是5s. |
设置了个降级超时时间,还有启动了feign访问外部httpClient配置和服务降级配置。
在spingbootApplication启动类上增加注解
@EnableFeignClients
@EnableHystrix
代码部分:
1
2
3
4
5
6
7
|
public interface HttpRequestFeign { @RequestLine ( "GET" ) String sendGetRequest(URI baseUri); @RequestLine ( "POST" ) String sendPostRequest(URI baseUri, Map map); } |
调用部分,这里我在我的BaseController构造注解,其他服务Controller继承,提供调用能力:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@Autowired public BaseController(Decoder decoder, Encoder encoder) { httpRequestFeign = Feign.builder().encoder(encoder).decoder(decoder) .target(Target.EmptyTarget.create(HttpRequestFeign. class )); } protected String httpPostSend( String url, Map map) { String response = "" ; try { response = httpRequestFeign.sendPostRequest( new URI(url), map); logger.info( "调用外部服务返回的数据为->{}" , response); // 这里改成重试的超时异常 } catch (RetryableException a) { logger.error( "调用外部服超时错误->{}" , response); } catch (Exception e) { logger.error( "调用外部服异常错误->{}" , response); } return response; } |
这里只列举了Post的,Get方式,就不用了携带map参数了。
然后在你的Controller层增加降级@HystrixCommand注解,并指定降级方法:
1
2
3
4
5
6
7
8
9
10
11
|
@HystrixCommand(fallbackMethod = "fallback") @PostMapping(value = "/1_0_0/{subServer}", produces = "application/json;charset=UTF-8") public Object send(@RequestBody Map< String , Object> map, @PathVariable String subServer) { ....................... .................... private Object fallback(Map< String , String> map, String subserver, Throwable e) { logger.error("xxx服务发生问题,入参:{},地址:{}", map, subserver); return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), ERROR_MSG + e.toString()); } |
在send方法里可以自行进行拼接url,而Map就是传递给第三方服务的数据。
FeignClient外部http请求
springboot 4.0.0
pom.xml 引入openfeign 2.0.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
< dependencyManagement > < dependencies > < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-openfeign</ artifactId > < version >2.0.2.BUILD-SNAPSHOT</ version > < type >pom</ type > < scope >import</ scope > </ dependency > </ dependencies > </ dependencyManagement > < dependencies > <!--外部http请求 FeignClient--> < dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-starter-openfeign</ artifactId > </ dependency > </ dependencies > < repositories > <!--外部http请求 FeignClient--> < repository > < id >spring-snapshots</ id > < name >Spring Snapshots</ name > < url >https://repo.spring.io/libs-snapshot</ url > < snapshots > < enabled >true</ enabled > </ snapshots > </ repository > </ repositories > |
启动类 添加注解@EnableFeignClients
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@SpringBootApplication @MapperScan ( "com.sichuang.repository.dao" ) //将项目中对应的mapper类的路径加进来就可以了 @ServletComponentScan @EnableFeignClients public class RepositoryApplication extends SpringBootServletInitializer{ public static void main(String[] args) { SpringApplication.run(RepositoryApplication. class , args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { // TODO Auto-generated method stub // return super.configure(builder); return builder.sources(RepositoryApplication. class ); } } |
外部接口类。调用方式同service
@RequestParam 参数注解
produces = MediaType.APPLICATION_JSON_UTF8_VALUE 返回json参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package com.sichuang.repository.api; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.Map; /** * 对接接口 * * @author xs * @date 2018/10/8 9:08 */ @FeignClient (url = "${url}" , name = "Ewaytec2001API" ) public interface Ewaytec2001API { /** */ @GetMapping (value = "${url}" , produces = MediaType.APPLICATION_JSON_UTF8_VALUE) String getEmployeeInfo( @RequestParam ( "id" ) int id, @RequestParam ( "sign" ) String sign); } |
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/gpdsjqws/article/details/106567397