草庐IT

Springboot中调用外部接口的三种方式

Chelsea__ 2024-01-11 原文

目录

1、简介

2、方式一:使用原始httpClient请求

3、方式二:使用RestTemplate方法

Get请求

Post 请求

4、方式三:使用Feign进行消费

在maven项目中添加依赖

启动类上加上@EnableFeignClients

此处编写接口模拟外部接口供feign调用外部接口方式使用

构建Feigin的Service

postman测试

添加Header解决方法




1、简介

SpringBoot不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。在Spring-Boot项目开发中,存在着本模块的代码需要访问外面模块接口,或外部url链接的需求, 比如在apaas开发过程中需要封装接口在接口中调用apaas提供的接口(像发起流程接口submit等等)下面也是提供了三种方式(不使用dubbo的方式)供我们选择

2、方式一:使用原始httpClient请求

 /*
     * @description get方式获取入参,插入数据并发起流程
     * @author lyx
     * @date 2022/8/24 16:05
     * @params documentId
     * @return String
     */
    //
    @RequestMapping("/submit/{documentId}")
    public String submit1(@PathVariable String documentId) throws ParseException {
        //此处将要发送的数据转换为json格式字符串
        Map<String,Object> map =task2Service.getMap(documentId);
        String jsonStr = JSON.toJSONString(map, SerializerFeature.WRITE_MAP_NULL_FEATURES,SerializerFeature.QuoteFieldNames);
        JSONObject jsonObject = JSON.parseObject(jsonStr);
        JSONObject sr = task2Service.doPost(jsonObject);
        return sr.toString();
    }
