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/05/15 00:38:02 UTC
[servicecomb-docs] branch master updated: [SCB-1895]add document
for how to add reponse headers using rest
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-docs.git
The following commit(s) were added to refs/heads/master by this push:
new 0a1ff5c [SCB-1895]add document for how to add reponse headers using rest
0a1ff5c is described below
commit 0a1ff5c3bd47e1c9366e47c8c97667104667fe52
Author: liubao <bi...@qq.com>
AuthorDate: Thu May 14 21:40:04 2020 +0800
[SCB-1895]add document for how to add reponse headers using rest
---
.../zh_CN/docs/build-provider/springmvc.md | 243 ++++++++++++++-------
java-chassis-reference/zh_CN/docs/index.md | 1 +
2 files changed, 169 insertions(+), 75 deletions(-)
diff --git a/java-chassis-reference/zh_CN/docs/build-provider/springmvc.md b/java-chassis-reference/zh_CN/docs/build-provider/springmvc.md
index 56d6d1e..2478653 100644
--- a/java-chassis-reference/zh_CN/docs/build-provider/springmvc.md
+++ b/java-chassis-reference/zh_CN/docs/build-provider/springmvc.md
@@ -1,76 +1,155 @@
-# 用SpringMVC 开发微服务
+# 用 Spring MVC 开发微服务
## 概念阐述
-ServiceComb支持SpringMVC注解,允许使用SpringMVC风格开发微服务。建议参照着
-项目 [SpringMVC](https://github.com/apache/servicecomb-samples/tree/master/java-chassis-samples/springmvc-sample) 进行详细阅读
+Spring MVC 是 spring-web 项目定义的一套注解,开发者可以使用这套注解定义 REST 接口。 servicecomb 也支持使用
+这套标签定义 REST 接口。
-## 开发示例
+可以参考示例项目 [SpringMVC](https://github.com/apache/servicecomb-samples/tree/master/java-chassis-samples/springmvc-sample) 。
-### 步骤1 定义服务接口(可选,方便使用RPC方式调用)
+## 开发步骤
-定义接口不是必须的,但是 一个好习惯,可以简化客户端使用RPC方式编写代码。
+* 定义服务接口(可选)
-```java
-public interface Hello {
- String sayHi(String name);
- String sayHello(Person person);
-}
-```
+ 定义接口是一个好习惯, 它不是必须的。
+
+ ```java
+ public interface Hello {
+ String sayHi(String name);
+ String sayHello(Person person);
+ }
+ ```
+* 实现服务接口
+在服务的实现类上打上注解 `@RestSchema`,指定 `schemaId`。 注意 `schemaId` 需要保证微服务范围内唯一。
-### 步骤2 实现服务
+ ```java
+ @RestSchema(schemaId = "springmvcHello")
+ @RequestMapping(path = "/springmvchello", produces = MediaType.APPLICATION_JSON)
+ public class SpringmvcHelloImpl implements Hello {
+ @Override
+ @RequestMapping(path = "/sayhi", method = RequestMethod.POST)
+ public String sayHi(@RequestParam(name = "name") String name) {
+ return "Hello " + name;
+ }
+
+ @Override
+ @RequestMapping(path = "/sayhello", method = RequestMethod.POST)
+ public String sayHello(@RequestBody Person person) {
+ return "Hello person " + person.getName();
+ }
+ }
+ ```
-使用Spring MVC注解开发业务代码,Hello的服务实现如下。在服务的实现类上打上注解@RestSchema,指定schemaId,schemaId必须保证微服务范围内唯一。
+* 发布服务 (可选,默认会扫描 main 函数所在的 package )
+
+在`resources/META-INF/spring`目录下创建`springmvcprovider.bean.xml`文件,命名规则为`\*.bean.xml`,配置spring进行服务扫描的base-package,文件内容如下:
+
+ ```xml
+ <?xml version="1.0" encoding="UTF-8"?>
+
+ <beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:cse="http://www.huawei.com/schema/paas/cse/rpc"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.huawei.com/schema/paas/cse/rpc classpath:META-INF/spring/spring-paas-cse-rpc.xsd">
+
+ <context:component-scan base-package="org.apache.servicecomb.samples.springmvc.povider"/>
+ </beans>
+ ```
+
+* 启动 provider 服务
+
+servicecomb 依赖于 Spring, 只需要将 Spring 框架启动起来即可。
+
+ ```java
+ public class SpringmvcProviderMain {
+
+ public static void main(String[] args) throws Exception {
+ BeanUtils.init();
+ }
+ }
+ ```
+
+## 在响应中包含 HTTP header
+
+可以有多种方式在响应中包含 HTTP header, 下面代码展示了使用 ResponseEntity 包含 HTTP header。 需要注意
+使用 @ResponseHeaders 声明返回的 header 信息。 包含了 @ResponseHeaders 以后, 接口生成的契约中,也可以
+看到对应的 header 参数。
```java
-@RestSchema(schemaId = "springmvcHello")
-@RequestMapping(path = "/springmvchello", produces = MediaType.APPLICATION_JSON)
-public class SpringmvcHelloImpl implements Hello {
- @Override
- @RequestMapping(path = "/sayhi", method = RequestMethod.POST)
- public String sayHi(@RequestParam(name = "name") String name) {
- return "Hello " + name;
- }
+ @ResponseHeaders({@ResponseHeader(name = "h1", response = String.class),
+ @ResponseHeader(name = "h2", response = String.class)})
+ @RequestMapping(path = "/responseEntity", method = RequestMethod.POST)
+ public ResponseEntity<Date> responseEntity(InvocationContext c1,
+ @RequestAttribute("date") Date date) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("h1", "h1v " + c1.getContext().get(Const.SRC_MICROSERVICE));
+
+ InvocationContext c2 = ContextUtils.getInvocationContext();
+ headers.add("h2", "h2v " + c2.getContext().get(Const.SRC_MICROSERVICE));
+
+ return new ResponseEntity<>(date, headers, HttpStatus.ACCEPTED);
+ }
+```
- @Override
- @RequestMapping(path = "/sayhello", method = RequestMethod.POST)
- public String sayHello(@RequestBody Person person) {
- return "Hello person " + person.getName();
- }
-}
+也可以使用 Response 对象返回 HTTP header,示例代码如下:
+
+```java
+ @ApiResponse(code = 202, response = User.class, message = "")
+ @ResponseHeaders({@ResponseHeader(name = "h1", response = String.class),
+ @ResponseHeader(name = "h2", response = String.class)})
+ @RequestMapping(path = "/cseResponse", method = RequestMethod.GET)
+ public Response cseResponse(InvocationContext c1) {
+ Response response = Response.createSuccess(Status.ACCEPTED, new User());
+ Headers headers = response.getHeaders();
+ headers.addHeader("h1", "h1v " + c1.getContext().get(Const.SRC_MICROSERVICE));
+
+ InvocationContext c2 = ContextUtils.getInvocationContext();
+ headers.addHeader("h2", "h2v " + c2.getContext().get(Const.SRC_MICROSERVICE));
+
+ return response;
+ }
```
-### 步骤3 发布服务 (可选,默认会扫描main函数所在的package)
+这个示例代码还通过 @ApiResponse 指定了返回 202 错误码及其类型, 这个响应值会在契约体现。
-在`resources/META-INF/spring`目录下创建`springmvcprovider.bean.xml`文件,命名规则为`\*.bean.xml`,配置spring进行服务扫描的base-package,文件内容如下:
+***注意***: HIGHWAY 协议不支持指定返回错误码和类型。需要同时使用 HIGHWAY 和 REST 访问的接口,
+请勿使用。
-```xml
-<?xml version="1.0" encoding="UTF-8"?>
+## 指定 String 类型 body 编码方式
-<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 classpath:org/springframework/beans/factory/xml/spring-beans-3.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+使用 REST 通信的服务, 一般采用 json 进行编解码。 String 类型的数据, 编码为 json 的时候,存在
+双引号。 比如 `abc` 编码以后为 `"abc"` 。 但是 Spring 自身的实现, 将 String 类型的数据,编码
+为不带双引号。 为了保持 Spring 原始实现的方式兼容, servicecomb 提供了 `RawJsonRequestBody` 接收
+不带双引号的参数。
- <context:component-scan base-package="org.apache.servicecomb.samples.springmvc.povider"/>
-</beans>
+```java
+ @ResponseBody
+ public String testRawJsonAnnotation(@RawJsonRequestBody String jsonInput) {
+ return jsonInput;
+ }
```
-### 步骤4 启动provider 服务
-
-下面的代码使用Log4j作为日志记录器。开发者可以使用其他日志框架。
+或者使用 MediaType.TEXT_PLAIN_VALUE, 不使用 MediaType.APPLICATION_JSON_VALUE
```java
-public class SpringmvcProviderMain {
+ @RequestMapping(path = "/textPlain", method = RequestMethod.POST,
+ consumes = MediaType.TEXT_PLAIN_VALUE)
+ public String textPlain(@RequestBody String body) {
+ return body;
+ }
+```
+
+如果响应不期望带双引号,可以使用 `produces = MediaType.TEXT_PLAIN_VALUE`
- public static void main(String[] args) throws Exception {
- Log4jUtils.init();
- BeanUtils.init();
+```java
+ @RequestMapping(path = "/sayhi/compressed/{name}/v2",
+ method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
+ public String sayHiForCompressed(@PathVariable(name = "name") String name) {
+ return name;
}
-}
```
## Query参数聚合为POJO对象
@@ -174,17 +253,21 @@ String result = restTemplate.getForObject(
String.class); // 调用效果与RPC方式相同
```
-## ServiceComb支持的Spring MVC标签说明
+## ServiceComb支持的 Spring MVC 注解说明
-ServiceComb支持使用Spring MVC提供的标签\(org.springframework.web.bind.annotation\)来声明REST接口,但是两者是独立的实现,而且有不一样的设计目标。CSE的目标是提供跨语言、支持多通信协议的框架,因此去掉了Spring MVC中一些对跨语言支持不是很好的特性,也不支持特定运行框架强相关的特性,比如直接访问Servlet协议定义的`HttpServletRequest`。ServiceComb没有实现`@Controller`相关功能, 只实现了`@RestController`,即通过MVC模式进行页面渲染等功能都是不支持的。
+ServiceComb支持使用 Spring MVC 提供的注解\(org.springframework.web.bind.annotation\)来声
+明REST接口,但是两者是独立的实现,而且有不一样的设计目标。CSE的目标是提供跨语言、支持多通信协议的
+框架,因此去掉了Spring MVC中一些对跨语言支持不是很好的特性,也不支持特定运行框架强相关的特性,比
+如直接访问Servlet协议定义的`HttpServletRequest`。ServiceComb没有实现`@Controller`相关功
+能, 只实现了`@RestController`,即通过MVC模式进行页面渲染等功能都是不支持的。
下面是一些具体差异。
* 常用标签支持
-下面是CSE对于Spring MVC常用标签的支持情况。
+ 下面是CSE对于Spring MVC常用标签的支持情况。
-### 表1-1 Spring MVC注解情况说明
+ ### 表1-1 Spring MVC注解情况说明
| 标签名称 | 是否支持 | 说明 |
| :--- | :--- | :--- |
@@ -213,40 +296,50 @@ ServiceComb支持使用Spring MVC提供的标签\(org.springframework.web.bind.a
* 服务声明方式
-Spring MVC使用`@RestController`声明服务,而ServiceComb使用`@RestSchema`声明服务,并且需要显式地使用`@RequestMapping`声明服务路径,以区分该服务是采用Spring MVC的标签还是使用JAX RS的标签。
+ Spring MVC使用`@RestController`声明服务,而ServiceComb使用`@RestSchema`声明服务,并且需
+ 要显式地使用`@RequestMapping`声明服务路径,以区分该服务是采用Spring MVC的标签还是使用JAX RS的标签。
-```
-@RestSchema(schemaId = "hello")
-@RequestMapping(path = "/")
-```
+ ```
+ @RestSchema(schemaId = "hello")
+ @RequestMapping(path = "/")
+ ```
-Schema是CSE的服务契约,是服务运行时的基础,服务治理、编解码等都基于契约进行。在跨语言的场景,契约也定义了不同语言能够同时理解的部分。
+ Schema 是 CSE 的服务契约,是服务运行时的基础,服务治理、编解码等都基于契约进行。在跨语言的场景,契约
+ 也定义了不同语言能够同时理解的部分。
-最新版本也支持`@RestController`声明,等价于`@RestSchma(schemaId="服务的class名称")`,建议用户使用`@RestSchema`显式声明schemaId,在管理接口基本的配置项的时候,更加直观。
+ servicecomb 也支持 `@RestController` 声明,等价于 `@RestSchma(schemaId="服务的class名称")`,这个
+ 功能可以简化用户将老的应用改造为 servicecomb 。 建议用户使用`@RestSchema`显式声明schemaId,在管理
+ 接口基本的配置项的时候,更加直观。
-**注意**:如果不希望Java-Chassis扫描`@RestController`注解作为REST接口类处理,需要增加配置
-`servicecomb.provider.rest.scanRestController=false`以关闭此功能。
+ **注意**:如果不希望Java-Chassis扫描`@RestController`注解作为REST接口类处理,需要增加配置
+ `servicecomb.provider.rest.scanRestController=false` 以关闭此功能。
* 数据类型支持
-采用Spring MVC,可以在服务定义中使用多种数据类型,只要这种数据类型能够被json序列化和反序列化。比如:
+ Spring 技术实现的 Spring MVC,可以在服务定义中使用多种数据类型,只要这种数据类型能够被json序列化和
+ 反序列化。比如:
-```
-// 抽象类型
-public void postData(@RequestBody Object data)
-// 接口定义
-public void postData(@RequestBody IPerson interfaceData)
-// 没指定类型的泛型
-public void postData(@RequestBody Map rawData)
-// 具体协议相关的类型
-public void postData(HttpServletRequest rquest)
-```
+ ```
+ // 抽象类型
+ public void postData(@RequestBody Object data)
+ // 接口定义
+ public void postData(@RequestBody IPerson interfaceData)
+ // 没指定类型的泛型
+ public void postData(@RequestBody Map rawData)
+ // 具体协议相关的类型
+ public void postData(HttpServletRequest rquest)
+ ```
-ServiceComb会根据接口定义生成契约,从上面的接口定义,如果不结合实际的实现代码或者额外的开发文档说明,无法直接生成契约。也就是站在浏览器的REST视角,不知道如何在body里面构造消息内容。ServiceComb不建议定义接口的时候使用抽象类型、接口等。
+ servicecomb 对于数据类型存在一定的限制,不允许使用接口等数据类型定义参数,因为 servicecomb 会根据接口
+ 定义生成契约。 例子中的接口定义,如果不结合实现代码或者额外的开发文档说明,
+ 无法知道具体的参数信息。站在浏览器的 REST 视角,不知道如何在 body 里面构造消息内容。
-为了支持快速开发,ServiceComb的数据类型限制也在不停的扩充,比如支持HttpServletRequest,Object等。但是实际在使用的时候,他们与WEB服务器的语义是不一样的,比如不能直接操作流。因此建议开发者在ServiceComb的使用场景下,尽可能使用契约能够描述的类型,让代码阅读性更好。
+ 为了支持快速开发,servicecomb 支持 HttpServletRequest,Object。但
+ 是实际在使用的时候,他们与WEB服务器的语义是不一样的,比如不能直接操作流。因此建议开发者在 servicecomb 的
+ 使用场景下,尽可能不要使用 HttpServletRequest,Object 作为请求参数。
-ServiceComb在数据类型的支持方面的更多说明,请参考: [接口定义和数据类型](interface-constraints.md)
+ ServiceComb在数据类型的支持方面的更多说明,请参考: [接口定义和数据类型](interface-constraints.md)
* 其他
-更多开发过程中碰到的问题,可以参考[案例](https://bbs.huaweicloud.com/blogs/8b8d8584e70d11e8bd5a7ca23e93a891)。开发过程中存在疑问,也可以在这里进行提问。
+
+ 更多开发过程中碰到的问题,可以参考[案例](https://bbs.huaweicloud.com/blogs/8b8d8584e70d11e8bd5a7ca23e93a891)。开发过程中存在疑问,也可以在这里进行提问。
diff --git a/java-chassis-reference/zh_CN/docs/index.md b/java-chassis-reference/zh_CN/docs/index.md
index 655da57..67b322c 100644
--- a/java-chassis-reference/zh_CN/docs/index.md
+++ b/java-chassis-reference/zh_CN/docs/index.md
@@ -24,5 +24,6 @@ Apache ServiceComb Java Chassis 给开发者提供一个快速构建微服务的
推荐使用[Bing](https://cn.bing.com/), [Google](http://google.com.hk/)进行搜索。例子如下:
异常处理 site:docs.servicecomb.io
+
* 访问[文档源代码](https://github.com/apache/servicecomb-docs/tree/master/java-chassis-reference), 参考主页说明,采用 mkdocs 编译
后本地使用。 并在[issue](https://github.com/apache/servicecomb-docs/issues) 提交文档错误。