diff --git a/src/main/java/we/util/ScriptUtils.java b/src/main/java/we/util/ScriptUtils.java index ba0c76a..08bd975 100644 --- a/src/main/java/we/util/ScriptUtils.java +++ b/src/main/java/we/util/ScriptUtils.java @@ -18,10 +18,16 @@ package we.util; import org.apache.commons.lang3.StringUtils; +import org.springframework.core.io.ClassPathResource; import javax.script.*; + +import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; import java.util.HashMap; import java.util.Map; @@ -42,6 +48,8 @@ public abstract class ScriptUtils { private static final String clazz = "clazz"; private static final String resJsonStr = "resJsonStr"; + + private static final String COMMON_JS_PATH = "js/common.js"; public static Map recreateJavascriptEngineSignalMap = new HashMap<>(); @@ -51,10 +59,20 @@ public abstract class ScriptUtils { private static ScriptEngine createJavascriptEngine() throws ScriptException { ScriptEngine eng = engineManger.getEngineByName(JAVA_SCRIPT); - try { - eng.eval(new FileReader("js/common.js")); + try { + // custom common.js file + File f = new File(COMMON_JS_PATH); + if(f.exists()) { + eng.eval(new FileReader(COMMON_JS_PATH)); + return eng; + } + // use embedded common.js while there is not custom common.js file + ClassPathResource res = new ClassPathResource(COMMON_JS_PATH); + eng.eval(new InputStreamReader(res.getInputStream())); return eng; } catch (FileNotFoundException e) { + throw new ScriptException(e); + } catch (IOException e) { throw new ScriptException(e); } } diff --git a/src/main/resources/js/common.js b/src/main/resources/js/common.js new file mode 100644 index 0000000..689ff00 --- /dev/null +++ b/src/main/resources/js/common.js @@ -0,0 +1,230 @@ +/** + * context 上下文便捷操作函数 + * + */ +var common = { + /* *********** private function begin *********** */ + + // 获取上下文中客户端请求对象 + getInputReq: function (ctx){ + if(!ctx || !ctx['input'] || !ctx['input']['request']){ + return {}; + } + return ctx['input']['request'] + }, + + // 获取上下文步骤中请求接口的请求对象 + getStepReq: function (ctx, stepName, requestName){ + if(!ctx || !stepName || !requestName){ + return {}; + } + if(!ctx[stepName] || !ctx[stepName]['requests'] || !ctx[stepName]['requests'][requestName] || + !ctx[stepName]['requests'][requestName]['request']){ + return {}; + } + return ctx[stepName]['requests'][requestName]['request']; + }, + + // 获取上下文步骤中请求接口的响应对象 + getStepResp: function (ctx, stepName, requestName){ + if(!ctx || !stepName || !requestName){ + return {}; + } + if(!ctx[stepName] || !ctx[stepName]['requests'] || !ctx[stepName]['requests'][requestName] || + !ctx[stepName]['requests'][requestName]['response']){ + return {}; + } + return ctx[stepName]['requests'][requestName]['response']; + }, + + /* *********** private function end *********** */ + + /* *********** input begin ************ */ + + /** + * 获取客户端请求头 + * @param {*} ctx 上下文 【必填】 + * @param {*} headerName 请求头字段名 【选填】,不传时返回所有请求头 + */ + getInputReqHeader: function (ctx, headerName){ + var req = this.getInputReq(ctx); + var headers = req['headers'] || {}; + return headerName ? headers[headerName] : headers; + }, + + /** + * 获取客户端URL请求参数(query string) + * @param {*} ctx 上下文 【必填】 + * @param {*} paramName URL参数名 【选填】,不传时返回所有请求参数 + */ + getInputReqParam: function (ctx, paramName){ + var req = this.getInputReq(ctx); + var params = req['params'] || {}; + return paramName ? params[paramName] : params; + }, + + /** + * 获取客户端请求体 + * @param {*} ctx 上下文 【必填】 + * @param {*} field 字段名 【选填】,不传时返回整个请求体 + */ + getInputReqBody: function (ctx, field){ + var req = this.getInputReq(ctx); + var body = req['body'] || {}; + return field ? body[field] : body; + }, + + /** + * 获取返回给客户端的响应头 + * @param {*} ctx 上下文 【必填】 + * @param {*} headerName 响应头字段名 【选填】,不传时返回所有响应头 + */ + getInputRespHeader: function (ctx, headerName){ + var req = this.getInputReq(ctx); + var headers = req['headers'] || {}; + return headerName ? headers[headerName] : headers; + }, + + /** + * 获取返回给客户端的响应体 + * @param {*} ctx 上下文 【必填】 + * @param {*} field 字段名 【选填】,不传时返回整个响应体 + */ + getInputRespBody: function (ctx, field){ + var req = this.getInputReq(ctx); + var body = req['body'] || {}; + return field ? body[field] : body; + }, + + /* *********** input begin ************ */ + + /* *********** step request begin ************ */ + + /** + * 获取步骤中调用的接口的请求头 + * @param {*} ctx 上下文 【必填】 + * @param {*} stepName 步骤名【必填】 + * @param {*} requestName 请求的接口名 【必填】 + * @param {*} headerName 请求头字段名 【选填】,不传时返回所有请求头 + */ + getStepReqHeader: function (ctx, stepName, requestName, headerName){ + var req = this.getStepReq(ctx, stepName, requestName); + var headers = req['headers'] || {}; + return headerName ? headers[headerName] : headers; + }, + + /** + * 获取步骤中调用的接口的URL参数 + * @param {*} ctx 上下文 【必填】 + * @param {*} stepName 步骤名【必填】 + * @param {*} requestName 请求的接口名 【必填】 + * @param {*} paramName URL参数名 【选填】,不传时返回所有URL参数 + */ + getStepReqParam: function (ctx, stepName, requestName, paramName){ + var req = this.getStepReq(ctx, stepName, requestName); + var params = req['params'] || {}; + return paramName ? params[paramName] : params; + }, + + /** + * 获取步骤中调用的接口的请求体 + * @param {*} ctx 上下文 【必填】 + * @param {*} stepName 步骤名【必填】 + * @param {*} requestName 请求的接口名 【必填】 + * @param {*} field 字段名 【选填】,不传时返回整个请求体 + */ + getStepReqBody: function (ctx, stepName, requestName, field){ + var req = this.getStepReq(ctx, stepName, requestName); + var body = req['body'] || {}; + return field ? body[field] : body; + }, + + /** + * 获取步骤中调用的接口的响应头 + * @param {*} ctx 上下文 【必填】 + * @param {*} stepName 步骤名【必填】 + * @param {*} requestName 请求的接口名 【必填】 + * @param {*} headerName 响应头字段名 【选填】,不传时返回所有响应头 + */ + getStepRespHeader: function (ctx, stepName, requestName, headerName){ + var resp = this.getStepResp(ctx, stepName, requestName); + var headers = resp['headers'] || {}; + return headerName ? headers[headerName] : headers; + }, + + /** + * 获取步骤中调用的接口的响应头 + * @param {*} ctx 上下文 【必填】 + * @param {*} stepName 步骤名【必填】 + * @param {*} requestName 请求的接口名 【必填】 + * @param {*} field 字段名 【选填】,不传时返回整个响应头 + */ + getStepRespBody: function (ctx, stepName, requestName, field){ + var resp = this.getStepResp(ctx, stepName, requestName); + var body = resp['body'] || {}; + return field ? body[field] : body; + }, + + /** + * 获取步骤结果 + * @param {*} ctx 上下文 【必填】 + * @param {*} stepName 步骤名【必填】 + * @param {*} field 字段名 【选填】,不传时返回整个步骤结果对象 + */ + getStepResult: function (ctx, stepName, field){ + if(!ctx || !stepName || !ctx[stepName]){ + return {}; + } + var result = ctx[stepName]['result'] || {}; + return field ? result[field] : result; + } + + /* *********** step request end ************ */ + + ,/** + ** 乘法函数,用来得到精确的乘法结果 + ** 说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。 + ** 调用:accMul(arg1,arg2) + ** 返回值:arg1乘以 arg2的精确结果 + **/ + accMul:function (arg1, arg2) { + var m = 0, s1 = arg1.toString(), s2 = arg2.toString(); + try { + m += s1.split(".")[1].length; + } catch (e) { + } + try { + m += s2.split(".")[1].length; + } catch (e) { + } + return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) + / Math.pow(10, m); + }, + + /** + ** 除法函数,用来得到精确的除法结果 + ** 说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。 + ** 调用:accDiv(arg1,arg2) + ** 返回值:arg1除以arg2的精确结果 + **/ + accDiv:function (arg1, arg2) { + var t1 = 0, t2 = 0, r1, r2; + try { + t1 = arg1.toString().split(".")[1].length; + } catch (e) { + } + try { + t2 = arg2.toString().split(".")[1].length; + } catch (e) { + } + with (Math) { + r1 = Number(arg1.toString().replace(".", "")); + r2 = Number(arg2.toString().replace(".", "")); + return (r1 / r2) * pow(10, t2 - t1); + } + } + + +}; + +