This is an automated email from the ASF dual-hosted git repository. mabin pushed a commit to branch houserush-sample in repository https://gitbox.apache.org/repos/asf/servicecomb-samples.git
commit 9c9b18d326223868083b5eae15810703824773e1 Author: liubao <[email protected]> AuthorDate: Fri Apr 12 12:01:36 2019 +0800 项目升级到1.2.0,并且增加相关的说明 --- README.md | 14 +++- dependency_management/README.md | 19 ++++++ dependency_management/spring4/pom.xml | 4 +- dependency_management/spring5/pom.xml | 4 +- dependency_management/springboot1/pom.xml | 10 ++- dependency_management/springboot2/pom.xml | 3 +- porter_lightweight/README.md | 109 ++++++++++++++++++++++++++++++ porter_lightweight/pom.xml | 2 +- 8 files changed, 155 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 0c15baf..c1d8c06 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,17 @@ -# servicecomb samples +# ServiceComb samples ## porter_lightweight A sample shows an application with basic login, download file, delete file functions. ## dependency_management -A sample shows how to use dependency management to create spring 4, spring 5, spring boot 1 or spring boot 2 application. \ No newline at end of file +A sample shows how to use dependency management to create spring 4, spring 5, spring boot 1 or spring boot 2 application. + + +# 使用ServiceComb开发微服务的示例项目 + +## porter_lightweight +该项目演示了一个包括网关、文件下载、认证鉴权等功能的简单应用系统,同时演示了ServiceComb推荐的先写接口声明,再写业务代码的软件工程实践。 + +## dependency_management +该项目演示了ServiceComb如何依赖spring4, spring 5, spring boot1 和 spring boot 2。 + diff --git a/dependency_management/README.md b/dependency_management/README.md new file mode 100644 index 0000000..6caac86 --- /dev/null +++ b/dependency_management/README.md @@ -0,0 +1,19 @@ +## dependency_management + +A sample shows how to use dependency management to create spring 4, spring 5, spring boot 1 or spring boot 2 application. + +Compile each project and run with IDE or command line. Each servcie provide a simple REST api. This api can be access using +``` +http://localhost:9090/hello?name=jack +``` + +# dependency_management + +该项目演示了ServiceComb如何依赖spring4, spring 5, spring boot1 和 spring boot 2。 + +启动项目后,可以通过: +``` +http://localhost:9090/hello?name=jack +``` + +来访问微服务。 diff --git a/dependency_management/spring4/pom.xml b/dependency_management/spring4/pom.xml index 9ee8710..cd5e946 100644 --- a/dependency_management/spring4/pom.xml +++ b/dependency_management/spring4/pom.xml @@ -29,11 +29,10 @@ <dependencyManagement> <dependencies> - <!-- need to compile lastest java-chassis code --> <dependency> <groupId>org.apache.servicecomb</groupId> <artifactId>java-chassis-dependencies-spring4</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>1.2.0</version> <type>pom</type> <scope>import</scope> </dependency> @@ -52,6 +51,7 @@ <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> + <version>1.5.14.RELEASE</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> diff --git a/dependency_management/spring5/pom.xml b/dependency_management/spring5/pom.xml index 375c070..343b60f 100644 --- a/dependency_management/spring5/pom.xml +++ b/dependency_management/spring5/pom.xml @@ -29,11 +29,10 @@ <dependencyManagement> <dependencies> - <!-- need to compile lastest java-chassis code --> <dependency> <groupId>org.apache.servicecomb</groupId> <artifactId>java-chassis-dependencies-spring5</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>1.2.0</version> <type>pom</type> <scope>import</scope> </dependency> @@ -52,6 +51,7 @@ <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> + <version>2.1.2.RELEASE</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> diff --git a/dependency_management/springboot1/pom.xml b/dependency_management/springboot1/pom.xml index da6b1a7..417164c 100644 --- a/dependency_management/springboot1/pom.xml +++ b/dependency_management/springboot1/pom.xml @@ -29,14 +29,19 @@ <dependencyManagement> <dependencies> - <!-- need to compile lastest java-chassis code --> <dependency> <groupId>org.apache.servicecomb</groupId> <artifactId>java-chassis-dependencies-springboot1</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>1.2.0</version> <type>pom</type> <scope>import</scope> </dependency> + <!-- spring boot 1.5.14.RELEASE use a low version of validation-api, must override it --> + <dependency> + <groupId>javax.validation</groupId> + <artifactId>validation-api</artifactId> + <version>2.0.0.Final</version> + </dependency> </dependencies> </dependencyManagement> @@ -66,6 +71,7 @@ <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> + <version>1.5.14.RELEASE</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> diff --git a/dependency_management/springboot2/pom.xml b/dependency_management/springboot2/pom.xml index 8cb3bd9..215afd9 100644 --- a/dependency_management/springboot2/pom.xml +++ b/dependency_management/springboot2/pom.xml @@ -33,7 +33,7 @@ <dependency> <groupId>org.apache.servicecomb</groupId> <artifactId>java-chassis-dependencies-springboot2</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>1.2.0</version> <type>pom</type> <scope>import</scope> </dependency> @@ -62,6 +62,7 @@ <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> + <version>2.1.2.RELEASE</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> diff --git a/porter_lightweight/README.md b/porter_lightweight/README.md index 9870398..93d7bd5 100644 --- a/porter_lightweight/README.md +++ b/porter_lightweight/README.md @@ -79,4 +79,113 @@ java $JAVA_OPT -Dgateway.webroot=webapp -jar porter-gateway-service-0.0.1-SNAPSH 2. 选择一个文件上传,上传成功,上传成功后的文件会保存在file-service的当前目录, 文件名称是一个随机的数字,这个数字就是文件ID。 3. 删除文件:输入上一步的文件ID,点击删除。 如果是admin用户,上传成功;如果是guest用户,上传失败。 +# 接口使用说明 +ServiceComb推荐先定义接口,再定义实现的开发模式。将接口定义为一个独立项目,可以由设计者统一管控,对于接口的修改,需要设计者进行审核。先定义接口还可以让开发者培养良好的开发习惯,避免将对外接口采用内部实现数据结构(比如JsonObject)、运行平台有关的数据结构(比如HttpServletResponse)来定义,使得以后将项目改在为其他技术框架变得复杂。采用这种方式组织的项目,用户很容易在不同的开发框架上进行迁移,比如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> +``` + + * 采用RCP方式调用 +``` + @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_lightweight/pom.xml b/porter_lightweight/pom.xml index f891518..08a5500 100644 --- a/porter_lightweight/pom.xml +++ b/porter_lightweight/pom.xml @@ -50,7 +50,7 @@ <dependency> <groupId>org.apache.servicecomb</groupId> <artifactId>java-chassis-dependencies</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>1.2.0</version> <type>pom</type> <scope>import</scope> </dependency>
