
com.github.dadiyang.mockjs.Mock Maven / Gradle / Ivy
package com.github.dadiyang.mockjs;
import com.alibaba.fastjson.JSON;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 支持 Mockjs 的 Mock.mock 方法
*
* 原理: 使用 ScriptEngine 执行封装的 mockjs 脚本
*
* @author huangxuyang
* @since 2021/2/11
*/
public class Mock {
private static final ScriptEngine SCRIPT_ENGINE = new ScriptEngineManager().getEngineByName("javascript");
private static final String MOCK_JS_PREFIX = "Mock.mock(";
private static final String JSON_OBJECT_PREFIX = "{";
private static final String JSON_ARRAY_PREFIX = "[";
private Mock() {
throw new UnsupportedOperationException("静态工具类不允许被实例化");
}
static {
try (InputStream is = Mock.class.getClassLoader().getResourceAsStream("script/mock-min.js")) {
if (is != null) {
List lines = IOUtils.readLines(is, StandardCharsets.UTF_8);
String tpl = String.join("\n", lines);
SCRIPT_ENGINE.eval(tpl);
}
} catch (Exception e) {
throw new IllegalStateException("加载 mockjs 脚本出错", e);
}
}
/**
* 执行 mockjs 脚本
*
* @param tpl mockjs模板脚本,必须是一个JSON对象或数组,或者以 Mock.mock( 直接调用 mockjs api 的形式提供
* @return 如果模板是一个对象,则为 key->value,如果是数组则为 index -> key -> value
* @throws IllegalArgumentException tpl 为空或不是 JSON 对象或数组且不以 Mock.mock( 时抛出非法参数异常
* @throws IllegalStateException 脚本执行失败时抛出此异常
*/
public static Map mock(String tpl) {
checkMockTpl(tpl);
tpl = tpl.trim();
// 添加 Mock.mock() 调用
if (tpl.startsWith(JSON_OBJECT_PREFIX) || tpl.startsWith(JSON_ARRAY_PREFIX)) {
tpl = MOCK_JS_PREFIX + tpl + ")";
}
try {
//noinspection unchecked
return (Map) SCRIPT_ENGINE.eval(tpl);
} catch (ScriptException e) {
throw new IllegalStateException("脚本执行失败" + e.getMessage() + " 脚本: " + tpl, e);
}
}
/**
* 执行 mockjs 脚本
*
* 注:此方法依赖 FastJson
*
* @param tpl mockjs模板脚本,必须是一个JSON对象或数组,或者以 Mock.mock( 直接调用 mockjs api 的形式提供
* @throws IllegalArgumentException tpl 为空或不是 JSON 对象或数组且不以 Mock.mock( 时抛出非法参数异常
* @throws IllegalStateException 脚本执行失败时抛出此异常
*/
public static T mock(String tpl, Class clazz) {
Object obj = mock(tpl);
return JSON.parseObject(JSON.toJSONString(obj), clazz);
}
/**
* 通过 mockjs 模板生成一个对象列表
*
* @param tpl mockjs模板,必须是一个 JSON 数组
* @throws IllegalArgumentException tpl 为空或不是 JSON 对象时抛出
* @throws IllegalStateException 脚本执行失败时抛出此异常
*/
public static List