marmot

1.0.0 • Public • Published

Marmot

一个Java平台的Mock Server

模板引擎

  • Velocity
  • Freemarker

Install

Mac/Linux

$ sudo npm install -g marmot

Windows

windows中您需要在管理员模式下安装

$ npm install -g marmot

依赖环境

  • Node.js 4.0+
  • JDK 7+

Usage

init sub-command

进入项目目录下执行

$ marmot init

项目下如果存在 .marmotrc 配置文件,那么会根据文件中的配置进行初始化,如果不存在 .marmotrc 配置文件,执行后会出现问答式的初始化设置,并会生成一个 .marmotrc 配置文件。

  • marmot init 主要生成了项目的 WEB-INF 目录所需要的jar包及模板引擎的配置。
  • 由于 WEB-INF 目录是根据 .marmotrc 配置文件生成的,所以您在提交代码的时候,无需提交此目录。

参数:

  • -f, --force 强制初始化当前项目。

server sub-command

进入项目目录下执行

$ marmot server <command>

server 目前一共有五个命令,分别为:

  • 启动应用 marmot server start
  • 停止应用 marmot server stop
  • 重启应用 marmot server restart
  • 从应用列表中移除应用 marmot server remove
  • 显示所有应用列表 marmot server list

接下来针对每个命令进行详细说明。

启动应用

$ marmot server start

参数:

  • -p, --port 应用端口

初次启动时如果没有指定端口号,则默认为 8080 ,若指定了端口号则以指定的端口号启动。
当第二次启动的时候,如果没有指定端口号则默认为上次启动时使用的端口号。

示例
# 启动服务并指定端口为8090 
$ marmot server start -p 8090

停止应用

$ marmot server stop

参数:

  • -p, --port 应用端口
  • -i, --id 应用ID,该ID是由初次启动应用时生成的ID。可使用list命令查看
示例
# 通过端口停止应用 
$ marmot server stop -p 8090
 
# 通过id停止应用 
$ marmot server stop -i 1

重启应用

$ marmot server restart

移除应用

$ marmot server remove

参数:

  • -p, --port 应用端口
  • -i, --id 应用ID,该ID是由初次启动应用时生成的ID。可使用list命令查看

remove 的别名为 rm
注意:移除应用时,至少需要指定任意一个参数

示例
# 通过端口停止应用 
$ marmot server rm -p 8090
 
# 通过ID停止应用 
$ marmot server rm -i 1

显示所有应用列表

$ marmot server list

list 的别名为 ls

以上命令将输出如下列表。

┌──────┬─────────────────────────┬────────┬────────┬──────────┬────────────────────────────────┐
│  id  │  domain                 │  port  │  pid   │  status  │  pathname                      │
├──────┼─────────────────────────┼────────┼────────┼──────────┼────────────────────────────────┤
│  12  │  http://127.0.0.1:8080  │  8080  │  9088  │  online  │  /Users/evan/projects/cashier  │
└──────┴─────────────────────────┴────────┴────────┴──────────┴────────────────────────────────┘

路由配置

在初始化项目时,会提示您输入路由文件入口的生成位置,默认是在当前项目目录下生成router/main.xml,如果您需要自定义文件名,请务必使用后缀为.xml的文件名。

以下是一个简单的路由示例。

<!-- router/main.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<router>
  <cookies>
    <cookie name="JSESSIONID" value="jstl9vqr6dket28u0xreps9e" http-only="true" />
  </cookies>
  <import src="product.xml" />
  <routes>
    <route rule="/" location="/index.vm" />
    <route rule="/api/v1/user.json" proxy="http://127.0.0.1:3000" />
    <route rule="/user/center" content-type="text/html" proxy="http://xxx.xxx.xxx" />
  </routes>
  <routes proxy="...">
    <route rule="...">
    <!-- ... -->
  </routes>
</router>
 
<!-- router/product.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<routes>
  <route rule="/product/detail" location="/product/detail.vm" />
</routes>

在路由的配置中有 routerimportcookiescookieroutesroute 6种标签(不包括 xml 声明),接下来将逐一介绍其功能

router 标签

router 标签是路由入口文件的根元素,使用 import标签引入的其他路由文件则不需要使用此标签。

proxy 属性

原为provider属性,该属性仍然可用,但推荐使用proxy

该属性作用于整个路由文件中,proxy 指向一个可访问的IP/域名,其作用为当规则被命中后,当前请求将被转发到该IP/域名,此属性的值必须是一个有效的IP/域名,如果不写协议类型,那么将以当前启动的 Marmot 应用的协议作为缺省值。

Marmot 通过 proxy 转发的请求,Request Headers中会包含 X-Requested-With: MarmotHttpRequest 字段。

有效的HTTP地址:

http://xxx.xxx.xxx
//xxx.xxx.xxx
xxx.xxx.xxx

值得注意的是被命中的路由规则中,route 中的 location 属性将会被忽略。

示例:

<router proxy="http://x.x.x.x:3000">
  <routes>
    <route rule="/user/info.json" />
  </routes>
</router>

结果如下:

本地访问地址
http://127.0.0.1:8080

