You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2020/02/12 08:49:29 UTC

[servicecomb-samples] branch master updated: change porter_lightweight to run in spring boot web containers

This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-samples.git


The following commit(s) were added to refs/heads/master by this push:
     new fca7ec4  change porter_lightweight to run in spring boot web containers
fca7ec4 is described below

commit fca7ec4d18933b59904a5c7259f7911c10fd1666
Author: liubao <bi...@qq.com>
AuthorDate: Wed Feb 12 16:46:36 2020 +0800

    change porter_lightweight to run in spring boot web containers
---
 porter_springboot/README.md                        | 191 +++++++++++++++++++++
 porter_springboot/api/common/endpoint/pom.xml      |  38 ++++
 .../samples/porter/file/api/LogEndpoint.java       |  72 ++++++++
 porter_springboot/api/common/pom.xml               |  36 ++++
 porter_springboot/api/common/service/pom.xml       |  31 ++++
 .../samples/porter/common/api/LogService.java      |  26 +++
 .../api/file-service/endpoint/pom.xml              |  38 ++++
 .../samples/porter/file/api/FileEndpoint.java      |  52 ++++++
 .../porter/file/api/InternalAccessEndpoint.java    |  38 ++++
 porter_springboot/api/file-service/pom.xml         |  36 ++++
 porter_springboot/api/file-service/service/pom.xml |  31 ++++
 .../samples/porter/file/api/FileService.java       |  26 +++
 .../porter/file/api/InternalAccessService.java     |   5 +
 porter_springboot/api/pom.xml                      |  37 ++++
 .../api/user-service/endpoint/pom.xml              |  38 ++++
 .../samples/porter/user/api/UserEndpoint.java      |  51 ++++++
 porter_springboot/api/user-service/pom.xml         |  36 ++++
 porter_springboot/api/user-service/service/pom.xml |  31 ++++
 .../samples/porter/user/api/SessionInfo.java       |  50 ++++++
 .../samples/porter/user/api/UserService.java       |  27 +++
 porter_springboot/file-service/pom.xml             |  58 +++++++
 .../servicecomb/samples/porter/file/FileMain.java  |  34 ++++
 .../porter/file/service/FileServiceImpl.java       |  53 ++++++
 .../porter/file/service/FileStoreService.java      |  31 ++++
 .../file/service/InternalAccessServiceImpl.java    |  28 +++
 .../porter/file/service/LocalFileStoreService.java |  64 +++++++
 .../samples/porter/file/service/SessionInfo.java   |  81 +++++++++
 .../main/resources/META-INF/spring/file.bean.xml   |  27 +++
 .../src/main/resources/application.yml             |  53 ++++++
 .../file-service/src/main/resources/log4j2.xml     |  45 +++++
 porter_springboot/gateway-service/pom.xml          |  63 +++++++
 .../samples/porter/gateway/ApiDispatcher.java      |  66 +++++++
 .../samples/porter/gateway/AuthHandler.java        |  95 ++++++++++
 .../samples/porter/gateway/EdgeSSLCustom.java      |  38 ++++
 .../samples/porter/gateway/GatewayMain.java        |  35 ++++
 .../porter/gateway/InternalAccessHandler.java      |  37 ++++
 .../porter/gateway/StaticWebpageDispatcher.java    |  52 ++++++
 .../samples/porter/gateway/UserServiceClient.java  |  39 +++++
 ...cecomb.transport.rest.vertx.VertxHttpDispatcher |  19 ++
 .../main/resources/META-INF/spring/cse.bean.xml    |  27 +++
 .../src/main/resources/application.yml             |  66 +++++++
 .../src/main/resources/config/cse.handler.xml      |  23 +++
 .../gateway-service/src/main/resources/log4j2.xml  |  45 +++++
 .../src/main/resources/ui/css/style.css            |  49 ++++++
 .../src/main/resources/ui/js/jquery-1.11.1.min.js  |   4 +
 .../src/main/resources/ui/js/login.js              |  52 ++++++
 .../src/main/resources/ui/js/upload.js             |  63 +++++++
 .../src/main/resources/ui/login.html               |  45 +++++
 .../src/main/resources/ui/upload.html              |  61 +++++++
 porter_springboot/pom.xml                          | 105 +++++++++++
 porter_springboot/user-service/pom.xml             |  94 ++++++++++
 .../servicecomb/samples/porter/user/UserMain.java  |  34 ++++
 .../samples/porter/user/dao/SessionInfoModel.java  |  90 ++++++++++
 .../samples/porter/user/dao/SessionMapper.java     |  28 +++
 .../samples/porter/user/dao/UserInfo.java          |  61 +++++++
 .../samples/porter/user/dao/UserMapper.java        |  24 +++
 .../porter/user/service/UserServiceImpl.java       | 113 ++++++++++++
 .../main/resources/META-INF/spring/user.bean.xml   |  53 ++++++
 .../src/main/resources/application.yml             |  49 ++++++
 .../src/main/resources/config/SessionMapper.xml    |  57 ++++++
 .../src/main/resources/config/UserMapper.xml       |  46 +++++
 .../src/main/resources/config/create_db_user.sql   |  46 +++++
 .../src/main/resources/config/mybatis-config.xml   |  27 +++
 .../user-service/src/main/resources/log4j2.xml     |  45 +++++
 64 files changed, 3115 insertions(+)

