SpringBoot跨系统调用接口方案

本文介绍在SpringBoot项目中实现系统间调用的三种方法:使用Feign客户端简化远程调用,利用原始httpClient进行HTTP请求,以及采用RestTemplate进行GET和POST请求。文章详细解释了每种方案的实现步骤,包括依赖添加、接口定义和请求发送。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

      项目开发中存在系统之间互调问题,又不想用dubbo,这里提供几种springboot方案:

1、使用Feign进行消费(推荐)
2、使用原始httpClient请求
3、使用RestTemplate方法

二、方案

方案一:使用Feign进行消费(推荐)

1、在maven中添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.2.2</version>
</dependency>

2、启动类上加上@EnableFeignClients

@EnableHystrix
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.aaa.aurora"})
@SpringBootApplication
@EnableTransactionManagement
@ComponentScan(basePackages = "com.aaa.aurora")
@ImportResource(locations= {"classpath:spring.xml","spring-security.xml"})
@MapperScan("com.aaa.aurora.mapper")
public class AuroraWebApplication {
   public static void main(String[] args) {
         SpringApplication.run(AuroraWebApplication.class, args);
     }
}

3、编写service接口

@FeignClient(url = "${pangu.url}",name = "panguUrl")
public interface PanGuService {
    @RequestMapping(value = "/pangu/restful/check",method = RequestMethod.POST)
    JSONObject check(@RequestParam(name="queryEngine") String queryEngine, @RequestParam(name="querySql") String querySql, @RequestParam(name="jobNo") String jobNo);
}

其中:pangu.url是配置在application.properties中的ip及端口
pangu.url = 192.168.1.3:8080
/pangu/restful/check是要调的接口名

4、代码中调用

    @Autowired
    private PanGuService panGuService;

    JSONObject jsonObject = null;
    try {
         jsonObject = panGuService.auroraPriviledge(PRESTO_DRIVER, query.get("sql"), user.getWorkNo());
    } catch (Exception e) {
        throw new Exception("请求系统异常");
    }
    if (PANGU_FAIL.equals(jsonObject.get("code"))) {
        LOG.info(jsonObject.get("msg").toString());
        throw new BusinessException(jsonObject.get("msg").toString());
    }

方案二:使用原始httpClient请求

使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。
1. 创建HttpClient对象。
2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
6. 释放连接。无论执行方法是否成功,都必须释放连接。

