diff --git a/sop-example/sop-easyopen/.gitignore b/sop-example/sop-easyopen/.gitignore
new file mode 100644
index 00000000..18ccf36e
--- /dev/null
+++ b/sop-example/sop-easyopen/.gitignore
@@ -0,0 +1,25 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+/local-config/
diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml
new file mode 100644
index 00000000..cc9116c8
--- /dev/null
+++ b/sop-example/sop-easyopen/pom.xml
@@ -0,0 +1,108 @@
+
+
+ 4.0.0
+ com.gitee.sop
+ sop-easyopen
+ 1.0.0-SNAPSHOT
+ jar
+
+ easyopen-server-empty
+ easyopen Demo project for Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.2.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ Greenwich.RELEASE
+ 1.8
+
+
+
+
+
+ com.gitee.sop
+ sop-service-common
+ 1.0.0-SNAPSHOT
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-eureka-client
+
+
+ net.oschina.durcframework
+ easyopen
+ 1.16.1
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
+
+
+
+
+
diff --git a/sop-example/sop-easyopen/readme.md b/sop-example/sop-easyopen/readme.md
new file mode 100644
index 00000000..20cb4998
--- /dev/null
+++ b/sop-example/sop-easyopen/readme.md
@@ -0,0 +1,31 @@
+# easyopen-server
+
+接口服务器空项目,可在此基础上做开发。
+
+入口类:IndexController
+
+业务类在api下,重点关注这里即可。
+
+```
+└─com.gitee.easyopen.server
+ │ EmptySpringbootApplication.java // springboot启动类
+ │ IndexController.java // easyopen入口类
+ │
+ ├─api // 存放接口
+ │ │ GoodsApi.java // 示例接口
+ │ │
+ │ ├─param // 存放接口参数类
+ │ │ GoodsParam.java
+ │ │
+ │ └─result // 存放放回接口类
+ │ Goods.java
+ │
+ ├─config // spring配置
+ │ CorsConfig.java
+ │
+ ├─interceptor // easyopen拦截器
+ │ LogInterceptor.java
+ │
+ └─message // 错误处理
+ CommonErrors.java
+```
\ No newline at end of file
diff --git a/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/IndexController.java b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/IndexController.java
new file mode 100644
index 00000000..aec16dd7
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/IndexController.java
@@ -0,0 +1,25 @@
+package com.gitee.easyopen.server;
+
+import com.gitee.easyopen.ApiConfig;
+import com.gitee.easyopen.support.ApiController;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 文档地址:http://localhost:8080/api/doc
+ */
+@Controller
+@RequestMapping("api")
+public class IndexController extends ApiController {
+ @Override
+ protected void initApiConfig(ApiConfig apiConfig) {
+ apiConfig.setShowDoc(true); // 显示文档页面
+ // 配置国际化消息
+ Map appSecretStore = new HashMap();
+ appSecretStore.put("test", "123456");
+ apiConfig.addAppSecret(appSecretStore);
+ }
+}
diff --git a/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/SopEasyopenApplication.java b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/SopEasyopenApplication.java
new file mode 100644
index 00000000..f42762f5
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/SopEasyopenApplication.java
@@ -0,0 +1,14 @@
+package com.gitee.easyopen.server;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+@EnableDiscoveryClient
+@SpringBootApplication
+public class SopEasyopenApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SopEasyopenApplication.class, args);
+ }
+}
diff --git a/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/api/GoodsApi.java b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/api/GoodsApi.java
new file mode 100644
index 00000000..fab74c0c
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/api/GoodsApi.java
@@ -0,0 +1,31 @@
+package com.gitee.easyopen.server.api;
+
+import com.gitee.easyopen.annotation.Api;
+import com.gitee.easyopen.annotation.ApiService;
+import com.gitee.easyopen.doc.annotation.ApiDoc;
+import com.gitee.easyopen.doc.annotation.ApiDocMethod;
+import com.gitee.easyopen.server.api.param.GoodsParam;
+import com.gitee.easyopen.server.api.result.Goods;
+
+import java.math.BigDecimal;
+
+/**
+ * 业务类
+ *
+ * @author tanghc
+ */
+@ApiService
+@ApiDoc("商品模块")
+public class GoodsApi {
+
+ @Api(name = "goods.get")
+ @ApiDocMethod(description = "获取商品")
+ Goods getGoods(GoodsParam param) {
+ Goods goods = new Goods();
+ goods.setId(1L);
+ goods.setGoods_name("苹果iPhoneX");
+ goods.setPrice(new BigDecimal(8000));
+ return goods;
+ }
+
+}
diff --git a/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/api/param/GoodsParam.java b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/api/param/GoodsParam.java
new file mode 100644
index 00000000..c3f500c1
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/api/param/GoodsParam.java
@@ -0,0 +1,23 @@
+package com.gitee.easyopen.server.api.param;
+
+import com.gitee.easyopen.doc.annotation.ApiDocField;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotEmpty;
+
+public class GoodsParam {
+
+ @ApiDocField(description = "商品名称", required = true, example = "iphoneX")
+ @NotEmpty(message = "商品名称不能为空")
+ @Length(min = 3, max = 20, message = "{goods.name.length}=3,20")
+ private String goods_name;
+
+ public String getGoods_name() {
+ return goods_name;
+ }
+
+ public void setGoods_name(String goods_name) {
+ this.goods_name = goods_name;
+ }
+
+}
diff --git a/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/api/result/Goods.java b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/api/result/Goods.java
new file mode 100644
index 00000000..7ad6e9a9
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/api/result/Goods.java
@@ -0,0 +1,46 @@
+package com.gitee.easyopen.server.api.result;
+
+import com.gitee.easyopen.doc.DataType;
+import com.gitee.easyopen.doc.annotation.ApiDocField;
+
+import java.math.BigDecimal;
+
+public class Goods {
+
+ @ApiDocField(description = "id")
+ private Long id;
+ @ApiDocField(description = "商品名称")
+ private String goods_name;
+ @ApiDocField(description = "价格", dataType = DataType.FLOAT)
+ private BigDecimal price;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getGoods_name() {
+ return goods_name;
+ }
+
+ public void setGoods_name(String goods_name) {
+ this.goods_name = goods_name;
+ }
+
+ public BigDecimal getPrice() {
+ return price;
+ }
+
+ public void setPrice(BigDecimal price) {
+ this.price = price;
+ }
+
+ @Override
+ public String toString() {
+ return "Goods [id=" + id + ", goods_name=" + goods_name + ", price=" + price + "]";
+ }
+
+}
diff --git a/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/config/CorsConfig.java b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/config/CorsConfig.java
new file mode 100644
index 00000000..9c3c8d60
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/config/CorsConfig.java
@@ -0,0 +1,37 @@
+package com.gitee.easyopen.server.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * 解决js跨域
+ * @author tanghc
+ */
+@Configuration
+public class CorsConfig {
+
+ /**
+ * 跨域过滤器
+ *
+ * @return
+ */
+ @Bean
+ public CorsFilter corsFilter() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", buildConfig()); // 4
+ return new CorsFilter(source);
+ }
+
+ private CorsConfiguration buildConfig() {
+ CorsConfiguration corsConfiguration = new CorsConfiguration();
+ corsConfiguration.addAllowedOrigin("*");
+ corsConfiguration.addAllowedHeader("*");
+ corsConfiguration.addAllowedMethod("*");
+ return corsConfiguration;
+ }
+
+
+}
diff --git a/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/config/SopConfig.java b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/config/SopConfig.java
new file mode 100644
index 00000000..490e16f2
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/config/SopConfig.java
@@ -0,0 +1,11 @@
+package com.gitee.easyopen.server.config;
+
+import com.gitee.sop.servercommon.configuration.EasyopenServiceConfiguration;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author tanghc
+ */
+@Configuration
+public class SopConfig extends EasyopenServiceConfiguration {
+}
diff --git a/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/interceptor/LogInterceptor.java b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/interceptor/LogInterceptor.java
new file mode 100644
index 00000000..87e74910
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/interceptor/LogInterceptor.java
@@ -0,0 +1,23 @@
+package com.gitee.easyopen.server.interceptor;
+
+import com.gitee.easyopen.ApiContext;
+import com.gitee.easyopen.interceptor.ApiInterceptorAdapter;
+import com.gitee.easyopen.util.RequestUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.net.URLDecoder;
+
+public class LogInterceptor extends ApiInterceptorAdapter {
+
+ Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object serviceObj, Object argu)
+ throws Exception {
+ logger.info("收到客户端请求,ip={},参数={}", RequestUtil.getClientIP(request), URLDecoder.decode(ApiContext.getApiParam().toJSONString(), "UTF-8"));
+ return true;
+ }
+}
diff --git a/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/message/CommonErrors.java b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/message/CommonErrors.java
new file mode 100644
index 00000000..ecee0784
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/java/com/gitee/easyopen/server/message/CommonErrors.java
@@ -0,0 +1,16 @@
+package com.gitee.easyopen.server.message;
+
+import com.gitee.easyopen.message.ErrorMeta;
+
+/**
+ * 错误码放在这里
+ *
+ * 使用方式:throw CommonErrors.NUll_ERROR.getException();
+ */
+public interface CommonErrors {
+ String isvModule = "isv.error_"; // error_zh_CN2.properties内容前缀
+
+ ErrorMeta NUll_ERROR = new ErrorMeta(isvModule, "200", "不能为空");
+
+
+}
diff --git a/sop-example/sop-easyopen/src/main/resources/application.yml b/sop-example/sop-easyopen/src/main/resources/application.yml
new file mode 100644
index 00000000..73b63102
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/resources/application.yml
@@ -0,0 +1,26 @@
+server:
+ port: 2121
+
+
+
+# 指定注册中心
+eureka:
+ port: 1111
+ host: localhost
+ client:
+ serviceUrl:
+ defaultZone: http://${eureka.host}:${eureka.port}/eureka/
+
+spring:
+ application:
+ # 指定服务名
+ name: easyopen-service
+
+ # 指定zookeeper
+ cloud:
+ zookeeper:
+ connect-string: localhost:2181
+
+# 指定接口路径
+easyopen:
+ prefix-path: /api
diff --git a/sop-example/sop-easyopen/src/main/resources/i18n/isv/error_zh_CN.properties b/sop-example/sop-easyopen/src/main/resources/i18n/isv/error_zh_CN.properties
new file mode 100644
index 00000000..17981dd1
--- /dev/null
+++ b/sop-example/sop-easyopen/src/main/resources/i18n/isv/error_zh_CN.properties
@@ -0,0 +1,2 @@
+# common errors here
+isv.error_200=\u4E0D\u80FD\u4E3A\u7A7A
diff --git a/sop-example/sop-easyopen/src/test/java/com/gitee/durcframework/easyopen/server/SopEasyopenApplicationApplicationTests.java b/sop-example/sop-easyopen/src/test/java/com/gitee/durcframework/easyopen/server/SopEasyopenApplicationApplicationTests.java
new file mode 100644
index 00000000..aace584e
--- /dev/null
+++ b/sop-example/sop-easyopen/src/test/java/com/gitee/durcframework/easyopen/server/SopEasyopenApplicationApplicationTests.java
@@ -0,0 +1,16 @@
+package com.gitee.durcframework.easyopen.server;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class SopEasyopenApplicationApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}