pom.xml
@@ -166,6 +166,18 @@ <version>1.33</version> <scope>compile</scope> </dependency> <!--webclient请æ±--> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-webflux --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> <version>3.3.1</version> </dependency> </dependencies> <build> src/main/java/com/se/simu/constant/CacheConstants.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,48 @@ package com.se.simu.constant; /** * ç¼åçkey 常é * * @author ruoyi */ public class CacheConstants { /** * ç»å½ç¨æ· redis key */ public static final String LOGIN_TOKEN_KEY = "login_tokens:"; /** * éªè¯ç redis key */ public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; /** * åæ°ç®¡ç cache key */ public static final String SYS_CONFIG_KEY = "sys_config:"; /** * åå ¸ç®¡ç cache key */ public static final String SYS_DICT_KEY = "sys_dict:"; /** * é²éæäº¤ redis key */ public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; /** * éæµ redis key */ public static final String RATE_LIMIT_KEY = "rate_limit:"; /** * ç»å½è´¦æ·å¯ç éè¯¯æ¬¡æ° redis key */ public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; /** * ç¨æ·èªå®ä¹ç¼å redis key */ public static final String USER_CACHE_KEY = "user_cache_key:"; } src/main/java/com/se/simu/constant/RedisCache.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,243 @@ package com.se.simu.constant; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.BoundSetOperations; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import java.util.*; import java.util.concurrent.TimeUnit; /** * spring redis å·¥å ·ç±» * * @author ruoyi **/ @SuppressWarnings(value = {"unchecked", "rawtypes"}) @Component public class RedisCache { @Autowired public RedisTemplate redisTemplate; /** * ç¼ååºæ¬ç对象ï¼IntegerãStringãå®ä½ç±»ç * * @param key ç¼åçé®å¼ * @param value ç¼åçå¼ */ public <T> void setCacheObject(final String key, final T value) { redisTemplate.opsForValue().set(key, value); } /** * ç¼ååºæ¬ç对象ï¼IntegerãStringãå®ä½ç±»ç * * @param key ç¼åçé®å¼ * @param value ç¼åçå¼ * @param timeout æ¶é´ * @param timeUnit æ¶é´é¢ç²åº¦ */ public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) { redisTemplate.opsForValue().set(key, value, timeout, timeUnit); } /** * è®¾ç½®æææ¶é´ * * @param key Redisé® * @param timeout è¶ æ¶æ¶é´ * @return true=设置æåï¼false=设置失败 */ public boolean expire(final String key, final long timeout) { return expire(key, timeout, TimeUnit.SECONDS); } /** * è®¾ç½®æææ¶é´ * * @param key Redisé® * @param timeout è¶ æ¶æ¶é´ * @param unit æ¶é´åä½ * @return true=设置æåï¼false=设置失败 */ public boolean expire(final String key, final long timeout, final TimeUnit unit) { return redisTemplate.expire(key, timeout, unit); } /** * è·åæææ¶é´ * * @param key Redisé® * @return æææ¶é´ */ public long getExpire(final String key) { return redisTemplate.getExpire(key); } /** * 夿 keyæ¯å¦åå¨ * * @param key é® * @return true åå¨ falseä¸åå¨ */ public Boolean hasKey(String key) { return redisTemplate.hasKey(key); } /** * è·å¾ç¼åçåºæ¬å¯¹è±¡ã * * @param key ç¼åé®å¼ * @return ç¼åé®å¼å¯¹åºçæ°æ® */ public <T> T getCacheObject(final String key) { ValueOperations<String, T> operation = redisTemplate.opsForValue(); return operation.get(key); } /** * å é¤å个对象 * * @param key */ public boolean deleteObject(final String key) { return redisTemplate.delete(key); } /** * å é¤éå对象 * * @param collection å¤ä¸ªå¯¹è±¡ * @return */ public boolean deleteObject(final Collection collection) { return redisTemplate.delete(collection) > 0; } /** * ç¼åListæ°æ® * * @param key ç¼åçé®å¼ * @param dataList å¾ ç¼åçListæ°æ® * @return ç¼åç对象 */ public <T> long setCacheList(final String key, final List<T> dataList) { Long count = redisTemplate.opsForList().rightPushAll(key, dataList); return count == null ? 0 : count; } /** * è·å¾ç¼åçlist对象 * * @param key ç¼åçé®å¼ * @return ç¼åé®å¼å¯¹åºçæ°æ® */ public <T> List<T> getCacheList(final String key) { return redisTemplate.opsForList().range(key, 0, -1); } /** * ç¼åSet * * @param key ç¼åé®å¼ * @param dataSet ç¼åçæ°æ® * @return ç¼åæ°æ®ç对象 */ public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) { BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key); Iterator<T> it = dataSet.iterator(); while (it.hasNext()) { setOperation.add(it.next()); } return setOperation; } /** * è·å¾ç¼åçset * * @param key * @return */ public <T> Set<T> getCacheSet(final String key) { return redisTemplate.opsForSet().members(key); } /** * ç¼åMap * * @param key * @param dataMap */ public <T> void setCacheMap(final String key, final Map<String, T> dataMap) { if (dataMap != null) { redisTemplate.opsForHash().putAll(key, dataMap); } } /** * è·å¾ç¼åçMap * * @param key * @return */ public <T> Map<String, T> getCacheMap(final String key) { return redisTemplate.opsForHash().entries(key); } /** * å¾Hashä¸åå ¥æ°æ® * * @param key Redisé® * @param hKey Hashé® * @param value å¼ */ public <T> void setCacheMapValue(final String key, final String hKey, final T value) { redisTemplate.opsForHash().put(key, hKey, value); } /** * è·åHashä¸çæ°æ® * * @param key Redisé® * @param hKey Hashé® * @return Hashä¸ç对象 */ public <T> T getCacheMapValue(final String key, final String hKey) { HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash(); return opsForHash.get(key, hKey); } /** * è·åå¤ä¸ªHashä¸çæ°æ® * * @param key Redisé® * @param hKeys Hashé®éå * @return Hash对象éå */ public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) { return redisTemplate.opsForHash().multiGet(key, hKeys); } /** * å é¤Hashä¸çææ¡æ°æ® * * @param key Redisé® * @param hKey Hashé® * @return æ¯å¦æå */ public boolean deleteCacheMapValue(final String key, final String hKey) { return redisTemplate.opsForHash().delete(key, hKey) > 0; } /** * è·å¾ç¼åçåºæ¬å¯¹è±¡å表 * * @param pattern å符串åç¼ * @return 对象å表 */ public Collection<String> keys(final String pattern) { return redisTemplate.keys(pattern); } } src/main/java/com/se/simu/controller/ProjectRelatedController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,89 @@ package com.se.simu.controller; import com.se.simu.domain.EntityTypeInfo; import com.se.simu.domain.LoginParams; import com.se.simu.domain.vo.R; import com.se.simu.service.ProjectRelatedService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @Api(tags = "å®ä½åºç¸å ³æ¥å£") @CrossOrigin(origins = "*") @RequiredArgsConstructor @RestController @RequestMapping("/api/v1") public class ProjectRelatedController extends BaseController { @Resource private ProjectRelatedService projectRelatedService; /** * è·åå ¬é¥ * * @Cacheable æ·»å ç¼åï¼ç¸åæ¡ä»¶çæ¥è¯¢ä¸åæ¥è¯¢æ°æ®åºï¼èæ¯ä»ç¼å䏿¥è¯¢ï¼ * @CachePut æ¯æ¬¡é½ä¼è®¿é®æ°æ®åºï¼å¹¶æ´æ°ç¼åï¼ * @CacheEvict æ¸ é¤ç¼å * <p> * 注解ä¸åæ°è¯´æï¼ * cacheNames/valueï¼æå®ç¼åç»ä»¶çåå; * keyï¼ç¼åæ°æ®ä½¿ç¨çkey;å¯ä»¥ç¨å®æ¥æå®ãé»è®¤æ¯ä½¿ç¨æ¹æ³åæ°çå¼ 1-æ¹æ³å ¨å 2-æ¹æ³åæ°çæå 个 3-key(SpEL) * keyGeneratorï¼keyççæå¨ï¼å¯ä»¥èªå·±æå®keyççæå¨çç»ä»¶id * cacheManagerï¼æå®ç¼å管çå¨ï¼æè cacheResolveræå®è·åè§£æå¨ * conditionï¼æå®ç¬¦åæ¡ä»¶çæ åµä¸æç¼åï¼ * unlessï¼å¦å®ç¼åï¼å½unlessæå®çæ¡ä»¶ä¸ºtrueï¼æ¹æ³çè¿åå¼å°±ä¸ä¼è¢«ç¼åï¼å¯ä»¥è·åå°ç»æè¿è¡å¤æ * syncï¼æ¯å¦ä½¿ç¨å¼æ¥æ¨¡å¼ */ @ApiOperation("0-è·åå ¬é¥") // @Cacheable(cacheNames="api",value="cachespace=30", key = "#root.methodName") @GetMapping("/get-public-key") public Object getPublicKey() { return projectRelatedService.getPublicKey(); } /** * ç»å½å®ä½åº */ @ApiOperation("1-ç»å½å®ä½åº") // @Cacheable(cacheNames = "api", key = "#loginParams") @PostMapping("/login-entity") public R<Object> loginEntity(@RequestBody LoginParams loginParams) { return success(projectRelatedService.loginEntity(loginParams)); } /** * è·å访é®å®ä½åºçtoken */ @ApiOperation("1-è·å访é®å®ä½åºçtoken") @GetMapping("/entity-public-key") public R<Object> getEntityPublicKey() { return success(projectRelatedService.getEntityPublicKey()); } /** * è·å访é®å®ä½åºæ°æ®åºå表 */ @ApiOperation("2-è·å访é®å®ä½åºæ°æ®åºå表") @GetMapping("/db-list") public R<Object> getDbLits() { return success(projectRelatedService.getDbLits()); } /** * æ¥è¯¢å®ä½åºä¸åç±»åçä¿¡æ¯ */ @ApiOperation("3-æ¥è¯¢å®ä½åºä¸åç±»åçä¿¡æ¯") @GetMapping("/entity-type-info") public Object getEntityTypeInfo(EntityTypeInfo entityTypeInfo) { return projectRelatedService.getEntityTypeInfo(entityTypeInfo); } } src/main/java/com/se/simu/domain/EntityDataBase.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,38 @@ package com.se.simu.domain; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; /** * å®ä½æ°æ®åº * * @author xingjinshuang * @date 2024/07/04 */ @Data @ApiModel(value = "EntityDataBase", description = "å®ä½æ°æ®åºç¸å ³å 容") public class EntityDataBase implements Serializable { private static final long serialVersionUID = 1L; /** * ç¨æ·å */ @ApiModelProperty("ç¨æ·å") private String userName; /** * ç¨æ·å¯ç */ @ApiModelProperty("ç¨æ·å¯ç ") private String userPassword; /** * æ°æ®åºå */ @ApiModelProperty("æ°æ®åºå") private String databaseName; } src/main/java/com/se/simu/domain/EntityTypeInfo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,30 @@ package com.se.simu.domain; import io.swagger.annotations.ApiModel; import lombok.Data; import java.io.Serializable; @Data @ApiModel(value = "EntityTypeInfo", description = "å®ä½åºä¸åç±»åçä¿¡æ¯") public class EntityTypeInfo implements Serializable { private static final long serialVersionUID = 1L; private String token; private Integer start; private boolean containCount; private Integer count; private String dbid; private String layerid; private String like; private String querytype; } src/main/java/com/se/simu/domain/LoginParams.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,17 @@ package com.se.simu.domain; import lombok.Data; import java.io.Serializable; @Data public class LoginParams implements Serializable { private static final long serialVersionUID = 1L; // ç¨æ·å private String userid; // å¯ç private String password; } src/main/java/com/se/simu/service/Impl/ProjectRelatedServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,337 @@ package com.se.simu.service.Impl; import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm; import cn.hutool.crypto.asymmetric.AsymmetricCrypto; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.RSA; import com.alibaba.fastjson.JSONObject; import com.se.simu.constant.CacheConstants; import com.se.simu.constant.RedisCache; import com.se.simu.domain.EntityTypeInfo; import com.se.simu.domain.LoginParams; import com.se.simu.service.ProjectRelatedService; import com.se.simu.utils.CustomWebClient; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import reactor.core.publisher.Mono; import javax.annotation.Resource; import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.util.HashMap; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @Slf4j @Service public class ProjectRelatedServiceImpl implements ProjectRelatedService { @Resource private RedisCache redisCache; @Resource public RedisTemplate redisTemplate; // å ¬é¥å°å @Value(value = "${app-server.publicKeyUrl}") private String publicKeyUrl; // devops ç»å½å°å @Value(value = "${app-server.loginUrl}") private String loginUrl; @Value(value = "${app-server.getDbUrl}") private String getDbUrl; // æ¥è¯¢å°å @Value(value = "${app-server.queryUrl}") private String queryUrl; /** * è·åå ¬é¥ * * @return {@link Object} */ @Override public Object getPublicKey() { HashMap<String, String> headers = new HashMap<>(); headers.put("Content-Type", "application/json"); CompletableFuture<String> postResponse = CustomWebClient.postAsFuture(publicKeyUrl, "", headers, String.class); // 弿¥å¤çååº postResponse.thenAccept(response -> { log.info("response: {}", response); if (response.contains("code")) { try { JSONObject postResponseJson = JSONObject.parseObject(response); int statusCode = postResponseJson.getIntValue("code"); log.info("statusCode = " + statusCode); String data = postResponseJson.getString("data"); // ç¼ådata,并设置1å°æ¶æææ redisCache.deleteObject(CacheConstants.USER_CACHE_KEY + "rsa_data_set"); redisCache.setCacheObject(CacheConstants.USER_CACHE_KEY + "rsa_data_set", data, 1, TimeUnit.HOURS); log.info("publicKey = " + data); } catch (Exception e) { log.info("Failed to parse JSON: " + e.getMessage()); } } else { log.info("No 'code' field in the response: " + response); } }); return JSONObject.parseObject(postResponse.join()); } /** * ç»å½å®ä½ * * @param loginParams ç»å½åæ° * @return {@link String} */ @Override public Object loginEntity(LoginParams loginParams) { // 夿redisä¸ç¼åæ¯å¦åå¨ï¼è¿æï¼ Boolean isExists = redisCache.hasKey(CacheConstants.USER_CACHE_KEY + "entity_db_response"); if (isExists) { return JSONObject.parseObject(redisCache.getCacheObject(CacheConstants.USER_CACHE_KEY + "entity_db_response")); } // 设置请æ±ä½ // è·åç§é¥åå ¬é¥ï¼é¿åº¦å¿ é¡»æ¯16ã24æ32 String publicKey = redisCache.getCacheObject(CacheConstants.USER_CACHE_KEY + "rsa_data_set"); // å设ä»Redisä¸è·åå°ç¨æ·å,夿 if (!StringUtils.isNotBlank(publicKey)) { // ç¼å䏿²¡æç¨æ·å,åè¿è¡ç»å½ getPublicKey(); log.info("è°ç¨äºç»å½è·åç¨æ·åæ¹æ³ $= "); } // 鲿¢ä¸»çº¿ç¨æåç»æ try { // çå¾ å¼æ¥è¯·æ±å®æ Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } publicKey = redisCache.getCacheObject(CacheConstants.USER_CACHE_KEY + "rsa_data_set"); log.info("publicKey = " + publicKey); // å ¬é¥å å¯ AsymmetricCrypto rsa = SecureUtil.rsa(null, publicKey); String encrypt = rsa.encryptBase64(loginParams.getPassword(), KeyType.PublicKey); // 设置å å¯åçå¯ç loginParams.setPassword(encrypt); // å°loginParamså®ä½è½¬æJSONå符串 // String json = JSON.toJSONString(loginParams); // log.info("json = " + json); // åéç»å½è¯·æ± Mono<String> postResponse = CustomWebClient.postAsMono(loginUrl, loginParams, String.class); // ç¨äºä¿åååºæ°æ® AtomicReference<String> responseData = new AtomicReference<>(); postResponse.subscribe(response -> { // å°ååºæ°æ®ä¿åå°åéä¸ responseData.set(response); String code = JSONObject.parseObject(response).getString("code"); // 妿codeæ¯200åç»å½æå if (code.equals("200")) { // ç»å½æåå,è·ådata String data = JSONObject.parseObject(response).getString("data"); String token = JSONObject.parseObject(data).getString("token"); // 设置dataå°Redisä¸ redisCache.deleteObject(CacheConstants.USER_CACHE_KEY + "entity_db_response"); redisCache.setCacheObject(CacheConstants.USER_CACHE_KEY + "entity_db_response", response, 1, TimeUnit.HOURS); // 设置dataå°Redisä¸ redisCache.deleteObject(CacheConstants.USER_CACHE_KEY + "entity_db_token"); redisCache.setCacheObject(CacheConstants.USER_CACHE_KEY + "entity_db_token", token, 1, TimeUnit.HOURS); } else { // ç»å½å¤±è´¥ log.error("ç»å½å¤±è´¥ $= " + response); } }); // 鲿¢ä¸»çº¿ç¨æåç»æ try { postResponse.toFuture().get(); // é»å¡çå¾ è®¢é æä½å®æ // çå¾ å¼æ¥è¯·æ±å®æ Thread.sleep(1000); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } // è¿åtoken return JSONObject.parseObject(responseData.get()); } /** * èªå®ä¹å¯é¥çæå 坿°æ® * * @param data æ°æ® * @param publicKey å ¬é¥ * @return {@link String} */ private static String customKeysGenerateEncryptedData(String data, String publicKey) { AsymmetricCrypto rsa = SecureUtil.rsa(null, publicKey); String encrypt = rsa.encryptBase64(data, KeyType.PublicKey); System.out.println("encrypt = " + encrypt); return encrypt; } /** * èªå®ä¹ RSAgenerate å 坿°æ®0 */ private static void customRSAGenerateEncryptedData0() { RSA rsa = new RSA(); // è·åå ¬é¥åç§é¥ System.out.println(rsa.getPublicKey()); System.out.println(rsa.getPrivateKeyBase64()); System.out.println(rsa.getPrivateKey()); System.out.println(rsa.getPrivateKeyBase64()); // ç§é¥å å¯,å ¬é¥è§£å¯ System.out.println(new String(rsa.encrypt("testaa", KeyType.PrivateKey))); System.out.println(new String(rsa.decrypt(rsa.encrypt("testaa", KeyType.PrivateKey), KeyType.PublicKey))); // å ¬é¥å å¯,ç§é¥è§£å¯ System.out.println(new String(rsa.encrypt("testaa", KeyType.PublicKey))); System.out.println(new String(rsa.decrypt(rsa.encrypt("testaa", KeyType.PublicKey), KeyType.PrivateKey))); } /** * èªå®ä¹ RSAgenerate å 坿°æ®1 */ private static void customRSAGenerateEncryptedData1() { KeyPair keyPair = SecureUtil.generateKeyPair(AsymmetricAlgorithm.RSA.getValue()); PrivateKey privateKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic(); System.out.println(publicKey); System.out.println(privateKey); System.out.println("----------"); RSA rsa = new RSA(privateKey, publicKey); // ç§é¥å å¯,å ¬é¥è§£å¯ System.out.println(new String(rsa.encrypt("testaa", KeyType.PrivateKey))); System.out.println(new String(rsa.decrypt(rsa.encrypt("testaa", KeyType.PrivateKey), KeyType.PublicKey))); // å ¬é¥å å¯,ç§é¥è§£å¯ System.out.println(new String(rsa.encrypt("testaa", KeyType.PublicKey))); System.out.println(new String(rsa.decrypt(rsa.encrypt("testaa", KeyType.PublicKey), KeyType.PrivateKey))); } /** * è·å访é®å®ä½åºçtoken * * @return {@link Object} */ @Override public Object getEntityPublicKey() { // 夿redisä¸ç¼åæ¯å¦åå¨ï¼è¿æï¼ Boolean isExists = redisCache.hasKey(CacheConstants.USER_CACHE_KEY + "EntityPublicKey"); if (isExists) { return JSONObject.parseObject(redisCache.getCacheObject(CacheConstants.USER_CACHE_KEY + "EntityPublicKey")); } HashMap<String, String> headers = new HashMap<>(); headers.put("Content-Type", "application/json"); CompletableFuture<String> postResponse = CustomWebClient.postAsFuture(queryUrl, "", headers, String.class); // 弿¥å¤çååº postResponse.thenAccept(response -> { log.info("response: {}", response); if (response.contains("code")) { try { JSONObject postResponseJson = JSONObject.parseObject(response); int statusCode = postResponseJson.getIntValue("code"); log.info("statusCode = " + statusCode); String data = postResponseJson.getString("data"); // ç¼ådata,并设置1å°æ¶æææ redisCache.deleteObject(CacheConstants.USER_CACHE_KEY + "EntityPublicKey"); redisCache.setCacheObject(CacheConstants.USER_CACHE_KEY + "EntityPublicKey", response, 1, TimeUnit.HOURS); log.info("EntityPublicKey = " + data); } catch (Exception e) { log.info("Failed to parse JSON: " + e.getMessage()); } } else { log.info("No 'code' field in the response: " + response); } }); return JSONObject.parseObject(postResponse.join()); } /** * è·å访é®å®ä½åºçtoken * * @return {@link Object} */ @Override public Object getDbLits() { HashMap<String, String> headers = new HashMap<>(); headers.put("Content-Type", "application/json"); String token = redisCache.getCacheObject(CacheConstants.USER_CACHE_KEY + "entity_db_token"); log.info("token = " + token); // æ·»å formåæ° HashMap<String, Object> params = new HashMap<>(); params.put("token", token); CompletableFuture<String> postResponse = CustomWebClient.postAsFuture(getDbUrl, params, headers, String.class); // 弿¥å¤çååº postResponse.thenAccept(response -> { log.info("response: {}", response); if (response.contains("code")) { try { JSONObject postResponseJson = JSONObject.parseObject(response); int statusCode = postResponseJson.getIntValue("code"); log.info("statusCode = " + statusCode); String data = postResponseJson.getString("data"); // ç¼ådata,并设置1å°æ¶æææ redisCache.deleteObject(CacheConstants.USER_CACHE_KEY + "EntityDbNameList"); redisCache.setCacheObject(CacheConstants.USER_CACHE_KEY + "EntityDbNameList", response, 1, TimeUnit.HOURS); log.info("EntityDbNameList = " + data); } catch (Exception e) { log.info("Failed to parse JSON: " + e.getMessage()); } } else { log.info("No 'code' field in the response: " + response); } }); return JSONObject.parseObject(postResponse.join()); } @Override public Object getEntityTypeInfo(EntityTypeInfo entityTypeInfo) { HashMap<String, String> headers = new HashMap<>(); headers.put("Content-Type", "application/json"); String token = redisCache.getCacheObject(CacheConstants.USER_CACHE_KEY + "entity_db_token"); log.info("token = " + token); // æ·»å formåæ° HashMap<String, Object> params = new HashMap<>(); params.put("token", token); params.put("start", Objects.nonNull(entityTypeInfo.getStart()) ? entityTypeInfo.getStart() : 1); params.put("containCount", true); params.put("count", Objects.nonNull(entityTypeInfo.getCount()) ? entityTypeInfo.getCount() : 20); params.put("dbid", Objects.nonNull(entityTypeInfo.getDbid()) ? entityTypeInfo.getDbid() : "85257774fdb64e5f99f6778696cad02a"); params.put("layerid", "f6ff4412-4886-4c4b-83f7-13de24ee8353"); params.put("like", ""); params.put("querytype", "entity"); CompletableFuture<String> postResponse = CustomWebClient.postAsFuture(queryUrl, params, headers, String.class); // 弿¥å¤çååº postResponse.thenAccept(response -> { log.info("response: {}", response); if (response.contains("code")) { try { JSONObject postResponseJson = JSONObject.parseObject(response); int statusCode = postResponseJson.getIntValue("code"); log.info("statusCode = " + statusCode); String data = postResponseJson.getString("data"); log.info("getEntityTypeInfo = " + data); } catch (Exception e) { log.info("Failed to parse JSON: " + e.getMessage()); } } else { log.info("No 'code' field in the response: " + response); } }); return JSONObject.parseObject(postResponse.join()); } } src/main/java/com/se/simu/service/ProjectRelatedService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,33 @@ package com.se.simu.service; import com.se.simu.domain.EntityTypeInfo; import com.se.simu.domain.LoginParams; public interface ProjectRelatedService { /** * è·åå ¬é¥ * * @return {@link String} */ Object getPublicKey(); /** * ç»å½å®ä½ * * @param loginParams ç»å½åæ° * @return {@link String} */ Object loginEntity(LoginParams loginParams); /** * è·å访é®å®ä½åºçtoken * * @return {@link Object} */ Object getEntityPublicKey(); Object getDbLits(); Object getEntityTypeInfo(EntityTypeInfo entityTypeInfo); } src/main/java/com/se/simu/utils/CustomWebClient.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,500 @@ package com.se.simu.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; import java.time.Duration; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; /** * èªå®ä¹ Web 客æ·ç«¯ * * @author xingjinshuang@smartearth.cn * @date 2024/06/27 */ public class CustomWebClient { private static final Logger logger = LoggerFactory.getLogger(CustomWebClient.class); private static final WebClient webClient; static { // å¨éæä»£ç åä¸å®ä¾åWebClient.Builderå¹¶æå»ºWebClient对象 webClient = WebClient.builder().build(); } //====åºç¡è¯·æ±===================================================================================================================================== public static Mono<String> get(String url) { return webClient.get() .uri(url) .retrieve() .bodyToMono(String.class); } public static Mono<String> post(String url, Object requestBody) { return webClient.post() .uri(url) .bodyValue(requestBody) .retrieve() .bodyToMono(String.class); } public static Mono<String> postForm(String url, MultiValueMap<String, String> formData) { return webClient.post() .uri(url) .contentType(MediaType.APPLICATION_FORM_URLENCODED) .body(BodyInserters.fromFormData(formData)) .retrieve() .bodyToMono(String.class); } public static Mono<String> put(String url, Object requestBody) { return webClient.put() .uri(url) .bodyValue(requestBody) .retrieve() .bodyToMono(String.class); } // åéPUTè¯·æ± public static <T, R> Mono<T> put(String url, R requestBody, Class<T> responseType) { return webClient.put() .uri(url) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(requestBody)) .retrieve() .bodyToMono(responseType); } public static Mono<String> delete(String url) { return webClient.delete() .uri(url) .retrieve() .onStatus(HttpStatus::is4xxClientError, clientResponse -> Mono.error(new CustomWebClientException1("Client error: " + clientResponse.statusCode()))) .onStatus(HttpStatus::is5xxServerError, clientResponse -> Mono.error(new CustomWebClientException1("Server error: " + clientResponse.statusCode()))) .bodyToMono(String.class); } //=======èªå®ä¹è¿åç±»åç请æ±=================================================================================================================================== public static <T> Mono<T> getAndParse(String url, Class<T> responseType) { return webClient.get() .uri(url) .accept(MediaType.APPLICATION_JSON) .retrieve() .bodyToMono(responseType); } public static <T, R> Mono<T> postAndParse(String url, R requestBody, Class<T> responseType) { return webClient.post() .uri(url) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(requestBody)) .retrieve() .bodyToMono(responseType); } /** * toBodilessEntityä¸è½½æè å é¤çæ¶åä¸éè¦å¯¹ååºä½å¤çç * toBodilessEntity() æ¯ Java Play Framework ä¸ WebClient ç±»çä¸ä¸ªæ¹æ³ï¼å®ç¨äºå°ååºè½¬æ¢ä¸ºæ²¡æä½çååºå®ä½ã * éå¸¸ï¼æä»¬å¨å¤çä¸éè¦è¯»åååºä½ç大åä¸è½½æ¶ï¼å¯ä»¥ä½¿ç¨è¿ä¸ªæ¹æ³æ¥é¿å ä¸å¿ è¦çå åå ç¨ã */ public static Mono<String> postAndReceiveLocation(String url, Object requestBody) { return webClient.post() .uri(url) .bodyValue(requestBody) .retrieve() .toBodilessEntity() .flatMap(response -> { if (response.getHeaders().getLocation() != null) { return Mono.just(response.getHeaders().getLocation().toString()); } else { // 妿Location为空ï¼è¿åresponse return Mono.just(response.getStatusCode().toString()); } }); } public static Mono<String> postFormAndReceiveLocation(String url, MultiValueMap<String, String> formData) { return webClient.post() .uri(url) .contentType(MediaType.APPLICATION_FORM_URLENCODED) .body(BodyInserters.fromFormData(formData)) .retrieve() .toBodilessEntity() .flatMap(response -> { if (response.getHeaders().getLocation() != null) { return Mono.just(response.getHeaders().getLocation().toString()); } else { // 妿Location为空ï¼è¿åresponseçç¶æç return Mono.just(response.getStatusCode().toString()); } }); } //========================================================================================================================================== // 弿¥è¯·æ±çGETãPOSTæ¹å¼ public static <T> Mono<T> getAsMono(String path, Class<T> responseType) { return webClient.get() .uri(path) .accept(MediaType.APPLICATION_JSON) .retrieve() .bodyToMono(responseType); } public static <T> Mono<T> postAsMono(String path, Object requestBody, Class<T> responseType) { return webClient.post() .uri(path) .contentType(MediaType.APPLICATION_JSON) .body(Mono.just(requestBody), requestBody.getClass()) .retrieve() .bodyToMono(responseType); } public static <T> CompletableFuture<T> getAsFuture(String path, Class<T> responseType) { return webClient .method(HttpMethod.GET) .uri(path) .accept(MediaType.APPLICATION_JSON) .retrieve() .bodyToMono(responseType) .toFuture(); } public static <T> CompletableFuture<T> postAsFuture(String path, Object requestBody, HashMap<String, String> headers, Class<T> responseType) { return webClient .method(HttpMethod.POST) .uri(path) .contentType(MediaType.APPLICATION_JSON) .headers(h -> headers.forEach(h::add)) .bodyValue(requestBody) .retrieve() .bodyToMono(responseType) .toFuture(); } //========================================================================================================================================== // å ¶ä»æ¹å¼ä¸åèµ·è¯·æ± private static final WebClient WEB_CLIENT = WebClient.create(); /** * åèµ·GET请æ±ï¼æ¯æGet parameter */ public static CompletableFuture<String> getParam(String url, HttpHeaders headers, MultiValueMap<String, String> queryParams) { return Mono.from(WEB_CLIENT.get() .uri(uriBuilder -> uriBuilder .path(url) .queryParams(queryParams) .build()) .headers(httpHeaders -> httpHeaders.putAll(headers)) //.headers(h -> headers.forEach(h::add)) .retrieve() .onStatus(HttpStatus::isError, clientResponse -> Mono.error(new RuntimeException("HTTP error status: " + clientResponse.statusCode()))) .bodyToMono(String.class)) .onErrorResume(error -> Mono.just("Error: " + error.getMessage())) // 妿æé误ï¼è¿åéè¯¯ä¿¡æ¯ .toFuture(); } /** * åèµ·GET请æ±ï¼æ¯æGet parameter * å¯ä»¥ç¨ */ public static CompletableFuture<String> getNoParam(String url, HttpHeaders headers) { return Mono.from(WEB_CLIENT.get() .uri(url) .headers(httpHeaders -> httpHeaders.putAll(headers)) //.headers(h -> headers.forEach(h::add)) .retrieve() .onStatus(HttpStatus::isError, clientResponse -> Mono.error(new RuntimeException("HTTP error status: " + clientResponse.statusCode()))) .bodyToMono(String.class)) .onErrorResume(error -> Mono.just("Error: " + error.getMessage())) // 妿æé误ï¼è¿åéè¯¯ä¿¡æ¯ .toFuture(); } /** * åèµ·POST请æ±ï¼æ¯æJSON body */ public static CompletableFuture<String> postJson(String url, Object body, HashMap<String, String> headers) { return Mono.from(WEB_CLIENT.post() .uri(url) .contentType(MediaType.APPLICATION_JSON) .headers(h -> headers.forEach(h::add)) .bodyValue(body) .retrieve() .onStatus(HttpStatus::isError, clientResponse -> Mono.error(new RuntimeException("HTTP error status: " + clientResponse.statusCode()))) .bodyToMono(String.class)) .onErrorResume(error -> Mono.just("Error: " + error.getMessage())) // 妿æé误ï¼è¿åéè¯¯ä¿¡æ¯ .toFuture(); } /** * åèµ·POST请æ±ï¼æ¯æè¡¨åæ°æ® */ public static CompletableFuture<String> postForm(String url, MultiValueMap<String, String> formData, Map<String, String> headers) { return Mono.from(WEB_CLIENT.post() .uri(url) .headers(h -> headers.forEach(h::add)) .contentType(MediaType.APPLICATION_FORM_URLENCODED) .body(BodyInserters.fromFormData(formData)) .retrieve() .bodyToMono(String.class)) .toFuture(); } //========================================================================================================================================= // å ¶ä»è¯·æ±æ¹å¼äº public Mono<String> getRequest(String url, long timeoutSeconds, int retryCount) { return executeRequest(url, HttpMethod.GET, null, HttpHeaders.EMPTY, timeoutSeconds, retryCount); } public Mono<String> postRequest(String url, Object requestBody, HttpHeaders headers, long timeoutSeconds, int retryCount) { return executeRequest(url, HttpMethod.POST, requestBody, headers, timeoutSeconds, retryCount); } /** * æ§è¡è¯·æ± * * @param url ç½å * @param method æ¹æ³ * @param requestBody è¯·æ±æ£æ * @param headers 头 * @param timeoutSeconds è¶ æ¶ç§æ° * @param retryCount éè¯è®¡æ° * @return {@link Mono}<{@link String}> */ private Mono<String> executeRequest(String url, HttpMethod method, Object requestBody, HttpHeaders headers, long timeoutSeconds, int retryCount) { return executeRequestInternal(url, method, requestBody, headers, timeoutSeconds, retryCount) .onErrorResume(throwable -> { logger.error("Error during request: {}", throwable.getMessage()); return Mono.error(throwable); }); } /** * å 鍿§è¡è¯·æ± * * @param url ç½å * @param method æ¹æ³ * @param requestBody è¯·æ±æ£æ * @param headers 头 * @param timeoutSeconds è¶ æ¶ç§æ° * @param retryCount éè¯è®¡æ° * @return {@link Mono}<{@link String}> */ private Mono<String> executeRequestInternal(String url, HttpMethod method, Object requestBody, HttpHeaders headers, long timeoutSeconds, int retryCount) { return webClient.method(method) .uri(url) .headers(httpHeaders -> httpHeaders.addAll(headers)) .bodyValue(requestBody) .retrieve() .bodyToMono(String.class) .timeout(Duration.ofSeconds(timeoutSeconds)) .doOnError(error -> logger.error("Error during request: {}", error)) .retry(retryCount); } //========================================================================================================================================= // å ¶ä»åæ° /** * 使ç¨è¶ æ¶è·å * * @param url ç«¯ç¹ * @param timeoutSeconds è¶ æ¶ç§æ° * @return {@link Mono}<{@link String}> */ public Mono<String> getWithTimeout(String url, long timeoutSeconds) { return webClient.get() .uri(url) .accept(MediaType.APPLICATION_JSON) .retrieve() .bodyToMono(String.class) .timeout(Duration.ofSeconds(timeoutSeconds)) .onErrorMap(error -> new CustomWebClientException("Request timeout", error)); } /** * 带æ é¢å¸å * * @param url ç«¯ç¹ * @param requestBody è¯·æ±æ£æ * @param headers 头 * @return {@link Mono}<{@link String}> */ public Mono<String> postWithHeaders(String url, Object requestBody, HttpHeaders headers) { return webClient.post() .uri(url) .bodyValue(requestBody) .headers(httpHeaders -> httpHeaders.addAll(headers)) .retrieve() .bodyToMono(String.class); } /** * è·åå¹¶å * * @param endpoint1 ç«¯ç¹ 1 * @param endpoint2 ç«¯ç¹ 2 * @return {@link Mono}<{@link String}> */ public Mono<String> getConcurrently(String endpoint1, String endpoint2) { Mono<String> result1 = webClient.get() .uri(endpoint1) .retrieve() .bodyToMono(String.class); Mono<String> result2 = webClient.get() .uri(endpoint2) .retrieve() .bodyToMono(String.class); return result1.zipWith(result2).map(tuple -> tuple.getT1() + tuple.getT2()); } //========================================================================================================================================== /** * èªå®ä¹ Web 客æ·ç«¯å¼å¸¸ * Custom exception class for WebClient error handling * * @author xingjinshuang@smartearth.cn * @date 2024/06/27 */ public static class CustomWebClientException1 extends RuntimeException { public CustomWebClientException1(String message) { super(message); } } /** * èªå®ä¹ Web 客æ·ç«¯å¼å¸¸ * * @author xingjinshuang * @date 2024/06/27 */ public static class CustomWebClientException extends RuntimeException { public CustomWebClientException(String message, Throwable cause) { super(message, cause); } } /** * ä¸»è¦ * * @param args åæ° */ public static void main(String[] args) { HashMap<String, String> headers = new HashMap<>(); headers.put("Content-Type", "application/json"); Mono<String> res = getAndParse("https://api.example.com/data", String.class); res.subscribe(dataResponse -> { // å¤çæ°æ®ååº System.out.println("Received data response: " + dataResponse); }); Mono<String> res1 = get("https://api.example.com/textdata"); res1.subscribe(textData -> { // å¤çææ¬æ°æ®ååº System.out.println("Received text data: " + textData); }); String requestBody00 = new String("test"); Mono<String> res2 = postAndReceiveLocation("https://api.example.com/resource", requestBody00); res2.subscribe(location -> { // å¤çè¿åçèµæºä½ç½® System.out.println("Resource location: " + location); }); MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); formData.add("key1", "value1"); formData.add("key2", "value2"); Mono<String> res3 = postFormAndReceiveLocation("https://api.example.com/formsubmit", formData); res3.subscribe(location -> { // å¤çè¿åç表åæäº¤ä½ç½® System.out.println("Form submission location: " + location); }); // 弿¥GET请æ±,éè¿subscribeæ¹æ³æ¥å¤çååº Mono<String> asyncResponse0 = getAsMono("/api/resource", String.class); // asyncResponse0.subscribe(System.out::println); asyncResponse0.flatMap(response -> { System.out.println("GET请æ±ç»æï¼" + response); return Mono.just(response); }).subscribe(); // 弿¥POST请æ±,éè¿subscribeæ¹æ³æ¥å¤çååº String requestBody0 = new String("data"); Mono<String> asyncPostedResponse0 = postAsMono("/api/resource", requestBody0, String.class); // asyncPostedResponse0.subscribe(System.out::println); asyncPostedResponse0.flatMap(response -> { System.out.println("POST请æ±ç»æï¼" + response); return Mono.just(response); }).subscribe(); // 弿¥GET请æ±ï¼ä¸ä¼ç´æ¥è¿åè¿åä½ CompletableFuture<String> asyncResponse = getAsFuture("/api/resource", String.class); asyncResponse.thenAccept(response -> { System.out.println("GET请æ±ç»æï¼" + response); }); // 弿¥POST请æ±ï¼ä¸ä¼ç´æ¥è¿åè¿åä½ String requestBody = new String("data"); CompletableFuture<String> asyncPostedResponse = postAsFuture("/api/resource", requestBody, headers, String.class); asyncPostedResponse.thenAccept(response -> { System.out.println("POST请æ±ç»æï¼" + response); }); // henAcceptæ¹æ³æ¯ä¸ä¸ªæ¶è´¹åçæ¹æ³ï¼å®ä¸ä¼è¿åä»»ä½å¼ã // è¦è·å弿¥è¯·æ±çè¿åå¼ï¼å¯ä»¥ä½¿ç¨thenApplyæ¹æ³ï¼è¿ä¸ªæ¹æ³ä¼è¿åä¸ä¸ªæ°çCompletableFuture对象ï¼éé¢å å«ç»è¿å¤çåçè¿åå¼ // 弿¥GET请æ±ï¼è¿åè¿åä½ CompletableFuture<String> asyncResponseRes = getAsFuture("/api/resource", String.class); asyncResponse.thenApply(response -> { System.out.println("GET请æ±ç»æï¼" + response); return response; }); // henAcceptæ¹æ³æ¯ä¸ä¸ªæ¶è´¹åçæ¹æ³ï¼å®ä¸ä¼è¿åä»»ä½å¼ã // è¦è·å弿¥è¯·æ±çè¿åå¼ï¼å¯ä»¥ä½¿ç¨thenApplyæ¹æ³ï¼è¿ä¸ªæ¹æ³ä¼è¿åä¸ä¸ªæ°çCompletableFuture对象ï¼éé¢å å«ç»è¿å¤çåçè¿åå¼ // 弿¥POST请æ±ï¼è¿åè¿åä½ String requestBody1 = new String("data"); CompletableFuture<String> asyncPostedResponseRes = postAsFuture("/api/resource", requestBody1, headers, String.class); asyncPostedResponse.thenApply(response -> { System.out.println("POST请æ±ç»æï¼" + response); return response; }); // 忥æ¹å¼ä¸è·åååºä½ï¼å¯ä»¥ä½¿ç¨joinæ¹æ³æ¥çå¾ å¼æ¥æä½ç宿并è·åæç»çç»æãè¿æ ·å¯ä»¥ç¡®ä¿å¨è·åç»æä¹åé»å¡å½å线ç¨ï¼ç´å°å¼æ¥æä½å®æã // 使ç¨joinæ¹æ³æ¥åæ¥è·åååºä½ï¼ String requestBody2 = new String("data"); CompletableFuture<String> asyncPostedResponse2 = CustomWebClient.postAsFuture("/api/resource", requestBody2, headers, String.class); asyncPostedResponse2.thenAccept(response -> { System.out.println("POST请æ±ç»æï¼" + response); }); String syncResponse = asyncPostedResponse2.join(); System.out.println("忥è·åçååºä½ï¼" + syncResponse); // 鲿¢ä¸»çº¿ç¨æåç»æ try { // çå¾ å¼æ¥è¯·æ±å®æ Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } } src/main/resources/application-prod.yml
@@ -91,6 +91,22 @@ connectTimeout: -1 readTimeout: -1 # 项ç®å®ä½åºæå¡ä¸é ç½® app-server: # å ¬é¥å°å publicKeyUrl: http://106.120.22.26:8024/account-service/security/publickey # ç»å½å°å loginUrl: http://106.120.22.26:8024/account-service/security/login # æ¥è¯¢æ°æ®åºå°å getDbUrl: http://106.120.22.26:8024/geo-service/entitydb/list/canview # æ¥è¯¢ä¸åæ°æ®åºç±»åä¸çæ°æ®å°å queryUrl: http://106.120.22.26:8024/geo-service/entitydbdata/layer/query config: ver: 0.2 cacheTime: 60 src/main/resources/application-zyy.yml
@@ -91,6 +91,19 @@ connectTimeout: -1 readTimeout: -1 # 项ç®å®ä½åºæå¡ä¸é ç½® app-server: # å ¬é¥å°å publicKeyUrl: http://106.120.22.26:8024/account-service/security/publickey # ç»å½å°å loginUrl: http://106.120.22.26:8024/account-service/security/login # æ¥è¯¢æ°æ®åºå°å getDbUrl: http://106.120.22.26:8024/geo-service/entitydb/list/canview # æ¥è¯¢ä¸åæ°æ®åºç±»åä¸çæ°æ®å°å queryUrl: http://106.120.22.26:8024/geo-service/entitydbdata/layer/query config: ver: 0.2 cacheTime: 60