为什么要使用远程调用?
SpringBoot不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。在Spring-Boot项目开发中,存在着本模块的代码需要访问外面模块接口,或外部url链接的需求, 比如在apaas开发过程中需要封装接口在接口中调用apaas提供的接口(像发起流程接口submit等等)下面也是提供了三种方式(不使用dubbo的方式)供我们选择。
方式一:使用原始httpClient请求
public static Map<String, String> httpPostRequest(String url, Map<String, Object> params, int timeout) {
Map<String, String> resultMap = new HashMap<>();
CloseableHttpClient httpClient = HttpClients.createDefault();
String result = "";
try {
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "application/json");
String s = Base64.getEncoder().encodeToString(getAuthorization().getBytes());
log.info("getAuthorization():{}", s);
httpPost.addHeader("authorization", "Basic " + s);
StringEntity se = new StringEntity(JSONObject.toJSONString(params), "utf-8");
se.setContentEncoding("UTF-8");
se.setContentType("application/json");
httpPost.setEntity(se);
HttpResponse response = httpClient.execute(httpPost);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeout)
.setConnectionRequestTimeout(timeout).setSocketTimeout(timeout).build();
httpPost.setConfig(requestConfig);
HttpEntity responseEntity = response.getEntity();
resultMap.put("scode", String.valueOf(response.getStatusLine().getStatusCode()));
resultMap.put("data", "");
if (responseEntity != null) {
result = EntityUtils.toString(responseEntity, java.nio.charset.Charset.forName("UTF-8"));
resultMap.put("data", result);
}
} catch (Exception e) {
resultMap.put("scode", "error");
resultMap.put("data", "HTTP请求失败: " + e.getMessage());
Writer w = new StringWriter();
e.printStackTrace(new PrintWriter(w));
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultMap;
}
方式二:使用RestTemplate
先封装哥工具类吧
public class RestTemplateUtils {
private static final RestTemplate REST_TEMPLATE;
static {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
// 超时
factory.setConnectTimeout(5000);
factory.setReadTimeout(15000);
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(createIgnoreVerifySSL(),
// 指定TLS版本
null,
// 指定算法
null,
// 取消域名验证
new HostnameVerifier() {
@Override
public boolean verify(String string, SSLSession ssls) {
return true;
}
});
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
factory.setHttpClient(httpClient);
REST_TEMPLATE = new RestTemplate(factory);
// 解决中文乱码问题
REST_TEMPLATE.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8")));
}
public static RestTemplate getRestTemplate() {
return REST_TEMPLATE;
}
/**
* @param url 请求完整地址
* @param method 请求方式
* @param param 请求参数
* @param cls 返回类型class
* @param <T> 泛型
* @return
*/
public static <T> T exchange(String url, HttpMethod method, Map param, Class<T> cls) {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json;charset=UTF-8");
return exchange(url, method, headers, param, cls);
}
public static <T> T exchange(String url, HttpMethod method, HttpHeaders headers, Map param, Class<T> cls) {
String jsonMap = "";
if (headers == null) {
headers = new HttpHeaders();
headers.add("Content-Type", "application/json;charset=UTF-8");
}
HttpEntity formEntity = new HttpEntity(param, headers);
ResponseEntity<T> result = REST_TEMPLATE.exchange(url, method, formEntity, cls);
logger.info("【Info-Http】Request:" + url + "--|--" + JSON.toJSONString(param) + "--|--Result:" + JSON.toJSONString(result));
return result.getBody();
}
public static String exchange(String url, HttpMethod method, Map param) {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json;charset=UTF-8");
HttpEntity formEntity = new HttpEntity(param, headers);
ResponseEntity<String> result = REST_TEMPLATE.exchange(url, method, formEntity, String.class);
return result.getBody();
}
/**
* 跳过证书效验的sslcontext
*
* @return
* @throws Exception
*/
private static SSLContext createIgnoreVerifySSL() {
try {
SSLContext sc = SSLContext.getInstance("TLS");
// 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
X509TrustManager trustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
String paramString) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
String paramString) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sc.init(null, new TrustManager[]{trustManager}, null);
return sc;
} catch (Exception e) {
log.info("建立 初始化异常");
throw new RuntimeException();
}
}
方式三:使用Feign进行调用
1:主启动类添加
启动类上加上@EnableFeignClients
@SpringBootApplication
@EnableFeignClients
@ComponentScan(basePackages = {"com.xx.mp", "com.ap.*" ,"com.xdp.*"})
public class XxApplication {
public static void main(String[] args) {
SpringApplication.run(XxApplication .class, args);
}
}
2:此处编写接口模拟外部接口供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);
}
添加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");
}
}
以上的是SpringBoot之远程调用的三大方式 若需完整代码 可识别二维码后 给您发代码。