4 Commits b26c7889b5 ... 2303726ff0

Author SHA1 Message Date
  andy 2303726ff0 更新 7 months ago
  andy e72c80fa9e feat(api):在 GenericApi 中向请求正文添加标头 8 months ago
  andy 183133d8d2 update 8 months ago
  andy 0546960555 ibmmq 增加 主题发送 8 months ago

+ 6 - 2
src/main/java/com/scbfkj/uni/api/GenericApi.java

@@ -64,7 +64,11 @@ public class GenericApi {
 			return ResponseEntity.ok(Map.of("code", "400", "msg", "请求体不能为空"));
 		}
 		String uri = RequestUtil.getUri(); // 获取当前请求的URI
-
+		return execService(body, uri);
+	}
+	
+	public static ResponseEntity<Map<String, Object>> execService(final Map<String, Object> body,
+	                                                                        final String uri) throws Exception {
 		// 查询数据库,尝试匹配服务
 		List<Map<String, Object>> serviceinfoList = DATA_BASE.query(Config.getCenterConnectionStr(), """
 				select serviceid
@@ -77,9 +81,9 @@ public class GenericApi {
 		// 获取匹配到的服务ID,并更新请求体
 		Object serviceid = serviceinfoList.get(0).get("serviceid");
 		body.put("serviceid", serviceid);
+		body.put("headers", RequestUtil.getHeaders());
 		// 执行服务处理并返回处理结果
 		return ResponseEntity.ok(new ProcessUtil().process(body));
 	}
-
 }
 

+ 232 - 209
src/main/java/com/scbfkj/uni/api/LogAop.java

@@ -1,6 +1,13 @@
 package com.scbfkj.uni.api;
 
 import com.google.common.util.concurrent.RateLimiter;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
 import com.scbfkj.uni.library.DataAliasGetUtil;
 import com.scbfkj.uni.library.DataFormatUtil;
 import com.scbfkj.uni.library.RequestUtil;
@@ -9,15 +16,14 @@ import com.scbfkj.uni.process.DataBase;
 import com.scbfkj.uni.service.LoggerService;
 import com.scbfkj.uni.system.Config;
 import com.scbfkj.uni.utils.Util;
-import jakarta.annotation.Resource;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Component;
 
 import java.time.LocalDateTime;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -26,207 +32,224 @@ import java.util.concurrent.TimeUnit;
 @Component
 @Aspect
 public class LogAop {
-
-	// 用于存储限流规则的映射
-	private static final Map<String, RateLimiter> rateLimiterMap = new HashMap<>();
-	// 数据库操作实例
-	private static final DataBase DATA_BASE = new DataBase();
-	// 工具类实例
-	@Resource
-	private Util util;
-
-	/**
-	 * 环绕通知,拦截指定包下的Api请求。
-	 *
-	 * @param joinPoint 切点表达式匹配到的连接点
-	 *
-	 * @return 返回处理后的响应实体
-	 *
-	 * @throws Throwable 抛出异常时处理
-	 */
-	@Around(value = "within(com.scbfkj.uni.api.*Api)")
-	public ResponseEntity<Object> invokeAround(ProceedingJoinPoint joinPoint) throws Throwable {
-
-		String methodName = joinPoint.getSignature().getName();
-		String className = joinPoint.getSignature().getDeclaringTypeName();
-
-		if ( "matchService".equals(methodName) && "com.scbfkj.uni.api.GenericApi".equals(className) ) {
-			String requestBody = RequestUtil.getRequestBody();
-			if ( requestBody != null ) {
-				Map<String, Object> body = (Map<String, Object>) DataFormatUtil.toMap(requestBody);
-				joinPoint.getArgs()[0] = body;
-			}
-		}
-
-		LocalDateTime requestTime = LocalDateTime.now();
-		// 获取请求信息
-		String uri = RequestUtil.getUri();
-		Object[] args = joinPoint.getArgs();
-		Map<String, Object> returnData = null;
-		String message = null;
-		Map<String, Object> userInfo = RequestUtil.getUserInfo();
-
-		Optional<String> serviceid = Optional.empty();
-		String userId = RequestUtil.getUserId();
-		
-
-		try {
-			Map<String, Object> body = null;
-			// 检查除特定接口外的服务状态
-			if ( args.length > 0 && ! uri.startsWith("/controlApi") && ! uri.startsWith("/file") && ! uri.startsWith("/user") && ! uri.startsWith("/foxlibc") && ! uri.startsWith("/ws") ) {
-				Object arg = args[0];
-				if ( arg instanceof Map<?, ?> map ) {
-					body = (Map<String, Object>) map;
-					Util.addFilter(body, serviceid, uri, true);
-					serviceid = DataAliasGetUtil.getValue("serviceid", (Map<String, Object>) map);
-					if ( serviceid.isEmpty() ) {
-						List<Map<String, Object>> query = DATA_BASE.query(Config.getCenterConnectionStr(), "select * from serviceinfo where urilist=?", uri);
-						if ( ! query.isEmpty() ) {
-							serviceid = DataAliasGetUtil.getValue("serviceid", query.get(0));
-						}
-					}
-					if ( serviceid.isPresent() ) {
-						// 检查服务运行状态
-						List<Map<String, Object>> mapList = DATA_BASE.query(Config.getCenterConnectionStr(), "select runstate from servicestate where stoptime is null and  serviceid=? and containercode = ?", serviceid.get(), Config.getContainerCode());
-						if ( mapList.isEmpty() ) {
-							throw new RuntimeException("服务没有运行或者被熔断");
-						} else {
-							Map<String, Object> serviceState = mapList.get(0);
-							Object o = serviceState.get("runstate");
-							// 判断服务状态
-							if ( Objects.equals(o.toString(), "0") ) {
-								throw new RuntimeException("服务没有运行或者被熔断");
-							}
-						}
-					}
-				}
-			}
-
-			// 检查是否符合限流规则
-			message = checkratelimitrule(uri);
-			if ( Objects.nonNull(message) ) {
-				return ResponseEntity.ok(UniReturnUtil.fail(message));
-			}
-
-			// 继续执行原方法逻辑
-			ResponseEntity<Map<String, Object>> responseEntity = (ResponseEntity<Map<String, Object>>) joinPoint.proceed(args);
-			Map<String, Object> responseEntityBody = responseEntity.getBody();
-			if ( responseEntity.getStatusCode().is2xxSuccessful() ) {
-				if ( Config.isDebug() ) {
-					System.out.println("返回值:" + DataFormatUtil.toString(returnData));
-				}
-				// 处理返回数据,如果是调试模式,直接返回
-				if ( "0".equals(responseEntityBody.get("code")) && serviceid.isPresent() ) {
-					List<Map<String, Object>> serviceInfoes = DATA_BASE.query(Config.getCenterConnectionStr(), "select * from serviceinfo where serviceid=?", serviceid.get());
-					if ( ! serviceInfoes.isEmpty() ) {
-						Map<String, Object> serviceInfo = serviceInfoes.get(0);
-						Object raw = serviceInfo.get("raw");
-						if ( raw != null && raw.toString().equalsIgnoreCase("1") ) {
-							Object data = responseEntityBody.getOrDefault("returnData", responseEntityBody);
-							if ( data instanceof List<?> d && d.size() == 1 ) {
-								data = d.get(0);
-							}
-							return ResponseEntity.ok(data);
-						}
-					}
-				}
-				return ResponseEntity.ok(responseEntityBody);
-			} else {
-				returnData = responseEntityBody;
-			}
-
-		} catch ( Throwable e ) {
-			if ( Config.isDebug() ) {
-				e.printStackTrace();
-			}
-			// 错误处理,生成错误日志消息
-			message = UniReturnUtil.getMessage(e);
-			returnData = UniReturnUtil.fail(message);
-		} finally {
-			// 记录日志
-			HashMap<String, Object> logData = new HashMap<>();
-			logData.put("requesttime", requestTime);
-			logData.put("requestpath", uri);
-			logData.put("requestdata", DataFormatUtil.toString(args));
-			logData.put("sessionid", RequestUtil.getSessionId());
-			logData.put("returndata", DataFormatUtil.toString(returnData));
-			logData.put("returntime", LocalDateTime.now());
-			try {
-				logData.put("applicationid", RequestUtil.getAppId());
-			} catch ( Exception e ) {
-				if ( Config.isDebug() ) {
-					e.printStackTrace();
-				}
-			}
-			LoggerService.log(LoggerService.LogType.INTERFACE, logData);
-		}
-
-		Object code = returnData.get("code");
-		// 过滤返回数据
-		if ( ! Config.isDebug() && Objects.nonNull(code) && "0".equals(code.toString()) && Objects.nonNull(userInfo) && ! "0".equals(userInfo.get("usergroupid").toString()) ) {
-			Object returnData1 = returnData.get("returnData");
-			if ( returnData1 instanceof List<?> ls ) {
-				if ( serviceid.isPresent() ) {
-					try {
-						List<String> columns = DATA_BASE.query(Config.getSecurityConnectionStr(), "select pagecode from pageconfiguration where pageconfigurationid  in (select userpermissions.pageconfigurationid from userpermissions where  userid =? and  serviceid = ?)", userId, serviceid.get()).stream().map(it -> it.get("pagecode").toString()).toList();
-						List<Object> list = ls.stream().map(it -> {
-							if ( it instanceof Map<?, ?> map ) {
-								HashMap<Object, Object> map1 = new HashMap<>();
-								columns.forEach(key -> {
-									map1.put(key, map.get(key));
-								});
-								return map1;
-							} else {
-								return it;
-							}
-						}).toList();
-						returnData.put("returnData", list);
-
-					} catch ( Exception e ) {
-						returnData.put("returnData", new ArrayList<>());
-					}
-
-				}
-			}
-		}
-		return ResponseEntity.ok(returnData);
-	}
-
-	/**
-	 * 检查请求是否符合限流规则。
-	 *
-	 * @param uri 请求的URI
-	 *
-	 * @return 如果请求超过限流规则,则返回提示消息;否则返回null。
-	 *
-	 * @throws Exception 抛出异常时处理
-	 */
-	private String checkratelimitrule(String uri) throws Exception {
-		// 从数据库查询限流规则
-		List<Map<String, Object>> ratelimitruleList = DATA_BASE.query(Config.getSecurityConnectionStr(), "select * from ratelimitrule ");
-		Optional<Map<String, Object>> optional = ratelimitruleList.stream().filter(it -> {
-			Object pathMatch = it.get("pathmatch");
-			if ( Objects.isNull(pathMatch) ) return true;
-			return uri.matches(pathMatch.toString());
-		}).findFirst();
-		if ( optional.isPresent() ) {
-			Map<String, Object> map = optional.get();
-			String pathMatch = map.get("pathmatch").toString();
-			if ( ! rateLimiterMap.containsKey(pathMatch) ) {
-				// 创建新的限流器
-				String duration = map.getOrDefault("duration", 1).toString();
-				String limitValue = map.getOrDefault("limitvalue", 100).toString();
-				rateLimiterMap.put(pathMatch, RateLimiter.create(Double.parseDouble(limitValue), Integer.parseInt(duration), TimeUnit.SECONDS));
-			}
-			RateLimiter rateLimiter = rateLimiterMap.get(pathMatch);
-			String timeOut = map.getOrDefault("timeout", 1).toString();
-			// 尝试获取许可,如果失败则表示请求超过限流阈值
-			boolean acquire = rateLimiter.tryAcquire(Integer.parseInt(timeOut), TimeUnit.SECONDS);
-			if ( ! acquire ) {
-				return map.getOrDefault("returnmessage", "请求频率过高,请降低请求频率").toString();
-			}
-		}
-		return null;
-	}
+    // 用于存储限流规则的映射
+    private static final Map<String, RateLimiter> rateLimiterMap = new HashMap<>();
+    
+    // 数据库操作实例
+    private static final DataBase DATA_BASE = new DataBase();
+    
+    /**
+     * 环绕通知,拦截指定包下的Api请求。
+     *
+     * @param joinPoint 切点表达式匹配到的连接点
+     *
+     * @return 返回处理后的响应实体
+     *
+     * @throws Throwable 抛出异常时处理
+     */
+    @Around(value = "within(com.scbfkj.uni.api.*Api)")
+    public ResponseEntity<Object> invokeAround(ProceedingJoinPoint joinPoint) throws Throwable {
+        String methodName = joinPoint.getSignature().getName();
+        String className = joinPoint.getSignature().getDeclaringTypeName();
+        if ("matchService".equals(methodName) && GenericApi.class.getName().equals(className)) {
+            String requestBody = RequestUtil.getRequestBody();
+            if (requestBody != null) {
+                Map<String, Object> body = (Map<String, Object>) DataFormatUtil.toMap(requestBody);
+                joinPoint.getArgs()[0] = body;
+            }
+        }
+        String uri = RequestUtil.getUri();
+        LocalDateTime requestTime = LocalDateTime.now();
+        // 获取请求信息
+        Object[] args = joinPoint.getArgs();
+        Map<String, Object> returnData = null;
+        String message = null;
+        Map<String, Object> userInfo = RequestUtil.getUserInfo();
+        Optional<String> serviceid = Optional.empty();
+        String userId = RequestUtil.getUserId();
+        try {
+            Map<String, Object> body = null;
+            // 检查除特定接口外的服务状态
+            if (args.length > 0 && ! uri.startsWith("/ws")) {
+                Object arg = args[0];
+                if (arg instanceof Map<?, ?> map) {
+                    body = (Map<String, Object>) map;
+                    Util.addFilter(body, serviceid, uri, true);
+                    serviceid = DataAliasGetUtil.getValue("serviceid", (Map<String, Object>) map);
+                    if (serviceid.isEmpty()) {
+                        List<Map<String, Object>> query = DATA_BASE.query(Config.getCenterConnectionStr(),
+                                                                          "select * from serviceinfo where urilist=?",
+                                                                          uri);
+                        if (! query.isEmpty()) {
+                            serviceid = DataAliasGetUtil.getValue("serviceid", query.get(0));
+                        }
+                    }
+                    if (serviceid.isPresent() && ! uri.startsWith("/controlApi") && ! uri.startsWith("/file") &&
+                            ! uri.startsWith("/user") && ! uri.startsWith("/foxlibc")) {
+                        // 检查服务运行状态
+                        List<Map<String, Object>> mapList = DATA_BASE.query(Config.getCenterConnectionStr(),
+                                                                            "select runstate from servicestate where " +
+                                                                                    "stoptime is null and  " +
+                                                                                    "serviceid=? and containercode = ?",
+                                                                            serviceid.get(), Config.getContainerCode());
+                        if (mapList.isEmpty()) {
+                            throw new RuntimeException("服务没有运行或者被熔断");
+                        } else {
+                            Map<String, Object> serviceState = mapList.get(0);
+                            Object o = serviceState.get("runstate");
+                            // 判断服务状态
+                            if (Objects.equals(o.toString(), "0")) {
+                                throw new RuntimeException("服务没有运行或者被熔断");
+                            }
+                        }
+                    }
+                }
+            }
+            // 检查是否符合限流规则
+            message = checkratelimitrule(uri);
+            if (Objects.nonNull(message)) {
+                return ResponseEntity.ok(UniReturnUtil.fail(message));
+            }
+            List<Map<String, Object>> maps =
+                    DATA_BASE.query(Config.getSecurityConnectionStr(), "select 1 from apiinfo where requestpath = ? " +
+                                            "limit 1 offset 0",
+                                    uri);
+            ResponseEntity<Map<String, Object>> responseEntity;
+            if (! maps.isEmpty()) {
+                responseEntity = GenericApi.execService(body, uri);
+            } else {
+                responseEntity = (ResponseEntity<Map<String, Object>>) joinPoint.proceed(args);
+            }
+            // 继续执行原方法逻辑
+            Map<String, Object> responseEntityBody = responseEntity.getBody();
+            if (responseEntity.getStatusCode().is2xxSuccessful()) {
+                if (Config.isDebug()) {
+                    System.out.println("返回值:" + DataFormatUtil.toString(returnData));
+                }
+                // 处理返回数据,如果是调试模式,直接返回
+                if ("0".equals(responseEntityBody.get("code")) && serviceid.isPresent()) {
+                    List<Map<String, Object>> serviceInfoes = DATA_BASE.query(Config.getCenterConnectionStr(),
+                                                                              "select * from serviceinfo where " +
+                                                                                      "serviceid=?",
+                                                                              serviceid.get());
+                    if (! serviceInfoes.isEmpty()) {
+                        Map<String, Object> serviceInfo = serviceInfoes.get(0);
+                        Object raw = serviceInfo.get("raw");
+                        if (raw != null && raw.toString().equalsIgnoreCase("1")) {
+                            Object data = responseEntityBody.getOrDefault("returnData", responseEntityBody);
+                            if (data instanceof List<?> d && d.size() == 1) {
+                                data = d.get(0);
+                            }
+                            return ResponseEntity.ok(data);
+                        }
+                    }
+                }
+                return ResponseEntity.ok(responseEntityBody);
+            } else {
+                returnData = responseEntityBody;
+            }
+        } catch (Throwable e) {
+            if (Config.isDebug()) {
+                e.printStackTrace();
+            }
+            // 错误处理,生成错误日志消息
+            message = UniReturnUtil.getMessage(e);
+            returnData = UniReturnUtil.fail(message);
+        } finally {
+            // 记录日志
+            HashMap<String, Object> logData = new HashMap<>();
+            logData.put("requesttime", requestTime);
+            logData.put("requestpath", uri);
+            logData.put("requestdata", DataFormatUtil.toString(args));
+            logData.put("sessionid", RequestUtil.getSessionId());
+            logData.put("returndata", DataFormatUtil.toString(returnData));
+            logData.put("returntime", LocalDateTime.now());
+            try {
+                logData.put("applicationid", RequestUtil.getAppId());
+            } catch (Exception e) {
+                if (Config.isDebug()) {
+                    e.printStackTrace();
+                }
+            }
+            LoggerService.log(LoggerService.LogType.INTERFACE, logData);
+        }
+        Object code = returnData.get("code");
+        // 过滤返回数据
+        if (! Config.isDebug() && Objects.nonNull(code) && "0".equals(code.toString()) && Objects.nonNull(userInfo) &&
+                ! "0".equals(userInfo.get("usergroupid").toString())) {
+            Object returnData1 = returnData.get("returnData");
+            if (returnData1 instanceof List<?> ls) {
+                if (serviceid.isPresent()) {
+                    try {
+                        List<String> columns = DATA_BASE.query(Config.getSecurityConnectionStr(),
+                                                               "select pagecode from pageconfiguration where " +
+                                                                       "pageconfigurationid  in (select " +
+                                                                       "userpermissions.pageconfigurationid from " +
+                                                                       "userpermissions where  userid =? and  " +
+                                                                       "serviceid = ?)",
+                                                               userId, serviceid.get()).stream()
+                                                        .map(it -> it.get("pagecode").toString()).toList();
+                        List<Object> list = ls.stream().map(it -> {
+                            if (it instanceof Map<?, ?> map) {
+                                HashMap<Object, Object> map1 = new HashMap<>();
+                                columns.forEach(key -> {
+                                    map1.put(key, map.get(key));
+                                });
+                                return map1;
+                            } else {
+                                return it;
+                            }
+                        }).toList();
+                        returnData.put("returnData", list);
+                    } catch (Exception e) {
+                        returnData.put("returnData", new ArrayList<>());
+                    }
+                }
+            }
+        }
+        return ResponseEntity.ok(returnData);
+    }
+    
+    /**
+     * 检查请求是否符合限流规则。
+     *
+     * @param uri 请求的URI
+     *
+     * @return 如果请求超过限流规则,则返回提示消息;否则返回null。
+     *
+     * @throws Exception 抛出异常时处理
+     */
+    private String checkratelimitrule(String uri) throws Exception {
+        // 从数据库查询限流规则
+        List<Map<String, Object>> ratelimitruleList =
+                DATA_BASE.query(Config.getSecurityConnectionStr(), "select * from ratelimitrule ");
+        Optional<Map<String, Object>> optional = ratelimitruleList.stream().filter(it -> {
+            Object pathMatch = it.get("pathmatch");
+            if (Objects.isNull(pathMatch)) {
+                return true;
+            }
+            return uri.matches(pathMatch.toString());
+        }).findFirst();
+        if (optional.isPresent()) {
+            Map<String, Object> map = optional.get();
+            String pathMatch = map.get("pathmatch").toString();
+            if (! rateLimiterMap.containsKey(pathMatch)) {
+                // 创建新的限流器
+                String duration = map.getOrDefault("duration", 1).toString();
+                String limitValue = map.getOrDefault("limitvalue", 100).toString();
+                rateLimiterMap.put(pathMatch,
+                                   RateLimiter.create(Double.parseDouble(limitValue), Integer.parseInt(duration),
+                                                      TimeUnit.SECONDS));
+            }
+            RateLimiter rateLimiter = rateLimiterMap.get(pathMatch);
+            String timeOut = map.getOrDefault("timeout", 1).toString();
+            // 尝试获取许可,如果失败则表示请求超过限流阈值
+            boolean acquire = rateLimiter.tryAcquire(Integer.parseInt(timeOut), TimeUnit.SECONDS);
+            if (! acquire) {
+                return map.getOrDefault("returnmessage", "请求频率过高,请降低请求频率").toString();
+            }
+        }
+        return null;
+    }
 }
 

+ 377 - 364
src/main/java/com/scbfkj/uni/library/RequestUtil.java

@@ -1,379 +1,392 @@
 package com.scbfkj.uni.library;
 
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.scbfkj.uni.process.DataBase;
 import com.scbfkj.uni.system.Config;
 import jakarta.servlet.ServletInputStream;
 import jakarta.servlet.http.HttpServletRequest;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.time.LocalDateTime;
-import java.util.*;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 
 public class RequestUtil {
-	public final static String APP_ID = "appid";
-	private static final DataBase DATABASE = new DataBase();
-
-	private RequestUtil() {
-	}
-
-	/**
-	 * 获取客户端IP地址 该方法首先尝试从HTTP请求头中的"x-forwarded-for"字段获取IP地址,如果该字段不存在或为空,
-	 * 则尝试从"Proxy-Client-IP"字段获取,接着是"WL-Proxy-Client-IP"字段, 如果所有尝试都失败或返回不可识别的值,则返回远程地址。
-	 * 注意:这个方法适用于通过代理或负载均衡服务器转发的请求获取真实客户端IP地址的场景。
-	 *
-	 * @return 客户端的IP地址字符串。如果无法确定客户端IP地址,则返回null。
-	 */
-	public static String getIpAddr() {
-		String ip = getHeader("x-forwarded-for"); // 尝试从"x-forwarded-for"头部获取IP地址
-		String unknown = "unknown";
-		if ( ip == null || ip.isEmpty() || unknown.equalsIgnoreCase(ip) ) {
-			ip = getHeader("Proxy-Client-IP"); // 如果失败,尝试从"Proxy-Client-IP"头部获取
-		}
-		if ( ip == null || ip.isEmpty() || unknown.equalsIgnoreCase(ip) ) {
-			ip = getHeader("WL-Proxy-Client-IP"); // 如果再次失败,尝试从"WL-Proxy-Client-IP"头部获取
-		}
-		if ( ip == null || ip.isEmpty() || unknown.equalsIgnoreCase(ip) ) {
-			ip = getRemoteAddr(); // 所有尝试失败,返回远程地址
-		}
-		return ip;
-	}
-
-	/**
-	 * 获取当前请求的客户端IP地址。
-	 * <p>
-	 * 该方法不接受任何参数,它通过检索当前线程绑定的ServletRequestAttributes, 进而获取HttpServletRequest对象,最后从HttpServletRequest中提取客户端的IP地址。
-	 *
-	 * @return String 客户端的IP地址。
-	 */
-	private static String getRemoteAddr() {
-		// 获取当前请求的属性
-		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
-		// 从属性中获取HttpServletRequest对象
-		HttpServletRequest request = requestAttributes.getRequest();
-		// 返回客户端的IP地址
-		return request.getRemoteAddr();
-	}
-
-	/**
-	 * 获取应用令牌。
-	 * <p>此方法从请求头中获取名为"token"的字段值,并返回其字符串表示形式。
-	 * 如果找不到该字段或字段值为null,则返回null。</p>
-	 *
-	 * @return 如果找到有效的token,则返回其字符串形式;否则返回null。
-	 */
-	public static String getAppToken() {
-		// 从请求头中获取名为"token"的字段值
-		Object appToken = getHeader("token");
-		// 判断appToken是否非空,非空则返回其字符串形式,否则返回null
-		return Objects.nonNull(appToken) ? appToken.toString() : null;
-	}
-
-	/**
-	 * 获取用户令牌。
-	 * <p>
-	 * 该方法从请求头中提取名为"usertoken"的字段,并返回其值。 如果不存在该字段,则返回null。
-	 *
-	 * @return 用户令牌的字符串表示,如果不存在则返回null。
-	 */
-	public static String getUserToken() {
-		// 从请求头中获取名为"usertoken"的字段
-		Object userToken = getHeader("usertoken");
-		// 判断用户令牌是否非空,非空则返回其字符串形式,否则返回null
-		return Objects.nonNull(userToken) ? userToken.toString() : null;
-	}
-
-	/**
-	 * 获取当前HTTP请求的指定头信息。
-	 *
-	 * @param headerName 需要获取的头名称。
-	 *
-	 * @return 返回请求头中指定头名称的值。如果不存在该头,则返回null。
-	 */
-	private static String getHeader(String headerName) {
-		// 获取当前请求的属性
-		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
-		// 从属性中获取HttpServletRequest对象
-		HttpServletRequest request = requestAttributes.getRequest();
-		// 返回指定头名称的值
-		return request.getHeader(headerName);
-	}
-
-	/**
-	 * 获取当前HTTP请求的所有头信息。
-	 * <p>
-	 * 该方法不接受任何参数,但需要当前线程绑定的HTTP请求上下文。
-	 *
-	 * @return 一个包含所有头信息的Map,其中头名称为键,头值为值。
-	 */
-	public static Map<String, String> getHeaders() {
-		// 获取当前请求的属性
-		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
-		// 从属性中获取HttpServletRequest对象
-		HttpServletRequest request = requestAttributes.getRequest();
-		// 获取所有头名称的枚举
-		Enumeration<String> headerNames = request.getHeaderNames();
-		// 创建一个空的Map来存储头信息
-		Map<String, String> headers = new HashMap<>();
-		// 遍历所有头名称,并将它们及其对应的值添加到Map中
-		while ( headerNames.hasMoreElements() ) {
-			String element = headerNames.nextElement();
-			headers.put(element, request.getHeader(element));
-		}
-		// 返回包含所有头信息的Map
-		return headers;
-	}
-
-	/**
-	 * 获取应用程序ID。 此方法首先尝试从会话ID中检索应用程序ID。如果会话ID不存在或相关应用程序ID未找到, 则方法将尝试从应用程序实例中获取应用程序ID。
-	 *
-	 * @return 返回应用程序ID的字符串表示。如果无法获取有效的应用程序ID,则返回null。
-	 *
-	 * @throws Exception 如果在获取会话ID或应用程序ID过程中遇到错误,则抛出异常。
-	 */
-	public static String getAppId() throws Exception {
-		String session = getSessionId(); // 尝试获取会话ID
-		if ( session == null ) {
-			return null; // 如果会话ID不存在,直接返回null
-		}
-		// 尝试从缓存中获取会话信息
-		Map<String, Object> sessionMap = Config.CACHE.get(session);
-		if ( sessionMap == null ) {
-			sessionMap = new Hashtable<>(); // 如果会话信息不存在,则创建新的会话信息容器
-			Config.CACHE.put(session, sessionMap); // 将新的会话信息容器放入缓存
-		}
-		// 尝试从会话信息中获取应用程序ID
-		Object appid = sessionMap.get(APP_ID);
-		if ( Objects.nonNull(appid) ) {
-			return appid.toString(); // 如果找到应用程序ID,返回其字符串形式
-		}
-		// 如果在会话信息中未找到应用程序ID,尝试从应用程序实例中获取并返回
-		return getApplication().get(APP_ID).toString();
-	}
-
-	/**
-	 * 获取当前应用的信息。
-	 * <p>
-	 * 这个方法首先会尝试从会话中获取应用信息。如果会话中不存在该信息,则会通过应用令牌和请求IP来查询数据库, 获取应用的详细信息,并将其保存到会话中,供后续使用。
-	 * </p>
-	 *
-	 * @return 一个包含应用信息的Map对象。如果会话不存在或应用未登录,则返回null。
-	 *
-	 * @throws Exception 如果查询数据库时发生错误,或者无法获取应用信息,则抛出异常。
-	 */
-	public static Map<String, Object> getApplication() throws Exception {
-
-		String session = getSessionId();
-		String clean = "delete from appconnectlog where expiretime <  ?";
-
-		// 清理数据库中过期的连接日志
-		DATABASE.update(Config.getSecurityConnectionStr(), clean, LocalDateTime.now());
-
-		// 检查会话是否有效
-		if ( session == null ) {
-			return null;
-		}
-		Map<String, Object> sessionMap = Config.CACHE.get(session);
-		if ( sessionMap == null ) {
-			sessionMap = new Hashtable<>();
-			Config.CACHE.put(session, sessionMap);
-		}
-		// 尝试从会话映射中获取应用信息
-		Object application = sessionMap.get("application");
-		if ( Objects.isNull(application) ) {
-			// 如果应用信息不存在,则通过应用令牌和IP地址查询应用连接日志
-			String appToken = getAppToken();
-			String requestIp = getIpAddr();
-			String query = "select appid from appconnectlog where apptoken=? and requestip =? and expiretime >  ?";
-			List<Map<String, Object>> appConnectLogList = DATABASE.query(Config.getSecurityConnectionStr(), query,
-			                                                             appToken, requestIp, LocalDateTime.now());
-			// 如果查询结果为空,表示应用未登录
-			if ( appConnectLogList.isEmpty() ) {
-				throw new RuntimeException("当前连接未登录");
-			}
-			// 获取应用ID
-			Map<String, Object> stringObjectMap = appConnectLogList.get(0);
-			Object applicationid = stringObjectMap.get(APP_ID);
-
-			// 根据应用ID查询应用的详细信息
-			query = """
-					select applicationid,
-					       appid,
-					       appsecret,
-					       appname,
-					       appengname,
-					       appdescribe,
-					       applogo,
-					       smalllogo,
-					       backgroundimage,
-					       apptokeneffective,
-					       securitycoderule,
-					       securitycodeeffective,
-					       multilogin,
-					       passwordrule,
-					       passwordeffective
-					from application
-					where appid = ?""";
-			List<Map<String, Object>> applicationList = DATABASE.query(Config.getSecurityConnectionStr(), query, applicationid);
-			// 如果查询结果为空,表示无法获取应用信息
-			if ( applicationList.isEmpty() ) {
-				throw new RuntimeException("获取应用失败");
-			}
-			// 保存查询到的应用信息到会话映射中
-			application = applicationList.get(0);
-
-			sessionMap.put("application", application);
-
-		}
-		// 将应用信息转换为Map对象并返回
-		Map<String, Object> applicationMap = (Map<String, Object>) application;
-
-		return applicationMap;
-
-
-	}
-
-	/**
-	 * 获取用户ID。
-	 * <p>此方法不接受任何参数,尝试从外部获取用户信息,并提取其中的用户ID。</p>
-	 *
-	 * @return 返回用户ID的字符串形式。如果无法获取用户信息或用户信息中不包含用户ID,则返回null。
-	 */
-	public static String getUserId() {
-
-		// 尝试获取用户信息
-		Map<String, Object> userInfo = getUserInfo();
-		if ( Objects.isNull(userInfo) ) {
-			return null;
-		} else {
-			// 从用户信息中提取用户ID,并转换为字符串格式
-			Object userid = userInfo.get("userid");
-			return Objects.isNull(userid) ? null : DataFormatUtil.toString(userid);
-		}
-	}
-
-	/**
-	 * 获取用户信息。 此方法会首先尝试从会话ID中获取用户信息,如果不存在,则返回null。 如果会话ID存在但对应用户信息为空,则创建一个新的用户信息容器并返回。
-	 *
-	 * @return Map<String, Object> 如果用户信息存在,则返回一个包含用户信息的Map;否则返回null。
-	 */
-	public static Map<String, Object> getUserInfo() {
-
-		// 获取当前会话ID
-		String session = getSessionId();
-		// 如果会话ID为空,则直接返回null
-		if ( session == null ) {
-			return null;
-		}
-		// 尝试从缓存中获取会话对应的用户信息
-		Map<String, Object> sessionMap = Config.CACHE.get(session);
-		// 如果该会话ID未被缓存,创建一个新的会话信息容器并加入缓存
-		if ( sessionMap == null ) {
-			sessionMap = new Hashtable<>();
-			Config.CACHE.put(session, sessionMap);
-		}
-		// 尝试从会话信息容器中获取用户信息
-		Object userInfo = sessionMap.get("userinfo");
-		// 如果用户信息存在,则返回,否则返回null
-		return Objects.nonNull(userInfo) ? (Map<String, Object>) userInfo : null;
-	}
-
-	/**
-	 * 获取会话ID。
-	 * <p>
-	 * 该方法是一个静态方法,不需要实例化对象即可调用。它通过调用另一个名为getHeader的方法, 并传入参数"sessionid"来获取会话ID。会话ID通常用于追踪和识别用户在应用程序中的会话。
-	 *
-	 * @return 返回一个String类型的会话ID。如果无法获取到会话ID,则可能返回null或空字符串, 具体取决于getHeader方法的实现。
-	 */
-	public static String getSessionId() {
-		return getHeader("sessionid");
-	}
-
-	/**
-	 * 获取当前请求的URI。
-	 * <p>
-	 * 该方法不接受任何参数。
-	 *
-	 * @return 返回当前HTTP请求的URI字符串。
-	 */
-	public static String getUri() {
-		// 获取当前请求的属性
-		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
-
-		// 从请求属性中提取并返回请求的URI
-		return requestAttributes.getRequest().getRequestURI();
-	}
-
-	/**
-	 * 获取当前线程中的HttpServletRequest对象。 本方法主要用于在Spring MVC环境下,获取当前请求的HttpServletRequest对象。
-	 * 通过利用Spring提供的RequestContextHolder工具类,可以方便地获取到当前线程绑定的请求属性, 进而获取到HttpServletRequest对象,以便进行后续的请求处理或信息获取操作。
-	 *
-	 * @return 当前线程中的HttpServletRequest对象,如果线程中没有绑定请求属性,则返回null。
-	 */
-	public static HttpServletRequest getRequest() {
-		// 通过RequestContextHolder获取当前线程绑定的请求属性
-		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
-
-		// 从请求属性中获取HttpServletRequest对象并返回
-		return requestAttributes.getRequest();
-	}
-
-	/**
-	 * 从HttpServletRequest中获取请求体的内容。
-	 * <p>
-	 * 注意:此操作会消费输入流,确保在调用此方法前未有其他组件读取过请求体
-	 *
-	 * @return 请求体中的字符串内容,如果发生IO异常则返回null。
-	 */
-	public static String getRequestBody() {
-		HttpServletRequest request = getRequest();
-		try {
-			StringBuilder stringBuilder = new StringBuilder();
-			BufferedReader bufferedReader = null;
-
-			// 获取请求的输入流
-			ServletInputStream inputStream = request.getInputStream();
-			if ( inputStream != null ) {
-				bufferedReader = new BufferedReader(new InputStreamReader(inputStream, request.getCharacterEncoding()));
-
-				// 读取请求体内容
-				char[] charBuffer = new char[128];
-				int bytesRead = - 1;
-				while ( (bytesRead = bufferedReader.read(charBuffer)) > 0 ) {
-					stringBuilder.append(charBuffer, 0, bytesRead);
-				}
-			}
-			String body = stringBuilder.toString();
-			try {
-				DataFormatUtil.getObjectMapper().readValue(body, Map.class);
-			} catch ( JsonProcessingException e ) {
-				Map<String, String> temp = new HashMap<>();
-				for ( String s : body.split("&") ) {
-					String[] strings = s.split("=");
-					temp.put(strings[0], strings[1]);
-				}
-				body = DataFormatUtil.toString(temp);
-			}
-
-			if ( ! request.getParameterMap().isEmpty() && stringBuilder.isEmpty() ) {
-				return DataFormatUtil.toString(request.getParameterMap());
-			}
-
-			// 关闭流(如果使用了bufferedReader)
-			if ( bufferedReader != null ) {
-				bufferedReader.close();
-			}
-
-			return body;
-		} catch ( IOException e ) {
-			// 处理读取时的IO异常
-			e.printStackTrace();
-			return null;
-		}
-	}
-
+    public final static String APP_ID = "appid";
+    
+    private static final DataBase DATABASE = new DataBase();
+    
+    private RequestUtil() {
+    }
+    
+    /**
+     * 获取客户端IP地址 该方法首先尝试从HTTP请求头中的"x-forwarded-for"字段获取IP地址,如果该字段不存在或为空,
+     * 则尝试从"Proxy-Client-IP"字段获取,接着是"WL-Proxy-Client-IP"字段, 如果所有尝试都失败或返回不可识别的值,则返回远程地址。
+     * 注意:这个方法适用于通过代理或负载均衡服务器转发的请求获取真实客户端IP地址的场景。
+     *
+     * @return 客户端的IP地址字符串。如果无法确定客户端IP地址,则返回null。
+     */
+    public static String getIpAddr() {
+        String ip = getHeader("x-forwarded-for"); // 尝试从"x-forwarded-for"头部获取IP地址
+        String unknown = "unknown";
+        if (ip == null || ip.isEmpty() || unknown.equalsIgnoreCase(ip)) {
+            ip = getHeader("Proxy-Client-IP"); // 如果失败,尝试从"Proxy-Client-IP"头部获取
+        }
+        if (ip == null || ip.isEmpty() || unknown.equalsIgnoreCase(ip)) {
+            ip = getHeader("WL-Proxy-Client-IP"); // 如果再次失败,尝试从"WL-Proxy-Client-IP"头部获取
+        }
+        if (ip == null || ip.isEmpty() || unknown.equalsIgnoreCase(ip)) {
+            ip = getRemoteAddr(); // 所有尝试失败,返回远程地址
+        }
+        return ip;
+    }
+    
+    /**
+     * 获取当前请求的客户端IP地址。
+     * <p>
+     * 该方法不接受任何参数,它通过检索当前线程绑定的ServletRequestAttributes, 进而获取HttpServletRequest对象,最后从HttpServletRequest中提取客户端的IP地址。
+     *
+     * @return String 客户端的IP地址。
+     */
+    private static String getRemoteAddr() {
+        // 获取当前请求的属性
+        ServletRequestAttributes requestAttributes =
+                (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
+        // 从属性中获取HttpServletRequest对象
+        HttpServletRequest request = requestAttributes.getRequest();
+        // 返回客户端的IP地址
+        return request.getRemoteAddr();
+    }
+    
+    /**
+     * 获取应用令牌。
+     * <p>此方法从请求头中获取名为"token"的字段值,并返回其字符串表示形式。
+     * 如果找不到该字段或字段值为null,则返回null。</p>
+     *
+     * @return 如果找到有效的token,则返回其字符串形式;否则返回null。
+     */
+    public static String getAppToken() {
+        // 从请求头中获取名为"token"的字段值
+        Object appToken = getHeader("token");
+        // 判断appToken是否非空,非空则返回其字符串形式,否则返回null
+        return Objects.nonNull(appToken) ? appToken.toString() : null;
+    }
+    
+    /**
+     * 获取用户令牌。
+     * <p>
+     * 该方法从请求头中提取名为"usertoken"的字段,并返回其值。 如果不存在该字段,则返回null。
+     *
+     * @return 用户令牌的字符串表示,如果不存在则返回null。
+     */
+    public static String getUserToken() {
+        // 从请求头中获取名为"usertoken"的字段
+        Object userToken = getHeader("usertoken");
+        // 判断用户令牌是否非空,非空则返回其字符串形式,否则返回null
+        return Objects.nonNull(userToken) ? userToken.toString() : null;
+    }
+    
+    /**
+     * 获取当前HTTP请求的指定头信息。
+     *
+     * @param headerName 需要获取的头名称。
+     *
+     * @return 返回请求头中指定头名称的值。如果不存在该头,则返回null。
+     */
+    private static String getHeader(String headerName) {
+        // 获取当前请求的属性
+        ServletRequestAttributes requestAttributes =
+                (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
+        // 从属性中获取HttpServletRequest对象
+        HttpServletRequest request = requestAttributes.getRequest();
+        // 返回指定头名称的值
+        return request.getHeader(headerName);
+    }
+    
+    /**
+     * 获取当前HTTP请求的所有头信息。
+     * <p>
+     * 该方法不接受任何参数,但需要当前线程绑定的HTTP请求上下文。
+     *
+     * @return 一个包含所有头信息的Map,其中头名称为键,头值为值。
+     */
+    public static Map<String, String> getHeaders() {
+        // 获取当前请求的属性
+        ServletRequestAttributes requestAttributes =
+                (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
+        // 从属性中获取HttpServletRequest对象
+        HttpServletRequest request = requestAttributes.getRequest();
+        // 获取所有头名称的枚举
+        Enumeration<String> headerNames = request.getHeaderNames();
+        // 创建一个空的Map来存储头信息
+        Map<String, String> headers = new HashMap<>();
+        // 遍历所有头名称,并将它们及其对应的值添加到Map中
+        while (headerNames.hasMoreElements()) {
+            String element = headerNames.nextElement();
+            headers.put(element, request.getHeader(element));
+        }
+        // 返回包含所有头信息的Map
+        return headers;
+    }
+    
+    /**
+     * 获取应用程序ID。 此方法首先尝试从会话ID中检索应用程序ID。如果会话ID不存在或相关应用程序ID未找到, 则方法将尝试从应用程序实例中获取应用程序ID。
+     *
+     * @return 返回应用程序ID的字符串表示。如果无法获取有效的应用程序ID,则返回null。
+     *
+     * @throws Exception 如果在获取会话ID或应用程序ID过程中遇到错误,则抛出异常。
+     */
+    public static String getAppId() throws Exception {
+        String session = getSessionId(); // 尝试获取会话ID
+        if (session == null) {
+            return null; // 如果会话ID不存在,直接返回null
+        }
+        // 尝试从缓存中获取会话信息
+        Map<String, Object> sessionMap = Config.CACHE.get(session);
+        if (sessionMap == null) {
+            sessionMap = new Hashtable<>(); // 如果会话信息不存在,则创建新的会话信息容器
+            Config.CACHE.put(session, sessionMap); // 将新的会话信息容器放入缓存
+        }
+        // 尝试从会话信息中获取应用程序ID
+        Object appid = sessionMap.get(APP_ID);
+        if (Objects.nonNull(appid)) {
+            return appid.toString(); // 如果找到应用程序ID,返回其字符串形式
+        }
+        // 如果在会话信息中未找到应用程序ID,尝试从应用程序实例中获取并返回
+        return getApplication().get(APP_ID).toString();
+    }
+    
+    /**
+     * 获取当前应用的信息。
+     * <p>
+     * 这个方法首先会尝试从会话中获取应用信息。如果会话中不存在该信息,则会通过应用令牌和请求IP来查询数据库, 获取应用的详细信息,并将其保存到会话中,供后续使用。
+     * </p>
+     *
+     * @return 一个包含应用信息的Map对象。如果会话不存在或应用未登录,则返回null。
+     *
+     * @throws Exception 如果查询数据库时发生错误,或者无法获取应用信息,则抛出异常。
+     */
+    public static Map<String, Object> getApplication() throws Exception {
+        String session = getSessionId();
+        String clean = "delete from appconnectlog where expiretime <  ?";
+        // 清理数据库中过期的连接日志
+        DATABASE.update(Config.getSecurityConnectionStr(), clean, LocalDateTime.now());
+        // 检查会话是否有效
+        if (session == null) {
+            return null;
+        }
+        Map<String, Object> sessionMap = Config.CACHE.get(session);
+        if (sessionMap == null) {
+            sessionMap = new Hashtable<>();
+            Config.CACHE.put(session, sessionMap);
+        }
+        // 尝试从会话映射中获取应用信息
+        Object application = sessionMap.get("application");
+        if (Objects.isNull(application)) {
+            // 如果应用信息不存在,则通过应用令牌和IP地址查询应用连接日志
+            String appToken = getAppToken();
+            String requestIp = getIpAddr();
+            String query = "select appid from appconnectlog where apptoken=? and requestip =? and expiretime >  ?";
+            List<Map<String, Object>> appConnectLogList =
+                    DATABASE.query(Config.getSecurityConnectionStr(), query, appToken, requestIp, LocalDateTime.now());
+            // 如果查询结果为空,表示应用未登录
+            if (appConnectLogList.isEmpty()) {
+                throw new RuntimeException("当前连接未登录");
+            }
+            // 获取应用ID
+            Map<String, Object> stringObjectMap = appConnectLogList.get(0);
+            Object applicationid = stringObjectMap.get(APP_ID);
+            // 根据应用ID查询应用的详细信息
+            query = """
+                    select applicationid,
+                           appid,
+                           appsecret,
+                           appname,
+                           appengname,
+                           appdescribe,
+                           applogo,
+                           smalllogo,
+                           backgroundimage,
+                           apptokeneffective,
+                           securitycoderule,
+                           securitycodeeffective,
+                           multilogin,
+                           passwordrule,
+                           passwordeffective
+                    from application
+                    where appid = ?""";
+            List<Map<String, Object>> applicationList =
+                    DATABASE.query(Config.getSecurityConnectionStr(), query, applicationid);
+            // 如果查询结果为空,表示无法获取应用信息
+            if (applicationList.isEmpty()) {
+                throw new RuntimeException("获取应用失败");
+            }
+            // 保存查询到的应用信息到会话映射中
+            application = applicationList.get(0);
+            sessionMap.put("application", application);
+        }
+        // 将应用信息转换为Map对象并返回
+        Map<String, Object> applicationMap = (Map<String, Object>) application;
+        return applicationMap;
+    }
+    
+    /**
+     * 获取用户ID。
+     * <p>此方法不接受任何参数,尝试从外部获取用户信息,并提取其中的用户ID。</p>
+     *
+     * @return 返回用户ID的字符串形式。如果无法获取用户信息或用户信息中不包含用户ID,则返回null。
+     */
+    public static String getUserId() throws Exception {
+        // 尝试获取用户信息
+        Map<String, Object> userInfo = getUserInfo();
+        if (Objects.isNull(userInfo)) {
+            return null;
+        } else {
+            // 从用户信息中提取用户ID,并转换为字符串格式
+            Object userid = userInfo.get("userid");
+            return Objects.isNull(userid) ? null : DataFormatUtil.toString(userid);
+        }
+    }
+    
+    /**
+     * 获取用户信息。 此方法会首先尝试从会话ID中获取用户信息,如果不存在,则返回null。 如果会话ID存在但对应用户信息为空,则创建一个新的用户信息容器并返回。
+     *
+     * @return Map<String, Object> 如果用户信息存在,则返回一个包含用户信息的Map;否则返回null。
+     */
+    public static Map<String, Object> getUserInfo() throws Exception {
+        // 获取当前会话ID
+        String session = getSessionId();
+        // 如果会话ID为空,则直接返回null
+        if (session == null) {
+            return null;
+        }
+        // 尝试从缓存中获取会话对应的用户信息
+        Map<String, Object> sessionMap = Config.CACHE.get(session);
+        // 如果该会话ID未被缓存,创建一个新的会话信息容器并加入缓存
+        if (sessionMap == null) {
+            sessionMap = new Hashtable<>();
+            Config.CACHE.put(session, sessionMap);
+        }
+        // 尝试从会话信息容器中获取用户信息
+        Object userInfo = sessionMap.get("userinfo");
+        if (userInfo == null) {
+            List<Map<String, Object>> useLloginLogList = DATABASE.query(Config.getSecurityConnectionStr(),
+                                                                        "select * " + "from " + "userloginlog where " +
+                                                                                "sessionid = ?", session);
+            if (! useLloginLogList.isEmpty()) {
+                Map<String, Object> stringObjectMap = useLloginLogList.get(0);
+                Object userIdObj = stringObjectMap.get("userid");
+                if (userIdObj != null) {
+                    long userId = Long.parseLong(userIdObj.toString());
+                    List<Map<String, Object>> userInfoMapList = DATABASE.query(Config.getSecurityConnectionStr(),
+                                                                               "select * " + "from " +
+                                                                                       "userinfo where " + "userid = ?",
+                                                                               userId);
+                    if (! userInfoMapList.isEmpty()) {
+                        userInfo = userInfoMapList.get(0);
+                    }
+                }
+            }
+        }
+        // 如果用户信息存在,则返回,否则返回null
+        return Objects.nonNull(userInfo) ? (Map<String, Object>) userInfo : null;
+    }
+    
+    /**
+     * 获取会话ID。
+     * <p>
+     * 该方法是一个静态方法,不需要实例化对象即可调用。它通过调用另一个名为getHeader的方法, 并传入参数"sessionid"来获取会话ID。会话ID通常用于追踪和识别用户在应用程序中的会话。
+     *
+     * @return 返回一个String类型的会话ID。如果无法获取到会话ID,则可能返回null或空字符串, 具体取决于getHeader方法的实现。
+     */
+    public static String getSessionId() {
+        return getHeader("sessionid");
+    }
+    
+    /**
+     * 获取当前请求的URI。
+     * <p>
+     * 该方法不接受任何参数。
+     *
+     * @return 返回当前HTTP请求的URI字符串。
+     */
+    public static String getUri() {
+        // 获取当前请求的属性
+        ServletRequestAttributes requestAttributes =
+                (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
+        // 从请求属性中提取并返回请求的URI
+        return requestAttributes.getRequest().getRequestURI();
+    }
+    
+    /**
+     * 获取当前线程中的HttpServletRequest对象。 本方法主要用于在Spring MVC环境下,获取当前请求的HttpServletRequest对象。
+     * 通过利用Spring提供的RequestContextHolder工具类,可以方便地获取到当前线程绑定的请求属性, 进而获取到HttpServletRequest对象,以便进行后续的请求处理或信息获取操作。
+     *
+     * @return 当前线程中的HttpServletRequest对象,如果线程中没有绑定请求属性,则返回null。
+     */
+    public static HttpServletRequest getRequest() {
+        // 通过RequestContextHolder获取当前线程绑定的请求属性
+        ServletRequestAttributes requestAttributes =
+                (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
+        // 从请求属性中获取HttpServletRequest对象并返回
+        return requestAttributes.getRequest();
+    }
+    
+    /**
+     * 从HttpServletRequest中获取请求体的内容。
+     * <p>
+     * 注意:此操作会消费输入流,确保在调用此方法前未有其他组件读取过请求体
+     *
+     * @return 请求体中的字符串内容,如果发生IO异常则返回null。
+     */
+    public static String getRequestBody() {
+        HttpServletRequest request = getRequest();
+        try {
+            StringBuilder stringBuilder = new StringBuilder();
+            BufferedReader bufferedReader = null;
+            // 获取请求的输入流
+            ServletInputStream inputStream = request.getInputStream();
+            if (inputStream != null) {
+                bufferedReader = new BufferedReader(new InputStreamReader(inputStream, request.getCharacterEncoding()));
+                // 读取请求体内容
+                char[] charBuffer = new char[128];
+                int bytesRead = - 1;
+                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+                    stringBuilder.append(charBuffer, 0, bytesRead);
+                }
+            }
+            String body = stringBuilder.toString();
+            try {
+                DataFormatUtil.getObjectMapper().readValue(body, Map.class);
+            } catch (JsonProcessingException e) {
+                Map<String, String> temp = new HashMap<>();
+                for (String s : body.split("&")) {
+                    String[] strings = s.split("=");
+                    temp.put(strings[0], strings[1]);
+                }
+                body = DataFormatUtil.toString(temp);
+            }
+            if (! request.getParameterMap().isEmpty() && stringBuilder.isEmpty()) {
+                return DataFormatUtil.toString(request.getParameterMap());
+            }
+            // 关闭流(如果使用了bufferedReader)
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+            return body;
+        } catch (IOException e) {
+            // 处理读取时的IO异常
+            e.printStackTrace();
+            return null;
+        }
+    }
 }

+ 114 - 94
src/main/java/com/scbfkj/uni/library/script/JavaScriptEngineUtil.java

@@ -1,14 +1,15 @@
 package com.scbfkj.uni.library.script;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.scbfkj.uni.library.DataFormatUtil;
-import com.scbfkj.uni.library.UniReturnUtil;
 import org.apache.commons.pool2.BaseKeyedPooledObjectFactory;
 import org.apache.commons.pool2.KeyedObjectPool;
 import org.apache.commons.pool2.PooledObject;
 import org.apache.commons.pool2.impl.DefaultPooledObject;
 import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.scbfkj.uni.library.DataFormatUtil;
+import com.scbfkj.uni.library.UniReturnUtil;
+
 import java.io.File;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -19,100 +20,115 @@ import java.util.Map;
 import java.util.Objects;
 
 public class JavaScriptEngineUtil {
-/**
- * 创建并管理Java应用执行实例的池子。这个池子keyed到具体的执行路径和类名上,允许复用Java方法的执行实例。
- */
-private static final KeyedObjectPool<String, JavaApply> javaRefPool = new GenericKeyedObjectPool<>(new BaseKeyedPooledObjectFactory<String, JavaApply>() {
-
-    /**
-     * 根据提供的key创建一个新的JavaApply实例。
-     * @param key 包含执行路径、类名和方法名的JSON字符串。
-     * @return 一个初始化好的JavaApply实例,准备放入池中供调用。
-     * @throws Exception 如果过程中出现错误,比如类加载失败或方法找不到。
-     */
-    @Override
-    public JavaApply create(String key) throws Exception {
-        // 从key解析出路径、类名和方法名
-        JsonNode jsonNode = DataFormatUtil.toJsonNode(key);
-        JsonNode path = jsonNode.get("path");
-        JsonNode className = jsonNode.get("className");
-        JsonNode method = jsonNode.get("methodName");
-        ClassLoader classLoader = null;
-        // 根据提供的路径加载外部类
-        if (Objects.nonNull(path) && !path.isNull()) {
-            String userPath = System.getProperty("user.dir");
-            File file = new File(userPath.concat(File.separator).concat("plugins").concat(File.separator).concat(path.asText()));
-            // 检查文件是否存在
-            if (!file.exists()) {
-                throw new RuntimeException("外部文件加载不存在:".concat(userPath).concat(File.separator).concat("plugins").concat(File.separator).concat(path.asText()));
-            }
-            URL url = file.toURI().toURL();
-            classLoader = new URLClassLoader(new URL[]{url}, Thread.currentThread().getContextClassLoader());
-        } else {
-            classLoader = Thread.currentThread().getContextClassLoader();
-        }
-        // 加载指定的类和方法
-        Class<?> classExample = classLoader.loadClass(className.asText());
-        Method javaMethod = null;
-        Method closeMethod = null;
-        for (Method currentMethod : classExample.getMethods()) {
-            String methodName = currentMethod.getName();
-            if (methodName.equals(method.asText())) {
-                javaMethod = currentMethod;
-            } else if ("close".equals(methodName)) {
-                closeMethod = currentMethod;
-            }
-        }
-
-        Object classInstance = null;
-        if (javaMethod != null) {
-            int modifiers = javaMethod.getModifiers();
-            boolean aStatic = Modifier.isStatic(modifiers);
-            // 如果方法非静态,则实例化类
-            if (!aStatic) {
-                classInstance = classExample.getConstructor().newInstance();
-            }
-        }
-
-        // 返回包含类实例、方法和关闭方法的JavaApply对象
-        return new JavaApply(classInstance, javaMethod, closeMethod);
-    }
-    /**
-     * 将JavaApply实例包装成池能够管理的形式。
-     * @param value 需要被包装的JavaApply实例。
-     * @return 一个DefaultPooledObject,包含了一个JavaApply实例。
-     */
-    @Override
-    public PooledObject<JavaApply> wrap(JavaApply value) {
-        return new DefaultPooledObject<>(value);
-    }
     /**
-     * 销毁从池中取出并使用后的JavaApply实例,调用其关闭方法。
-     * @param key 与该实例对应的key。
-     * @param p 包含了需要销毁的JavaApply实例的DefaultPooledObject。
-     * @throws Exception 如果在销毁过程中出现错误。
+     * 创建并管理Java应用执行实例的池子。这个池子keyed到具体的执行路径和类名上,允许复用Java方法的执行实例。
      */
-    @Override
-    public void destroyObject(String key, PooledObject<JavaApply> p) throws Exception {
-        JavaApply javaApply = p.getObject();
-        javaApply.invokeClose();
-    }
-});
-
+    private static final KeyedObjectPool<String, JavaApply> javaRefPool =
+            new GenericKeyedObjectPool<>(new BaseKeyedPooledObjectFactory<String, JavaApply>() {
+                /**
+                 * 根据提供的key创建一个新的JavaApply实例。
+                 * @param key 包含执行路径、类名和方法名的JSON字符串。
+                 * @return 一个初始化好的JavaApply实例,准备放入池中供调用。
+                 * @throws Exception 如果过程中出现错误,比如类加载失败或方法找不到。
+                 */
+                @Override
+                public JavaApply create(String key) throws Exception {
+                    // 从key解析出路径、类名和方法名
+                    JsonNode jsonNode = DataFormatUtil.toJsonNode(key);
+                    JsonNode path = jsonNode.get("path");
+                    JsonNode className = jsonNode.get("className");
+                    JsonNode method = jsonNode.get("methodName");
+                    ClassLoader classLoader = null;
+                    // 根据提供的路径加载外部类
+                    Class<?> classExample = null;
+                    try {
+                        if (Objects.nonNull(path) && ! path.isNull()) {
+                            String userPath = System.getProperty("user.dir");
+                            File file = new File(
+                                    userPath.concat(File.separator).concat("plugins").concat(File.separator)
+                                            .concat(path.asText()));
+                            // 检查文件是否存在
+                            if (! file.exists()) {
+                                throw new RuntimeException(
+                                        "外部文件加载不存在:".concat(userPath).concat(File.separator).concat("plugins")
+                                                             .concat(File.separator).concat(path.asText()));
+                            }
+                            URL url = file.toURI().toURL();
+                            classLoader =
+                                    new URLClassLoader(new URL[]{url}, Thread.currentThread().getContextClassLoader());
+                            classExample = classLoader.loadClass(className.asText());
+                        } else {
+                            classLoader = Thread.currentThread().getContextClassLoader();
+                            classExample = classLoader.loadClass(className.asText());
+                        }
+                    }catch (Exception e){
+                        e.printStackTrace();
+                        throw new RuntimeException(e);
+                    }
+                    // 加载指定的类和方法
+                    Method javaMethod = null;
+                    Method closeMethod = null;
+                    for (Method currentMethod : classExample.getMethods()) {
+                        String methodName = currentMethod.getName();
+                        if (methodName.equals(method.asText())) {
+                            javaMethod = currentMethod;
+                        } else if ("close".equals(methodName)) {
+                            closeMethod = currentMethod;
+                        }
+                    }
+                    Object classInstance = null;
+                    if (javaMethod != null) {
+                        int modifiers = javaMethod.getModifiers();
+                        boolean aStatic = Modifier.isStatic(modifiers);
+                        // 如果方法非静态,则实例化类
+                        if (! aStatic) {
+                            classInstance = classExample.getConstructor().newInstance();
+                        }
+                    }
+                    // 返回包含类实例、方法和关闭方法的JavaApply对象
+                    return new JavaApply(classInstance, javaMethod, closeMethod);
+                }
+                
+                /**
+                 * 将JavaApply实例包装成池能够管理的形式。
+                 * @param value 需要被包装的JavaApply实例。
+                 * @return 一个DefaultPooledObject,包含了一个JavaApply实例。
+                 */
+                @Override
+                public PooledObject<JavaApply> wrap(JavaApply value) {
+                    return new DefaultPooledObject<>(value);
+                }
+                
+                /**
+                 * 销毁从池中取出并使用后的JavaApply实例,调用其关闭方法。
+                 * @param key 与该实例对应的key。
+                 * @param p 包含了需要销毁的JavaApply实例的DefaultPooledObject。
+                 * @throws Exception 如果在销毁过程中出现错误。
+                 */
+                @Override
+                public void destroyObject(String key, PooledObject<JavaApply> p) throws Exception {
+                    JavaApply javaApply = p.getObject();
+                    javaApply.invokeClose();
+                }
+            });
+    
     /**
      * 根据提供的数据源、表达式和参数,调用相应的函数并返回结果。
+     *
      * @param datasource 包含调用所需数据源信息的Map对象,其中必须包含方法名。
      * @param expression 表达式,指定要调用的方法名。
      * @param args 调用方法时传递的参数数组。
+     *
      * @return 返回一个Map对象,包含调用结果或错误信息。
+     *
      * @throws Exception 如果调用过程中发生异常,则抛出。
      */
-    public static Map<String, Object> invoke(Map<String, Object> datasource, String expression, Object... args) throws Exception {
+    public static Map<String, Object> invoke(Map<String, Object> datasource, String expression, Object... args)
+            throws Exception {
         // 将表达式设置为要调用的方法名
         datasource.put("methodName", expression);
         // 通过数据源生成唯一的key
         String key = DataFormatUtil.toString(datasource);
-
         JavaApply javaApply = null;
         try {
             // 从对象池中根据key借用JavaApply对象
@@ -132,14 +148,17 @@ private static final KeyedObjectPool<String, JavaApply> javaRefPool = new Generi
             }
         }
     }
+    
     /**
      * JavaApply类用于封装对象实例、应用方法和关闭方法的调用。
      */
     private static class JavaApply {
         private Object instance; // 应用实例
+        
         private Method apply; // 应用的具体方法
+        
         private Method close; // 关闭资源的方法
-
+        
         /**
          * 构造函数,初始化应用实例、应用方法和关闭方法。
          *
@@ -152,37 +171,37 @@ private static final KeyedObjectPool<String, JavaApply> javaRefPool = new Generi
             this.apply = apply;
             this.close = close;
         }
-
+        
         // 获取应用实例的方法
         public Object getInstance() {
             return instance;
         }
-
+        
         // 设置应用实例的方法
         public void setInstance(Object instance) {
             this.instance = instance;
         }
-
+        
         // 获取应用方法的方法
         public Method getApply() {
             return apply;
         }
-
+        
         // 设置应用方法的方法
         public void setApply(Method apply) {
             this.apply = apply;
         }
-
+        
         // 获取关闭方法的方法
         public Method getClose() {
             return close;
         }
-
+        
         // 设置关闭方法的方法
         public void setClose(Method close) {
             this.close = close;
         }
-
+        
         /**
          * 调用关闭方法。
          *
@@ -194,12 +213,14 @@ private static final KeyedObjectPool<String, JavaApply> javaRefPool = new Generi
                 close.invoke(instance);
             }
         }
-
+        
         /**
          * 调用应用方法。
          *
          * @param args 方法调用的参数。
+         *
          * @return 方法的返回值。
+         *
          * @throws InvocationTargetException 如果调用目标抛出异常。
          * @throws IllegalAccessException 如果没有权限访问方法。
          */
@@ -208,7 +229,7 @@ private static final KeyedObjectPool<String, JavaApply> javaRefPool = new Generi
             // 参数类型检查与转换
             for (int i = 0; i < parameterTypes.length; i++) {
                 Object arg = args[i];
-                if (!parameterTypes[i].isInstance(arg)) {
+                if (! parameterTypes[i].isInstance(arg)) {
                     if (arg != null) {
                         args[i] = DataFormatUtil.castType(arg, parameterTypes[i]);
                     }
@@ -217,5 +238,4 @@ private static final KeyedObjectPool<String, JavaApply> javaRefPool = new Generi
             return apply.invoke(instance, args);
         }
     }
-
 }

+ 61 - 0
src/main/java/com/scbfkj/uni/process/ESB.java

@@ -0,0 +1,61 @@
+/*
+ * 版权所有 (c)
+ */
+
+package com.scbfkj.uni.process;
+
+import com.ibm.msg.client.jms.JmsConnectionFactory;
+import com.ibm.msg.client.jms.JmsConstants;
+import com.ibm.msg.client.jms.JmsFactoryFactory;
+import com.ibm.msg.client.wmq.WMQConstants;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+
+/**
+ * @author l7871
+ * @apiNote: 说明描述
+ * @description
+ * @date 2024/8/1 下午3:03
+ * @since
+ */
+public class ESB {
+        public void sendESBMessage(String data) throws JMSException {
+        JmsFactoryFactory ff = JmsFactoryFactory.getInstance(JmsConstants.WMQ_PROVIDER);
+        JmsConnectionFactory factory = ff.createConnectionFactory();
+        factory.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
+        factory.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, "QM_GW_DIB");
+        factory.setStringProperty(WMQConstants.WMQ_HOST_NAME, "edip.airchina.com.cn");
+        factory.setIntProperty(WMQConstants.WMQ_PORT, 14100);
+        factory.setStringProperty(WMQConstants.WMQ_CHANNEL, "SVRCONN_QM_GW_DIB");
+        factory.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "TEST Application");
+        factory.setIntProperty(WMQConstants.WMQ_CCSID, 1208);
+        factory.setStringProperty(WMQConstants.USERID, "BFPTS");
+        factory.setStringProperty(WMQConstants.PASSWORD, "=GDlgr)s5wIma");
+        Connection connection = null;
+        Session session = null;
+        MessageProducer producer = null;
+        try {
+            connection = factory.createConnection();
+            session = connection.createSession();
+            connection.start();
+            Queue queue = session.createQueue("COM.PUBSUB.PUBLISH.Q");
+            producer = session.createProducer(queue);
+            producer.send(session.createTextMessage(data));
+            System.out.println("已发送消息:" + data);
+        } finally {
+            if (producer != null) {
+                producer.close();
+            }
+            if (session != null) {
+                session.close();
+            }
+            if (connection != null) {
+                connection.close();
+            }
+        }
+    }
+}

+ 163 - 92
src/main/java/com/scbfkj/uni/process/IBMMQ.java

@@ -1,5 +1,8 @@
 package com.scbfkj.uni.process;
 
+import org.springframework.jms.connection.CachingConnectionFactory;
+import org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter;
+import org.springframework.jms.core.JmsTemplate;
 
 import com.ibm.mq.jakarta.jms.MQQueueConnectionFactory;
 import com.scbfkj.uni.exceptions.ConnectionNotFoundException;
@@ -9,39 +12,44 @@ import jakarta.jms.ConnectionFactory;
 import jakarta.jms.JMSException;
 import jakarta.jms.Message;
 import jakarta.jms.TextMessage;
-import org.springframework.jms.connection.CachingConnectionFactory;
-import org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter;
-import org.springframework.jms.core.JmsTemplate;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
 
 /**
  * IBM MQ客户端类,用于发送和接收消息。
  */
 public class IBMMQ {
-
     private static final DataBase DATA_BASE = new DataBase();
+    
     private JmsTemplate jmsTemplate = null;
-
+    
     /**
      * 根据数据源ID接收消息。
      * 通过给定的数据源ID查询连接配置,并使用这些配置连接到指定的队列管理器,从指定的队列中接收消息。
      *
      * @param dataSourceId 数据源ID,用于查询连接字符串。
-     * @param channel      通道名称。
+     * @param channel 通道名称。
      * @param queueManager 队列管理器名称。
-     * @param queueName    队列名称。
-     * @param ccsid        编码集ID。
+     * @param queueName 队列名称。
+     * @param ccsid 编码集ID。
      * @param receiveTimeout 接收超时时间。
-     * @param pollSize     每次轮询的大小。
-     * @param retry        重试次数。
+     * @param pollSize 每次轮询的大小。
+     * @param retry 重试次数。
+     *
      * @return 返回接收到的消息列表。
+     *
      * @throws Exception 如果连接配置查询失败或消息接收过程中出现错误,则抛出异常。
      */
-    public List<String> receptionMessageByDataSourceId(String dataSourceId, String channel, String queueManager, String queueName, Long ccsid, Long receiveTimeout, Long pollSize, Long retry) throws Exception {
+    public List<String> receptionMessageByDataSourceId(String dataSourceId, String channel, String queueManager,
+                                                       String queueName, Long ccsid, Long receiveTimeout, Long pollSize,
+                                                       Long retry) throws Exception {
         // 根据数据源ID查询连接配置
         Map<String, Object> config = queryConnectionStr(dataSourceId);
-
         long port = 1414L; // 默认端口号
         // 从连接配置中解析主机名和端口号
         String host = Objects.toString(config.get("host"));
@@ -62,11 +70,10 @@ public class IBMMQ {
             password = password1.toString();
         }
         // 使用解析出的配置信息进行消息接收
-        return receptionMessage(host, port, channel, queueManager, queueName, ccsid, username, password, receiveTimeout, pollSize, retry);
-
+        return receptionMessage(host, port, channel, queueManager, queueName, ccsid, username, password, receiveTimeout,
+                                pollSize, retry);
     }
-
-
+    
     /**
      * 从指定队列接收消息的函数。
      *
@@ -81,34 +88,36 @@ public class IBMMQ {
      * @param receiveTimeout 接收消息的超时时间。
      * @param pollSize 每次轮询的最大消息数。如果为0,则默认为100。
      * @param retry 接收消息失败后的最大重试次数。
+     *
      * @return 返回接收到的消息列表。
+     *
      * @throws JMSException 如果JMS操作失败,则抛出此异常。
      */
-    public List<String> receptionMessage(
-            String host, Long port, String channel, String queueManager, String queueName, Long ccsid, String username, String password, Long receiveTimeout, Long pollSize, Long retry) throws JMSException {
+    public List<String> receptionMessage(String host, Long port, String channel, String queueManager, String queueName,
+                                         Long ccsid, String username, String password, Long receiveTimeout,
+                                         Long pollSize, Long retry) throws JMSException {
         // 初始化JmsTemplate用于消息接收
-        JmsTemplate template = getJmsTemplate(host, port.intValue(), ccsid.intValue(), queueManager, channel, username, password);
-
+        JmsTemplate template =
+                getJmsTemplate(host, port.intValue(), ccsid.intValue(), queueManager, channel, username, password);
         // 设置接收超时时间
         jmsTemplate.setReceiveTimeout(receiveTimeout);
-
         // 设置最大轮询消息数
         long maxSize = 100; // 默认值
         if (pollSize > 0) {
             maxSize = pollSize;
         }
-
         // 初始化最大重试次数
         int maxRetry = 0;
         List<String> result = new ArrayList<>();
-
         // 不断尝试接收消息,直到满足退出条件
         while (true) {
             try {
                 // 尝试从指定队列接收消息
                 Message message = template.receive(queueName);
                 // 检查是否需要退出循环
-                if (checkIsBreak(message, result, maxSize)) break;
+                if (checkIsBreak(message, result, maxSize)) {
+                    break;
+                }
             } catch (Exception e) {
                 // 捕获异常,增加重试计数
                 maxRetry++;
@@ -124,15 +133,16 @@ public class IBMMQ {
         }
         return result; // 返回最终接收的消息列表
     }
-
-
+    
     /**
      * 检查是否应该中断处理消息的循环。
      *
      * @param message 需要检查的消息对象,如果为null表示找到终止条件。
      * @param result 存储处理结果的列表,每处理一个消息,将其文本添加到列表中。
      * @param maxSize 当结果列表的大小达到或超过此值时,视为找到终止条件。
+     *
      * @return 如果未找到终止条件,返回true;反之,返回false。
+     *
      * @throws JMSException 如果处理消息时发生错误。
      */
     private static boolean checkIsBreak(Message message, List<String> result, long maxSize) throws JMSException {
@@ -148,10 +158,9 @@ public class IBMMQ {
             found = true;
         }
         // 返回相反的逻辑,即未找到终止条件为true,找到为false
-        return !found;
+        return ! found;
     }
-
-
+    
     /**
      * 通过数据源ID发送单例消息。
      * 此方法将指定的消息数据作为列表中的单个元素发送,适用于需要发送单一消息体的情况。
@@ -162,17 +171,23 @@ public class IBMMQ {
      * @param queueName 队列名称,指定消息将被发送到的队列。
      * @param ccsid CCSID(字符集编码序列ID),指定消息的字符集。
      * @param data 要发送的消息数据对象。
+     *
      * @throws Exception 如果发送过程中遇到任何错误,则抛出异常。
      */
-    public void sendSingletonMessageByDataSourceId(
-            String dataSourceId, String channel, String queueManager, String queueName, Long ccsid,
-            Object data
-    ) throws Exception {
+    public void sendSingletonMessageByDataSourceId(String dataSourceId, String channel, String queueManager,
+                                                   String queueName, Long ccsid, Object data) throws Exception {
         // 使用Collections.singletonList将数据封装为列表,然后调用sendMessageByDataSourceId方法进行发送
-        sendMessageByDataSourceId(dataSourceId, channel, queueManager, queueName, ccsid, Collections.singletonList(data));
+        sendMessageByDataSourceId(dataSourceId, channel, queueManager, queueName, ccsid,
+                                  Collections.singletonList(data));
     }
-
-
+    
+    public void sendSingletonMessageToTopicByDataSourceId(String dataSourceId, String channel, String queueManager,
+                                                          String topic, Long ccsid, Object data) throws Exception {
+        // 使用Collections.singletonList将数据封装为列表,然后调用sendMessageByDataSourceId方法进行发送
+        sendMessageToTopicByDataSourceId(dataSourceId, channel, queueManager, topic, ccsid,
+                                         Collections.singletonList(data));
+    }
+    
     /**
      * 根据数据源ID发送消息。
      * 该方法通过查询数据源配置,获取连接信息,并使用提供的参数通过指定的通道、队列管理器和队列名称发送消息。
@@ -183,15 +198,13 @@ public class IBMMQ {
      * @param queueName 目标队列名称。
      * @param ccsid 编码集标识符。
      * @param data 要发送的消息数据列表。
+     *
      * @throws Exception 如果发送消息过程中遇到任何错误,则抛出异常。
      */
-    public void sendMessageByDataSourceId(
-            String dataSourceId, String channel, String queueManager, String queueName, Long ccsid,
-            List<Object> data
-    ) throws Exception {
+    public void sendMessageByDataSourceId(String dataSourceId, String channel, String queueManager, String queueName,
+                                          Long ccsid, List<Object> data) throws Exception {
         // 根据dataSourceId查询连接配置
         Map<String, Object> config = queryConnectionStr(dataSourceId);
-
         long port = 1414L; // 默认端口号
         // 从配置中解析主机名和端口号
         String host = Objects.toString(config.get("host"));
@@ -214,8 +227,34 @@ public class IBMMQ {
         // 发送消息
         sendMessage(host, port, channel, queueManager, queueName, ccsid, username, password, data);
     }
-
-
+    
+    public void sendMessageToTopicByDataSourceId(String dataSourceId, String channel, String queueManager, String topic,
+                                                 Long ccsid, List<Object> data) throws Exception {
+        // 根据dataSourceId查询连接配置
+        Map<String, Object> config = queryConnectionStr(dataSourceId);
+        long port = 1414L; // 默认端口号
+        // 从配置中解析主机名和端口号
+        String host = Objects.toString(config.get("host"));
+        if (host.contains(":")) {
+            String[] split = host.split(":");
+            port = Long.parseLong(split[1]);
+            host = split[0];
+        }
+        // 解析用户名和密码 from 配置
+        String username = null;
+        String password = null;
+        Object username1 = config.get("username");
+        if (Objects.nonNull(username1)) {
+            username = username1.toString();
+        }
+        Object password1 = config.get("password");
+        if (Objects.nonNull(password1)) {
+            password = password1.toString();
+        }
+        // 发送消息
+        sendMessageToTopic(host, port, channel, queueManager, topic, ccsid, username, password, data);
+    }
+    
     /**
      * 发送单个消息到指定的队列。此方法封装了消息的发送过程,方便发送单个消息。
      *
@@ -228,17 +267,24 @@ public class IBMMQ {
      * @param username 用户名,用于认证发送消息的用户。
      * @param password 密码,与用户名一起用于认证。
      * @param data 要发送的数据,该方法支持任意类型的数据对象。
+     *
      * @throws JMSException 如果发送消息过程中发生任何JMS异常,则抛出。
      */
-    public void sendSingletonMessage(
-            String host, Long port, String channel, String queueManager, String queueName, Long ccsid, String username, String password,
-            Object data
-    ) throws JMSException {
+    public void sendSingletonMessage(String host, Long port, String channel, String queueManager, String queueName,
+                                     Long ccsid, String username, String password, Object data) throws JMSException {
         // 将数据封装为单元素列表,并调用sendMessage方法发送消息
-        sendMessage(host, port, channel, queueManager, queueName, ccsid, username, password, Collections.singletonList(data));
+        sendMessage(host, port, channel, queueManager, queueName, ccsid, username, password,
+                    Collections.singletonList(data));
     }
-
-
+    
+    public void sendSingletonMessageToTopic(String host, Long port, String channel, String queueManager, String topic,
+                                            Long ccsid, String username, String password, Object data)
+            throws JMSException {
+        // 将数据封装为单元素列表,并调用sendMessage方法发送消息
+        sendMessageToTopic(host, port, channel, queueManager, topic, ccsid, username, password,
+                           Collections.singletonList(data));
+    }
+    
     /**
      * 发送消息到指定的队列
      *
@@ -251,23 +297,19 @@ public class IBMMQ {
      * @param username 用户名,用于认证
      * @param password 密码,用于认证
      * @param data 要发送的消息数据列表
+     *
      * @throws JMSException 如果发送消息过程中出现JMS异常
      */
-    public void sendMessage(
-            String host, Long port, String channel, String queueManager, String queueName, Long ccsid, String username, String password,
-            List<Object> data
-    ) throws JMSException {
-
+    public void sendMessage(String host, Long port, String channel, String queueManager, String queueName, Long ccsid,
+                            String username, String password, List<Object> data) throws JMSException {
         // 初始化JMS模板,配置连接信息
-        JmsTemplate template = getJmsTemplate(host, port.intValue(), ccsid.intValue(), queueManager, channel, username, password);
-
+        JmsTemplate template =
+                getJmsTemplate(host, port.intValue(), ccsid.intValue(), queueManager, channel, username, password);
         try {
             // 遍历数据列表,发送每条消息
             for (Object it : data) {
-
                 execSend(template, it, queueName);
             }
-
         } catch (Exception e) {
             // 若开启调试模式,打印异常堆栈
             if (Config.isDebug()) {
@@ -277,12 +319,32 @@ public class IBMMQ {
             if (jmsTemplate != null) {
                 jmsTemplate = null;
             }
-
         }
     }
-
-
-
+    
+    public void sendMessageToTopic(String host, Long port, String channel, String queueManager, String topicName,
+                                   Long ccsid, String username, String password, List<Object> data)
+            throws JMSException {
+        // 初始化JMS模板,配置连接信息
+        JmsTemplate template =
+                getJmsTemplate(host, port.intValue(), ccsid.intValue(), queueManager, channel, username, password);
+        try {
+            // 遍历数据列表,发送每条消息
+            for (Object it : data) {
+                execSendToTopic(template, it, topicName);
+            }
+        } catch (Exception e) {
+            // 若开启调试模式,打印异常堆栈
+            if (Config.isDebug()) {
+                e.printStackTrace();
+            }
+            // 出现异常时,清理jmsTemplate对象
+            if (jmsTemplate != null) {
+                jmsTemplate = null;
+            }
+        }
+    }
+    
     /**
      * 使用JmsTemplate发送消息到指定的队列。
      *
@@ -290,19 +352,23 @@ public class IBMMQ {
      * @param data 要发送的数据,可以是任意类型,最终会被转换为字符串格式发送。
      * @param queueName 队列名称,指定消息要发送到的目标队列。
      */
-    private void execSend(
-            JmsTemplate template,
-            Object data,
-            String queueName
-    ) {
+    private void execSend(JmsTemplate template, Object data, String queueName) {
         // 将数据转换为字符串格式
         String message = DataFormatUtil.toString(data);
         // 使用JmsTemplate发送消息,将消息封装为TextMessage并发送到指定队列
         template.send(queueName, session -> session.createTextMessage(message));
     }
-
-
-
+    
+    private void execSendToTopic(JmsTemplate template, Object data, String topic) {
+        String message = DataFormatUtil.toString(data);
+        template.setDefaultDestinationName(topic);
+        if (message != null) {
+            template.convertAndSend(message);
+        } else {
+            System.out.println("message is null");
+        }
+    }
+    
     /**
      * 创建一个 MQ 队列连接工厂实例。
      *
@@ -311,10 +377,14 @@ public class IBMMQ {
      * @param ccsid CCSID(Character Code Set Identifier),用于指定字符集。
      * @param queueManager 队列管理器名,标识一个 MQ 队列管理器。
      * @param channel 通道名,用于客户端和队列管理器之间的通信。
+     *
      * @return 初始化后的 MQQueueConnectionFactory 实例。
+     *
      * @throws JMSException 如果创建连接工厂时发生错误。
      */
-    private MQQueueConnectionFactory createMqQueueConnectionFactory(String host, int port, int ccsid, String queueManager, String channel) throws JMSException {
+    private MQQueueConnectionFactory createMqQueueConnectionFactory(String host, int port, int ccsid,
+                                                                    String queueManager, String channel)
+            throws JMSException {
         MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
         // 设置连接工厂的主机名
         mqQueueConnectionFactory.setHostName(host);
@@ -330,13 +400,12 @@ public class IBMMQ {
         mqQueueConnectionFactory.setTransportType(1);
         return mqQueueConnectionFactory;
     }
-
-
-
+    
     /**
      * 创建并配置一个JmsTemplate实例。
      *
      * @param factory CachingConnectionFactory的实例,用于设置JmsTemplate的消息工厂。
+     *
      * @return 配置好的JmsTemplate实例,可用于发送消息。
      */
     private JmsTemplate createJmsTemplate(CachingConnectionFactory factory) {
@@ -344,13 +413,13 @@ public class IBMMQ {
         template.setConnectionFactory(factory); // 设置消息工厂
         return template;
     }
-
-
+    
     /**
      * 创建一个 CachingConnectionFactory 实例。
      * 此方法通过将一个给定的 ConnectionFactory 设置为缓存工厂的目标ConnectionFactory来配置 CachingConnectionFactory。
      *
      * @param factory 用于创建缓存工厂的目标ConnectionFactory。
+     *
      * @return 配置好的 CachingConnectionFactory 实例。
      */
     private CachingConnectionFactory createCachingConnectionFactory(ConnectionFactory factory) {
@@ -359,8 +428,7 @@ public class IBMMQ {
         cachingConnectionFactory.setTargetConnectionFactory(factory);
         return cachingConnectionFactory;
     }
-
-
+    
     /**
      * 创建并配置一个 UserCredentialsConnectionFactoryAdapter 实例。
      * 这个方法通过提供用户名、密码和一个ConnectionFactory,来创建一个已经设置了认证信息的ConnectionFactory适配器。
@@ -368,16 +436,18 @@ public class IBMMQ {
      * @param username 将要用于认证的用户名。
      * @param password 将要用于认证的密码。
      * @param factory 是底层的ConnectionFactory,认证通过后将使用这个ConnectionFactory创建连接。
+     *
      * @return 配置好的 UserCredentialsConnectionFactoryAdapter 实例,可用于进一步的使用。
      */
-    private UserCredentialsConnectionFactoryAdapter createAdapter(String username, String password, ConnectionFactory factory) {
+    private UserCredentialsConnectionFactoryAdapter createAdapter(String username, String password,
+                                                                  ConnectionFactory factory) {
         UserCredentialsConnectionFactoryAdapter adapter = new UserCredentialsConnectionFactoryAdapter();
         adapter.setUsername(username); // 设置认证使用的用户名
         adapter.setPassword(password); // 设置认证使用的密码
         adapter.setTargetConnectionFactory(factory); // 设置目标ConnectionFactory
         return adapter;
     }
-
+    
     /**
      * 获取一个配置好的JmsTemplate实例,用于与MQ队列进行交互。
      *
@@ -388,33 +458,36 @@ public class IBMMQ {
      * @param channel 与MQ队列管理器通信的通道名称。
      * @param username 连接MQ时的用户名。
      * @param password 连接MQ时的密码。
+     *
      * @return 配置好的JmsTemplate实例。
+     *
      * @throws JMSException 如果在创建JMS连接工厂或模板时发生错误。
      */
-    private JmsTemplate getJmsTemplate(String host, int port, int ccsid, String queueManager, String channel, String username, String password) throws JMSException {
+    private JmsTemplate getJmsTemplate(String host, int port, int ccsid, String queueManager, String channel,
+                                       String username, String password) throws JMSException {
         // 如果jmsTemplate尚未初始化,则进行初始化
         if (jmsTemplate == null) {
             // 创建MQ队列连接工厂
-            MQQueueConnectionFactory mqQueueConnectionFactory = createMqQueueConnectionFactory(host, port, ccsid, queueManager, channel);
+            MQQueueConnectionFactory mqQueueConnectionFactory =
+                    createMqQueueConnectionFactory(host, port, ccsid, queueManager, channel);
             // 使用用户名和密码适配器包装MQ队列连接工厂
-            UserCredentialsConnectionFactoryAdapter adapter = createAdapter(username, password, mqQueueConnectionFactory);
+            UserCredentialsConnectionFactoryAdapter adapter =
+                    createAdapter(username, password, mqQueueConnectionFactory);
             // 创建缓存连接工厂,以提高性能
             CachingConnectionFactory cachingConnectionFactory = createCachingConnectionFactory(adapter);
-
             // 创建并配置JmsTemplate实例
             jmsTemplate = createJmsTemplate(cachingConnectionFactory);
-
         }
         return jmsTemplate;
     }
-
-
-
+    
     /**
      * 查询指定数据源ID的连接字符串信息。
      *
      * @param datasourceId 数据源的唯一标识符。
+     *
      * @return 返回一个包含主机名、密码和用户名的Map对象。
+     *
      * @throws Exception 如果查询过程中发生错误,或者未找到指定的数据源ID,则抛出异常。
      */
     private static Map<String, Object> queryConnectionStr(String datasourceId) throws Exception {
@@ -425,12 +498,10 @@ public class IBMMQ {
                 username,
                 from datasource
                 where datasourceid = ?""", datasourceId).stream().findFirst();
-
         // 如果查询结果为空,抛出连接未找到异常
         if (result.isEmpty()) {
             throw new ConnectionNotFoundException("数据源错误:没有找到数据源");
         }
-
         // 返回查询结果
         return result.get();
     }

