Skip to content

Commit 2bc8925

Browse files
committed
Server:对存储过程 "@key()":"fun(arg0,arg1...)" 新增格式校验和取值传参;加强对远程函数 "key()":"fun(arg0,arg1...)" 的格式校验
1 parent 595c38d commit 2bc8925

File tree

2 files changed

+179
-57
lines changed

2 files changed

+179
-57
lines changed

APIJSON-Java-Server/APIJSONORM/src/main/java/zuo/biao/apijson/server/AbstractObjectParser.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import zuo.biao.apijson.NotNull;
4242
import zuo.biao.apijson.RequestMethod;
4343
import zuo.biao.apijson.StringUtil;
44+
import zuo.biao.apijson.server.RemoteFunction.FunctionBean;
4445
import zuo.biao.apijson.server.exception.ConflictException;
4546
import zuo.biao.apijson.server.exception.NotExistException;
4647

@@ -743,16 +744,19 @@ public void onFunctionResponse(String type) throws Exception {
743744

744745
public void parseFunction(JSONObject json, String key, String value) throws Exception {
745746
Object result;
746-
if (key.startsWith("@")) {
747+
if (key.startsWith("@")) { //TODO 以后这种小众功能从 ORM 移出,作为一个 plugin/APIJSONProcedure
748+
FunctionBean fb = RemoteFunction.parseFunction(value, json, true);
749+
747750
SQLConfig config = newSQLConfig(true);
748-
config.setProcedure(value);
751+
config.setProcedure(fb.toFunctionCallString(true));
749752

750753
SQLExecutor executor = null;
751754
try {
752755
executor = parser.getSQLExecutor();
753756
result = executor.execute(config, true);
754757
}
755758
catch (NotExistException e) {
759+
e.printStackTrace();
756760
return;
757761
}
758762
}

APIJSON-Java-Server/APIJSONORM/src/main/java/zuo/biao/apijson/server/RemoteFunction.java

+173-55
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
import java.lang.reflect.InvocationTargetException;
1818

19+
import javax.activation.UnsupportedDataTypeException;
20+
21+
import com.alibaba.fastjson.JSONArray;
1922
import com.alibaba.fastjson.JSONObject;
2023

2124
import zuo.biao.apijson.NotNull;
@@ -35,61 +38,13 @@ public class RemoteFunction {
3538
*/
3639
public static Object invoke(@NotNull RemoteFunction fun, @NotNull JSONObject request, @NotNull String function) throws Exception {
3740

38-
int start = function.indexOf("(");
39-
int end = function.lastIndexOf(")");
40-
String method = function.substring(0, start);
41-
if (StringUtil.isEmpty(method, true)) {
42-
throw new IllegalArgumentException("字符 " + function + " 不合法!远程函数的名称function不能为空,"
43-
+ "且必须为 function(key0,key1,...) 这种单函数格式!"
44-
+ "\nfunction必须符合Java函数命名,key是用于在request内取值的键!");
45-
}
46-
47-
String[] keys = StringUtil.split(function.substring(start + 1, end));
48-
49-
int length = keys == null ? 0 : keys.length;
50-
51-
Class<?>[] types = new Class<?>[length + 1];
52-
types[0] = JSONObject.class;
53-
54-
Object[] values = new Object[length + 1];
55-
values[0] = request;
56-
57-
for (int i = 0; i < length; i++) {
58-
types[i + 1] = String.class;
59-
values[i + 1] = keys[i];
60-
}
61-
62-
//碰到null就挂了!!!Number还得各种转换不灵活!不如直接传request和对应的key到函数里,函数内实现时自己 getLongValue,getJSONObject ...
63-
// for (int i = 0; i < length; i++) {
64-
// v = values[i] = request == null ? null : request.get(keys[i]);
65-
// if (v instanceof Boolean) {
66-
// types[i] = Boolean.class; //只支持JSON的几种类型
67-
// }
68-
// else if (v instanceof Number) {
69-
// types[i] = Number.class;
70-
// }
71-
// else if (v instanceof String) {
72-
// types[i] = String.class;
73-
// }
74-
// else if (v instanceof JSONObject) { // Map) {
75-
// types[i] = JSONObject.class;
76-
// //性能比较差 values[i] = request.getJSONObject(keys[i]);
77-
// }
78-
// else if (v instanceof JSONArray) { // Collection) {
79-
// types[i] = JSONArray.class;
80-
// //性能比较差 values[i] = request.getJSONArray(keys[i]);
81-
// }
82-
// else { //FIXME 碰到null就挂了!!!
83-
// throw new UnsupportedDataTypeException(keys[i] + ":value 中value不合法!远程函数 key():" + function + " 中的arg对应的值类型"
84-
// + "只能是 [Boolean, Number, String, JSONObject, JSONArray] 中的一种!");
85-
// }
86-
// }
41+
FunctionBean fb = parseFunction(function, request, false);
8742

8843
try {
89-
return invoke(fun, method, types, values);
44+
return invoke(fun, fb.getMethod(), fb.getTypes(), fb.getValues());
9045
} catch (Exception e) {
9146
if (e instanceof NoSuchMethodException) {
92-
throw new IllegalArgumentException("字符 " + function + " 对应的远程函数 " + getFunction(method, keys) + " 不在后端工程的DemoFunction内!"
47+
throw new IllegalArgumentException("字符 " + function + " 对应的远程函数 " + getFunction(fb.getMethod(), fb.getKeys()) + " 不在后端工程的DemoFunction内!"
9348
+ "\n请检查函数名和参数数量是否与已定义的函数一致!"
9449
+ "\n且必须为 function(key0,key1,...) 这种单函数格式!"
9550
+ "\nfunction必须符合Java函数命名,key是用于在request内取值的键!"
@@ -101,13 +56,99 @@ public static Object invoke(@NotNull RemoteFunction fun, @NotNull JSONObject req
10156
throw te instanceof Exception ? (Exception) te : new Exception(te.getMessage());
10257
}
10358
throw new IllegalArgumentException("字符 " + function + " 对应的远程函数传参类型错误!"
104-
+ "\n请检查 key:value 中value的类型是否满足已定义的函数 " + getFunction(method, keys) + " 的要求!");
59+
+ "\n请检查 key:value 中value的类型是否满足已定义的函数 " + getFunction(fb.getMethod(), fb.getKeys()) + " 的要求!");
10560
}
10661
throw e;
10762
}
10863

10964
}
11065

66+
/**解析函数
67+
* @param function
68+
* @param request
69+
* @param isSQLFunction
70+
* @return
71+
* @throws Exception
72+
*/
73+
@NotNull
74+
public static FunctionBean parseFunction(@NotNull String function, @NotNull JSONObject request, boolean isSQLFunction) throws Exception {
75+
76+
int start = function.indexOf("(");
77+
int end = function.lastIndexOf(")");
78+
String method = end != function.length() - 1 ? null : function.substring(0, start);
79+
if (StringUtil.isEmpty(method, true)) {
80+
throw new IllegalArgumentException("字符 " + function + " 不合法!函数的名称 function 不能为空,"
81+
+ "且必须为 function(key0,key1,...) 这种单函数格式!"
82+
+ "\nfunction必须符合 " + (isSQLFunction ? "SQL 函数/SQL 存储过程" : "Java 函数") + " 命名,key 是用于在 request 内取值的键!");
83+
}
84+
85+
String[] keys = StringUtil.split(function.substring(start + 1, end));
86+
87+
int length = keys == null ? 0 : keys.length;
88+
89+
Class<?>[] types;
90+
Object[] values;
91+
92+
if (isSQLFunction) {
93+
types = new Class<?>[length];
94+
values = new Object[length];
95+
96+
//碰到null就挂了!!!Number还得各种转换不灵活!不如直接传request和对应的key到函数里,函数内实现时自己 getLongValue,getJSONObject ...
97+
Object v;
98+
for (int i = 0; i < length; i++) {
99+
v = values[i] = request.get(keys[i]);
100+
if (v == null) {
101+
types[i] = Object.class;
102+
values[i] = null;
103+
break;
104+
}
105+
106+
if (v instanceof Boolean) {
107+
types[i] = Boolean.class; //只支持JSON的几种类型
108+
}
109+
else if (v instanceof Number) {
110+
types[i] = Number.class;
111+
}
112+
else if (v instanceof String) {
113+
types[i] = String.class;
114+
}
115+
else if (v instanceof JSONObject) { // Map) {
116+
types[i] = JSONObject.class;
117+
//性能比较差 values[i] = request.getJSONObject(keys[i]);
118+
}
119+
else if (v instanceof JSONArray) { // Collection) {
120+
types[i] = JSONArray.class;
121+
//性能比较差 values[i] = request.getJSONArray(keys[i]);
122+
}
123+
else { //FIXME 碰到null就挂了!!!
124+
throw new UnsupportedDataTypeException(keys[i] + ":value 中value不合法!远程函数 key():" + function + " 中的arg对应的值类型"
125+
+ "只能是 [Boolean, Number, String, JSONObject, JSONArray] 中的一种!");
126+
}
127+
}
128+
}
129+
else {
130+
types = new Class<?>[length + 1];
131+
types[0] = JSONObject.class;
132+
133+
values = new Object[length + 1];
134+
values[0] = request;
135+
136+
for (int i = 0; i < length; i++) {
137+
types[i + 1] = String.class;
138+
values[i + 1] = keys[i];
139+
}
140+
}
141+
142+
FunctionBean fb = new FunctionBean();
143+
fb.setFunction(function);
144+
fb.setMethod(method);
145+
fb.setKeys(keys);
146+
fb.setTypes(types);
147+
fb.setValues(values);
148+
149+
return fb;
150+
}
151+
111152

112153
/**反射调用
113154
* @param methodName
@@ -126,16 +167,93 @@ public static Object invoke(@NotNull RemoteFunction fun, @NotNull String methodN
126167
*/
127168
public static String getFunction(String method, String[] keys) {
128169
String f = method + "(JSONObject request";
129-
170+
130171
if (keys != null) {
131172
for (int i = 0; i < keys.length; i++) {
132173
f += (", String " + keys[i]);
133174
}
134175
}
135-
176+
136177
f += ")";
137-
178+
138179
return f;
139180
}
140181

182+
183+
public static class FunctionBean {
184+
private String function;
185+
private String method;
186+
private String[] keys;
187+
private Class<?>[] types;
188+
private Object[] values;
189+
190+
public String getFunction() {
191+
return function;
192+
}
193+
public void setFunction(String function) {
194+
this.function = function;
195+
}
196+
197+
public String getMethod() {
198+
return method;
199+
}
200+
public void setMethod(String method) {
201+
this.method = method;
202+
}
203+
204+
public String[] getKeys() {
205+
return keys;
206+
}
207+
public void setKeys(String[] keys) {
208+
this.keys = keys;
209+
}
210+
211+
public Class<?>[] getTypes() {
212+
return types;
213+
}
214+
public void setTypes(Class<?>[] types) {
215+
this.types = types;
216+
}
217+
218+
public Object[] getValues() {
219+
return values;
220+
}
221+
public void setValues(Object[] values) {
222+
this.values = values;
223+
}
224+
225+
226+
/**
227+
* @param useValue
228+
* @return
229+
*/
230+
public String toFunctionCallString(boolean useValue) {
231+
return toFunctionCallString(useValue, null);
232+
}
233+
/**
234+
* @param useValue
235+
* @param quote
236+
* @return
237+
*/
238+
public String toFunctionCallString(boolean useValue, String quote) {
239+
String s = getMethod() + "(";
240+
241+
Object[] args = useValue ? getValues() : getKeys();
242+
if (args != null && args.length > 0) {
243+
if (quote == null) {
244+
quote = "'";
245+
}
246+
247+
Object arg;
248+
for (int i = 0; i < args.length; i++) {
249+
arg = args[i];
250+
s += (i <= 0 ? "" : ",") + (arg instanceof Boolean || arg instanceof Number ? arg : quote + arg + quote);
251+
}
252+
}
253+
254+
return s + ")";
255+
}
256+
257+
}
258+
141259
}

0 commit comments

Comments
 (0)