14
14
15
15
package apijson .boot ;
16
16
17
- import static apijson .RequestMethod .DELETE ;
18
- import static apijson .RequestMethod .GET ;
19
- import static apijson .RequestMethod .GETS ;
20
- import static apijson .RequestMethod .HEAD ;
21
- import static apijson .RequestMethod .HEADS ;
22
- import static apijson .RequestMethod .POST ;
23
- import static apijson .RequestMethod .PUT ;
24
- import static apijson .framework .APIJSONConstant .ACCESS_ ;
25
- import static apijson .framework .APIJSONConstant .COUNT ;
26
- import static apijson .framework .APIJSONConstant .FORMAT ;
27
- import static apijson .framework .APIJSONConstant .FUNCTION_ ;
28
- import static apijson .framework .APIJSONConstant .ID ;
29
- import static apijson .framework .APIJSONConstant .REQUEST_ ;
30
- import static apijson .framework .APIJSONConstant .USER_ID ;
31
- import static apijson .framework .APIJSONConstant .VERSION ;
32
- import static org .springframework .http .HttpHeaders .COOKIE ;
33
- import static org .springframework .http .HttpHeaders .SET_COOKIE ;
17
+ import com .alibaba .fastjson .JSONArray ;
18
+ import com .alibaba .fastjson .JSONObject ;
19
+ import com .fasterxml .jackson .databind .util .LRUMap ;
20
+
21
+ import org .springframework .beans .factory .annotation .Autowired ;
22
+ import org .springframework .http .HttpEntity ;
23
+ import org .springframework .http .HttpHeaders ;
24
+ import org .springframework .http .HttpMethod ;
25
+ import org .springframework .http .ResponseEntity ;
26
+ import org .springframework .stereotype .Service ;
27
+ import org .springframework .web .bind .annotation .GetMapping ;
28
+ import org .springframework .web .bind .annotation .PathVariable ;
29
+ import org .springframework .web .bind .annotation .PostMapping ;
30
+ import org .springframework .web .bind .annotation .RequestBody ;
31
+ import org .springframework .web .bind .annotation .RequestMapping ;
32
+ import org .springframework .web .bind .annotation .RequestParam ;
33
+ import org .springframework .web .bind .annotation .RestController ;
34
+ import org .springframework .web .client .RestTemplate ;
34
35
35
36
import java .net .URLDecoder ;
36
37
import java .rmi .ServerException ;
38
+ import java .sql .PreparedStatement ;
39
+ import java .sql .ResultSet ;
40
+ import java .sql .ResultSetMetaData ;
41
+ import java .sql .Statement ;
37
42
import java .util .ArrayList ;
38
43
import java .util .Arrays ;
39
44
import java .util .Enumeration ;
49
54
import javax .servlet .http .HttpServletResponse ;
50
55
import javax .servlet .http .HttpSession ;
51
56
52
- import org .springframework .beans .factory .annotation .Autowired ;
53
- import org .springframework .http .HttpEntity ;
54
- import org .springframework .http .HttpHeaders ;
55
- import org .springframework .http .HttpMethod ;
56
- import org .springframework .http .ResponseEntity ;
57
- import org .springframework .stereotype .Service ;
58
- import org .springframework .web .bind .annotation .GetMapping ;
59
- import org .springframework .web .bind .annotation .PathVariable ;
60
- import org .springframework .web .bind .annotation .PostMapping ;
61
- import org .springframework .web .bind .annotation .RequestBody ;
62
- import org .springframework .web .bind .annotation .RequestMapping ;
63
- import org .springframework .web .bind .annotation .RequestParam ;
64
- import org .springframework .web .bind .annotation .RestController ;
65
- import org .springframework .web .client .RestTemplate ;
66
-
67
- import com .alibaba .fastjson .JSONObject ;
68
- import com .fasterxml .jackson .databind .util .LRUMap ;
69
-
70
57
import apijson .JSON ;
71
58
import apijson .JSONResponse ;
72
59
import apijson .Log ;
73
60
import apijson .RequestMethod ;
74
61
import apijson .StringUtil ;
75
62
import apijson .demo .DemoFunctionParser ;
76
63
import apijson .demo .DemoParser ;
64
+ import apijson .demo .DemoSQLConfig ;
65
+ import apijson .demo .DemoSQLExecutor ;
77
66
import apijson .demo .DemoVerifier ;
78
67
import apijson .demo .model .Privacy ;
79
68
import apijson .demo .model .User ;
86
75
import apijson .orm .exception .OutOfRangeException ;
87
76
import apijson .router .APIJSONRouterController ;
88
77
78
+ import static apijson .RequestMethod .DELETE ;
79
+ import static apijson .RequestMethod .GET ;
80
+ import static apijson .RequestMethod .GETS ;
81
+ import static apijson .RequestMethod .HEAD ;
82
+ import static apijson .RequestMethod .HEADS ;
83
+ import static apijson .RequestMethod .POST ;
84
+ import static apijson .RequestMethod .PUT ;
85
+ import static apijson .framework .APIJSONConstant .ACCESS_ ;
86
+ import static apijson .framework .APIJSONConstant .COUNT ;
87
+ import static apijson .framework .APIJSONConstant .FORMAT ;
88
+ import static apijson .framework .APIJSONConstant .FUNCTION_ ;
89
+ import static apijson .framework .APIJSONConstant .ID ;
90
+ import static apijson .framework .APIJSONConstant .REQUEST_ ;
91
+ import static apijson .framework .APIJSONConstant .USER_ID ;
92
+ import static apijson .framework .APIJSONConstant .VERSION ;
93
+ import static org .springframework .http .HttpHeaders .COOKIE ;
94
+ import static org .springframework .http .HttpHeaders .SET_COOKIE ;
95
+
89
96
90
97
/**请求路由入口控制器,包括通用增删改查接口等,转交给 APIJSON 的 Parser 来处理
91
98
* 具体见 SpringBoot 文档
92
99
* https://www.springcloud.cc/spring-boot.html#boot-features-spring-mvc
93
- * 以及 APIJSON 通用文档 3.设计规范 3.1 操作方法
100
+ * 以及 APIJSON 通用文档 3.设计规范 3.1 操作方法
94
101
* https://github.com/Tencent/APIJSON/blob/master/Document.md#3.1
95
102
* <br > 建议全通过HTTP POST来请求:
96
103
* <br > 1.减少代码 - 客户端无需写HTTP GET,PUT等各种方式的请求代码
@@ -123,7 +130,7 @@ public String getRequestURL() {
123
130
public String router (@ PathVariable String method , @ PathVariable String tag , @ RequestParam Map <String , String > params , @ RequestBody String request , HttpSession session ) {
124
131
return super .router (method , tag , params , request , session );
125
132
}
126
-
133
+
127
134
// 通用接口,非事务型操作 和 简单事务型操作 都可通过这些接口自动化实现 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
128
135
129
136
/**增删改查统一入口,这个一个方法可替代以下 7 个方法,牺牲一些路由解析性能来提升一点开发效率
@@ -713,7 +720,7 @@ public JSONObject login(@RequestBody String request, HttpSession session) {
713
720
return privacyResponse ;
714
721
}
715
722
716
- //校验凭证
723
+ //校验凭证
717
724
if (isPassword ) {//password密码登录
718
725
response = new JSONResponse (
719
726
new DemoParser (HEADS , false ).parseResponse (
@@ -853,7 +860,7 @@ public JSONObject register(@RequestBody String request) {
853
860
requestObject .put (JSONRequest .KEY_TAG , REGISTER );
854
861
}
855
862
requestObject .put (JSONRequest .KEY_FORMAT , true );
856
- response = new JSONResponse (
863
+ response = new JSONResponse (
857
864
new DemoParser (POST ).setNeedVerifyLogin (false ).parseResponse (requestObject )
858
865
);
859
866
@@ -982,7 +989,7 @@ public JSONObject putPassword(@RequestBody String request){
982
989
} else {
983
990
privacy .setPayPassword (oldPassword );
984
991
}
985
- JSONResponse response = new JSONResponse (
992
+ JSONResponse response = new JSONResponse (
986
993
new DemoParser (HEAD , false ).parseResponse (
987
994
new JSONRequest (privacy ).setFormat (true )
988
995
)
@@ -1169,11 +1176,11 @@ public void remove(String key) {
1169
1176
@ SuppressWarnings ("unchecked" )
1170
1177
@ RequestMapping (value = "delegate" )
1171
1178
public String delegate (
1172
- @ RequestParam ("$_delegate_url" ) String url ,
1179
+ @ RequestParam ("$_delegate_url" ) String url ,
1173
1180
@ RequestParam (value = "$_type" , required = false ) String type ,
1174
1181
@ RequestParam (value = "$_except_headers" , required = false ) String exceptHeaders ,
1175
- @ RequestParam (value = "$_delegate_id" , required = false ) String sessionId ,
1176
- @ RequestBody (required = false ) String body ,
1182
+ @ RequestParam (value = "$_delegate_id" , required = false ) String sessionId ,
1183
+ @ RequestBody (required = false ) String body ,
1177
1184
HttpMethod method , HttpSession session
1178
1185
) {
1179
1186
@@ -1210,7 +1217,7 @@ public String delegate(
1210
1217
if (names != null ) {
1211
1218
headers = new HttpHeaders ();
1212
1219
//Arrays.asList(null) 抛异常,可以排除不存在的头来替代 exceptHeaders == null //空字符串表示不排除任何头
1213
- List <String > exceptHeaderList = StringUtil .isEmpty (exceptHeaders , true )
1220
+ List <String > exceptHeaderList = StringUtil .isEmpty (exceptHeaders , true )
1214
1221
? EXCEPT_HEADER_LIST : Arrays .asList (StringUtil .split (exceptHeaders ));
1215
1222
1216
1223
@@ -1221,7 +1228,7 @@ public String delegate(
1221
1228
while (names .hasMoreElements ()) {
1222
1229
name = names .nextElement ();
1223
1230
if (name != null && exceptHeaderList .contains (name .toLowerCase ()) == false ) {
1224
- //APIAuto 是一定精准发送 Set-Cookie 名称过来的,预留其它命名可实现覆盖原 Cookie Header 等更多可能
1231
+ //APIAuto 是一定精准发送 Set-Cookie 名称过来的,预留其它命名可实现覆盖原 Cookie Header 等更多可能
1225
1232
if (SET_COOKIE .toLowerCase ().equals (name .toLowerCase ())) { //接收到时就已经被强制小写
1226
1233
setCookie = Arrays .asList (httpServletRequest .getHeader (name )); // JSON.parseArray(request.getHeader(name), String.class);
1227
1234
}
@@ -1317,6 +1324,96 @@ else if (APIJSON_DELEGATE_ID.toLowerCase().equals(name.toLowerCase())) {
1317
1324
return entity .getBody ();
1318
1325
}
1319
1326
1327
+ /**执行 SQL 语句,支持 SQLAuto,注意仅仅不要开放给后端组外的任何人,更不要暴露到公司外的公网!
1328
+ * @param request 只用String,避免encode后未decode
1329
+ * @return
1330
+ * @see
1331
+ * <pre>
1332
+ {
1333
+ "sql": "SELECT * FROM sys.Access LIMIT ${limit}", // SQL 语句,可以带占位符
1334
+ "arg": {
1335
+ "limit": 5
1336
+ }
1337
+ }
1338
+ * </pre>
1339
+ */
1340
+ @ PostMapping ("execute" )
1341
+ public String execute (@ RequestBody String request , HttpSession session ) {
1342
+ try {
1343
+ if (Log .DEBUG == false ) {
1344
+ return DemoParser .newErrorResult (new IllegalAccessException ("非 DEBUG 模式下不允许调用 /execute !" )).toJSONString ();
1345
+ }
1346
+
1347
+ DemoVerifier .verifyLogin (session );
1348
+
1349
+ long startTime = System .currentTimeMillis ();
1350
+
1351
+ JSONObject req = JSON .parseObject (request );
1352
+ String uri = req .getString ("uri" );
1353
+ String sql = req .getString ("sql" );
1354
+ List <Object > valueList = req .getJSONArray ("arg" );
1355
+
1356
+ DemoSQLExecutor executor = new DemoSQLExecutor ();
1357
+ DemoSQLConfig config = new DemoSQLConfig ();
1358
+
1359
+ if (StringUtil .isNotEmpty (uri )) {
1360
+ config .setDBUri (uri );
1361
+ }
1362
+ config .setPrepared (true );
1363
+ config .setPreparedValueList (valueList );
1364
+
1365
+ Statement statement = executor .getStatement (config , sql );
1366
+ if (statement instanceof PreparedStatement ) {
1367
+ ((PreparedStatement ) statement ).execute ();
1368
+ } else {
1369
+ statement .execute (sql );
1370
+ }
1371
+
1372
+ ResultSet rs = statement .getResultSet ();
1373
+ ResultSetMetaData rsmd = rs .getMetaData ();
1374
+ int length = rsmd .getColumnCount ();
1375
+
1376
+ JSONArray arr = new JSONArray ();
1377
+
1378
+ long cursorDuration = 0 ;
1379
+ long rsDuration = 0 ;
1380
+
1381
+ long cursorStartTime = System .currentTimeMillis ();
1382
+ while (rs .next ()) {
1383
+ cursorDuration += System .currentTimeMillis () - cursorStartTime ;
1384
+
1385
+ JSONObject obj = new JSONObject (true );
1386
+ for (int i = 1 ; i <= length ; i ++) {
1387
+ long sqlStartTime = System .currentTimeMillis ();
1388
+ String label = rsmd .getColumnLabel (i );
1389
+ Object value = rs .getObject (i );
1390
+ rsDuration += System .currentTimeMillis () - sqlStartTime ;
1391
+
1392
+ obj .put (label , value );
1393
+ }
1394
+
1395
+ arr .add (obj );
1396
+ }
1397
+
1398
+ JSONObject result = DemoParser .newSuccessResult ();
1399
+ result .put ("count" , statement .getUpdateCount ());
1400
+ result .put ("list" , arr );
1401
+
1402
+ long endTime = System .currentTimeMillis ();
1403
+ long duration = endTime - startTime ;
1404
+
1405
+ long sqlDuration = cursorDuration + rsDuration ;
1406
+ long parseDuration = duration - sqlDuration ;
1407
+
1408
+ result .put ("time:start|duration|end|parse|sql" , startTime + "|" + duration + "|" + endTime + "|" + parseDuration + "|" + sqlDuration );
1409
+
1410
+ return result .toJSONString ();
1411
+ } catch (Exception e ) {
1412
+ return DemoParser .newErrorResult (e ).toJSONString ();
1413
+ }
1414
+
1415
+ }
1416
+
1320
1417
1321
1418
/**Swagger 文档 Demo,供 APIAuto 测试导入 Swagger 文档到数据库用
1322
1419
* @return
0 commit comments