+ 285 - 0
src/main/java/com/scbfkj/uni/process/IBMMQ2.java

@@ -0,0 +1,285 @@
+package com.scbfkj.uni.process;
+
+import com.ibm.msg.client.jms.JmsConnectionFactory;
+import com.ibm.msg.client.jms.JmsConstants;
+import com.ibm.msg.client.jms.JmsFactoryFactory;
+import com.ibm.msg.client.wmq.WMQConstants;
+import com.scbfkj.uni.exceptions.ConnectionNotFoundException;
+import com.scbfkj.uni.system.Config;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.jms.Topic;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * IBM MQ客户端类,用于发送和接收消息。
+ */
+public class IBMMQ2 {
+    private static final DataBase DATA_BASE = new DataBase();
+    
+    private JmsConnectionFactory jmsConnectionFactory = null;
+    
+    public List<String> receptionMessageByDataSourceId(String dataSourceId, String channel, String targetUri,
+                                                       Long ccsid, Long receiveTimeout, Long pollSize)
+            throws Exception {
+        // 根据数据源ID查询连接配置
+        Map<String, Object> config = queryConnectionStr(dataSourceId);
+        long port = 1414L; // 默认端口号
+        // 从连接配置中解析主机名和端口号
+        String host = Objects.toString(config.get("host"));
+        if (host.contains(":")) {
+            String[] split = host.split(":");
+            port = Long.parseLong(split[1]);
+            host = split[0];
+        }
+        // 从连接配置中解析用户名和密码
+        String username = null;
+        String password = null;
+        Object username1 = config.get("username");
+        if (Objects.nonNull(username1)) {
+            username = username1.toString();
+        }
+        Object password1 = config.get("password");
+        if (Objects.nonNull(password1)) {
+            password = password1.toString();
+        }
+        // 使用解析出的配置信息进行消息接收
+        return receptionMessage(host, port, channel, targetUri, ccsid, username, password, receiveTimeout, pollSize);
+    }
+    
+    public List<String> receptionMessage(String host, Long port, String channel, String targetUri, Long ccsid,
+                                         String username, String password, Long receiveTimeout, Long pollSize)
+            throws JMSException {
+        JmsConnectionFactory factory = getJmsConnectionFactory(host, port, channel, ccsid, username, password);
+        Connection connection = null;
+        Session session = null;
+        MessageConsumer consumer = null;
+        List<String> result = new ArrayList<>();
+        try {
+            connection = factory.createConnection();
+            session = connection.createSession();
+            connection.start();
+            if (targetUri.startsWith("queue://")) {
+                Queue queue = session.createQueue(targetUri);
+                consumer = session.createConsumer(queue);
+            } else if (targetUri.startsWith("topic://")) {
+                Topic topic = session.createTopic(targetUri);
+                consumer = session.createConsumer(topic);
+            }
+            while (true) {
+                Message receive = consumer.receive(receiveTimeout);
+                if (receive != null) {
+                    if (receive instanceof TextMessage textMessage) {
+                        result.add(textMessage.getText());
+                    } else {
+                        result.add(receive.toString());
+                    }
+                    if (result.size() > pollSize) {
+                        return result;
+                    }
+                } else {
+                    return result;
+                }
+            }
+        } finally {
+            if (consumer != null) {
+                consumer.close();
+            }
+            if (session != null) {
+                session.close();
+            }
+            if (connection != null) {
+                connection.close();
+            }
+        }
+    }
+    
+    /**
+     * 通过数据源ID发送单例消息。
+     * 此方法将指定的消息数据作为列表中的单个元素发送,适用于需要发送单一消息体的情况。
+     *
+     * @param dataSourceId 数据源ID,用于标识消息发送的目标数据源。
+     * @param channel 通道名称,指定消息将通过的通道。
+     * @param queueManager 队列管理器名称,指定消息将由哪个队列管理器处理。
+     * @param queueName 队列名称,指定消息将被发送到的队列。
+     * @param ccsid CCSID(字符集编码序列ID),指定消息的字符集。
+     * @param data 要发送的消息数据对象。
+     *
+     * @throws Exception 如果发送过程中遇到任何错误,则抛出异常。
+     */
+    public void sendSingletonMessageByDataSourceId(String dataSourceId, String channel, String queueManager,
+                                                   String queueName, Long ccsid, String data) throws Exception {
+        // 使用Collections.singletonList将数据封装为列表,然后调用sendMessageByDataSourceId方法进行发送
+        sendMessageByDataSourceId(dataSourceId, channel, queueManager, queueName, ccsid,
+                                  Collections.singletonList(data));
+    }
+    
+    public void sendSingletonMessageToTopicByDataSourceId(String dataSourceId, String channel, String queueManager,
+                                                          String topic, Long ccsid, String data) throws Exception {
+        // 使用Collections.singletonList将数据封装为列表,然后调用sendMessageByDataSourceId方法进行发送
+        sendMessageToTopicByDataSourceId(dataSourceId, channel, queueManager, topic, ccsid,
+                                         Collections.singletonList(data));
+    }
+    
+    /**
+     * 根据数据源ID发送消息。
+     * 该方法通过查询数据源配置,获取连接信息,并使用提供的参数通过指定的通道、队列管理器和队列名称发送消息。
+     *
+     * @param dataSourceId 数据源ID,用于查询连接配置。
+     * @param channel 通信通道名称。
+     * @param queueManager 队列管理器名称。
+     * @param targetUri 目标队列名称。
+     * @param ccsid 编码集标识符。
+     * @param data 要发送的消息数据列表。
+     *
+     * @throws Exception 如果发送消息过程中遇到任何错误,则抛出异常。
+     */
+    public void sendMessageByDataSourceId(String dataSourceId, String channel, String queueManager, String targetUri,
+                                          Long ccsid, List<String> data) throws Exception {
+        // 根据dataSourceId查询连接配置
+        Map<String, Object> config = queryConnectionStr(dataSourceId);
+        long port = 1414L; // 默认端口号
+        // 从配置中解析主机名和端口号
+        String host = Objects.toString(config.get("host"));
+        if (host.contains(":")) {
+            String[] split = host.split(":");
+            port = Long.parseLong(split[1]);
+            host = split[0];
+        }
+        // 解析用户名和密码 from 配置
+        String username = null;
+        String password = null;
+        Object username1 = config.get("username");
+        if (Objects.nonNull(username1)) {
+            username = username1.toString();
+        }
+        Object password1 = config.get("password");
+        if (Objects.nonNull(password1)) {
+            password = password1.toString();
+        }
+        // 发送消息
+        sendMessage(host, port, channel, queueManager, ccsid, username, password, targetUri, data);
+    }
+    
+    public void sendMessageToTopicByDataSourceId(String dataSourceId, String channel, String queueManager,
+                                                 String targetUri, Long ccsid, List<String> data) throws Exception {
+        // 根据dataSourceId查询连接配置
+        Map<String, Object> config = queryConnectionStr(dataSourceId);
+        long port = 1414L; // 默认端口号
+        // 从配置中解析主机名和端口号
+        String host = Objects.toString(config.get("host"));
+        if (host.contains(":")) {
+            String[] split = host.split(":");
+            port = Long.parseLong(split[1]);
+            host = split[0];
+        }
+        // 解析用户名和密码 from 配置
+        String username = null;
+        String password = null;
+        Object username1 = config.get("username");
+        if (Objects.nonNull(username1)) {
+            username = username1.toString();
+        }
+        Object password1 = config.get("password");
+        if (Objects.nonNull(password1)) {
+            password = password1.toString();
+        }
+        // 发送消息
+        sendMessage(host, port, channel, queueManager, ccsid, username, password, targetUri, data);
+    }
+    
+    public void sendSingletonMessage(String host, Long port, String channel, String queueManager, String targetUri,
+                                     Long ccsid, String username, String password, String data) throws JMSException {
+        sendMessage(host, port, channel, queueManager, ccsid, username, password, targetUri, List.of(data));
+        // 将数据封装为单元素列表,并调用sendMessage方法发送消息
+    }
+    
+    private void sendMessage(String host, Long port, String channel, String queueManager, Long ccsid, String user,
+                             String password, String targetUri, List<String> data) throws JMSException {
+        JmsConnectionFactory factory = getJmsConnectionFactory(host, port, channel, ccsid, user, password);
+        Connection connection = null;
+        Session session = null;
+        MessageProducer producer = null;
+        try {
+            connection = factory.createConnection();
+            session = connection.createSession();
+            connection.start();
+            if (targetUri.startsWith("queue://")) {
+                Queue queue = session.createQueue(targetUri);
+                producer = session.createProducer(queue);
+            } else if (targetUri.startsWith("topic://")) {
+                Topic topic = session.createTopic(targetUri);
+                producer = session.createProducer(topic);
+            }
+            for (String item : data) {
+                producer.send(session.createTextMessage(item));
+            }
+            session.commit();
+        } finally {
+            if (producer != null) {
+                producer.close();
+            }
+            if (session != null) {
+                session.close();
+            }
+            if (connection != null) {
+                connection.close();
+            }
+        }
+    }
+    
+    private JmsConnectionFactory getJmsConnectionFactory(final String host, final Long port, final String channel,
+                                                         final Long ccsid, final String user, final String password)
+            throws JMSException {
+        if (jmsConnectionFactory == null) {
+            JmsFactoryFactory ff = JmsFactoryFactory.getInstance(JmsConstants.WMQ_PROVIDER);
+            jmsConnectionFactory = ff.createConnectionFactory();
+            jmsConnectionFactory.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
+            jmsConnectionFactory.setStringProperty(WMQConstants.WMQ_HOST_NAME, host);
+            jmsConnectionFactory.setIntProperty(WMQConstants.WMQ_PORT, port.intValue());
+            jmsConnectionFactory.setStringProperty(WMQConstants.WMQ_CHANNEL, channel);
+            jmsConnectionFactory.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "UNI Application");
+            jmsConnectionFactory.setIntProperty(WMQConstants.WMQ_CCSID, ccsid.intValue());
+            jmsConnectionFactory.setStringProperty(WMQConstants.USERID, user);
+            jmsConnectionFactory.setStringProperty(WMQConstants.PASSWORD, password);
+        }
+        return jmsConnectionFactory;
+    }
+    
+    /**
+     * 查询指定数据源ID的连接字符串信息。
+     *
+     * @param datasourceId 数据源的唯一标识符。
+     *
+     * @return 返回一个包含主机名、密码和用户名的Map对象。
+     *
+     * @throws Exception 如果查询过程中发生错误,或者未找到指定的数据源ID,则抛出异常。
+     */
+    private static Map<String, Object> queryConnectionStr(String datasourceId) throws Exception {
+        // 执行数据库查询,获取符合条件的第一条记录
+        Optional<Map<String, Object>> result = DATA_BASE.query(Config.getCenterConnectionStr(), """
+                select host,
+                password,
+                username,
+                from datasource
+                where datasourceid = ?""", datasourceId).stream().findFirst();
+        // 如果查询结果为空,抛出连接未找到异常
+        if (result.isEmpty()) {
+            throw new ConnectionNotFoundException("数据源错误:没有找到数据源");
+        }
+        // 返回查询结果
+        return result.get();
+    }
+}

