为什么要使用远程调用?
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() {@Overridepublic 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() {@Overridepublic void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,String paramString) throws CertificateException {}@Overridepublic void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,String paramString) throws CertificateException {}@Overridepublic 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 {@Overridepublic 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)@ResponseBodypublic 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 {@Overridepublic void apply(RequestTemplate requestTemplate) {//添加tokenrequestTemplate.header("token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ4ZGFwYXBwaWQiOiIzNDgxMjU4ODk2OTI2OTY1NzYiLCJleHAiOjE2NjEyMjY5MDgsImlhdCI6MTY2MTIxOTcwOCwieGRhcHRlbmFudGlkIjoiMzAwOTgxNjA1MTE0MDUyNjA5IiwieGRhcHVzZXJpZCI6IjEwMDM0NzY2MzU4MzM1OTc5NTIwMCJ9.fZAO4kJSv2rSH0RBiL1zghdko8Npmu_9ufo6Wex_TI2q9gsiLp7XaW7U9Cu7uewEOaX4DTdpbFmMPvLUtcj_sQ");}
}
以上的是SpringBoot之远程调用的三大方式 若需完整代码 可识别二维码后 给您发代码。