实际项目开发中免不了要跟其他系统交互,系统之间互调问题,如果是自己本系统的还好,可以通过打jar包引用的方式放到本项目中直接调用,如果是其他系统的就需要通过远程接口调用。SpringBoot可以有多种方式选择,如传统的HttpClient方式,SpringBoot的RestTemplate方法,使用Feign进行消费等。
1、原始HttpClient方式
在没有springboot之前,HttpClient是一个很好的选择。HttpClient是Apache中的一个开源的项目。它实现了HTTP标准中Client端的所有功能,使用它能够很容易地进行HTTP信息的传输。HttpClient的主要功能:
- 实现了所有 HTTP 的方法(GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS 等)
- 支持 HTTPS 协议
- 支持代理服务器(Nginx)
- 支持自动(跳转)转向 等等
- HttpCLient最关键的方法是执行HTTP请求的方法execute。只要把HTTP请求传入,就可以得到HTTP响应。
使用HttpClient请求一个Http请求的步骤为:
- 创建一个HttpClient对象。
- 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
- 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
- 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
- 处理response。调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
- 关闭HttpClient,无论执行方法是否成功,都必须释放连接。
1.1 引入httpclient依赖
首先引入httpClient的maven依赖:
引入httpcomponents的httpclient
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
</dependency>
也可以使用fegin包下面的httpclient
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
</dependency>
1.2 HttpClient Get方式请求接口
/**
* 封装HTTP GET方法
*
* @param url 请求地址
* @param paramMap 请求参数
* @param charset 编码
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String doGet(String url, Map<String, String> paramMap, String charset) throws ClientProtocolException, IOException {
List<NameValuePair> formparams = setHttpParams(paramMap);
String param = URLEncodedUtils.format(formparams, charset);
String urlParam = url + "?" + param;
return doGet(urlParam, charset);
}
/**
* 封装HTTP GET方法
*
* @param url 请求地址
* @param charset 编码
*
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String doGet(String url, String charset) throws ClientProtocolException, IOException{
HttpClient httpClient = HttpClients.createDefault();
// HttpGet httpGet = new HttpGet(url);
HttpGet httpGet = new HttpGet();
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000)
.setConnectTimeout(60000).setConnectionRequestTimeout(60000).build();
httpGet.setConfig(requestConfig);
httpGet.setURI(URI.create(url));
httpGet.setHeader("Accept", DEFAULT_HEADER_ACCEPT);
httpGet.setHeader("Content-Type", DEFAULT_GET_HEADER_CONTENT_TYPE);
httpGet.setHeader("User-Agent", DEFAULT_HEADER_USER_AGENT);
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
String result = null;
if(entity != null){
result = EntityUtils.toString(entity,charset);
}
httpGet.abort();
return result;
}
1.3 HttpClient Post方式请求接口
/**
* 封装HTTP POST方法
*
* @param url 请求地址
* @param paramMap 请求参数Map
* @param charset 编码
*
* @return
* @throws IOException
*/
public static String doPost(String url, Map<String, String> paramMap, String charset) throws ClientProtocolException, IOException{
List<NameValuePair> formparams = setHttpParams(paramMap);
UrlEncodedFormEntity param = new UrlEncodedFormEntity(formparams, charset);
return doPost(url, param, charset);
}
/**
* 封装HTTP POST方法
*
* @param url 请求地址
* @param data 请求参数(如JSON串)
* @param charset 编码
*
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static String post(String url, String data, String charset) throws ClientProtocolException, IOException {
StringEntity entity = new StringEntity(URLEncoder.encode(data, charset));
return doPost(url, entity, charset);
}
/**
* 设置请求参数
*
* @param
* @return
*/
private static List<NameValuePair> setHttpParams(Map<String, String> paramMap) {
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
Set<Map.Entry<String, String>> set = paramMap.entrySet();
for (Map.Entry<String, String> entry : set) {
formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
return formparams;
}
/**
* 封装HTTP POST方法
*
* @param url 请求地址
* @param entity 请求参数实体
* @param charset 编码
*
* @return
* @throws ClientProtocolException
* @throws IOException
*/
private static String doPost(String url, HttpEntity entity, String charset) throws ClientProtocolException, IOException{
// CloseableHttpClient
HttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
//设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000)
.setConnectTimeout(60000).setConnectionRequestTimeout(60000).build();
httpPost.setConfig(requestConfig);
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
httpPost.setHeader("Accept", DEFAULT_HEADER_ACCEPT);
httpPost.setHeader("Content-Type", DEFAULT_POST_HEADER_CONTENT_TYPE);
httpPost.setHeader("User-Agent", DEFAULT_HEADER_USER_AGENT);
HttpEntity entity = response.getEntity();
String result = null;
if(entity != null){
result = EntityUtils.toString(entity,charset);
}
httpPost.abort();
return result;
}
1.4 CloseableHttpClient Get方式请求接口
示例1:
/**
* GET---有参测试 (方式一:手动在url后面加上参数)
*
*/
@Test
public void doGetTestWayOne() {
// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 参数
StringBuffer params = new StringBuffer();
try {
// 字符数据最好encoding以下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)
params.append("name=" + URLEncoder.encode("&", "utf-8"));
params.append("&");
params.append("age=24");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
// 创建Get请求
HttpGet httpGet = new HttpGet("http://localhost:12345/doGetControllerTwo" + "?" + params);
// 响应模型
CloseableHttpResponse response = null;
try {
// 配置信息
RequestConfig requestConfig = RequestConfig.custom()
// 设置连接超时时间(单位毫秒)
.setConnectTimeout(5000)
// 设置请求超时时间(单位毫秒)
.setConnectionRequestTimeout(5000)
// socket读写超时时间(单位毫秒)
.setSocketTimeout(5000)
// 设置是否允许重定向(默认为true)
.setRedirectsEnabled(true).build();
// 将上面的配置信息 运用到这个Get请求里
httpGet.setConfig(requestConfig);
// 由客户端执行(发送)Get请求
response = httpClient.execute(httpGet);
// 从响应模型中获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 释放资源
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例2:
/**
* GET---有参测试 (方式二:将参数放入键值对类中,再放入URI中,从而通过URI得到HttpGet实例)
*
*/
@Test
public void doGetTestWayTwo() {
// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 参数
URI uri = null;
try {
// 将参数放入键值对类NameValuePair中,再放入集合中
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("name", "&"));
params.add(new BasicNameValuePair("age", "18"));
// 设置uri信息,并将参数集合放入uri;
// 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)
uri = new URIBuilder().setScheme("http").setHost("localhost")
.setPort(12345).setPath("/doGetControllerTwo")
.setParameters(params).build();
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
// 创建Get请求
HttpGet httpGet = new HttpGet(uri);
// 响应模型
CloseableHttpResponse response = null;
try {
// 配置信息
RequestConfig requestConfig = RequestConfig.custom()
// 设置连接超时时间(单位毫秒)
.setConnectTimeout(5000)
// 设置请求超时时间(单位毫秒)
.setConnectionRequestTimeout(5000)
// socket读写超时时间(单位毫秒)
.setSocketTimeout(5000)
// 设置是否允许重定向(默认为true)
.setRedirectsEnabled(true).build();
// 将上面的配置信息 运用到这个Get请求里
httpGet.setConfig(requestConfig);
// 由客户端执行(发送)Get请求
response = httpClient.execute(httpGet);
// 从响应模型中获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 释放资源
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.5 CloseableHttpClient Post方式请求接口
POST无参:
/**
* POST---无参测试
*
*/
@Test
public void doPostTestOne() {
// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 创建Post请求
HttpPost httpPost = new HttpPost("http://localhost:12345/doPostControllerOne");
// 响应模型
CloseableHttpResponse response = null;
try {
// 由客户端执行(发送)Post请求
response = httpClient.execute(httpPost);
// 从响应模型中获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 释放资源
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
POST有参(普通参数):
POST传递普通参数时,方式与GET一样即可,这里以直接在url后缀上参数的方式示例。
/**
* POST---有参测试(普通参数)
*
*/
@Test
public void doPostTestFour() {
// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 参数
StringBuffer params = new StringBuffer();
try {
// 字符数据最好encoding以下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)
params.append("name=" + URLEncoder.encode("&", "utf-8"));
params.append("&");
params.append("age=24");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
// 创建Post请求
HttpPost httpPost = new HttpPost("http://localhost:12345/doPostControllerFour" + "?" + params);
// 设置ContentType(注:如果只是传普通参数的话,ContentType不一定非要用application/json)
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
// 响应模型
CloseableHttpResponse response = null;
try {
// 由客户端执行(发送)Post请求
response = httpClient.execute(httpPost);
// 从响应模型中获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 释放资源
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
POST有参(对象参数):
/**
* POST---有参测试(对象参数)
*
*/
@Test
public void doPostTestTwo() {
// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 创建Post请求
HttpPost httpPost = new HttpPost("http://localhost:12345/doPostControllerTwo");
User user = new User();
user.setName("潘晓婷");
user.setAge(18);
user.setGender("女");
user.setMotto("姿势要优雅~");
// 我这里利用阿里的fastjson,将Object转换为json字符串;
// (需要导入com.alibaba.fastjson.JSON包)
String jsonString = JSON.toJSONString(user);
StringEntity entity = new StringEntity(jsonString, "UTF-8");
// post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
httpPost.setEntity(entity);
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
// 响应模型
CloseableHttpResponse response = null;
try {
// 由客户端执行(发送)Post请求
response = httpClient.execute(httpPost);
// 从响应模型中获取响应实体
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 释放资源
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2、SpringBoot的RestTemplate方式
Spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
-
RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。
-
RestTemplate提供有get、post等方式。RestTemplate官方网站
- get请求:getForObject(…)和getForEntity(…)两个方法,区别在于前者直接返回预期的对象,即返回体中的body对象,后者返回的是ResponseEntity封装类,里面包含了HTTP请求的头信息。
- post请求:与get请求类似,只是多一个request参数,request对象会作为httpEntity进行处理。
RestTemplate restTemplate = new RestTemplate();
// 方法一: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);
// 方法二: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");
通过rest接口调用远程服务步骤:
2.1 调用和被调用的接口
1)需要调用三方服务的类
@RestController
@RequestMapping("demo")
public class DemoController {
@GetMapping("getUser")
public void getUser(@RequestParam("name")String name){
//此处需要远程调用第三方服务 获取user对象
}
@GetMapping("saveUser")
public void getUser(){
UserDto userDto = new UserDto();
userDto.setName("resttemplate");
userDto.setAge(17);
userDto.setBirthday(new Date());
//此处需要远程调用第三方服务 将user对象发送给第三方
}
}
2)第三方服务
@RestController
@RequestMapping("api")
//此类是模拟第三方提供服务的
public class ApiController {
//模拟获取数据
@GetMapping("get")
public UserDto get(@RequestParam("username")String username){
System.out.println("从数据库中查询username【"+username+"】的数据");
UserDto userDto = new UserDto();
userDto.setName("springboot");
userDto.setAge(18);
userDto.setBirthday(new Date());
return userDto;
}
//模拟接收数据保存到数据库
@GetMapping("save")
public UserDto save(@RequestBody UserDto userDto) throws JsonProcessingException {
System.out.println(new ObjectMapper().writeValueAsString(userDto));
//TODO:保存到数据库
return userDto;
}
}
假设第三方服务的两个接口分别为:localhost:8080/demo/api/get 和 localhost:8080/demo/api/save。
2.2 使用RestTemplate进行远程调用
在Application中声明一个RestTemplate。
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
在DemoController中使用@Resource注入进来。
实际生产实例中还会涉及到超时,如果第三方响应太慢了,则不再等待。RestTemplate也可以做到,我们不是在Application中声明了一个RestTemplate吗?,只需要将如下代码替换即可。
@Bean
public SimpleClientHttpRequestFactory httpClientFactory() {
SimpleClientHttpRequestFactory httpRequestFactory = new SimpleClientHttpRequestFactory();
httpRequestFactory.setReadTimeout(1000*5);//读取超时
httpRequestFactory.setConnectTimeout(1000*5);//链接超时
return httpRequestFactory;
}
@Bean
public RestTemplate restTemplate(SimpleClientHttpRequestFactory httpClientFactory) {
RestTemplate restTemplate = new RestTemplate(httpClientFactory);
return restTemplate;
}
2.3 RestTemplate工具类
/**
* 远程连接工具类
*/
@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 远程方法
* @aram params 方法参数
* @eturn
*/
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");
}
}
工具类中提供了远程过程中传递参数的两种格式:其中 headers.add(“Content-Type”, “application/x-www-form-urlencoded”) 为form表单格式,支持键值对数据传输;当参数类型为form表单时,数据需要封装成MultiValueMap<String,String>格式,前台使用controller接受时,可以直接使用 MultiValueMap 变量接收,代码如下:
接受参数为form对象
/**
* 保存分组策略对象
* @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);
}
headers.setContentType(MediaType.APPLICATION_JSON_UTF8)
接收参数为复杂json串
当参数为json格式时,远程服务器接受参数需加上注解@RequestBody,对于复杂参数可以使用对象接受,将对象转为Map,对数据进行加工,再将map转化为JSONObject。
/**
* 保存试卷策略
* @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);
}
3、使用Feign进行消费
3.1 在maven中添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.2</version>
</dependency>
3.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.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是要调的接口名
3.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());
}
4、HttpURLConnection方式
使用java.net自带的HttpURLConnection进行第三方接口的调用:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.logging.log4j.util.Strings;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.*;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class HttpUtil2 {
/****************************************x-www-form-urlencoded*********************************************/
public static <T> T getRequestByUrlencoded(String path , HashMap<String , Object> params, Type clazz){
HttpURLConnection conn = null;
BufferedReader br = null;
InputStream is = null;
String body = "";
StringBuffer sb = new StringBuffer(path);
//请求参数拼接到路径上
if (!CollectionUtils.isEmpty(params)){
sb.append("?");
for (Map.Entry<String , Object> entry : params.entrySet()){
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
body = sb.substring(0 , sb.length()-1);
}
try {
URL url = new URL(body);
//打开与url之间的连接
conn = (HttpURLConnection) url.openConnection();
//不设置默认使用get
conn.setRequestMethod("GET");
conn.setRequestProperty("accept" , "*/*");
conn.setRequestProperty("user-agent" , "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
conn.setRequestProperty("content-Type" , "application/x-www-form-urlencoded");
conn.setRequestProperty("connection" , "keep-Alive");
//本次连接是否自动使用重定向
conn.setInstanceFollowRedirects(true);
is = conn.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
StringBuffer result = new StringBuffer();
while ((body=br.readLine()) != null){
result.append(body);
}
body = result.toString();
if (Strings.isNotBlank(body)){
Gson gson = new GsonBuilder().create();
return gson.fromJson(body , clazz);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (conn != null){
conn.disconnect();
}
}
return null;
}
public static <T> T postRequestByUrlencoded(String path , HashMap<String , String> headers , Type clazz){
DataOutputStream out = null;
BufferedReader br = null;
InputStream is = null;
HttpURLConnection conn = null;
StringBuffer sb = new StringBuffer();
StringBuffer result = new StringBuffer();
String body = "";
try {
URL url = new URL(path);
//打开与url之间的连接
conn = (HttpURLConnection) url.openConnection();
//设置请求方式
conn.setRequestMethod("POST");
// Post 请求不能使用缓存
conn.setUseCaches(false);
//设置本次连接是否自动重定向
conn.setInstanceFollowRedirects(true);
//设置通用的请求属性
conn.setRequestProperty("accept" , "*/*");
conn.setRequestProperty("connection" , "keep-Alive");
conn.setRequestProperty("user-agent" , "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
conn.setRequestProperty("content-Type" , "application/x-www-form-urlencoded");
if (!CollectionUtils.isEmpty(headers)){
for (Map.Entry<String , String> entry : headers.entrySet()){
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
body = sb.substring(0 , sb.length()-1);
}
//setDoOutput设置是否向httpUrlConnection输出,setDoInput设置是否向httpUrlConnection读入,发送post请求必须设置这两个属性
conn.setDoOutput(true);
conn.setDoInput(true);
//获取URLConnection对象对应的输出流
out = new DataOutputStream(conn.getOutputStream());
//发送请求参数即数据
out.writeBytes(body);
out.flush();
//获取URLConnection对象对应的输入流
is = conn.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String str = "";
while ((str=br.readLine())!=null){
result.append(str);
}
str = result.toString();
if (Strings.isNotBlank(str)){
Gson gson = new GsonBuilder().create();
return gson.fromJson(str , clazz);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (conn != null){
conn.disconnect();
}
}
return null;
}
/*************************************application/json*************************************************/
//此方法可以使用,但具体是否正确有待商榷
//首先:get请求方式传递json数据应该放在请求协议包的哪里,其次:setDoOutput方法要设置为true,即使是get方式,否则无法向URLConnection发送数据
public static <T> T getRequestByJson(String path , String data ,Type clazz){
OutputStreamWriter out = null;
BufferedReader br = null;
InputStream is = null;
HttpURLConnection conn = null;
StringBuffer sb = new StringBuffer();
String result = "";
try {
URL url = new URL(path);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("accept" , "*/*");
conn.setRequestProperty("connection" , "keep-Alive");
conn.setRequestProperty("user-agent" , "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
conn.setRequestProperty("content-Type" , "application/json;charset=utf-8");
//从源码看,应该是检查是否连接,未连接的话进行连接
conn.setDoOutput(true);
conn.setDoInput(true);
out = new OutputStreamWriter(conn.getOutputStream() , "UTF-8");
out.write(data);
out.flush();
is = conn.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String body = "";
while ((body=br.readLine())!=null){
sb.append(body);
}
result = sb.toString();
if (Strings.isNotBlank(result)){
Gson gson = new GsonBuilder().create();
return gson.fromJson(result , clazz);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (conn != null){
conn.disconnect();
}
}
return null;
}
public static <T> T postRequestByJson(String path , String data , Type clazz){
OutputStreamWriter out = null;
BufferedReader br = null;
InputStream is = null;
HttpURLConnection conn = null;
StringBuffer sb = new StringBuffer();
String result = "";
try {
URL url = new URL(path);
//打开与url之间的连接
conn = (HttpURLConnection) url.openConnection();
//设置请求方式
conn.setRequestMethod("POST");
//设置通用的请求属性
conn.setRequestProperty("accept" , "*/*");
conn.setRequestProperty("connection" , "keep-Alive");
conn.setRequestProperty("user-agent" , "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
conn.setRequestProperty("content-Type" , "application/json;charset=utf-8");
//setDoOutput设置是否向httpUrlConnection输出,setDoInput设置是否向httpUrlConnection读入,发送post请求必须设置这两个属性
conn.setDoOutput(true);
conn.setDoInput(true);
//获取URLConnection对象对应的输出流
out = new OutputStreamWriter(conn.getOutputStream() , "UTF-8");
//发送请求参数即数据
out.write(data);
out.flush();
//获取URLConnection对象对应的输入流
is = conn.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String str = "";
while ((str=br.readLine())!=null){
sb.append(str);
}
str = sb.toString();
if (Strings.isNotBlank(str)){
Gson gson = new GsonBuilder().create();
return gson.fromJson(sb.toString() , clazz);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (conn != null){
conn.disconnect();
}
}
return null;
}
}
评论区