Skip to content

Commit 7c5700d

Browse files
committed
Java:MultiDataSource 重新集成 UnitAuto
1 parent f4cfda7 commit 7c5700d

File tree

3 files changed

+318
-94
lines changed

3 files changed

+318
-94
lines changed

APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/java/apijson/boot/DemoApplication.java

Lines changed: 98 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@
1414

1515
package apijson.boot;
1616

17+
import apijson.JSON;
1718
import apijson.fastjson2.APIJSONApplication;
1819
import apijson.fastjson2.APIJSONCreator;
1920
import apijson.fastjson2.APIJSONVerifier;
2021
import apijson.fastjson2.APIJSONSQLConfig;
2122
import apijson.orm.AbstractParser;
2223
import apijson.orm.AbstractVerifier;
24+
import com.alibaba.fastjson.JSONObject;
25+
import com.alibaba.fastjson.serializer.PropertyFilter;
2326
import org.springframework.boot.SpringApplication;
2427
import org.springframework.boot.autoconfigure.SpringBootApplication;
2528
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
@@ -30,6 +33,8 @@
3033
import org.springframework.web.servlet.config.annotation.CorsRegistry;
3134
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
3235

36+
import java.lang.reflect.Modifier;
37+
import java.util.List;
3338
import java.util.Map;
3439
import java.util.regex.Pattern;
3540

@@ -43,12 +48,11 @@
4348
import apijson.demo.DemoSQLConfig;
4449
import apijson.demo.DemoSQLExecutor;
4550
import apijson.demo.DemoVerifier;
46-
import apijson.orm.Verifier;
47-
//import unitauto.MethodUtil;
48-
//import unitauto.MethodUtil.Argument;
49-
//import unitauto.MethodUtil.InstanceGetter;
50-
//import unitauto.MethodUtil.JSONCallback;
51-
//import unitauto.jar.UnitAutoApp;
51+
import unitauto.MethodUtil;
52+
import unitauto.MethodUtil.Argument;
53+
import unitauto.MethodUtil.InstanceGetter;
54+
import unitauto.MethodUtil.JSONCallback;
55+
import unitauto.jar.UnitAutoApp;
5256

5357