访问以下地址
http://127.0.0.1:8080/user/info.json

实际上将从以下url中获取数据
http://x.x.x.x:3000/user/info.json

cookies 标签

此标签用于包含所有的 cookie 设置,该标签应放在 router 标签下的第一个位置,如此才会应用于所有路由规则中。

示例:

<!-- main.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<router>
  <cookies>
    <cookie
      name="JSESSIONID"
      value="jstl9vqr6dket28u0xreps9e"
      http-only="true"
    />
    <cookie
      name="accessToken"
      value="jstl9vqr6dket28u0xreps9e"
      max-age="3600"
      http-only="true"
    />
  </cookies>
  <import src="product.xml">
  <routes>
    <route rule="/" location="/index.vm">
  </routes>
</router>

cookie 标签

设置一条cookie

属性:

  • name cookie名称
  • value cookie值
  • domain cookie适用的域名,通常没必要设置
  • path 在指定的访问路径下发起请求,cookie才会被携带
  • max-age cookie最大存活期,单位: 秒
  • http-only 默认false,当设置为true时,该cookie在浏览器端不可被JS读取

示例:

<cookies>
  <cookie
    name="accessToken"
    value="abj3de2vjqp43mf2dd9fj1fd"
    domain="localhost"
    path="/profile"
    max-age="3600"
    http-only="true"
  />
</cookies>

import 标签

引入一个新的路由文件,该文件的路径是相对于主入口文件的,建议所有路由文件统一放到同一目录下。

目录结构:

router/
  main.xml
  product.xml

路由引入方式:

<!-- main.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<router>
  <import src="product.xml">
  <!-- 等同如下方式 -->
  <import src="./product.xml">
</router>

routes route-map 标签

此标签用于包含一组路由规则,路由规则的匹配仅处理 routes 标签包含的元素,写在其他位置的路由规则将不会被匹配到。

原为 route-map 标签,目前不建议使用,0.7.0 版本中将被移除。

proxy 属性

原为provider属性,该属性仍然可用,但推荐使用proxy

该属性与 router 标签上的 proxy 是一样的,不同的是只作用于 routes 下的路由规则。若 routerroutes 同时指定 proxy ,则优先使用 routesproxy

示例:

<router proxy="http://x.x.x.x:8888">
  <routes proxy="http://x.x.x.x:3002">
    <route rule="/user/info.json" />
  </routes>
  <routes>
    <route rule="/movie/list.json" />
  </routes>
</router>

结果如下:

本地访问地址
http://127.0.0.1:8080

访问以下地址
http://127.0.0.1:8080/user/info.json

实际上将从以下url中获取数据
http://x.x.x.x:3002/user/info.json

访问以下地址
http://127.0.0.1:8080/movie/list.json

实际上将从以下url中获取数据
http://x.x.x.x:8888/movie/list.json

route 标签

该标签用于配置路由规则,以下为 route 标签所支持的属性。

rule uri 属性

rule 属性表示路由的匹配规则,其值可以是普通的字符串也可以是一个正则表达式,并且规则仅对URL中的路径部分进行匹配,其余部分(query string,anchor name)不会参与匹配。

原为 uri 属性,目前不建议使用,0.7.0 版本中将被移除。

<!-- 推荐 -->
<route rule="/foo" location="foo.vm">
<!-- 不推荐 -->
<route uri="/foo" location="foo.vm">

我们可以通过正则中的**捕获组()来实现在location属性中使用 $1, $2, $n 的方式来获取捕获组的值,如果要跳过某些分组不匹配则使用非捕获组(?:)**来进行匹配,其中 $0 表示整个匹配的字符串,$1 表示第一个捕获组,$2 表示第二个捕获组,以此类推。

如下示例:

<route rule="/foo/(?:[\w-]+)/(\w+)" location="/$1/foo.vm">
请求地址:
http://127.0.0.0:8080/foo/bar/baz.html

实际访问模版:
/baz/foo.vm

redirect 属性

针对命中的路由进行重定向,会忽略其他属性如:location, proxy, content-type

<route rule="/xxx" redirect="/aaa">

location target 属性

location 属性表示该规则命中后,指向的本地访问的文件,通常是一个模板文件或者JSON文件,当然也可以是一个JSP文件。

原为 target 属性,目前不建议使用,0.7.0 版本中将被移除。

<!-- 推荐 -->
<route rule="/xxx" location="xxx.vm">
<!-- 不推荐 -->
<route rule="/xxx" target="xxx.vm">

proxy 属性

原为provider属性,该属性仍然可用,但推荐使用proxy

router/routes 中的 proxy 功能一样,都是将当前命中规则的请求转发到指定的地址,唯一不同的是改属性存在于route标签中的话,其作用仅针对于当前规则。

示例:

<routes proxy="http://www.a.com">
  <route rule="/foo.json" proxy="http://www.b.com" />
</routes>
<!-- 最终的转发地址将会是: http://www.b.com/test.json -->

content-type 属性

该属性用于指定当前规则命中后的响应内容类型。

