使用SpringBoot跨系统调用接口的方案

一、简介

项目开发中存在系统之间互调问题,又不想用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");
 }
}

补充:SpringBoot关于系统之间的远程互相调用

1、SpringBoot关于系统之间的远程互相调用

可以采用RestTemplate方式发起Rest Http调用,提供有get、post等方式。

1、1远程工具类

此处使用Post方式,参考下面封装的HttpClient类 1.1

/**
 * Created by @kai on 2018/12/24/024.
 * Time: 13:54
 * Desc: 远程连接工具类
 */
@Service
public class HttpClient {
​
 /**
 * 根据远程地址发起访问-参数类型为form表单
 * @param url 远程地址
 * @param method 远程方法
 * @param params  方法参数
 * @return
 */
 public Object client(String url,HttpMethod method,MultiValueMap<String,String> params){
  RestTemplate restTemplate = new RestTemplate();
  HttpHeaders headers = new HttpHeaders();
  headers.add("Content-Type", "application/x-www-form-urlencoded");
  HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(params, headers);
  ResponseEntity<String> responseEntity = restTemplate.postForEntity(url,httpEntity,String.class);
  String body = responseEntity.getBody();
  JSONObject jsonObject = JSONObject.parseObject(body);
  return jsonObject.get("data");
 }
​
 /**
 * 根据远程地址发起访问-参数类型为JSON
 * @param url 远程地址
 * @param method 远程方法
 * @param params  方法参数
 * @return
 */
 public Object clientJson(String url,HttpMethod method,Map<String,Object> params){
  RestTemplate restTemplate = new RestTemplate();
  HttpHeaders headers = new HttpHeaders();
  headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
  cn.hutool.json.JSONObject jsonObject = JSONUtil.parseFromMap(params);
  HttpEntity<cn.hutool.json.JSONObject> httpEntity = new HttpEntity<>(jsonObject, headers);
  ResponseEntity<String> responseEntity = restTemplate.postForEntity(url,httpEntity,String.class);
  String body = responseEntity.getBody();
  JSONObject jsonObjectResult = JSONObject.parseObject(body);
  return jsonObjectResult.get("data");
 }
​
}

[ 1.1​]

1、2远程参数说明

工具类中提供了远程过程中传递参数的两种格式:

其中 headers.add("Content-Type", "application/x-www-form-urlencoded") 为form表单格式,支持键值对数据传输;

当参数类型为form表单时,数据需要封装成MultiValueMap<String,String>格式,前台使用controller接受时,可以直接使用 MultiValueMap 变量接收,参照代码如下 1.2

/**
 * 保存分组策略对象
 * @param
 * @return
 */
@RequestMapping(value = "/saveDocGroupPolicy",method = RequestMethod.POST)
public ApiResult saveGroupPolicy(@RequestParam MultiValueMap<String,String> paramMap,@Valid GroupStrategyIO groupStrategyIO){
 Integer userId = ShiroUtil.getExamUserId();
 List<String> userList = new ArrayList<>();
 userList.add(userId+"");
 paramMap.put("userId",userList);
 Object jsonObject = httpClient.client(ExamConfigConstants.url+"/exam/configPolicy/saveDocGroupPolicy", HttpMethod.POST, paramMap);
 return ApiResult.success(jsonObject);
}

[ 1.2] 接受参数为form对象

headers.setContentType(MediaType.APPLICATION_JSON_UTF8) 

为json数据格式

当参数为json格式时,远程服务器接受参数需加上注解@RequestBody,对于复杂参数可以使用对象接受,将对象转为Map,对数据进行加工,再将map转化为JSONObject,参照代码如下:1.3

/**
 * 保存试卷策略
 * @param paperStrategyIO 试卷策略对象
 * @return
 */
@RequestMapping(value = "/savePaperConfig")
public ApiResult savePaperConfig(@RequestBody PaperStrategyIO paperStrategyIO){
 Map<String, Object> paramMap = BeanUtil.beanToMap(paperStrategyIO);
 Integer userId = ShiroUtil.getExamUserId();
 paramMap.put("userId",userId);
 Object jsonObject = httpClient.clientJson(ExamConfigConstants.url+"/exam/paper/savePaperConfigWithMap", HttpMethod.POST, paramMap);
 return ApiResult.success(jsonObject);
}

[ 1.3​] 接收参数为复杂json串

2、后记

关于RestTemplate还有很多可调用的API,可以查看官方网站了解

