maven依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
yaml配置
monitoring:
url:
appId:
secret:
server:
port: 8080
spring:
redis:
host: 127.0.0.1
database: 9
port: 6379
初始化连接池RestTemplateConfig
package com.jen.resttemplatedemo.resttemplate
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.http.client.ClientHttpRequestFactory
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
import org.springframework.stereotype.Component
import org.springframework.web.client.RestTemplate
import org.apache.http.client.HttpClient
import org.apache.http.client.config.RequestConfig
import org.apache.http.config.Registry
import org.apache.http.config.RegistryBuilder
import org.apache.http.conn.socket.ConnectionSocketFactory
import org.apache.http.conn.socket.PlainConnectionSocketFactory
import org.apache.http.conn.ssl.SSLConnectionSocketFactory
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.client.ClientHttpRequestFactory
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
import org.springframework.web.client.RestTemplate
/**
* @author Rick Jen
* @Description 初始化连接池
* @date 2022/8/18 11:55
*/
@Component
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build()
}
@Bean
public HttpClient httpClient() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build()
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry)
// 最大连接数
connectionManager.setMaxTotal(100)
//单个路由最大连接数
connectionManager.setDefaultMaxPerRoute(20)
// 最大空间时间
connectionManager.setValidateAfterInactivity(3000000)
RequestConfig requestConfig = RequestConfig.custom()
//服务器返回数据(response)的时间,超过抛出read timeout
.setSocketTimeout(10000)
//连接上服务器(握手成功)的时间,超出抛出connect timeout
.setConnectTimeout(1000)
//从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
.setConnectionRequestTimeout(500)
.build()
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.build()
}
}
调用监控API MonitoringService
@Component
@Slf4j
public class MonitoringService {
@Autowired
private MonitoringConfiguration monitoringConfiguration;
@Autowired
private RedisTemplate<String, String> stringRedisTemplate;
@Autowired
private RestTemplate restTemplate;
public String getToken() throws NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, InvalidKeyException, UnsupportedEncodingException {
String token = stringRedisTemplate.opsForValue().get(MONITORING_TOKEN_REDIS_KEY);
if (StrUtil.isNotBlank(token)) {
log.info("请求监控API从Redis中获取到Token数据:{}", JSONUtil.toJsonStr(token));
return token;
}
MonitoringTokenParam param = MonitoringTokenParam.builder()
.operatorType(1)
.sig(SecureUtil.md5(monitoringConfiguration.getAppId() + monitoringConfiguration.getSecret()))
.build();
String currentTimestamp = String.valueOf(DateUtil.current());
MonitoringCreateHeaderSignParam headerSignParam = new MonitoringCreateHeaderSignParam(monitoringConfiguration.getAppId(), SecureUtil.md5(JSONUtil.toJsonStr(param)), currentTimestamp);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("appid", monitoringConfiguration.getAppId());
log.info("参数的json:{}", JSONUtil.toJsonStr(param));
headers.set("md5", SecureUtil.md5(JSONUtil.toJsonStr(param)));
headers.set("timestamp", headerSignParam.getTimestamp());
headers.set("version", headerSignParam.getVersion());
headers.set("signature", getSign(headerSignParam));
HttpEntity<MonitoringTokenParam> request = new HttpEntity<>(param, headers);
String result = restTemplate.postForObject(monitoringConfiguration.getUrl() + "/token", request, String.class);
assert result != null;
log.info("请求监控API获取Token返回数据:{}", result);
MonitoringTokenResult tokenResult = convertToBean(result, MonitoringTokenResult.class);
assert tokenResult != null;
token = tokenResult.getToken();
stringRedisTemplate.opsForValue().set(MONITORING_TOKEN_REDIS_KEY, token, 86400, TimeUnit.SECONDS);
log.info("请求监控API获取到Token数据:{}", JSONUtil.toJsonStr(tokenResult));
return tokenResult.getToken();
}
public static String getSign(MonitoringCreateHeaderSignParam param) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException, UnsupportedEncodingException {
assert param != null;
SortedMap<String, String> sortedMap = new TreeMap<>();
sortedMap.put("appid", param.getAppid());
sortedMap.put("md5", param.getMd5());
sortedMap.put("timestamp", param.getTimestamp());
sortedMap.put("version", param.getVersion());
if (StrUtil.isNotBlank(param.getMsgSeq())) {
sortedMap.put("msgSeq", param.getMsgSeq());
}
if (StrUtil.isNotBlank(param.getBundleId())) {
sortedMap.put("bundleId", param.getBundleId());
}
if (StrUtil.isNotBlank(param.getToken())) {
sortedMap.put("token", param.getToken());
}
String jsonString = JSONUtil.toJsonStr(sortedMap);
log.info("监控头部数据转换成JSON:{}", jsonString);
Base64.Encoder encoder = Base64.getEncoder();
Base64.Decoder decoder = Base64.getDecoder();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoder.decode(MonitoringConstant.MONITORING_RSA_PRIVATE_KEY.getBytes()));
PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initSign(priKey);
signature.update(jsonString.getBytes(StandardCharsets.UTF_8));
String signatureString = encoder.encodeToString(signature.sign());
log.info("监控生成签名:{}", signatureString);
return signatureString;
}
public <T extends SuperResult> T convertToBean(String result, Class<T> clazz) throws NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, InvalidKeyException, UnsupportedEncodingException {
MonitoringBaseResult monitoringBaseResult = JSONUtil.toBean(result, MonitoringBaseResult.class);
assert monitoringBaseResult != null;
if (!Objects.equals(monitoringBaseResult.getResultCode(), SUCCESS.getCode())) {
log.error("调用视频接口失败!错误码:{},错误码说明:{}", monitoringBaseResult.getResultCode(), monitoringBaseResult.getResultMsg());
if (Objects.equals(monitoringBaseResult.getResultCode(), TOKEN_EXPR.getCode())) {
log.error("监控token过期...");
getToken();
throw new RuntimeException("令牌失效,请重新获取!");
}
throw new RuntimeException("视频接口调用异常!原因:" + monitoringBaseResult.getResultCode() + "-" + monitoringBaseResult.getResultMsg());
}
return JSONUtil.toBean(monitoringBaseResult.getData(), clazz);
}
}
返回值封装MonitoringBaseResult MonitoringTokenResult
package com.jen.resttemplatedemo.result;
import lombok.Data;
import java.io.Serializable;
@Data
public class MonitoringBaseResult implements Serializable {
private String resultCode;
private String resultMsg;
private String data;
}
package com.jen.resttemplatedemo.result;
import lombok.Data;
@Data
public class MonitoringTokenResult extends SuperResult{
private Integer expires_in;
private String token;
private String tokenNum;
}