diff --git a/porter_springboot/README.md b/porter_springboot/README.md
new file mode 100644
index 0000000..297dbb6
--- /dev/null
+++ b/porter_springboot/README.md
@@ -0,0 +1,191 @@
+This project shows how to using java-chassis and service-center to create a simple microservice application. It shows basic authentication and authorization, uploading files and delete files operations.
+
+## build and run
+
+* compile
+
+```
+mvn clean install
+```
+
+* run
+  * create a database using mysql with user name and password(e.g. root/root)
+  * execute create_db_user.sql
+
+* run user-service:
+
+```
+java $JAVA_OPT -Ddb.url="jdbc:mysql://localhost/porter_user_db?useSSL=false" -Ddb.username=root -Ddb.password=root -jar porter-user-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+* run file-service:
+
+```
+java $JAVA_OPT -jar porter-file-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+* run gateway-service:
+
+gateway-service contains static web pages in resources/ui. First copy to web root folder,e.g webapp, which is relative to working directory. 
+
+```
+java $JAVA_OPT -Dgateway.webroot=webapp -jar porter-gateway-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+## Try it
+
+1. Using browser: http://localhost:9090/ui/login.html with user admin or guest to login, password is test.
+2. Choose a file to upload. Uploaded file is stored in file-service working directory. And name is random number generated. 
+3. Delete file. Input the random number generated in step 2. 
+
+
+这个项目帮助开发者学习如何使用ServiceComb开发完整的微服务。 这个项目实现的功能非常简单,用户登录后,上传一个文件和删除一个文件,验证了没有权限的用户无法删除文件。
+
+# 编译和运行
+
+* 编译
+
+```
+mvn clean install
+```
+
+* 运行
+  * 安装mysql数据库,设置用户名密码(假设为root/root)
+  * 执行脚本create_db_user.sql
+
+
+* 启动user-service:
+
+```
+java $JAVA_OPT -Ddb.url="jdbc:mysql://localhost/porter_user_db?useSSL=false" -Ddb.username=root -Ddb.password=root -jar porter-user-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+* 启动file-service:
+
+```
+java $JAVA_OPT -jar porter-file-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+* 启动gateway-serivce:
+
+gateway-service包含了静态页面文件,在resources/ui目录。首先需要将页面文件拷贝到WEB主目录(相对路径,当前运行目录),比如: webapp,然后将ui目录整体拷贝到webapp/ui目录。启动:
+```
+java $JAVA_OPT -Dgateway.webroot=webapp -jar porter-gateway-service-0.0.1-SNAPSHOT.jar >/dev/null 2>&1 &
+```
+
+# 使用
+
+1. 输入: http://localhost:9090/ui/login.html 使用admin或者guest登陆,密码为test。
+2. 选择一个文件上传,上传成功,上传成功后的文件会保存在file-service的当前目录, 文件名称是一个随机的数字,这个数字就是文件ID。
+3. 删除文件:输入上一步的文件ID,点击删除。 如果是admin用户,上传成功;如果是guest用户,上传失败。
+
+# 接口使用说明
+ServiceComb推荐先定义接口,再定义实现的开发模式。将接口定义为一个独立项目,可以由设计者统一管控,对于接口的修改,需要设计者进行审核。先定义接口还可以让开发者培养良好的开发习惯,避免将对外接口采用内部实现数据结构(比如JsonObject)、运行平台有关的数据结构(比如HttpServletResponse、HttpServletRequest)来定义,使得以后将项目改造为其他技术框架变得复杂。采用这种方式组织的项目,用户很容易在不同的开发框架上进行迁移,比如gRPC、Spring Cloud等。这里的接口定义代码,对于这些运行框架都是通用的,并且具备跨平台特性。
+
+## 对于接口实现者(provider)
+  * 依赖api对应的jar包
+
+```
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>user-service-api-endpoint</artifactId>
+    </dependency>
+  </dependencies>
+```
+
+  * 实现Service接口
+```
+@Service
+public class UserServiceImpl implements UserService
+```
+
+## 对于接口使用者(consumer)
+  * 依赖service对应的jar包(只包含model和接口)
+
+```
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>user-service-api-service</artifactId>
+    </dependency>
+  </dependencies>
+```
+
+  * 采用RPC方式调用
+```
+  @RpcReference(microserviceName = "user-service", schemaId = "user")
+  private static UserService sserService
+```
+
+# REST接口常见争议问题和处理
+
+## 查询接口参数很复杂
+
+比如:
+
+```
+public List<Goods> queryGoodsByTags(String orgId, List<GoodsTag> tags)
+```
+
+当查询参数很复杂的时候,不建议采用query参数或者path参数。主要有如下原因:
+
+* HTTP对于URL的长度有限制
+* 复杂参数可能包含特殊字符,需要客户端在拼接URL的时候,进行URL转码,客户端开发者通常会遗漏。
+* 对象无法和query参数进行合理的映射。
+* query参数或者path参数会被proxy、web server等记录到日志里面,导致日志过大,或者造成敏感信息泄露。
+
+对于复杂的查询操作,建议使用POST方法,相关复杂参数都封装为body。比如:
+
+```
+@PostMapping(path = "queryGoodsByTags")
+public List<Goods> queryGoodsByTags(@RequestParam(name = "orgId") String orgId, @RequestBody List<GoodsTag> tags)
+```
+
+一般的,通过query传递参数的场景,尽可能要保证参数个数少,参数类型为基础类型(字符串、数字等)。参数比较多的场景采用POST来传参。
+
+本项目的处理原则是“尽可能遵循HTTP REST语义,但是不盲目,以系统可靠优先”。
+
+对于DELETE请求,也有类似的情况。在设计GET和DELETE方法时,建议都不使用body参数,尽管HTTP协议并没有强制要求不能使用body,但是由于历史因素,很多WEB服务器支持上会有问题,接口设计应该尽可能避免不必要的麻烦和陷阱。只在POST、PUT、PATCH方法中使用body参数。
+
+## REST接口的Path是否包含操作
+
+比如:下面的接口定义path是否包含deleteGoodsUnitConvertor。 
+
+```
+  @DeleteMapping(path = "deleteGoodsUnitConvertor")
+  public ResponseBase deleteGoodsUnitConvertor(String goodsUnitConvertorId)
+```
+
+由于HTTP的方法POST/PUT/PATCH/GET/DELETE已经包含了增、改、查、删语义,path里面包含delete显得多余。不过由于项目的接口通常比较多,过多的思考接口语义反而增加了理解的难度。所以本项目path全部都包含了方法名字。包含名称有个好处,可以从URL中看出operation id,从而很简单的将URL和契约对应起来,方便查找。此外就是上面提到的原因,并不是所有的删除操作都一定对应于DELETE操作,出于系统可靠性、安全等方面考虑,可能使用POST/PATCH等代表查询或者删除操作。
+
+## 多个对象参数
+
+由于HTTP只能有一个body,所有多个对象参数需要包装为一个参数。 比如:
+
+```
+public ResponseBase inboundOrder(InboundOrder inboundOrder, Set<InboundOrderItem> inboundOrderItems)
+```
+
+封装为下面的REST接口定义:
+
+```
+  @PostMapping(path = "inboundOrder")
+  public ResponseBase inboundOrder(@RequestBody InboundOrderRequest inboundOrderRequest) {
+    return stockService.inboundOrder(inboundOrderRequest.getInboundOrder(), inboundOrderRequest.getInboundOrderItems());
+  }
+```
+
+## 敏感信息不能采用query参数
+
+Query参数可能被各种proxy、web server记录,因此对于用户敏感信息,不能使用query参数。 比如:
+
+```
+public ResponseBase rechargePrepaidCard(String cardId, double amount)
+```
+
+涉及到卡号和金额的数据,需要采用POST提交,参数存储在body。 虽然有些接口仅仅只是查询, 但也可能被设计为POST。 调整后的接口:
+
+```
+public ResponseBase rechargePrepaidCard(@RequestBody PrepaidAmountRequest prepaidAmountRequest)
+```
diff --git a/porter_springboot/api/common/endpoint/pom.xml b/porter_springboot/api/common/endpoint/pom.xml
new file mode 100644
index 0000000..018d9a6
--- /dev/null
+++ b/porter_springboot/api/common/endpoint/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>common-api</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>common-api-endpoint</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>common-api-service</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/porter_springboot/api/common/endpoint/src/main/java/org/apache/servicecomb/samples/porter/file/api/LogEndpoint.java b/porter_springboot/api/common/endpoint/src/main/java/org/apache/servicecomb/samples/porter/file/api/LogEndpoint.java
new file mode 100644
index 0000000..8e49a6e
--- /dev/null
+++ b/porter_springboot/api/common/endpoint/src/main/java/org/apache/servicecomb/samples/porter/file/api/LogEndpoint.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.file.api;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.apache.servicecomb.samples.porter.common.api.LogService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import com.netflix.config.DynamicPropertyFactory;
+
+@RestSchema(schemaId = "log")
+@RequestMapping(path = "/v1/log")
+public class LogEndpoint implements LogService {
+  // protect your file in real applications
+  private static final File LOG_DIR =
+      new File(DynamicPropertyFactory.getInstance().getStringProperty("servicecomb.samples.logdir", ".").get());
+
+  private static final String FILE_POST_FIX = ".log";
+
+  @Override
+  @GetMapping(path = "/getLogFileList")
+  public List<String> getLogFileList() {
+    File[] files = LOG_DIR.listFiles(new FileFilter() {
+      @Override
+      public boolean accept(File file) {
+        return isLogFile(file);
+      }
+    });
+
+    List<String> result = new ArrayList<>(files.length);
+    for (int i = 0; i < files.length; i++) {
+      result.add(files[i].getName());
+    }
+    return result;
+  }
+
+  @Override
+  @GetMapping(path = "/getLogFileContent")
+  public File getLogFileContent(@RequestParam(name = "fileName") String fileName) {
+    File file = new File(LOG_DIR, fileName);
+    if (isLogFile(file)) {
+      return file;
+    }
+    return null;
+  }
+
+  private boolean isLogFile(File file) {
+    return file.isFile() && file.canRead() && file.getName().endsWith(FILE_POST_FIX);
+  }
+}
diff --git a/porter_springboot/api/common/pom.xml b/porter_springboot/api/common/pom.xml
new file mode 100644
index 0000000..da72f94
--- /dev/null
+++ b/porter_springboot/api/common/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-api</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>common-api</artifactId>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>service</module>
+    <module>endpoint</module>
+  </modules>
+</project>
\ No newline at end of file
diff --git a/porter_springboot/api/common/service/pom.xml b/porter_springboot/api/common/service/pom.xml
new file mode 100644
index 0000000..9c65fd9
--- /dev/null
+++ b/porter_springboot/api/common/service/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>common-api</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>common-api-service</artifactId>
+  <packaging>jar</packaging>
+
+</project>
diff --git a/porter_springboot/api/common/service/src/main/java/org/apache/servicecomb/samples/porter/common/api/LogService.java b/porter_springboot/api/common/service/src/main/java/org/apache/servicecomb/samples/porter/common/api/LogService.java
new file mode 100644
index 0000000..9991543
--- /dev/null
+++ b/porter_springboot/api/common/service/src/main/java/org/apache/servicecomb/samples/porter/common/api/LogService.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.common.api;
+
+import java.io.File;
+import java.util.List;
+
+public interface LogService {
+  List<String> getLogFileList();
+  File getLogFileContent(String fileName);
+}
diff --git a/porter_springboot/api/file-service/endpoint/pom.xml b/porter_springboot/api/file-service/endpoint/pom.xml
new file mode 100644
index 0000000..75b4ab3
--- /dev/null
+++ b/porter_springboot/api/file-service/endpoint/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>file-service-api</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>file-service-api-endpoint</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>file-service-api-service</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/porter_springboot/api/file-service/endpoint/src/main/java/org/apache/servicecomb/samples/porter/file/api/FileEndpoint.java b/porter_springboot/api/file-service/endpoint/src/main/java/org/apache/servicecomb/samples/porter/file/api/FileEndpoint.java
new file mode 100644
index 0000000..8ff7dac
--- /dev/null
+++ b/porter_springboot/api/file-service/endpoint/src/main/java/org/apache/servicecomb/samples/porter/file/api/FileEndpoint.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.file.api;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.apache.servicecomb.samples.porter.file.api.FileService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.multipart.MultipartFile;
+
+@RestSchema(schemaId = "file")
+@RequestMapping(path = "/")
+public class FileEndpoint {
+  @Autowired
+  private FileService fileService;
+  
+  /**
+   * upload and return file id
+   */
+  @PostMapping(path = "/upload", produces = MediaType.TEXT_PLAIN_VALUE)
+  public String uploadFile(@RequestPart(name = "fileName") MultipartFile file) {
+      return fileService.uploadFile(file);
+  }
+
+  /**
+   * delete file by id
+   */
+  @DeleteMapping(path = "/delete", produces = MediaType.APPLICATION_JSON_VALUE)
+  public boolean deleteFile(@RequestParam(name = "id") String id) {
+      return fileService.deleteFile(id);
+  }
+}
diff --git a/porter_springboot/api/file-service/endpoint/src/main/java/org/apache/servicecomb/samples/porter/file/api/InternalAccessEndpoint.java b/porter_springboot/api/file-service/endpoint/src/main/java/org/apache/servicecomb/samples/porter/file/api/InternalAccessEndpoint.java
new file mode 100644
index 0000000..1a7d94d
--- /dev/null
+++ b/porter_springboot/api/file-service/endpoint/src/main/java/org/apache/servicecomb/samples/porter/file/api/InternalAccessEndpoint.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.file.api;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import io.swagger.annotations.Api;
+
+@RestSchema(schemaId = "InternalAccessEndpoint")
+@RequestMapping(path = "/")
+@Api(tags = {"INTERNAL"})
+public class InternalAccessEndpoint {
+  @Autowired
+  private InternalAccessService internalAccessService;
+  
+  @GetMapping(path = "localAccess")
+  public String localAccess(String name) {
+    return internalAccessService.localAccess(name);
+  }
+}
diff --git a/porter_springboot/api/file-service/pom.xml b/porter_springboot/api/file-service/pom.xml
new file mode 100644
index 0000000..0acf65a
--- /dev/null
+++ b/porter_springboot/api/file-service/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-api</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>file-service-api</artifactId>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>service</module>
+    <module>endpoint</module>
+  </modules>
+</project>
\ No newline at end of file
diff --git a/porter_springboot/api/file-service/service/pom.xml b/porter_springboot/api/file-service/service/pom.xml
new file mode 100644
index 0000000..75ecd19
--- /dev/null
+++ b/porter_springboot/api/file-service/service/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>file-service-api</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>file-service-api-service</artifactId>
+  <packaging>jar</packaging>
+
+</project>
diff --git a/porter_springboot/api/file-service/service/src/main/java/org/apache/servicecomb/samples/porter/file/api/FileService.java b/porter_springboot/api/file-service/service/src/main/java/org/apache/servicecomb/samples/porter/file/api/FileService.java
new file mode 100644
index 0000000..ff7777a
--- /dev/null
+++ b/porter_springboot/api/file-service/service/src/main/java/org/apache/servicecomb/samples/porter/file/api/FileService.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.file.api;
+
+import org.springframework.web.multipart.MultipartFile;
+
+public interface FileService {
+  public String uploadFile(MultipartFile file);
+
+  public boolean deleteFile(String id);
+}
diff --git a/porter_springboot/api/file-service/service/src/main/java/org/apache/servicecomb/samples/porter/file/api/InternalAccessService.java b/porter_springboot/api/file-service/service/src/main/java/org/apache/servicecomb/samples/porter/file/api/InternalAccessService.java
new file mode 100644
index 0000000..7e627fb
--- /dev/null
+++ b/porter_springboot/api/file-service/service/src/main/java/org/apache/servicecomb/samples/porter/file/api/InternalAccessService.java
@@ -0,0 +1,5 @@
+package org.apache.servicecomb.samples.porter.file.api;
+
+public interface InternalAccessService {
+  public String localAccess(String name);
+}
diff --git a/porter_springboot/api/pom.xml b/porter_springboot/api/pom.xml
new file mode 100644
index 0000000..de89135
--- /dev/null
+++ b/porter_springboot/api/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-application</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>porter-api</artifactId>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>common</module>
+    <module>file-service</module>
+    <module>user-service</module>
+  </modules>
+</project>
\ No newline at end of file
diff --git a/porter_springboot/api/user-service/endpoint/pom.xml b/porter_springboot/api/user-service/endpoint/pom.xml
new file mode 100644
index 0000000..ecdd25f
--- /dev/null
+++ b/porter_springboot/api/user-service/endpoint/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>user-service-api</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>user-service-api-endpoint</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>user-service-api-service</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/porter_springboot/api/user-service/endpoint/src/main/java/org/apache/servicecomb/samples/porter/user/api/UserEndpoint.java b/porter_springboot/api/user-service/endpoint/src/main/java/org/apache/servicecomb/samples/porter/user/api/UserEndpoint.java
new file mode 100644
index 0000000..40df5bb
--- /dev/null
+++ b/porter_springboot/api/user-service/endpoint/src/main/java/org/apache/servicecomb/samples/porter/user/api/UserEndpoint.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.user.api;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.apache.servicecomb.samples.porter.user.api.SessionInfo;
+import org.apache.servicecomb.samples.porter.user.api.UserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "user")
+@RequestMapping(path = "/")
+public class UserEndpoint {
+  @Autowired
+  private UserService userService;
+
+  @PostMapping(path = "/v1/user/login", produces = MediaType.APPLICATION_JSON_VALUE)
+  public SessionInfo login(@RequestParam(name = "userName") String userName,
+      @RequestParam(name = "password") String password) {
+    return userService.login(userName, password);
+  }
+
+  @GetMapping(path = "/v1/user/session", produces = MediaType.APPLICATION_JSON_VALUE)
+  public SessionInfo getSession(@RequestParam(name = "sessionId") String sessionId) {
+    return userService.getSession(sessionId);
+  }
+
+  @GetMapping(path = "/v1/user/ping", produces = MediaType.APPLICATION_JSON_VALUE)
+  public String ping(@RequestParam(name = "message") String message) {
+    return userService.ping(message);
+  }
+}
diff --git a/porter_springboot/api/user-service/pom.xml b/porter_springboot/api/user-service/pom.xml
new file mode 100644
index 0000000..8080919
--- /dev/null
+++ b/porter_springboot/api/user-service/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-api</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>user-service-api</artifactId>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>service</module>
+    <module>endpoint</module>
+  </modules>
+</project>
\ No newline at end of file
diff --git a/porter_springboot/api/user-service/service/pom.xml b/porter_springboot/api/user-service/service/pom.xml
new file mode 100644
index 0000000..310be1e
--- /dev/null
+++ b/porter_springboot/api/user-service/service/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>user-service-api</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>user-service-api-service</artifactId>
+  <packaging>jar</packaging>
+
+</project>
diff --git a/porter_springboot/api/user-service/service/src/main/java/org/apache/servicecomb/samples/porter/user/api/SessionInfo.java b/porter_springboot/api/user-service/service/src/main/java/org/apache/servicecomb/samples/porter/user/api/SessionInfo.java
new file mode 100644
index 0000000..6358104
--- /dev/null
+++ b/porter_springboot/api/user-service/service/src/main/java/org/apache/servicecomb/samples/porter/user/api/SessionInfo.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.user.api;
+
+public class SessionInfo {
+  private String sessiondId;
+
+  private String userName;
+
+  private String roleName;
+
+  public String getSessiondId() {
+    return sessiondId;
+  }
+
+  public void setSessiondId(String sessiondId) {
+    this.sessiondId = sessiondId;
+  }
+
+  public String getUserName() {
+    return userName;
+  }
+
+  public void setUserName(String userName) {
+    this.userName = userName;
+  }
+
+  public String getRoleName() {
+    return roleName;
+  }
+
+  public void setRoleName(String roleName) {
+    this.roleName = roleName;
+  }
+}
diff --git a/porter_springboot/api/user-service/service/src/main/java/org/apache/servicecomb/samples/porter/user/api/UserService.java b/porter_springboot/api/user-service/service/src/main/java/org/apache/servicecomb/samples/porter/user/api/UserService.java
new file mode 100644
index 0000000..aa882f9
--- /dev/null
+++ b/porter_springboot/api/user-service/service/src/main/java/org/apache/servicecomb/samples/porter/user/api/UserService.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.user.api;
+
+public interface UserService {
+  public SessionInfo login(String userName,
+      String password);
+
+  public SessionInfo getSession(String sessionId);
+
+  public String ping(String message);
+}
diff --git a/porter_springboot/file-service/pom.xml b/porter_springboot/file-service/pom.xml
new file mode 100644
index 0000000..9605101
--- /dev/null
+++ b/porter_springboot/file-service/pom.xml
@@ -0,0 +1,58 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-application</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>porter-file-service</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-servlet</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>file-service-api-endpoint</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>common-api-endpoint</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+  </dependencies>
+  <properties>
+    <main.class>org.apache.servicecomb.samples.porter.file.FileMain</main.class>
+  </properties>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/FileMain.java b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/FileMain.java
new file mode 100644
index 0000000..a50170c
--- /dev/null
+++ b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/FileMain.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.file;
+
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableServiceComb
+public class FileMain {
+  public static void main(String[] args) throws Exception {
+    try {
+      SpringApplication.run(FileMain.class, args);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileServiceImpl.java b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileServiceImpl.java
new file mode 100644
index 0000000..5053aee
--- /dev/null
+++ b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileServiceImpl.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.file.service;
+
+import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+@Service
+public class FileServiceImpl implements org.apache.servicecomb.samples.porter.file.api.FileService {
+    @Autowired
+    private FileStoreService fileService;
+
+    public String uploadFile(MultipartFile file) {
+        return fileService.uploadFile(file);
+    }
+
+    public boolean deleteFile(String id) {
+        String session = ContextUtils.getInvocationContext().getContext("session-info");
+        if (session == null) {
+            throw new InvocationException(403, "", "not allowed");
+        } else {
+            SessionInfo sessionInfo = null;
+            try {
+                sessionInfo = JsonUtils.readValue(session.getBytes("UTF-8"), SessionInfo.class);
+            } catch (Exception e) {
+                throw new InvocationException(403, "", "session not allowed");
+            }
+            if (sessionInfo == null || !sessionInfo.getRoleName().equals("admin")) {
+                throw new InvocationException(403, "", "not allowed");
+            }
+        }
+        return fileService.deleteFile(id);
+    }
+}
diff --git a/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileStoreService.java b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileStoreService.java
new file mode 100644
index 0000000..f9ff5c9
--- /dev/null
+++ b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/FileStoreService.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.file.service;
+
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * file storage service, can implement using file system, OBS, etc.
+ */
+public interface FileStoreService {
+
+    public String uploadFile(MultipartFile file);
+
+    public boolean deleteFile(String id);
+
+}
diff --git a/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/InternalAccessServiceImpl.java b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/InternalAccessServiceImpl.java
new file mode 100644
index 0000000..d723945
--- /dev/null
+++ b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/InternalAccessServiceImpl.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.file.service;
+
+import org.apache.servicecomb.samples.porter.file.api.InternalAccessService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class InternalAccessServiceImpl implements InternalAccessService {
+  public String localAccess(String name) {
+    return "Hello, " + name;
+  }
+}
diff --git a/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/LocalFileStoreService.java b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/LocalFileStoreService.java
new file mode 100644
index 0000000..adb8b19
--- /dev/null
+++ b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/LocalFileStoreService.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.file.service;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.UUID;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ *  Simple file storage implementation.
+ *  Caution: file check and other security constraints not implemented. 
+ */
+@Component
+public class LocalFileStoreService implements FileStoreService {
+    // maxmum BUFFER_SIZE * BUFFER_NUM
+    private static final int BUFFER_SIZE = 10240;
+
+    private static final File BASE_FILE = new File(".");
+
+    @Override
+    public String uploadFile(MultipartFile file) {
+        byte[] buffer = new byte[BUFFER_SIZE];
+        String fileId = UUID.randomUUID().toString();
+
+        File outFile = new File(BASE_FILE, fileId);
+        int len;
+        try (InputStream is = file.getInputStream(); OutputStream os = new FileOutputStream(outFile)) {
+            while ((len = is.read(buffer)) != -1) {
+                os.write(buffer, 0, len);
+            }
+        } catch (IOException e) {
+            return null;
+        }
+        return fileId;
+    }
+
+    @Override
+    public boolean deleteFile(String id) {
+        File outFile = new File(BASE_FILE, id);
+        return outFile.delete();
+    }
+
+}
diff --git a/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/SessionInfo.java b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/SessionInfo.java
new file mode 100644
index 0000000..eeff226
--- /dev/null
+++ b/porter_springboot/file-service/src/main/java/org/apache/servicecomb/samples/porter/file/service/SessionInfo.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.file.service;
+
+public class SessionInfo {
+    private int id;
+
+    private String sessiondId;
+
+    private String userName;
+
+    private String roleName;
+
+    private java.sql.Timestamp creationTime;
+
+    private java.sql.Timestamp activeTime;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getSessiondId() {
+        return sessiondId;
+    }
+
+    public void setSessiondId(String sessiondId) {
+        this.sessiondId = sessiondId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+
+    public java.sql.Timestamp getCreationTime() {
+        return creationTime;
+    }
+
+    public void setCreationTime(java.sql.Timestamp creationTime) {
+        this.creationTime = creationTime;
+    }
+
+    public java.sql.Timestamp getActiveTime() {
+        return activeTime;
+    }
+
+    public void setActiveTime(java.sql.Timestamp activeTime) {
+        this.activeTime = activeTime;
+    }
+
+}
diff --git a/porter_springboot/file-service/src/main/resources/META-INF/spring/file.bean.xml b/porter_springboot/file-service/src/main/resources/META-INF/spring/file.bean.xml
new file mode 100644
index 0000000..ca83464
--- /dev/null
+++ b/porter_springboot/file-service/src/main/resources/META-INF/spring/file.bean.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns:context="http://www.springframework.org/schema/context"
+  xsi:schemaLocation="
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+  <bean id="servicecomb.samples.executor.groupThreadPool" class="org.apache.servicecomb.core.executor.GroupExecutor"
+    init-method="init"/>
+</beans>
\ No newline at end of file
diff --git a/porter_springboot/file-service/src/main/resources/application.yml b/porter_springboot/file-service/src/main/resources/application.yml
new file mode 100644
index 0000000..c1f0727
--- /dev/null
+++ b/porter_springboot/file-service/src/main/resources/application.yml
@@ -0,0 +1,53 @@
+#
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+# spring boot configurations
+server:
+  port: 9091  # should be same with servicecomb.rest.address to use web container
+
+# override common configurations in common module
+servicecomb-config-order: 10
+
+APPLICATION_ID: porter-application
+
+service_description:
+  version: 0.0.1
+  name: file-service
+
+servicecomb:
+  service:
+    registry:
+      address: http://localhost:30100
+      instance:
+        watch: false
+
+  rest:
+    address: 0.0.0.0:9091  # should be same with server.port to use web container
+
+  uploads:
+    directory: tmp_for_upload_file
+
+  samples:
+    logdir: D:\code\servicecomb-samples\porter_lightweight\file-service
+    
+  inspector:
+    enabled: false
+
+  executors:
+   Provider:
+     log: servicecomb.samples.executor.groupThreadPool
+     inspector: servicecomb.samples.executor.groupThreadPool
\ No newline at end of file
diff --git a/porter_springboot/file-service/src/main/resources/log4j2.xml b/porter_springboot/file-service/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..313d1fc
--- /dev/null
+++ b/porter_springboot/file-service/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./file/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10 MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/porter_springboot/gateway-service/pom.xml b/porter_springboot/gateway-service/pom.xml
new file mode 100644
index 0000000..5a16f3f
--- /dev/null
+++ b/porter_springboot/gateway-service/pom.xml
@@ -0,0 +1,63 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-application</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>porter-gateway-service</artifactId>
+  <packaging>jar</packaging>
+
+  <properties>
+    <main.class>org.apache.servicecomb.samples.porter.gateway.GatewayMain</main.class>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-standalone</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>user-service-api-service</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>common-api-endpoint</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>edge-core</artifactId>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/ApiDispatcher.java b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/ApiDispatcher.java
new file mode 100644
index 0000000..391fd2b
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/ApiDispatcher.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.gateway;
+
+import java.util.Map;
+
+import org.apache.servicecomb.edge.core.AbstractEdgeDispatcher;
+import org.apache.servicecomb.edge.core.EdgeInvocation;
+
+import io.vertx.core.http.Cookie;
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.RoutingContext;
+
+public class ApiDispatcher extends AbstractEdgeDispatcher {
+  @Override
+  public int getOrder() {
+    return 10002;
+  }
+
+  @Override
+  public void init(Router router) {
+    String regex = "/api/([^\\/]+)/(.*)";
+    router.routeWithRegex(regex).handler(createBodyHandler());
+    router.routeWithRegex(regex).failureHandler(this::onFailure).handler(this::onRequest);
+  }
+
+  protected void onRequest(RoutingContext context) {
+    Map<String, String> pathParams = context.pathParams();
+    String microserviceName = pathParams.get("param0");
+    String path = "/" + pathParams.get("param1");
+
+    EdgeInvocation invoker = new EdgeInvocation() {
+      // Authentication. Notice: adding context must after setContext or will override by network
+      protected void setContext() throws Exception {
+        super.setContext();
+        // get session id from header and cookie for debug reasons
+        String sessionId = context.request().getHeader("session-id");
+        if (sessionId != null) {
+          this.invocation.addContext("session-id", sessionId);
+        } else {
+          Cookie sessionCookie = context.cookieMap().get("session-id");
+          if (sessionCookie != null) {
+            this.invocation.addContext("session-id", sessionCookie.getValue());
+          }
+        }
+      }
+    };
+    invoker.init(microserviceName, context, path, httpServerFilters);
+    invoker.edgeInvoke();
+  }
+}
diff --git a/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/AuthHandler.java b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/AuthHandler.java
new file mode 100644
index 0000000..4d1b8ec
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/AuthHandler.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.gateway;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.servicecomb.core.Handler;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.samples.porter.user.api.SessionInfo;
+import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
+
+public class AuthHandler implements Handler {
+  private UserServiceClient userServiceClient = BeanUtils.getBean("UserServiceClient");
+
+  // session expires in 10 minutes, cache for 1 seconds to get rid of concurrent scenarios.
+  private Cache<String, String> sessionCache = CacheBuilder.newBuilder()
+      .expireAfterAccess(30, TimeUnit.SECONDS)
+      .build();
+
+  @Override
+  public void handle(Invocation invocation, AsyncResponse asyncResponse) throws Exception {
+    if (invocation.getMicroserviceName().equals("user-service")
+        && (invocation.getOperationName().equals("login")
+            || (invocation.getOperationName().equals("getSession")))) {
+      // login:return session id, set cookie by javascript
+      invocation.next(asyncResponse);
+    } else {
+      // check session
+      String sessionId = invocation.getContext("session-id");
+      if (sessionId == null) {
+        throw new InvocationException(403, "", "session is not valid.");
+      }
+
+      String sessionInfo = sessionCache.getIfPresent(sessionId);
+      if (sessionInfo != null) {
+        try {
+          // session info stored in InvocationContext. Microservices can get it. 
+          invocation.addContext("session-id", sessionId);
+          invocation.addContext("session-info", sessionInfo);
+          invocation.next(asyncResponse);
+        } catch (Exception e) {
+          asyncResponse.complete(Response.failResp(new InvocationException(500, "", e.getMessage())));
+        }
+        return;
+      }
+
+      // In edge, handler is executed in reactively. Must have no blocking logic.
+      CompletableFuture<SessionInfo> result = userServiceClient.getGetSessionOperation().getSession(sessionId);
+      result.whenComplete((info, e) -> {
+        if (result.isCompletedExceptionally()) {
+          asyncResponse.complete(Response.failResp(new InvocationException(403, "", "session is not valid.")));
+        } else {
+          if (info == null) {
+            asyncResponse.complete(Response.failResp(new InvocationException(403, "", "session is not valid.")));
+            return;
+          }
+          try {
+            // session info stored in InvocationContext. Microservices can get it. 
+            invocation.addContext("session-id", sessionId);
+            String sessionInfoStr = JsonUtils.writeValueAsString(info);
+            invocation.addContext("session-info", sessionInfoStr);
+            invocation.next(asyncResponse);
+            sessionCache.put(sessionId, sessionInfoStr);
+          } catch (Exception ee) {
+            asyncResponse.complete(Response.failResp(new InvocationException(500, "", ee.getMessage())));
+          }
+        }
+      });
+    }
+  }
+}
diff --git a/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/EdgeSSLCustom.java b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/EdgeSSLCustom.java
new file mode 100644
index 0000000..159c10d
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/EdgeSSLCustom.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.gateway;
+
+import java.io.File;
+
+import org.apache.servicecomb.foundation.ssl.SSLCustom;
+
+public class EdgeSSLCustom extends SSLCustom {
+
+    @Override
+    public char[] decode(char[] plain) {
+        return plain;
+    }
+
+    @Override
+    public String getFullPath(String name) {
+        String fullName = System.getProperty("user.dir") + File.separator + name;
+        System.out.println(fullName);
+        return (new File(fullName)).getAbsolutePath();
+    }
+
+}
diff --git a/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/GatewayMain.java b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/GatewayMain.java
new file mode 100644
index 0000000..81ff019
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/GatewayMain.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.gateway;
+
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+@EnableServiceComb
+public class GatewayMain {
+  public static void main(String[] args) throws Exception {
+    try {
+      new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(GatewayMain.class).run(args);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/InternalAccessHandler.java b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/InternalAccessHandler.java
new file mode 100644
index 0000000..0b181d8
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/InternalAccessHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.gateway;
+
+import org.apache.servicecomb.core.Handler;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+
+public class InternalAccessHandler implements Handler {
+
+  @Override
+  public void handle(Invocation invocation, AsyncResponse asyncReponse) throws Exception {
+    if (invocation.getOperationMeta().getSwaggerOperation().getTags() != null
+        && invocation.getOperationMeta().getSwaggerOperation().getTags().contains("INTERNAL")) {
+      asyncReponse.consumerFail(new InvocationException(403, "", "not allowed"));
+      return;
+    }
+    invocation.next(asyncReponse);
+  }
+
+}
diff --git a/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/StaticWebpageDispatcher.java b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/StaticWebpageDispatcher.java
new file mode 100644
index 0000000..791c512
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/StaticWebpageDispatcher.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.gateway;
+
+import org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netflix.config.DynamicPropertyFactory;
+
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.handler.StaticHandler;
+
+public class StaticWebpageDispatcher implements VertxHttpDispatcher {
+  private static final Logger LOGGER = LoggerFactory.getLogger(StaticWebpageDispatcher.class);
+
+  private static final String WEB_ROOT = DynamicPropertyFactory.getInstance()
+      .getStringProperty("gateway.webroot", "/var/static")
+      .get();
+
+  @Override
+  public int getOrder() {
+    return Integer.MAX_VALUE;
+  }
+
+  @Override
+  public void init(Router router) {
+    String regex = "/ui/(.*)";
+    StaticHandler webpageHandler = StaticHandler.create();
+    webpageHandler.setWebRoot(WEB_ROOT);
+    LOGGER.info("server static web page for WEB_ROOT={}", WEB_ROOT);
+    router.routeWithRegex(regex).failureHandler((context) -> {
+      LOGGER.error("", context.failure());
+    }).handler(webpageHandler);
+  }
+
+}
diff --git a/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/UserServiceClient.java b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/UserServiceClient.java
new file mode 100644
index 0000000..701a357
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/java/org/apache/servicecomb/samples/porter/gateway/UserServiceClient.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.gateway;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.samples.porter.user.api.SessionInfo;
+import org.springframework.stereotype.Component;
+
+interface GetSessionOperation {
+  CompletableFuture<SessionInfo> getSession(String sessionId);
+}
+
+
+@Component("UserServiceClient")
+public class UserServiceClient {
+  @RpcReference(microserviceName = "user-service", schemaId = "user")
+  private GetSessionOperation getSessionOperation;
+
+  public GetSessionOperation getGetSessionOperation() {
+    return getSessionOperation;
+  }
+}
diff --git a/porter_springboot/gateway-service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher b/porter_springboot/gateway-service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
new file mode 100644
index 0000000..71009db
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.apache.servicecomb.samples.porter.gateway.ApiDispatcher
+org.apache.servicecomb.samples.porter.gateway.StaticWebpageDispatcher
\ No newline at end of file
diff --git a/porter_springboot/gateway-service/src/main/resources/META-INF/spring/cse.bean.xml b/porter_springboot/gateway-service/src/main/resources/META-INF/spring/cse.bean.xml
new file mode 100644
index 0000000..b5816c3
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/META-INF/spring/cse.bean.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns:context="http://www.springframework.org/schema/context"
+  xsi:schemaLocation="
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+  <bean id="servicecomb.samples.executor.groupThreadPool" class="org.apache.servicecomb.core.executor.GroupExecutor"
+    init-method="init"/>
+</beans>
diff --git a/porter_springboot/gateway-service/src/main/resources/application.yml b/porter_springboot/gateway-service/src/main/resources/application.yml
new file mode 100644
index 0000000..58a668a
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/application.yml
@@ -0,0 +1,66 @@
+#
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+# override common configurations in common module
+servicecomb-config-order: 100
+
+APPLICATION_ID: porter-application
+service_description:
+  version: 0.0.1
+  name: gateway-service
+
+servicecomb:
+  service:
+    registry:
+      address: http://localhost:30100
+      instance:
+        watch: false
+
+  rest:
+    address: 0.0.0.0:9090?sslEnabled=false
+
+  handler:
+    chain:
+      Consumer:
+        default: internalAccess,auth,qps-flowcontrol-consumer,loadbalance
+
+  uploads:
+    directory: tmp_for_upload_gateway
+
+  samples:
+    logdir: D:\code\servicecomb-samples\porter_lightweight\gateway-service
+    
+  inspector:
+    enabled: false
+
+  executors:
+   Provider:
+     log: servicecomb.samples.executor.groupThreadPool
+     inspector: servicecomb.samples.executor.groupThreadPool
+
+  http:
+    dispatcher:
+      edge:
+        default:
+          enabled: false
+      rest:
+        pattern: '[/v1/log/|/inspector](.*)'
+
+# This is web root for windows server, change this path according to where you put your source code
+gateway:
+  webroot: /code/servicecomb-samples/porter_lightweight/gateway-service/src/main/resources
diff --git a/porter_springboot/gateway-service/src/main/resources/config/cse.handler.xml b/porter_springboot/gateway-service/src/main/resources/config/cse.handler.xml
new file mode 100644
index 0000000..e9dd306
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/config/cse.handler.xml
@@ -0,0 +1,23 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<config>
+  <handler id="auth"
+    class="org.apache.servicecomb.samples.porter.gateway.AuthHandler" />
+  <handler id="internalAccess"
+    class="org.apache.servicecomb.samples.porter.gateway.InternalAccessHandler" />
+</config>
diff --git a/porter_springboot/gateway-service/src/main/resources/log4j2.xml b/porter_springboot/gateway-service/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..e9bb265
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./gateway/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10 MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file
diff --git a/porter_springboot/gateway-service/src/main/resources/ui/css/style.css b/porter_springboot/gateway-service/src/main/resources/ui/css/style.css
new file mode 100644
index 0000000..5731863
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/ui/css/style.css
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.error {
+    font-family:verdana;
+    color:red;
+}
+
+.header {
+    background-color:black;
+    color:white;
+    text-align:center;
+    padding:5px;
+}
+
+.nav {
+    line-height:30px;
+    background-color:#eeeeee;
+    height:300px;
+    width:100px;
+    float:left;
+    padding:5px; 
+}
+
+.section {
+    text-align:center;
+    padding:5px;
+}
+
+.footer {
+    color:red;
+    clear:both;
+    text-align:center;
+    padding:25px; 
+}
\ No newline at end of file
diff --git a/porter_springboot/gateway-service/src/main/resources/ui/js/jquery-1.11.1.min.js b/porter_springboot/gateway-service/src/main/resources/ui/js/jquery-1.11.1.min.js
new file mode 100644
index 0000000..ab28a24
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/ui/js/jquery-1.11.1.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b [...]
+if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&& [...]
+},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.prop [...]
diff --git a/porter_springboot/gateway-service/src/main/resources/ui/js/login.js b/porter_springboot/gateway-service/src/main/resources/ui/js/login.js
new file mode 100644
index 0000000..c7e7c8e
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/ui/js/login.js
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function loginAction() {
+     var username = document.getElementById("username").value;
+     var password = document.getElementById("paasword").value;
+     var formData = {};
+     formData.userName = username;
+     formData.password = password;
+
+     $.ajax({
+        type: 'POST',
+        url: "/api/user-service/v1/user/login",
+        data: formData,
+        success: function (data) {
+            console.log(data);
+            setCookie("session-id", data.sessiondId, 1);
+            window.location = "/ui/upload.html";
+        },
+        error: function(data) {
+            console.log(data);
+            var error = document.getElementById("error");
+            error.textContent="Login failed";
+            error.hidden=false;
+        },
+        async: true
+    });
+}
+
+function setCookie(name,value,days) {
+    var expires = "";
+    if (days) {
+        var date = new Date();
+        date.setTime(date.getTime() + (days*24*60*60*1000));
+        expires = "; expires=" + date.toUTCString();
+    }
+    document.cookie = name + "=" + (value || "")  + expires + "; path=/";
+}
\ No newline at end of file
diff --git a/porter_springboot/gateway-service/src/main/resources/ui/js/upload.js b/porter_springboot/gateway-service/src/main/resources/ui/js/upload.js
new file mode 100644
index 0000000..34b9c34
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/ui/js/upload.js
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function uploadAction() {
+     var formData = new FormData(document.getElementById("upload_form"));
+
+     $.ajax({
+        type: 'POST',
+        url: "/api/file-service/upload",
+        data: formData,
+        processData:false,
+        contentType:false,
+        success: function (data) {
+            console.log(data);
+            var error = document.getElementById("error");
+            error.textContent="Upload Successfully, file id=" + data;
+            error.hidden=false;
+        },
+        error: function(data) {
+            console.log(data);
+            var error = document.getElementById("error");
+            error.textContent="Upload failed";
+            error.hidden=false;
+        },
+        async: true
+    });
+}
+
+function deleteAction() {
+     var fileID = document.getElementById("fileID").value;
+     $.ajax({
+        type: 'DELETE',
+        url: "/api/file-service/delete?" + $.param({ id: fileID }),
+        data: {},
+        success: function (data) {
+            console.log(data);
+            var error = document.getElementById("error");
+            error.textContent="Delete successfully";
+            error.hidden=false;
+        },
+        error: function(data) {
+            console.log(data);
+            var error = document.getElementById("error");
+            error.textContent="Delete failed";
+            error.hidden=false;
+        },
+        async: true
+    });
+}
\ No newline at end of file
diff --git a/porter_springboot/gateway-service/src/main/resources/ui/login.html b/porter_springboot/gateway-service/src/main/resources/ui/login.html
new file mode 100644
index 0000000..c8b45fb
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/ui/login.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<html>
+
+    <head>
+        <title>PORTER</title>
+        <link href="css/style.css" rel="stylesheet" type="text/css" media="all" />
+        <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
+        <script type="text/javascript" src="js/login.js"></script>
+    </head>
+
+    <body>
+    <div class="header">
+        <h2>Login</h2>
+    </div>
+    <div class="section">
+        <form method="POST" enctype="multipart/form-data">
+            <input id="username" type="text" placeholder="Username" required="true"/>
+            <input id="paasword" type="password" placeholder="Password" required="true"/>
+            <input type="button" value="Login" onclick="loginAction()">
+        </form>
+    </div>
+    <div class="footer">
+        <p id="error" hidden="true" class="error"/>
+    </div>
+    </body>
+
+</html>
\ No newline at end of file
diff --git a/porter_springboot/gateway-service/src/main/resources/ui/upload.html b/porter_springboot/gateway-service/src/main/resources/ui/upload.html
new file mode 100644
index 0000000..bd5eeff
--- /dev/null
+++ b/porter_springboot/gateway-service/src/main/resources/ui/upload.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<html>
+
+    <head>
+        <title>PORTER</title>
+        <link href="css/style.css" rel="stylesheet" type="text/css" media="all" />
+        <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
+        <script type="text/javascript" src="js/upload.js"></script>
+    </head>
+
+    <body>
+    <div class="header">
+        <h2>Upload</h2>
+    </div>
+    <div class="section">
+        <form id="upload_form" method="POST">
+            <p>
+                File Name: <input type="file" name="fileName"/>
+            </p>
+            <p>
+                <input type="button" value="Upload" onclick="uploadAction()">
+            </p>
+        </form>
+    </div>
+
+    <div class="header">
+        <h2>Delete file</h2>
+    </div>
+    <div class="section">
+        <form id="delete_form" method="DELETE">
+            <p>
+                File ID: <input id="fileID" type="text"/>
+            </p>
+            <p>
+                <input type="button" value="Delete" onclick="deleteAction()">
+            </p>
+        </form>
+    </div>
+    <div class="footer">
+        <p id="error" hidden="true" class="error"/>
+    </div>
+    </body>
+
+</html>
\ No newline at end of file
diff --git a/porter_springboot/pom.xml b/porter_springboot/pom.xml
new file mode 100644
index 0000000..86dc1aa
--- /dev/null
+++ b/porter_springboot/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.servicecomb.samples.porter</groupId>
+  <artifactId>porter-application</artifactId>
+  <version>2.0.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.mybatis</groupId>
+        <artifactId>mybatis</artifactId>
+        <version>3.4.5</version>
+      </dependency>
+      <dependency>
+        <groupId>org.mybatis</groupId>
+        <artifactId>mybatis-spring</artifactId>
+        <version>1.3.0</version>
+      </dependency>
+      <dependency>
+        <groupId>mysql</groupId>
+        <artifactId>mysql-connector-java</artifactId>
+        <version>5.1.46</version>
+      </dependency>
+      <!-- need to compile lastest java-chassis code -->
+      <dependency>
+        <groupId>org.apache.servicecomb</groupId>
+        <artifactId>java-chassis-dependencies</artifactId>
+        <version>${project.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>solution-basic</artifactId>
+    </dependency>
+  </dependencies>
+
+  <modules>
+    <module>api</module>
+    <module>file-service</module>
+    <module>user-service</module>
+    <module>gateway-service</module>
+  </modules>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.1</version>
+          <configuration>
+            <source>1.8</source>
+            <target>1.8</target>
+            <compilerArgument>-parameters</compilerArgument>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.springframework.boot</groupId>
+          <artifactId>spring-boot-maven-plugin</artifactId>
+          <version>2.1.6.RELEASE</version>
+          <executions>
+            <execution>
+              <goals>
+                <goal>repackage</goal>
+              </goals>
+              <configuration>
+                <mainClass>${main.class}</mainClass>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>
\ No newline at end of file
diff --git a/porter_springboot/user-service/pom.xml b/porter_springboot/user-service/pom.xml
new file mode 100644
index 0000000..1e4ec44
--- /dev/null
+++ b/porter_springboot/user-service/pom.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.servicecomb.samples.porter</groupId>
+    <artifactId>porter-application</artifactId>
+    <version>2.0.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>porter-user-service</artifactId>
+  <packaging>jar</packaging>
+
+  <properties>
+    <main.class>org.apache.servicecomb.samples.porter.user.UserMain</main.class>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>java-chassis-spring-boot-starter-servlet</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>user-service-api-endpoint</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb.samples.porter</groupId>
+      <artifactId>common-api-endpoint</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.mybatis</groupId>
+      <artifactId>mybatis</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>mysql</groupId>
+      <artifactId>mysql-connector-java</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-dbcp2</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.mybatis</groupId>
+      <artifactId>mybatis-spring</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-jdbc</artifactId>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-aop</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context-support</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-tx</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
diff --git a/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/UserMain.java b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/UserMain.java
new file mode 100644
index 0000000..9bcc9f5
--- /dev/null
+++ b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/UserMain.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.user;
+
+import org.apache.servicecomb.springboot2.starter.EnableServiceComb;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableServiceComb
+public class UserMain {
+  public static void main(String[] args) throws Exception {
+    try {
+      SpringApplication.run(UserMain.class, args);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
diff --git a/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionInfoModel.java b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionInfoModel.java
new file mode 100644
index 0000000..fa60d33
--- /dev/null
+++ b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionInfoModel.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.user.dao;
+
+import org.apache.servicecomb.samples.porter.user.api.SessionInfo;
+
+public class SessionInfoModel {
+  private int id;
+
+  private String sessiondId;
+
+  private String userName;
+
+  private String roleName;
+
+  private java.sql.Timestamp creationTime;
+
+  private java.sql.Timestamp activeTime;
+
+  public int getId() {
+    return id;
+  }
+
+  public void setId(int id) {
+    this.id = id;
+  }
+
+  public String getSessiondId() {
+    return sessiondId;
+  }
+
+  public void setSessiondId(String sessiondId) {
+    this.sessiondId = sessiondId;
+  }
+
+  public String getUserName() {
+    return userName;
+  }
+
+  public void setUserName(String userName) {
+    this.userName = userName;
+  }
+
+  public String getRoleName() {
+    return roleName;
+  }
+
+  public void setRoleName(String roleName) {
+    this.roleName = roleName;
+  }
+
+  public java.sql.Timestamp getCreationTime() {
+    return creationTime;
+  }
+
+  public void setCreationTime(java.sql.Timestamp creationTime) {
+    this.creationTime = creationTime;
+  }
+
+  public java.sql.Timestamp getActiveTime() {
+    return activeTime;
+  }
+
+  public void setActiveTime(java.sql.Timestamp activeTime) {
+    this.activeTime = activeTime;
+  }
+
+  public static SessionInfo toSessionInfo(SessionInfoModel entity) {
+    SessionInfo info = new SessionInfo();
+    info.setSessiondId(entity.getSessiondId());
+    info.setUserName(entity.getUserName());
+    info.setRoleName(entity.getRoleName());
+    return info;
+  }
+}
diff --git a/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionMapper.java b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionMapper.java
new file mode 100644
index 0000000..e09df8e
--- /dev/null
+++ b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/SessionMapper.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.user.dao;
+
+import org.apache.servicecomb.samples.porter.user.api.SessionInfo;
+
+public interface SessionMapper {
+    void createSession(SessionInfo sessionInfo);
+
+    SessionInfoModel getSessioinInfo(String sessionId);
+    
+    void updateSessionInfo(String sessionId);
+}
diff --git a/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserInfo.java b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserInfo.java
new file mode 100644
index 0000000..b0e2003
--- /dev/null
+++ b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserInfo.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.user.dao;
+
+public class UserInfo {
+    private int id;
+
+    private String userName;
+
+    private String password;
+
+    private String roleName;
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(String roleName) {
+        this.roleName = roleName;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+}
diff --git a/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserMapper.java b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserMapper.java
new file mode 100644
index 0000000..5c2d331
--- /dev/null
+++ b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/dao/UserMapper.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.user.dao;
+
+public interface UserMapper {
+    void createUser(UserInfo userInfo);
+
+    UserInfo getUserInfo(String userName);
+}
diff --git a/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/service/UserServiceImpl.java b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/service/UserServiceImpl.java
new file mode 100644
index 0000000..5f69582
--- /dev/null
+++ b/porter_springboot/user-service/src/main/java/org/apache/servicecomb/samples/porter/user/service/UserServiceImpl.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.samples.porter.user.service;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.servicecomb.samples.porter.user.api.SessionInfo;
+import org.apache.servicecomb.samples.porter.user.api.UserService;
+import org.apache.servicecomb.samples.porter.user.dao.SessionInfoModel;
+import org.apache.servicecomb.samples.porter.user.dao.SessionMapper;
+import org.apache.servicecomb.samples.porter.user.dao.UserInfo;
+import org.apache.servicecomb.samples.porter.user.dao.UserMapper;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.netflix.config.DynamicPropertyFactory;
+
+@Service
+public class UserServiceImpl implements UserService {
+  private static Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
+
+  @Autowired
+  private UserMapper userMapper;
+
+  @Autowired
+  private SessionMapper sessionMapper;
+
+
+  public SessionInfo login(String userName,
+      String password) {
+    UserInfo userInfo = userMapper.getUserInfo(userName);
+    if (userInfo != null) {
+      if (validatePassword(password, userInfo.getPassword())) {
+        SessionInfo sessionInfo = new SessionInfo();
+        sessionInfo.setSessiondId(UUID.randomUUID().toString());
+        sessionInfo.setUserName(userInfo.getUserName());
+        sessionInfo.setRoleName(userInfo.getRoleName());
+        sessionMapper.createSession(sessionInfo);
+        return sessionInfo;
+      }
+    }
+    return null;
+  }
+
+  public SessionInfo getSession(String sessionId) {
+    if (sessionId == null) {
+      throw new InvocationException(405, "", "invalid session.");
+    }
+    SessionInfoModel sessionInfo = sessionMapper.getSessioinInfo(sessionId);
+    if (sessionInfo != null) {
+      if (System.currentTimeMillis() - sessionInfo.getActiveTime().getTime() > 10 * 60 * 1000) {
+        LOGGER.info("user session expired.");
+        return null;
+      } else {
+        sessionMapper.updateSessionInfo(sessionInfo.getSessiondId());
+        return SessionInfoModel.toSessionInfo(sessionInfo);
+      }
+    }
+    return null;
+  }
+
+  private boolean validatePassword(String plain, String encrypt) {
+    // simple password encryption, please change it in product environment if necessary. e.g. add salts for each encryption.
+    try {
+      MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
+      messageDigest.update(plain.getBytes("UTF-8"));
+      byte byteBuffer[] = messageDigest.digest();
+      String encryptedText = Base64.encodeBase64String(byteBuffer);
+      return encryptedText.equals(encrypt);
+    } catch (NoSuchAlgorithmException e) {
+      LOGGER.error("", e);
+    } catch (UnsupportedEncodingException e) {
+      LOGGER.error("", e);
+    }
+    return false;
+  }
+
+
+  public String ping(String message) {
+    long delay = DynamicPropertyFactory.getInstance().getLongProperty("user.ping.delay", 0).get();
+    if (delay > 0) {
+      try {
+        TimeUnit.SECONDS.sleep(delay);
+      } catch (InterruptedException e) {
+        LOGGER.error("", e);
+      }
+    }
+    return message;
+  }
+}
diff --git a/porter_springboot/user-service/src/main/resources/META-INF/spring/user.bean.xml b/porter_springboot/user-service/src/main/resources/META-INF/spring/user.bean.xml
new file mode 100644
index 0000000..cfb2b59
--- /dev/null
+++ b/porter_springboot/user-service/src/main/resources/META-INF/spring/user.bean.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns:context="http://www.springframework.org/schema/context"
+  xsi:schemaLocation="
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+  <bean id="servicecomb.samples.executor.groupThreadPool" class="org.apache.servicecomb.core.executor.GroupExecutor"
+    init-method="init"/>
+    
+    <bean id="dataSource"
+        class="org.apache.commons.dbcp2.BasicDataSource"
+        destroy-method="close">
+        <property name="driverClassName" value="${db.driverClassName:com.mysql.jdbc.Driver}" />
+        <property name="url"
+            value="${db.url:jdbc:mysql://localhost/porter_user_db}" />
+        <property name="username" value="${db.username:root}" />
+        <property name="password" value="${db.password:root}" />
+    </bean>
+
+    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
+        <property name="dataSource" ref="dataSource" />
+        <property name="configLocation" value="classpath:/config/mybatis-config.xml"></property>
+    </bean>
+
+    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
+        <property name="mapperInterface"
+            value="org.apache.servicecomb.samples.porter.user.dao.UserMapper" />
+        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
+    </bean>
+    <bean id="sessionMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
+        <property name="mapperInterface"
+            value="org.apache.servicecomb.samples.porter.user.dao.SessionMapper" />
+        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
+    </bean>
+</beans>
\ No newline at end of file
diff --git a/porter_springboot/user-service/src/main/resources/application.yml b/porter_springboot/user-service/src/main/resources/application.yml
new file mode 100644
index 0000000..e489c55
--- /dev/null
+++ b/porter_springboot/user-service/src/main/resources/application.yml
@@ -0,0 +1,49 @@
+#
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+# spring boot configurations
+server:
+  port: 9093  # should be same with servicecomb.rest.address to use web container
+
+# override common configurations in common module
+servicecomb-config-order: 10
+
+APPLICATION_ID: porter-application
+service_description:
+  version: 0.0.1
+  name: user-service
+
+servicecomb:
+  service:
+    registry:
+      address: http://localhost:30100
+      instance:
+        watch: false
+
+  rest:
+    address: 0.0.0.0:9093 # should be same with server.port to use web container
+
+  samples:
+    logdir: D:\code\servicecomb-samples\porter_lightweight\user-service
+    
+  inspector:
+    enabled: false
+
+  executors:
+   Provider:
+     log: servicecomb.samples.executor.groupThreadPool
+     inspector: servicecomb.samples.executor.groupThreadPool
\ No newline at end of file
diff --git a/porter_springboot/user-service/src/main/resources/config/SessionMapper.xml b/porter_springboot/user-service/src/main/resources/config/SessionMapper.xml
new file mode 100644
index 0000000..989e786
--- /dev/null
+++ b/porter_springboot/user-service/src/main/resources/config/SessionMapper.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.apache.servicecomb.samples.porter.user.dao.SessionMapper">
+    <resultMap id="sessionInfo" type="org.apache.servicecomb.samples.porter.user.dao.SessionInfoModel">
+        <result column="ID" jdbcType="INTEGER" property="id" />
+        <result column="SESSION_ID" jdbcType="VARCHAR" property="sessiondId" />
+        <result column="USER_NAME" jdbcType="VARCHAR" property="userName" />
+        <result column="ROLE_NAME" jdbcType="VARCHAR" property="roleName" />
+        <result column="CREATION_TIME" jdbcType="TIMESTAMP" property="creationTime" />
+        <result column="ACTIVE_TIME" jdbcType="TIMESTAMP" property="activeTime" />
+    </resultMap>
+
+    <sql id="all_column">
+        ID, SESSION_ID, USER_NAME, ROLE_NAME, CREATION_TIME, ACTIVE_TIME
+    </sql>
+
+    <sql id="all_column_auto">
+        SESSION_ID, USER_NAME, ROLE_NAME
+    </sql>
+
+    <insert id="createSession" parameterType="org.apache.servicecomb.samples.porter.user.dao.SessionInfoModel">
+        insert into T_SESSION (
+        <include refid="all_column_auto" />
+        )
+        values (#{sessiondId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR},
+        #{roleName,jdbcType=VARCHAR})
+    </insert>
+
+    <select id="getSessioinInfo" parameterType="java.lang.String"
+        resultMap="sessionInfo">
+        select
+        <include refid="all_column" />
+        from T_SESSION where SESSION_ID = #{0,jdbcType=VARCHAR}
+    </select>
+    
+    <update id="updateSessionInfo" parameterType="java.lang.String">
+        update T_SESSION
+        set CREATION_TIME = CREATION_TIME where SESSION_ID = #{0,jdbcType=VARCHAR};
+    </update>
+</mapper>
\ No newline at end of file
diff --git a/porter_springboot/user-service/src/main/resources/config/UserMapper.xml b/porter_springboot/user-service/src/main/resources/config/UserMapper.xml
new file mode 100644
index 0000000..c02e60d
--- /dev/null
+++ b/porter_springboot/user-service/src/main/resources/config/UserMapper.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.apache.servicecomb.samples.porter.user.dao.UserMapper">
+    <resultMap id="userInfo" type="org.apache.servicecomb.samples.porter.user.dao.UserInfo">
+        <result column="ID" jdbcType="INTEGER" property="id" />
+        <result column="USER_NAME" jdbcType="VARCHAR" property="userName" />
+        <result column="PASSWORD" jdbcType="VARCHAR" property="password" />
+        <result column="ROLE_NAME" jdbcType="VARCHAR" property="roleName" />
+    </resultMap>
+
+    <sql id="all_column">
+        ID, USER_NAME, PASSWORD, ROLE_NAME
+    </sql>
+
+    <insert id="createUser" parameterType="org.apache.servicecomb.samples.porter.user.dao.UserInfo">
+        insert into T_USER (
+        <include refid="all_column" />
+        )
+        values (#{id,jdbcType=INTEGER}, #{userName,jdbcType=VARCHAR},
+        #{password,jdbcType=VARCHAR},#{roleName,jdbcType=VARCHAR})
+    </insert>
+
+    <select id="getUserInfo" parameterType="java.lang.String"
+        resultMap="userInfo">
+        select
+        <include refid="all_column" />
+        from T_USER where USER_NAME = #{0,jdbcType=VARCHAR}
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/porter_springboot/user-service/src/main/resources/config/create_db_user.sql b/porter_springboot/user-service/src/main/resources/config/create_db_user.sql
new file mode 100644
index 0000000..a07c5d9
--- /dev/null
+++ b/porter_springboot/user-service/src/main/resources/config/create_db_user.sql
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CREATE DATABASE IF NOT EXISTS porter_user_db;
+
+USE porter_user_db;
+
+DROP TABLE IF EXISTS T_USER;
+
+CREATE TABLE `T_USER` (
+  `ID`  INTEGER(8) NOT NULL AUTO_INCREMENT COMMENT 'user id',
+  `USER_NAME`  VARCHAR(64) NOT NULL COMMENT 'user name',
+  `PASSWORD`  VARCHAR(64) NOT NULL COMMENT 'user password',
+  `ROLE_NAME`  VARCHAR(64) NOT NULL COMMENT 'user role',
+  PRIMARY KEY (`ID`)
+);
+
+#### password is encrypted for test
+insert into T_USER(USER_NAME, PASSWORD, ROLE_NAME) values("admin", "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", "admin");
+insert into T_USER(USER_NAME, PASSWORD, ROLE_NAME) values("guest", "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=", "guest");
+
+DROP TABLE IF EXISTS T_SESSION;
+
+CREATE TABLE `T_SESSION` (
+  `ID`  INTEGER(8) NOT NULL AUTO_INCREMENT COMMENT 'id',
+  `SESSION_ID`  VARCHAR(64) NOT NULL COMMENT 'session id',
+  `USER_NAME`  VARCHAR(64) NOT NULL COMMENT 'user name',
+  `ROLE_NAME`  VARCHAR(64) NOT NULL COMMENT 'user role',
+  `CREATION_TIME`  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'creation time',
+  `ACTIVE_TIME`  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'last active time',
+  PRIMARY KEY (`ID`)
+);
diff --git a/porter_springboot/user-service/src/main/resources/config/mybatis-config.xml b/porter_springboot/user-service/src/main/resources/config/mybatis-config.xml
new file mode 100644
index 0000000..894caac
--- /dev/null
+++ b/porter_springboot/user-service/src/main/resources/config/mybatis-config.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!DOCTYPE configuration
+  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
+  "http://mybatis.org/dtd/mybatis-3-config.dtd">
+<configuration>
+    <mappers>
+        <mapper resource="config/UserMapper.xml"/>
+        <mapper resource="config/SessionMapper.xml"/>
+    </mappers>
+</configuration>
\ No newline at end of file
diff --git a/porter_springboot/user-service/src/main/resources/log4j2.xml b/porter_springboot/user-service/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..56fc9a0
--- /dev/null
+++ b/porter_springboot/user-service/src/main/resources/log4j2.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!--this is sample configuration, please modify as your wish -->
+
+<configuration>
+  <Properties>
+    <Property name="log_path">./user/log/</Property>
+  </Properties>
+
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+    </Console>
+    <RollingFile name="DailyRollingFile" fileName="${log_path}/output.log"
+      filePattern="${log_path}/zcrTest%d{yyyy-MM-dd}.log">
+      <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n" />
+      <Policies>
+        <TimeBasedTriggeringPolicy interval="1" />
+        <SizeBasedTriggeringPolicy size="10MB" />
+      </Policies>
+    </RollingFile>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console" />
+      <AppenderRef ref="DailyRollingFile" />
+    </Root>
+  </Loggers>
+</configuration>
\ No newline at end of file