+ 17 - 7
src/main/java/com/scbfkj/uni/process/Web.java

@@ -35,6 +35,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 
 /**
  * Web API调用类
@@ -129,25 +130,34 @@ public class Web {
             }
             HttpHeaders headers = new HttpHeaders();
             headers.putAll(webApiHeader);
-            HttpEntity<Object> entity = new HttpEntity<>(defaultBody.toString().trim(), headers);
             Object responseEntity = null;
             switch (webapiMethod) {
                 case "get" -> {
-                    ResponseEntity<JsonNode> response =
-                            restTemplate.exchange(webapiURL, HttpMethod.GET, entity, JsonNode.class);
+                    HttpEntity<Object> entity = new HttpEntity<>(headers);
+                    ResponseEntity<String> response =
+                            restTemplate.exchange(webapiURL, HttpMethod.GET, entity, String.class);
                     responseEntity = response.getBody();
                 }
                 case "put" -> {
-                    ResponseEntity<JsonNode> response =
-                            restTemplate.exchange(webapiURL, HttpMethod.PUT, entity, JsonNode.class);
+                    HttpEntity<Object> entity =
+                            new HttpEntity<>(Optional.ofNullable(defaultBody).map(it->it.toString().trim()).orElse(null),
+                                             headers);
+                    ResponseEntity<String> response =
+                            restTemplate.exchange(webapiURL, HttpMethod.PUT, entity, String.class);
                     responseEntity = response.getBody();
                 }
                 case "delete" -> {
-                    ResponseEntity<JsonNode> response =
-                            restTemplate.exchange(webapiURL, HttpMethod.DELETE, entity, JsonNode.class);
+                    HttpEntity<Object> entity =
+                            new HttpEntity<>(Optional.ofNullable(defaultBody).map(it->it.toString().trim()).orElse(null),
+                                             headers);
+                    ResponseEntity<String> response =
+                            restTemplate.exchange(webapiURL, HttpMethod.DELETE, entity, String.class);
                     responseEntity = response.getBody();
                 }
                 default -> {
+                    HttpEntity<Object> entity =
+                            new HttpEntity<>(Optional.ofNullable(defaultBody).map(it->it.toString().trim()).orElse(null),
+                                             headers);
                     ResponseEntity<String> response =
                             restTemplate.exchange(webapiURL, HttpMethod.POST, entity, String.class);
                     responseEntity = response.getBody();

+ 2 - 1
src/main/resources/application.yml

@@ -12,4 +12,5 @@ server:
   port: 9500
 spring:
   profiles:
-    default: test
+    default: test
+debug: false