http://spring.io/blog/2009/03/27/rest-in-spring-3-resttemplate

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • 使用SpringBoot跨系统调用接口的方案

    一.简介 项目开发中存在系统之间互调问题,又不想用dubbo,这里提供几种springboot方案: 1.使用Feign进行消费(推荐) 2.使用原始httpClient请求 3.使用RestTemplate方法 二.方案 方案一:使用Feign进行消费(推荐) 1.在maven中添加依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-st

  • Springboot单体架构http请求转换https请求来支持微信小程序调用接口

    http请求转换https请求 1.话不多说,直接上代码! application.properties配置文件 #(密钥文件路径,也可以配置绝对路径) server.ssl.key-store= classpath:证书文件名.pfx #(密钥生成时输入的密钥库口令) server.ssl.key-store-password:123456 #(密钥类型,与密钥生成命令一致) server.ssl.key-store-type:PKCS12 证书一般最好放在resources目录下 接下来配置

  • SpringBoot如何使用feign实现远程接口调用和错误熔断

    这篇文章主要介绍了SpringBoot如何使用feign实现远程接口调用和错误熔断,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.第一步,新建两个简单的springboot项目并创建rest接口 demo系统的rest接口 plus系统的调用接口 2.在项目pom文件里导入feign和hystrix的pom依赖包 <properties> <java.version>1.8</java.version> <s

  • springboot调用支付宝第三方接口(沙箱环境)

    springboot+调用支付宝第三方接口(沙箱环境) 大神勿喷!! 网址:https://developers.alipay.com/platform/developerIndex.htm 沙箱环境中给测试提供了一些必要和非必要的参数,需要自己动手修改的只有RSA密钥,需要通过支付宝提供的开发工具生成RSA密钥,下载链接:https://docs.open.alipay.com/291/105971#LDsXr 下载完成安装之后,可以生成RSA密钥.生成的密钥分为应用公钥,应用私钥.应用私钥自

  • 解决Vue调用springboot接口403跨域问题

    最近在做一个前后端分离的项目, 前端用的是Vue后端使用的是springboot, 在项目整合的时候发现前端调用后端接口报错403跨域请求问题 前端跨域请求已解决, 那么问题就出在后端了, 找了一些资料找到了很多种方法, 这里说两个简单粗暴的. 注意:"@CrossOrigin"注解要求jdk1.8及以上版本, SpringMVC 4.2及以上版本 1. 在controller层上添加@Configuration注解, 如果没有效果请制定RequestMapping总的method类型

  • SpringBoot框架RESTful接口设置跨域允许

    跨域 跨域请求是指浏览器脚本文件在发送请求时,脚本所在的服务器和请求的服务器地址不一样.跨域是有浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制, 同源策略:是指协议.域名.端口都要相同,其中有一个不同都会产生跨域 SpringBoot框架RESTful接口解决跨域 此处是有配置文件的方式来解决的 package com.prereadweb.config.cors; import org.springframework.context.annotation.Bean; im

  • Springboot 跨域配置无效及接口访问报错的解决方法

    跨域配置如下,Springboot 版本为 2.4.1 ///跨域访问配置 @Configuration public class CorsConfig { private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowCredentials(true); //sessionid 多次访问一致 co

  • SpringBoot跨域Access-Control-Allow-Origin实现解析

    这篇文章主要介绍了SpringBoot跨域Access-Control-Allow-Origin实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 跨域(CORS)是指不同域名之间相互访问. 跨域,指的是浏览器不能执行其他网站的脚本,它是由浏览器的同源策略所造成的,是浏览器对于JavaScript所定义的安全限制策略. 只要协议,子域名,主域名,端口号有一项不同,就属于跨域 跨域的解决方法 前端: 使用jsonp 后端: 实现WebMvcC

  • springboot跨域CORS处理代码解析

    这篇文章主要介绍了springboot跨域CORS处理代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 源(Origin) 源指URL的协议,域名,端口三部分组成,如果这个三个成分都相同,就判定是同源,否则为不同源. 同源策略(Same origin policy)是一种浏览器的约定,即在浏览器中禁止非同源访问. 二 CORS CORS即"跨域资源共享"(Cross-origin resource sharing),是一个W

  • springboot跨域问题解决方案

    这篇文章主要介绍了springboot跨域问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 springboot中的跨域问题,如果不注意的话,容易造成错误,本次springboot版本为2.13 前端错误信息: Access to XMLHttpRequest at 'http://localhost:8080/user/loginOn' from origin 'http://localhost:8082' has been blo

  • SpringBoot中默认缓存实现方案的示例代码

    在上一节中,我带大家学习了在Spring Boot中对缓存的实现方案,尤其是结合Spring Cache的注解的实现方案,接下来在本章节中,我带大家通过代码来实现. 一. Spring Boot实现默认缓存 1. 创建web项目 我们按照之前的经验,创建一个web程序,并将之改造成Spring Boot项目,具体过程略. 2. 添加依赖包 <dependency> <groupId>org.springframework.boot</groupId> <artif

  • 解决SpringBoot跨域的三种方式

    一.什么是跨域 1.1.为什么会出现跨域问题 出于浏览器的同源策略限制.同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现.同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互.所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port) 简单说A应用只能访问

  • SpringBoot跨域问题的五种解决方式

    目录 一.什么是跨域 CORS 二.为什么会有跨域问题 三.有哪些跨域类型 四.解决跨域问题的五种方式 1. 添加跨域配置类 2. 重写WebMvcConfigurer 3. 注解 @CrossOrigin 4. 自定义过滤器 5. 手动设置响应头 前后分离的跨域问题其他解决方案 Nginx服务器反向代理 或者直接在Nginx中进行配置 总结 一.什么是跨域 CORS 当一台服务器资源从另一台服务器(不同 的域名或者端口)请求一个资源或者接口,就会发起一个跨域 HTTP 请求. 举个简单的例子,

  • 使用SpringBoot + Redis 实现接口限流的方式

    目录 配置 限流注解 定制 RedisTemplate Lua 脚本 注解解析 接口测试 全局异常处理 Redis 除了做缓存,还能干很多很多事情:分布式锁.限流.处理请求接口幂等性...太多太多了 配置 首先我们创建一个 Spring Boot 工程,引入 Web 和 Redis 依赖,同时考虑到接口限流一般是通过注解来标记,而注解是通过 AOP 来解析的,所以我们还需要加上 AOP 的依赖,最终的依赖如下: <dependency> <groupId>org.springfra

随机推荐