5458
/**
@@ -265,96 +269,96 @@ public DemoSQLExecutor createSQLExecutor() {
265269

266270
// UnitAuto 单元测试配置 https://github.com/TommyLemon/UnitAuto <<<<<<<<<<<<<<<<<<<<<<<<<<<
267271
// FIXME 不要开放给项目组后端之外的任何人使用 UnitAuto(强制登录鉴权)!!!如果不需要单元测试则移除相关代码或 unitauto.Log.DEBUG = false;
268-
//UnitAutoApp.init();
272+
UnitAutoApp.init();
269273

270274
// 适配 Spring 注入的类及 Context 等环境相关的类
271-
//final InstanceGetter ig = MethodUtil.INSTANCE_GETTER;
272-
//MethodUtil.INSTANCE_GETTER = new InstanceGetter() {
273-
//
274-
// @Override
275-
// public Object getInstance(@NotNull Class<?> clazz, List<Argument> classArgs, Boolean reuse) throws Exception {
276-
// if (APPLICATION_CONTEXT != null && ApplicationContext.class.isAssignableFrom(clazz) && clazz.isAssignableFrom(APPLICATION_CONTEXT.getClass())) {
277-
// return APPLICATION_CONTEXT;
278-
// }
279-
//
280-
// if (reuse != null && reuse && (classArgs == null || classArgs.isEmpty())) {
281-
// return APPLICATION_CONTEXT.getBean(clazz);
282-
// }
283-
//
284-
// return ig.getInstance(clazz, classArgs, reuse);
285-
// }
286-
//};
287-
//
288-
//// 排除转换 JSON 异常的类,一般是 Context 等环境相关的类
289-
//final JSONCallback jc = MethodUtil.JSON_CALLBACK;
290-
//MethodUtil.JSON_CALLBACK = new JSONCallback() {
291-
//
292-
// @Override
293-
// public JSONObject newSuccessResult() {
294-
// return jc.newSuccessResult();
295-
// }
296-
//
297-
// @Override
298-
// public JSONObject newErrorResult(Throwable e) {
299-
// return jc.newErrorResult(e);
300-
// }
301-
//
302-
// @Override
303-
// public JSONObject parseJSON(String type, Object value) {
304-
// if (value == null || unitauto.JSON.isBooleanOrNumberOrString(value) || value instanceof JSON || value instanceof Enum) {
305-
// return jc.parseJSON(type, value);
306-
// }
307-
//
308-
// if (value instanceof ApplicationContext
309-
// || value instanceof Context
310-
// || value instanceof org.apache.catalina.Context
311-
// // SpringBoot 2.6.7 已移除 || value instanceof ch.qos.logback.core.Context
312-
// ) {
313-
// value = value.toString();
314-
// } else {
315-
// try {
316-
// value = parseJSON(JSON.toJSONString(value, new PropertyFilter() {
317-
// @Override
318-
// public boolean apply(Object object, String name, Object value) {
319-
// if (value == null) {
320-
// return true;
321-
// }
322-
//
323-
// if (value instanceof ApplicationContext
324-
// || value instanceof Context
325-
// || value instanceof org.apache.catalina.Context
326-
// // SpringBoot 2.6.7 已移除 || value instanceof ch.qos.logback.core.Context
327-
// ) {
328-
// return false;
329-
// }
330-
//
331-
// // 防止通过 UnitAuto 远程执行 getDBPassword 等方法来查到敏感信息,但如果直接调用 public String getDBUri 这里没法拦截,仍然会返回敏感信息
332-
// // if (object instanceof SQLConfig) {
333-
// // // 这个类部分方法不序列化返回
334-
// // if ("dBUri".equalsIgnoreCase(name) || "dBPassword".equalsIgnoreCase(name) || "dBAccount".equalsIgnoreCase(name)) {
335-
// // return false;
336-
// // }
337-
// // return false; // 这个类所有方法都不序列化返回
338-
// // }
339-
//
340-
// // 所有类中的方法只要包含关键词就不序列化返回
341-
// String n = StringUtil.toLowerCase(name);
342-
// if (n.contains("database") || n.contains("schema") || n.contains("dburi") || n.contains("password") || n.contains("account")) {
343-
// return false;
344-
// }
345-
//
346-
// return Modifier.isPublic(value.getClass().getModifiers());
347-
// }
348-
// }));
349-
// } catch (Exception e) {
350-
// Log.e(TAG, "toJSONString catch \n" + e.getMessage());
351-
// }
352-
// }
353-
//
354-
// return jc.parseJSON(type, value);
355-
// }
356-
//
357-
//};
275+
final InstanceGetter ig = MethodUtil.INSTANCE_GETTER;
276+
MethodUtil.INSTANCE_GETTER = new InstanceGetter() {
277+
278+
@Override
279+
public Object getInstance(@NotNull Class<?> clazz, List<Argument> classArgs, Boolean reuse) throws Exception {
280+
if (APPLICATION_CONTEXT != null && ApplicationContext.class.isAssignableFrom(clazz) && clazz.isAssignableFrom(APPLICATION_CONTEXT.getClass())) {
281+
return APPLICATION_CONTEXT;
282+
}
283+
284+
if (reuse != null && reuse && (classArgs == null || classArgs.isEmpty())) {
285+
return APPLICATION_CONTEXT.getBean(clazz);
286+
}
287+
288+
return ig.getInstance(clazz, classArgs, reuse);
289+
}
290+
};
291+
292+
// 排除转换 JSON 异常的类,一般是 Context 等环境相关的类
293+
final JSONCallback jc = MethodUtil.JSON_CALLBACK;
294+
MethodUtil.JSON_CALLBACK = new JSONCallback() {
295+
296+
@Override
297+
public JSONObject newSuccessResult() {
298+
return jc.newSuccessResult();
299+
}
300+
301+
@Override
302+
public JSONObject newErrorResult(Throwable e) {
303+
return jc.newErrorResult(e);
304+
}
305+
306+
@Override
307+
public JSONObject parseJSON(String type, Object value) {
308+
if (value == null || unitauto.JSON.isBooleanOrNumberOrString(value) || value instanceof JSON || value instanceof Enum) {
309+
return jc.parseJSON(type, value);
310+
}
311+
312+
if (value instanceof ApplicationContext
313+
|| value instanceof Context
314+
|| value instanceof org.apache.catalina.Context
315+
// SpringBoot 2.6.7 已移除 || value instanceof ch.qos.logback.core.Context
316+
) {
317+
value = value.toString();
318+
} else {
319+
try {
320+
value = com.alibaba.fastjson.JSON.parse(com.alibaba.fastjson.JSON.toJSONString(value, new PropertyFilter() {
321+
@Override
322+
public boolean apply(Object object, String name, Object value) {
323+
if (value == null) {
324+
return true;
325+
}
326+
327+
if (value instanceof ApplicationContext
328+
|| value instanceof Context
329+
|| value instanceof org.apache.catalina.Context
330+
// SpringBoot 2.6.7 已移除 || value instanceof ch.qos.logback.core.Context
331+
) {
332+
return false;
333+
}
334+
335+
// 防止通过 UnitAuto 远程执行 getDBPassword 等方法来查到敏感信息,但如果直接调用 public String getDBUri 这里没法拦截,仍然会返回敏感信息
336+
// if (object instanceof SQLConfig) {
337+
// // 这个类部分方法不序列化返回
338+
// if ("dBUri".equalsIgnoreCase(name) || "dBPassword".equalsIgnoreCase(name) || "dBAccount".equalsIgnoreCase(name)) {
339+
// return false;
340+
// }
341+
// return false; // 这个类所有方法都不序列化返回
342+
// }
343+
344+
// 所有类中的方法只要包含关键词就不序列化返回
345+
String n = StringUtil.toLowerCase(name);
346+
if (n.contains("database") || n.contains("schema") || n.contains("dburi") || n.contains("password") || n.contains("account")) {
347+
return false;
348+
}
349+
350+
return Modifier.isPublic(value.getClass().getModifiers());
351+
}
352+
}));
353+
} catch (Exception e) {
354+
Log.e(TAG, "toJSONString catch \n" + e.getMessage());
355+
}
356+
}
357+
358+
return jc.parseJSON(type, value);
359+
}
360+
361+
};
358362

359363
// UnitAuto 单元测试配置 https://github.com/TommyLemon/UnitAuto >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
360364

APIJSON-Java-Server/APIJSONBoot-MultiDataSource/src/main/java/apijson/boot/DemoController.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import com.alibaba.fastjson2.JSONObject;
2323
import com.fasterxml.jackson.databind.util.LRUMap;
2424

25+
import jakarta.servlet.AsyncContext;
26+
import jakarta.servlet.ServletResponse;
2527
import org.springframework.beans.factory.annotation.Autowired;
2628
import org.springframework.http.*;
2729
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
@@ -31,6 +33,7 @@
3133
import org.springframework.web.client.RestTemplate;
3234

3335
import java.lang.reflect.Array;
36+
import java.lang.reflect.Method;
3437
import java.net.URLDecoder;
3538
import java.net.URLEncoder;
3639
import java.rmi.ServerException;
@@ -2679,6 +2682,65 @@ public String ui() {
26792682
// super.invokeMethod(request, servletRequest);
26802683
//}
26812684

2685+
@PostMapping("method/list")
2686+
public Map<String, Object> listMethod(@RequestBody String request) {
2687+
if (Log.DEBUG == false) {
2688+
return MethodUtil.JSON_CALLBACK.newErrorResult(new IllegalAccessException("非 DEBUG 模式下不允许使用 UnitAuto 单元测试!"));
2689+
}
2690+
return MethodUtil.listMethod(request);
2691+
}
2692+
2693+
@PostMapping("method/invoke")
2694+
public void invokeMethod(@RequestBody String request, HttpServletRequest servletRequest) {
2695+
AsyncContext asyncContext = servletRequest.startAsync();
2696+
2697+
final boolean[] called = new boolean[] { false };
2698+
MethodUtil.Listener<com.alibaba.fastjson.JSONObject> listener = new MethodUtil.Listener<com.alibaba.fastjson.JSONObject>() {
2699+
2700+
@Override
2701+
public void complete(com.alibaba.fastjson.JSONObject data, Method method, MethodUtil.InterfaceProxy proxy, Object... extras) throws Exception {
2702+
2703+
ServletResponse servletResponse = called[0] ? null : asyncContext.getResponse();
2704+
if (servletResponse == null) { // || servletResponse.isCommitted()) { // isCommitted 在高并发时可能不准,导致写入多次
2705+
Log.w(TAG, "invokeMethod listener.complete servletResponse == null || servletResponse.isCommitted() >> return;");
2706+
return;
2707+
}
2708+
called[0] = true;
2709+
2710+
servletResponse.setCharacterEncoding(servletRequest.getCharacterEncoding());
2711+
servletResponse.setContentType(servletRequest.getContentType());
2712+
servletResponse.getWriter().println(data);
2713+
asyncContext.complete();
2714+
}
2715+
};
2716+
2717+
if (Log.DEBUG == false) {
2718+
try {
2719+
listener.complete(MethodUtil.JSON_CALLBACK.newErrorResult(new IllegalAccessException("非 DEBUG 模式下不允许使用 UnitAuto 单元测试!")));
2720+
}
2721+
catch (Exception e1) {
2722+
e1.printStackTrace();
2723+
asyncContext.complete();
2724+
}
2725+
2726+
return;
2727+
}
2728+
2729+
try {
2730+
MethodUtil.invokeMethod(request, null, listener);
2731+
}
2732+
catch (Exception e) {
2733+
Log.e(TAG, "invokeMethod try { JSONObject req = JSON.parseObject(request); ... } catch (Exception e) { \n" + e.getMessage());
2734+
try {
2735+
listener.complete(MethodUtil.JSON_CALLBACK.newErrorResult(e));
2736+
}
2737+
catch (Exception e1) {
2738+
e1.printStackTrace();
2739+
asyncContext.complete();
2740+
}
2741+
}
2742+
}
2743+
26822744
// 为 UnitAuto 提供的单元测试接口 https://github.com/TommyLemon/UnitAuto >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
26832745

26842746
// 为 APIAuto, UnitAuto, SQLAuto 提供的后台 Headless 无 UI 测试转发接口 <<<<<<<<<<<<<<<<<<<<<<<<<<<

0 commit comments

Comments
 (0)