diff --git a/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/config/RestTemplateConfig.java b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/config/RestTemplateConfig.java new file mode 100644 index 0000000..b382726 --- /dev/null +++ b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/config/RestTemplateConfig.java @@ -0,0 +1,34 @@ +package com.zt.plat.module.contractorder.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.Charset; + +/** + * RestTemplate配置类 + * @author ChenZhaoxue + * @date 2025/3/27 + */ +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate(ClientHttpRequestFactory factory){ + RestTemplate restTemplate = new RestTemplate(factory); + restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8"))); + return restTemplate; + } + + @Bean + public ClientHttpRequestFactory simpleClientHttpRequestFactory(){ + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + factory.setConnectTimeout(10000);//单位为ms + factory.setReadTimeout(30000);//单位为ms + return factory; + } +} diff --git a/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/util/RedisUtil.java b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/util/RedisUtil.java new file mode 100644 index 0000000..5b925b3 --- /dev/null +++ b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/util/RedisUtil.java @@ -0,0 +1,565 @@ +package com.zt.plat.module.contractorder.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * redis 工具类 + * + */ +@Slf4j +@Component +public class RedisUtil { + + @Autowired + private RedisTemplate redisTemplate; + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + if (time > 0) { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String key) { + redisTemplate.delete(key); + } + + // ============================String============================= + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 递增 + * + * @param key 键 + * @param by 要增加几(大于0) + * @return + */ + public long incr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递增因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * + * @param key 键 + * @param by 要减少几(小于0) + * @return + */ + public long decr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递减因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, -delta); + } + + // ================================Map================================= + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public double hincr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public double hdecr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + + // ============================set============================= + /** + * 根据key获取Set中的所有值 + * + * @param key 键 + * @return + */ + public Set sGet(String key) { + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + /** + * 根据value从一个set中查询,是否存在 + * + * @param key 键 + * @param value 值 + * @return true 存在 false不存在 + */ + public boolean sHasKey(String key, Object value) { + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将数据放入set缓存 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSet(String key, Object... values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 将set数据放入缓存 + * + * @param key 键 + * @param time 时间(秒) + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSetAndTime(String key, long time, Object... values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if (time > 0) { + expire(key, time); + } + return count; + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 获取set缓存的长度 + * + * @param key 键 + * @return + */ + public long sGetSetSize(String key) { + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 移除值为value的 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 移除的个数 + */ + public long setRemove(String key, Object... values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + // ===============================list================================= + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + log.error(e.getMessage(), e); + return null; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key 键 + * @param index 索引 + * @param value 值 + * @return + */ + public boolean lUpdateIndex(String key, long index, Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + } + + /** + * 移除N个值为value + * + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public long lRemove(String key, long count, Object value) { + try { + Long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } catch (Exception e) { + log.error(e.getMessage(), e); + return 0; + } + } +} diff --git a/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/util/ShareServiceUtil.java b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/util/ShareServiceUtil.java new file mode 100644 index 0000000..5565b4e --- /dev/null +++ b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/util/ShareServiceUtil.java @@ -0,0 +1,129 @@ +package com.zt.plat.module.contractorder.util; + +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +/** + * ePlat共享服务调用工具类 + * @author ChenZhaoxue + * @date 2025/3/27 + */ +@Slf4j +@Configuration +@Component +public class ShareServiceUtil { + private static final String SHARE_TOKEN_KEY = "eplat:cache:shareToken"; + private static final String SHARE_REFRESH_TOKEN_KEY = "eplat:cache:shareRefreshToken"; + private static final int TOKEN_TIME_OUT = 5000; // token过期时间,默认7200秒,这里设置建议小一些,如7000秒 + + @Value("${eplat.share.urlPrex}") + private String urlPrex; + @Value("${eplat.share.clientId}") + private String clientId; + @Value("${eplat.share.clientSecret}") + private String clientSecret; + + + @Resource + private RestTemplate restTemplate; + @Resource + private RedisUtil redisUtil; + + + /** + * ePlat共享服务调用 + * @param serviceNo 服务号 + * @param request 请求json字符串 + * @return + */ + public String callShareService(String serviceNo, String request) { + String url = String.format("%s/service/%s", urlPrex, serviceNo); + log.info("ePlat共享服务调用url:[" + url + "],request:[" + request + "]"); + String token = generateToken(); + log.info("目标token:" + token); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON_UTF8); + headers.add("Xplat-Token", token); + HttpEntity entity = new HttpEntity<>(request, headers); + ResponseEntity result = restTemplate.exchange(url, HttpMethod.POST, entity, String.class); + return result.getBody(); + } + + private String generateToken() { + // 先从redis中获取未过期token + String token = (String) redisUtil.get(SHARE_TOKEN_KEY); + if (token == null) { + synchronized (ShareServiceUtil.class) { + token = (String) redisUtil.get(SHARE_TOKEN_KEY); + if (token == null) { + try { + token = refreshToken(); + } catch (Exception e) { + log.warn("生成token出错,可能刷新token有问题,重新尝试下", e); + redisUtil.del(SHARE_REFRESH_TOKEN_KEY); + token = refreshToken(); + } + } + } + } + return token; + } + + private String refreshToken() { + // 先从redis中获取未过期的刷新token + String refreshToken = (String) redisUtil.get(SHARE_REFRESH_TOKEN_KEY); + if (refreshToken == null) { + // 重新创建token和刷新token + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + // 构造form表单 + MultiValueMap paramsMap = new LinkedMultiValueMap<>(); + paramsMap.set("client_id", clientId); + paramsMap.set("client_secret", clientSecret); + paramsMap.set("grant_type", "client_credentials"); + paramsMap.set("scope", "read"); + String url = String.format("%s/eplat/oauth/token", urlPrex); + // 构造请求的实体。包含body和headers的内容 + HttpEntity> entity = new HttpEntity<>(paramsMap, headers); + log.info("获取token调用url:[" + url + "],request:[" + paramsMap + "]"); + ResponseEntity result = restTemplate.exchange(url, HttpMethod.POST, entity, String.class); + JSONObject json = JSONUtil.parseObj(result.getBody()); + String accessToken = json.getStr("access_token"); + refreshToken = json.getStr("refresh_token"); + // 缓存token、刷新token(刷新token过期时间为2倍token过期时间) + redisUtil.set(SHARE_TOKEN_KEY, accessToken, TOKEN_TIME_OUT); + redisUtil.set(SHARE_REFRESH_TOKEN_KEY, refreshToken, TOKEN_TIME_OUT * 2); + return accessToken; + } else { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + // 构造form表单 + MultiValueMap paramsMap = new LinkedMultiValueMap<>(); + paramsMap.set("client_id", clientId); + paramsMap.set("client_secret", clientSecret); + paramsMap.set("grant_type", "refresh_token"); + paramsMap.set("refresh_token", refreshToken); + String url = String.format("%s/eplat/oauth/token", urlPrex); + // 构造请求的实体。包含body和headers的内容 + HttpEntity> entity = new HttpEntity<>(paramsMap, headers); + log.info("刷新token调用url:[" + url + "],request:[" + paramsMap + "]"); + ResponseEntity result = restTemplate.exchange(url, HttpMethod.POST, entity, String.class); + JSONObject json = JSONUtil.parseObj(result.getBody()); + String accessToken = json.getStr("access_token"); + refreshToken = json.getStr("refresh_token"); + // 缓存token、刷新token(刷新token过期时间为2倍token过期时间) + redisUtil.set(SHARE_TOKEN_KEY, accessToken, TOKEN_TIME_OUT); + redisUtil.set(SHARE_REFRESH_TOKEN_KEY, refreshToken, TOKEN_TIME_OUT * 2); + return accessToken; + } + } +}