/*
     * @description 使用原生httpClient调用外部接口
     * @author lyx
     * @date 2022/8/24 16:08
     * @params date
     * @return JSONObject
     */
    public static JSONObject doPost(JSONObject date) {
        String assessToken="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ4ZGFwYXBwaWQiOiIzNDgxMjU4ODk2OTI2OTY1NzYiLCJleHAiOjE2NjEyMjY5MDgsImlhdCI6MTY2MTIxOTcwOCwieGRhcHRlbmFudGlkIjoiMzAwOTgxNjA1MTE0MDUyNjA5IiwieGRhcHVzZXJpZCI6IjEwMDM0NzY2MzU4MzM1OTc5NTIwMCJ9.fZAO4kJSv2rSH0RBiL1zghdko8Npmu_9ufo6Wex_TI2q9gsiLp7XaW7U9Cu7uewEOaX4DTdpbFmMPvLUtcj_sQ";
        CloseableHttpClient client = HttpClients.createDefault();
        // 要调用的接口url
        String url = "http://39.103.201.110:30661 /xdap-open/open/process/v1/submit";
        HttpPost post = new HttpPost(url);
        JSONObject jsonObject = null;
        try {
            //创建请求体并添加数据
            StringEntity s = new StringEntity(date.toString());
            //此处相当于在header里头添加content-type等参数
            s.setContentType("application/json");
            s.setContentEncoding("UTF-8");
            post.setEntity(s);
            //此处相当于在Authorization里头添加Bear token参数信息
            post.addHeader("Authorization", "Bearer " +assessToken);
            HttpResponse res = client.execute(post);
            String response1 = EntityUtils.toString(res.getEntity());
            if (res.getStatusLine()
                    .getStatusCode() == HttpStatus.SC_OK) {
                // 返回json格式:
                String result = EntityUtils.toString(res.getEntity());
                jsonObject = JSONObject.parseObject(result);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return jsonObject;
    }

3、方式二:使用RestTemplate方法

Spring-Boot开发中,RestTemplate同样提供了对外访问的接口API,这里主要介绍Get和Post方法的使用。

  • Get请求

提供了getForObject 、getForEntity两种方式,其中getForEntity如下三种方法的实现:

Get--getForEntity,存在以下两种方式重载

getForEntity(Stringurl,Class responseType,Object…urlVariables)

getForEntity(URI url,Class responseType)

  • Get--getForEntity(URI url,Class responseType)
//该方法使用URI对象来替代之前的url和urlVariables参数来指定访问地址和参数绑定。URI是JDK java.net包下的一个类,表示一个统一资源标识符(Uniform Resource Identifier)引用。参考如下:
RestTemplate restTemplate=new RestTemplate();
UriComponents 
uriComponents=UriComponentsBuilder.fromUriString("http://USER-SERVICE/user?name={name}")
.build()
.expand("dodo")
.encode();
URI uri=uriComponents.toUri();
ResponseEntityresponseEntity=restTemplate.getForEntity(uri,String.class).getBody();
  • Get--getForEntity(Stringurl,Class responseType,Object…urlVariables)
//该方法提供了三个参数,其中url为请求的地址,responseType为请求响应body的包装类型,urlVariables为url中的参数绑定,该方法的参考调用如下:
// http://USER-SERVICE/user?name={name)
RestTemplate restTemplate=new RestTemplate();
Mapparams=new HashMap<>();
params.put("name","dada"); //
ResponseEntityresponseEntity=restTemplate.getForEntity("http://USERSERVICE/user?name={name}",String.class,params);

Get--getForObject,存在以下三种方式重载

getForObject(String url,Class responseType,Object...urlVariables)
getForObject(String url,Class responseType,Map urlVariables)
getForObject(URI url,Class responseType)

getForObject方法可以理解为对getForEntity的进一步封装,它通过HttpMessageConverterExtractor对HTTP的请求响应体body内容进行对象转换,实现请求直接返回包装好的对象内容。

  • Post 请求

Post请求提供有postForEntity、postForObject和postForLocation三种方式,其中每种方式都有三种方法,下面介绍postForEntity的使用方法。

Post--postForEntity,存在以下三种方式重载

postForEntity(String url,Object request,Class responseType,Object...  uriVariables) postForEntity(String url,Object request,Class responseType,Map  uriVariables) postForEntity(URI url,Object request,Class responseType)

如下仅演示第二种重载方式

  /*
     * @description post方式获取入参,插入数据并发起流程
     * @author lyx
     * @date 2022/8/24 16:07
     * @params
     * @return
     */
    @PostMapping("/submit2")
    public Object insertFinanceCompensation(@RequestBody JSONObject jsonObject) {
        String documentId=jsonObject.get("documentId").toString();
        return task2Service.submit(documentId);
    }
/*
     * @description 使用restTimeplate调外部接口
     * @author lyx
     * @date 2022/8/24 16:02
     * @params documentId
     * @return String
     */
    public String submit(String documentId){
        String assessToken="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ4ZGFwYXBwaWQiOiIzNDgxMjU4ODk2OTI2OTY1NzYiLCJleHAiOjE2NjEyMjY5MDgsImlhdCI6MTY2MTIxOTcwOCwieGRhcHRlbmFudGlkIjoiMzAwOTgxNjA1MTE0MDUyNjA5IiwieGRhcHVzZXJpZCI6IjEwMDM0NzY2MzU4MzM1OTc5NTIwMCJ9.fZAO4kJSv2rSH0RBiL1zghdko8Npmu_9ufo6Wex_TI2q9gsiLp7XaW7U9Cu7uewEOaX4DTdpbFmMPvLUtcj_sQ";
        RestTemplate restTemplate = new RestTemplate();
        //创建请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        //此处相当于在Authorization里头添加Bear token参数信息
        httpHeaders.add(HttpHeaders.AUTHORIZATION, "Bearer " + assessToken);
        //此处相当于在header里头添加content-type等参数
        httpHeaders.add(HttpHeaders.CONTENT_TYPE,"application/json");
        Map<String, Object> map = getMap(documentId);
        String jsonStr = JSON.toJSONString(map);
        //创建请求体并添加数据
        HttpEntity<Map> httpEntity = new HttpEntity<Map>(map, httpHeaders);
        String url = "http://39.103.201.110:30661/xdap-open/open/process/v1/submit";
        ResponseEntity<String> forEntity = restTemplate.postForEntity(url,httpEntity,String.class);//此处三个参数分别是请求地址、请求体以及返回参数类型
        return forEntity.toString();
    }

        

4、方式三:使用Feign进行消费

  • 在maven项目中添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.2.2.RELEASE</version>
</dependency>
  • 启动类上加上@EnableFeignClients


@SpringBootApplication
@EnableFeignClients
@ComponentScan(basePackages = {"com.definesys.mpaas", "com.xdap.*" ,"com.xdap.*"})
public class MobilecardApplication {

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

}
  • 此处编写接口模拟外部接口供feign调用外部接口方式使用

定义controller

    @Autowired
    PrintService printService;
 
    @PostMapping("/outSide")
    public String test(@RequestBody TestDto testDto) {
        return printService.print(testDto);
    }

定义service

@Service
public interface PrintService {
    public String print(TestDto testDto);
}

定义serviceImpl

public class PrintServiceImpl implements PrintService {

    @Override
    public String print(TestDto testDto) {
        return "模拟外部系统的接口功能"+testDto.getId();
    }
}
  • 构建Feigin的Service

定义service

//此处name需要设置不为空,url需要在.properties中设置
@Service
@FeignClient(url = "${outSide.url}", name = "service2")
public interface FeignService2 {
    @RequestMapping(value = "/custom/outSide", method = RequestMethod.POST)
    @ResponseBody
    public String getMessage(@Valid @RequestBody TestDto testDto);
}

定义controller

    @Autowired
    FeignService2 feignService2;
    //测试feign调用外部接口入口
    @PostMapping("/test2")
    public String test2(@RequestBody TestDto testDto) {
        return feignService2.getMessage(testDto);
    }
  • postman测试

 此处因为我使用了所在项目,所以需要添加一定的请求头等信息,关于Feign的请求头添加也会在后续补充

补充如下:

添加Header解决方法

将token等信息放入Feign请求头中,主要通过重写RequestInterceptor的apply方法实现

定义config

@Configuration
public class FeignConfig implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        //添加token
        requestTemplate.header("token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ4ZGFwYXBwaWQiOiIzNDgxMjU4ODk2OTI2OTY1NzYiLCJleHAiOjE2NjEyMjY5MDgsImlhdCI6MTY2MTIxOTcwOCwieGRhcHRlbmFudGlkIjoiMzAwOTgxNjA1MTE0MDUyNjA5IiwieGRhcHVzZXJpZCI6IjEwMDM0NzY2MzU4MzM1OTc5NTIwMCJ9.fZAO4kJSv2rSH0RBiL1zghdko8Npmu_9ufo6Wex_TI2q9gsiLp7XaW7U9Cu7uewEOaX4DTdpbFmMPvLUtcj_sQ");
    }
}

定义service

@Service
@FeignClient(url = "${outSide.url}",name = "feignServer", configuration = FeignDemoConfig.class)
public interface TokenDemoClient {
    @RequestMapping(value = "/custom/outSideAddToken", method = RequestMethod.POST)
    @ResponseBody
    public String getMessage(@Valid @RequestBody TestDto testDto);
}

定义controller

//测试feign调用外部接口入口,加上token
    @PostMapping("/testToken")
    public String test4(@RequestBody TestDto testDto) {
        return tokenDemoClient.getMessage(testDto);
    }

有关Springboot中调用外部接口的三种方式的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  4. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

    question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

  5. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  6. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  7. ruby - 调用其他方法的 TDD 方法的正确方法 - 2

    我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent

  8. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  9. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  10. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

随机推荐