值得注意的是如果你在使用 proxy 提供的数据渲染本地模板的时候,content-type 必须设置为 text/htmltext/htm,否则将会直接显示 proxy 响应的内容

示例:

路由规则配置:

<route rule="/index" content-type="text/html" proxy="http://127.0.0.1:3000">

本地 Marmot 启动端口为 8080

访问地址:
http://127.0.0.1:8080/index

规则命中,使用proxy转发后的地址
http://127.0.0.1:3000/index

velocity模板如下:

<!-- views/index.vm -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>$!{title}</title>
  </head>
  <body></body>
</html>

http://127.0.0.1:3000/index 返回结果

{
  "title": "Hello World"
}

此时 http://127.0.0.1:8080/index 响应结果为

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello World</title>
  </head>
  <body></body>
</html>

数据模拟

数据模拟主要分两类:

  1. 本地数据模拟
  2. 使用proxy来访问其他服务提供的模拟数据,如:本地启动的express模拟数据或者测试服务器提供的数据

本地数据模拟

模板数据模拟

当路由规则被命中后,会渲染 location 指定的模板文件,而模板绑定的数据会从先前指定的模拟数据目录中以相同路径的方式先匹配JSP文件,其次匹配JSON文件。

参考自 jello

示例:

<route rule="/index.html" location="/xxx/index.vm">

目录结构:

app/
  views/
    xxx/
      index.vm
  mock/
    xxx/
      index.jsp
      index.json

index.vm 内容:

<!DOCTYPE html>
<html>
  <head>
   <meta charset="utf-8">
    <title>$!{title}</title>
  </head>
  <body>
    <h1>
      Hello, $!{username}
    </h1>
  </body>
</html>

本地环境模拟数据支持JSP与JSON两种格式

JSON:

{
  "title": "foo",
  "username": "evan2x"
}

JSP:

<%@page pageEncoding="UTF-8"%>
<%
  request.setAttribute("title", "foo");
  request.setAttribute("username", "evan2x");
%>

REST API 数据模拟

当路由规则被命中后,会返回 location 所指定文件的内容,支持静态的JSON文件或者动态JSP文件

示例:

<route rule="/user/\w+" location="/mock/api/user.json">

/mock/api/users.json

{
  "name": "evan2x",
  "age": 24
}

若指定为JSP文件,那么该JSP需要输出JSON字符串

<route rule="/users" location="/mock/api/users.jsp">

/mock/api/users.jsp

<%@ page trimDirectiveWhitespaces="true" %>
<%@ page contentType="application/json; charset=utf-8" %>
<%@ page import="com.alibaba.fastjson.*" %>
<%
  class Person {
    private String name;
    private int age;
 
    public void setName(String name) {
      this.name = name;
    }
 
    public String getName() {
      return name;
    }
 
    public void setAge(int age) {
      this.age = age;
    }
 
    public int getAge() {
      return age;
    }
  }
%>
<%
  Person p = new Person();
  p.setName("evan2x");
  p.setAge(24);
 
  out.print(JSON.toJSONString(p));
%>

以上代码输出结果与之前的 /mock/api/users.json 内容一致。

在Marmot中解析JSON用的jar包就是 fastjson,所以你可以直接导入 fastjson 来将POJO、Map、List、Collection、Enum等类型序列化为JSON字符串。

远程数据模拟

上面说了Marmot本身提供的模拟数据,接下来要说下关于远程服务/本地其他服务提供模拟数据。

模板数据模拟

之前介绍过 proxy 属性的作用,其作用就是将命中的路由转发给proxy指定的IP/域名。

以下为使用Marmot及express来演示一个由Node.js提供数据模拟服务的栗子:

Marmot路由配置:

<route rule="/index.html" render-template="/index.vm" proxy="http://127.0.0.1:3000">

Node.js服务的入口 app.js

var express = require('express');
var router = express.Router();
var app = express();
 
router.get('/index.html', function(req, res){
  // returns the JSON
  res.send({
    "title": "Hello World",
    "description": "This is an example"
  });
});
 
app.use(router);
 
app.listen(3000);

velocity模板 /index.vm

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>$!{title}</title>
  </head>
  <body>
    <h1>$!{title}</h1>
    <p>$!{description}</p>
  </body>
</html>

输出:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello World</title>
  </head>
  <body>
    <h1>Hello World</h1>
    <p>This is an example</p>
  </body>
</html>

注意:

  1. 如果路由中没有指定 content-type 属性,则不会渲染模板,而是将 proxy (以上例子中即express服务)响应的结果提供给客户端。
  2. express中的 /index.html 路由返回了一个JSON格式的数据,Marmot会将其绑定到模板上。

REST API 模拟数据

<route rule="/users.json" proxy="http://127.0.0.1:3000">

当路由命中后,Marmot直接将请求转发给 proxy,返回结果由 proxy 决定。当用于REST API的时候,通常是返回JSON字符串。

Readme

Keywords

none

Package Sidebar

Install

npm i marmot

Weekly Downloads

31

Version

1.0.0

License

MIT

Unpacked Size

9.44 MB

Total Files

18

Last publish

Collaborators

  • evan2x