public JSONObject doPost(String queryEngine, String querySql, String jobNo) {
        JSONObject jsonObject = null;
        //1.创建httpClient对象
        CloseableHttpClient client = HttpClients.createDefault();
        //2.创建请求方法的实例,并指定请求URL
        String url = "http://192.168.1.11:8080";
        HttpPost post = new HttpPost(url);
        post.setHeader("Content-Type", "application/json;charset=utf8");
        //3.参数
        AuroraPriviledge auroraPriviledge = new AuroraPriviledge();
        auroraPriviledge.setQueryEngine(queryEngine);
        auroraPriviledge.setQuerySql(querySql);
        auroraPriviledge.setJobNo(jobNo);
        String jsonString = JSON.toJSONString(auroraPriviledge);
        StringEntity entity = new StringEntity(jsonString, "UTF-8");
        post.setEntity(entity);
        //4.调用execute,返回response
        CloseableHttpResponse response = null;
        try {
            response = client.execute(post);
            HttpEntity responseEntity = response.getEntity();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return jsonObject;
    }

方案三:使用RestTemplate方法

1.get请求:getForObject(...)和getForEntity(...)两个方法,区别在于前者直接返回预期的对象,即返回体中的body对象,后者返回的是ResponseEntity封装类,里面包含了HTTP请求的头信息。

2.post请求:与get请求类似,只是多一个request参数,request对象会作为httpEntity进行处理。

package com.yyy.aurora;

import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

/**
 * Description
 *
 * @author Bob
 * @date 2020/4/15
 **/
public class TestRest {
    public static void main(String[] args) {
        RestTemplate restTemplate = new RestTemplate();
        //get请求
        //方法一:getForEntity(String url, Class<T> responseType, Object... uriVariables),没有参数
        String url = "https://restapi.amap.com/v3/ip?key=075b6eddd825148a674dfa8a8558ac62";
        ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
        System.out.println(forEntity);
        // <200,{"status":"1","info":"OK","infocode":"10000","province":"上海市","city":"上海市","adcode":"310000","rectangle":"120.8397067,30.77980118;122.1137989,31.66889673"},{Server=[Tengine], Date=[Sat, 18 Apr 2020 02:47:38 GMT], Content-Type=[application/json;charset=UTF-8], Content-Length=[167], Connection=[close], X-Powered-By=[ring/1.0.0], gsid=[011130051098158717805837600019751129378], sc=[0.071], Access-Control-Allow-Origin=[*], Access-Control-Allow-Methods=[*], Access-Control-Allow-Headers=[DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,key,x-biz,x-info,platinfo,encr,enginever,gzipped,poiid]}>

        String s = restTemplate.getForObject(url, String.class);
        System.out.println(s);
        // {"province":"上海市","city":"上海市","adcode":"310000","infocode":"10000","rectangle":"120.8397067,30.77980118;122.1137989,31.66889673","status":"1","info":"OK"}

        //方法一:getForEntity(String url, Class<T> responseType, Object... uriVariables),url中用占位符,传入参数
        //该方法提供了三个参数,其中var1为请求的地址(即url),var2为请求响应body的包装类型,var3为url中的参数绑定
        url = "https://restapi.amap.com/v3/ip?key={?}";
        forEntity = restTemplate.getForEntity(url, String.class, "075b6eddd825148a674dfa8a8558ac62");

        //方法二:getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables),map传参
        url = "https://restapi.amap.com/v3/ip?key={key}";
        Map<String, Object> map = new HashMap<>();
        map.put("key", "075b6eddd825148a674dfa8a8558ac62");
        forEntity = restTemplate.getForEntity(url, String.class, map);

        //方法三:getForEntity(URI url, Class<T> responseType),uri传参
        URI uri = URI.create("https://restapi.amap.com/v3/ip?key=075b6eddd825148a674dfa8a8558ac62");
        forEntity = restTemplate.getForEntity(uri, String.class);

        //post请求,与get请求类型,只是多一个必填request对象
        //postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables)
        forEntity = restTemplate.postForEntity(url, null, String.class, "075b6eddd825148a674dfa8a8558ac62");

        s = restTemplate.postForObject(url, null, String.class, "075b6eddd825148a674dfa8a8558ac62");
    }
}

完整的post请求:

		try{
			SimpleClientHttpRequestFactory rf = new SimpleClientHttpRequestFactory();
			//设置请求超时
			rf.setConnectTimeout(3000);
			rf.setReadTimeout(30000);e
			RestTemplate restTemplate = new RestTemplate(rf);
			HttpHeaders headers = new HttpHeaders();
			//请求type
			headers.setContentType(MediaType.APPLICATION_JSON);
			//返回type
			headers.add("accept",MediaType.APPLICATION_JSON.toString());
			String url = "http://ip:port/rest/11111";
			Map<String,Object> map = new HashMap<>();
			map.put("no","426335367373");
			HttpEntity<String> httpEntity = new HttpEntity<String>(JSONObject.toJSONString(map),headers);
			String result = restTemplate.postForObject(url,httpEntity,String.class);
			log.info("res:{}",JSONObject.toJSONString(result))
		}catch (Exception e){
			log.error(e);	
		}

避免每次都要new restTemplate,可以用下面注入的方式:

@Configuration
public class RestTemplateConfig {

   @Bean
   public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
       return new RestTemplate(factory);
   }

   @Bean
   public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
       SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
       factory.setReadTimeout(3000); // ms
       factory.setConnectTimeout(30000); // ms
       return factory;
   }
}

service中直接注入即可:

@Autowired
private RestTemplate restTemplate;

参考:

Spring-Boot 访问外部接口的几种方案总结_polo2044的博客-优快云博客_springboot调用外部接口

Spring Boot实现跨系统接口调用_henry_ying的博客-优快云博客

HttpClient详细使用示例_justry_deng的博客-优快云博客_httpclient

HttpClient用法--这一篇全了解(内含例子)_Franco蜡笔小强的博客-优快云博客_httpclient

Springboot之restTemplate配置及使用_L-960的博客-优快云博客_springboot配置resttemplate

https://www.jb51.net/article/226111.htm 

### Spring Boot 中的内部接口调用方法 在微服务架构中,Spring Boot 提供了多种方式用于实现服务间的通信。以下是几种常见的内部接口调用方法及其示例。 #### 1. 使用 RestTemplate 进行 HTTP 请求 `RestTemplate` 是一种简单易用的方式来进行 HTTP 调用。它可以通过 GET、POST 等请求方法访问其他服务的 API 接口[^2]。 ```java import org.springframework.web.client.RestTemplate; @RestController public class InternalController { @Autowired private RestTemplate restTemplate; @GetMapping("/internal-call") public String callInternalService() { String url = "http://localhost:8081/external-service"; return restTemplate.getForObject(url, String.class); } } ``` 上述代码展示了如何通过 `RestTemplate` 向另一个服务发送 GET 请求并获取响应数据。 --- #### 2. 使用 WebClient 实现反应式编程风格 `WebClient` 是基于 Project Reactor 的现代替代方案,支持异步和非阻塞操作。它是 Spring 5 引入的新特性之一。 ```java import reactor.core.publisher.Mono; import org.springframework.web.reactive.function.client.WebClient; @RestController public class ReactiveController { private final WebClient webClient; public ReactiveController(WebClient.Builder builder) { this.webClient = builder.baseUrl("http://localhost:8081").build(); } @GetMapping("/reactive-call") public Mono<String> reactiveCall() { return webClient.get() .uri("/external-service") .retrieve() .bodyToMono(String.class); } } ``` 此代码片段说明了如何利用 `WebClient` 执行反应式的 HTTP 请求。 --- #### 3. 利用 Feign 客户端简化声明式 REST 调用 Feign 是一个声明式的 Web Service 客户端,能够帮助开发者轻松发起 HTTP 请求。只需定义接口即可完成复杂的远程调用逻辑[^1]。 ```java @FeignClient(name = "service-provider", url = "http://localhost:8081") public interface ServiceProviderClient { @GetMapping("/data") String fetchData(); } @RestController public class FeignController { @Autowired private ServiceProviderClient serviceProviderClient; @GetMapping("/feign-call") public String feignCall() { return serviceProviderClient.fetchData(); } } ``` 这段代码展示了一个典型的 Feign 客户端配置过程以及其使用场景。 --- #### 4. 验证开放接口的安全性 (可选) 如果涉及外部系统的交互或者存在安全风险,则需要对接口实施签名机制以保障安全性[^4]。通常情况下,这种需求适用于对外暴露的服务而非完全封闭环境下的内部调用。 ```java // 假设我们有一个简单的加密工具类 EncryptUtil 来生成 MD5 或 HMAC-SHA 密钥 String timestamp = System.currentTimeMillis() + ""; String secretKey = "your_secret_key_here"; Map<String, Object> params = new HashMap<>(); params.put("timestamp", timestamp); String sign = EncryptUtil.generateSign(params, secretKey); // 自定义函数 params.put("sign", sign); restTemplate.postForEntity("http://example.com/api", params, Void.class); ``` 以上代码实现了基本参数加签流程,确保每次请求携带合法校验信息。 --- ### 注意事项 - **性能优化**:对于高并发场景下推荐优先考虑 `WebClient` 替代传统同步模式。 - **容错处理**:无论采用哪种技术栈都应加入必要的异常捕获与重试策略。 - **负载均衡**:当目标地址可能发生变化时可以集成 Ribbon 组件自动管理多个实例分布情况。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值