add descriptions about Spring MVC supported annotations and differences.
diff --git a/java-chassis-reference/en_US/build-provider/springmvc.md b/java-chassis-reference/en_US/build-provider/springmvc.md
index 91e270c..4a2b06f 100644
--- a/java-chassis-reference/en_US/build-provider/springmvc.md
+++ b/java-chassis-reference/en_US/build-provider/springmvc.md
@@ -1,131 +1,227 @@
# Develop Microservice with SpringMVC
## Concept Description
-ServiceComb supports Spring MVC remark and allows you to develop microservices in Spring MVC mode.
+ServiceComb supports Spring MVC annotations to define your REST services. The [samples project](https://github.com/apache/servicecomb-java-chassis/tree/master/samples/springmvc-sample) has a lot of working examples.
## Development Example
-* **Step 1** Import dependencies into your maven project:
+### Define the service interface (optional)
- ```xml
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.apache.servicecomb</groupId>
- <artifactId>java-chassis-dependencies</artifactId>
- <version>1.0.0-m1</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- <dependencies>
- <!--transport can optional import through endpoint setting in microservice.yaml, we import both rest and highway as example-->
- <dependency>
- <groupId>org.apache.servicecomb</groupId>
- <artifactId>transport-rest-vertx</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb</groupId>
- <artifactId>transport-highway</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb</groupId>
- <artifactId>provider-springmvc</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </dependency>
- </dependencies>
- ```
+Writing a interface for the REST service make it easy to call the service in client in RPC style.
+
+```java
+public interface Hello {
+ String sayHi(String name);
+ String sayHello(Person person);
+}
+```
* **Step 2** Implement the services. Spring MVC is used to describe the development of service code. The implementation of the Hello service is as follow:
- ```java
- import javax.ws.rs.core.MediaType;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.apache.servicecomb.samples.common.schema.models.Person;
+ ```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;
+ }
- @RequestMapping(path = "/springmvchello", produces = MediaType.APPLICATION_JSON)
- public class SpringmvcHelloImpl {
- @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();
+ }
+}
+```
- @RequestMapping(path = "/sayhello", method = RequestMethod.POST)
- public String sayHello(@RequestBody Person person) {
- return "Hello person " + person.getName();
- }
- }
- ```
-
- **Note: PLEASE MAKE SURE TO MARK @RequestMapping ON YOUR PRODUCER(SpringmvcHelloImpl), OR THE PATH AND METHOD OF PUBLISHED WILL BE INCORRECT!**
-
- In this sample the Path of sayHi is `/springmvchello/sayhi`, and the Path of sayHello is `/springmvchello/sayhello`, if you wish them `/sayhi` and `/sayhello`, please change the setting of `@RequestMapping` on the SpringmvcHelloImpl to `@RequestMapping("/")`.
+### add a component scan (optional)
-* **Step 3** Release the service. Add @RestSchema as the annotation of the service implementation class and specify schemaId, which indicates that the implementation is released as a schema of the current microservice. The code is as follows:
+create `resources/META-INF/spring` folder and add `springmvcprovider.bean.xml`, add component-scan to specify the bean package. This step is optional. The package where main class located is automatically added.
- ```java
- import org.apache.servicecomb.provider.rest.common.RestSchema;
- // other code omitted
- @RestSchema(schemaId = "springmvcHello")
- public class SpringmvcHelloImpl {
- // other code omitted
- }
- ```
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
- Create the ```springmvcHello.bean.xml``` file(the file name format is *.bean.xml) in the ``` resources/META-INF/spring``` directory and configure base-package that performs scanning. The content of the file is as follows:
+<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">
- ```xml
- <?xml version="1.0" encoding="UTF-8"?>
+ <context:component-scan base-package="org.apache.servicecomb.samples.springmvc.povider"/>
+</beans>
+```
- <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">
+### Wrtie a main class
- <context:component-scan base-package="org.apache.servicecomb.samples.springmvc.provider"/>
- </beans>
- ```
+This code using log4j as the logger framework. Users can change it to any other favorite logger framework.
-* **Step 4** Add service definition file:
+```java
+public class SpringmvcProviderMain {
- Add [microservice.yaml](http://servicecomb.incubator.apache.org/cn/users/service-definition/) file into resources folder of your project.
+ public static void main(String[] args) throws Exception {
+ Log4jUtils.init();
+ BeanUtils.init();
+ }
+}
+```
-* **Step 5** Add Main class:
+## Using POJO as query parameters
- ```java
- import org.apache.servicecomb.foundation.common.utils.BeanUtils;
- import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
+### Description
- public class Application {
- public static void main(String[] args) throws Exception {
- //initializing log, loading bean(including its parameters), and registering service, more detail can be found here : http://servicecomb.incubator.apache.org/users/application-boot-process/
- Log4jUtils.init();
- BeanUtils.init();
- }
- }
- ```
+SpringBoot supports to map a bean parameter to HTTP queries.
+```java
+@RequestMapping("/hello")
+public class HelloService {
+ @RequestMapping(value = "/sayHello", method = RequestMethod.GET)
+ public String sayHello(Person person) {
+ System.out.println("sayHello is called, person = [" + person + "]");
+ return "Hello, your name is " + person.getName() + ", and age is " + person.getAge();
+ }
+}
+```
-## Involved APIs
+ServiceComb supports this usage too, but has following constraints.
+1. Must not add any mapping annotations, such as @QueryParam
+2. Only map to query parameters, headers and forms not supported.
+3. Variables name in POJO definition must be the same as query keys.
+4. Only primitive and String types supported in POJO, add `@JsonIgnore` to other types to ignore it.
+5. In consumer site(e.g RestTemplate), still need to use query parameters, can not use POJO.
-Currently, the Spring MVC development mode supports the following annotations in the org.springframework.web.bind.annotation package. For details about how to use the annotations, see [Spring MVC official documentation](https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html)。
+### Examples
-| Remarks | Location | Description |
-| :------------- | :--------------- | :--------------------------------------- |
-| RequestMapping | schema/operation | Data of path, method or produces is allowed. By default, an operation inherits produces from a schema. |
-| GetMapping | schema/operation | Data of path or produces is allowed. By default, an operation inherits produces from a schema. |
-| PutMapping | schema/operation | Data of path or produces is allowed, an operation inherits produces from a schema. |
-| PostMapping | schema/operation | Data of path or produces is allowed, an operation inherits produces from a schema. |
-| DeleteMapping | schema/operation | Data of path or produces is allowed, an operation inherits produces from a schema. |
-| PatchMapping | schema/operation | Data of path or produces is allowed, an operation inherits produces from a schema. |
-| PathVariable | parameter | Obtain parameters from path. |
-| RequestParam | parameter | Obtain parameters from query. |
-| RequestHeader | parameter | Obtain parameters from header. |
-| RequestBody | parameter | Obtain parameters from body. Each operation can have only one body parameter. |
+#### Provider
+
+- service definition
+```java
+ @RestSchema(schemaId = "helloService")
+ @RequestMapping("/hello")
+ public class HelloService {
+ @RequestMapping(value = "/sayHello", method = RequestMethod.GET)
+ public String sayHello(Person person) {
+ System.out.println("sayHello is called, person = [" + person + "]");
+ return "Hello, your name is " + person.getName() + ", and age is " + person.getAge();
+ }
+ }
+```
+- parameters
+```java
+ public class Person {
+ private String name;
+ private int age;
+ @JsonIgnore // add @JsonIgnore to unsupported types
+ private List<Person> children;
+ }
+```
+- Schemas
+```yaml
+
+basePath: "/hello"
+paths:
+ /sayHello:
+ get:
+ operationId: "sayHello"
+ parameters:
+ # name and age is query parameter
+ - name: "name"
+ in: "query"
+ required: false
+ type: "string"
+ - name: "age"
+ in: "query"
+ required: false
+ type: "integer"
+ format: "int32"
+ responses:
+ 200:
+ description: "response of 200"
+ schema:
+ type: "string"
+```
+
+#### Consumer
+
+- Call using RPC
+ - add an interface
+ ```java
+ public interface HelloServiceIntf {
+ String sayHello(String name, int age);
+ }
+ ```
+ - call the interface
+ ```java
+ String result = helloService.sayHello("Bob", 22); // result is "Hello, your name is Bob, and age is 22"
+ ```
+- Call using RestTemplate
+ ```java
+ String result = restTemplate.getForObject(
+ "cse://provider-service/hello/sayHello?name=Bob&age=22",
+ String.class);
+ ```
+
+## ServiceComb suppoted Spring MVC annotations and differences
+
+ServiceComb supports Spring MVC annotatioins\(org.springframework.web.bind.annotation\) to define REST interfaces, but they are different. ServiceComb do not support @Controller frameworks and only support @RestController frameworks.
+
+* Differences in supported annotations
+
+### Table 1-1 annotations
+
+| annotation | supported | notes |
+| :--- | :--- | :--- |
+| RequestMapping | Yes | Can only have one path, multiple path is not supported. |
+| GetMapping | Yes | |
+| PutMapping | Yes | |
+| PostMapping | Yes | |
+| DeleteMapping | Yes | |
+| PatchMapping | Yes | |
+| RequestParam | Yes | |
+| CookieValue | Yes | |
+| PathVariable | Yes | |
+| RequestHeader | Yes | |
+| RequestBody | Yes | supports application/json,plain/text |
+| RequestPart | Yes | Used in file upload. Using Part、MultipartFile annotations. |
+| ResponseBody | No | @Controller framework is not supported |
+| ResponseStatus | No | Using ApiResponse to define status code |
+| RequestAttribute | No | |
+| SessionAttribute | No | |
+| MatrixVariable | No | |
+| ModelAttribute | No | |
+| ControllerAdvice | No | |
+| CrossOrigin | No | |
+| ExceptionHandler | No | |
+| InitBinder | No | |
+
+* Define a REST service
+
+Spring MVC using @RestController to define a REST service,ServiceComb using @RestSchema to define a REST service,and path value in @RequestMapping is required.
+
+```
+@RestSchema(schemaId = "hello")
+@RequestMapping(path = "/")
+```
+
+@RestController is also supported and equals to @RestSchma(schemaId="class name"). However we suggest using @RestSchemaand define a schemaId,it more convenient when used in configurations.
+
+* Supported data types
+
+Spring MVC supports almost all java types in service difinition, e.g.
+
+```
+// abstract class
+public void postData(@RequestBody Object data)
+// interface
+public void postData(@RequestBody IPerson interfaceData)
+// generic without types
+public void postData(@RequestBody Map rawData)
+// servlet types
+public void postData(HttpServletRequest rquest)
+```
+
+ServiceComb need to generate Open API schemas based on definition, and support cross language features, so some of there usage is not supported.
+
+HttpServletRequest,Object is supported in latest version, but they are different. We suggest not using there features if possible.
+
+please refer to [API Constraints](/build-provider/interface-constraints.md) for data type supports.
diff --git a/java-chassis-reference/zh_CN/build-provider/springmvc.md b/java-chassis-reference/zh_CN/build-provider/springmvc.md
index 9f24be5..2da2dae 100644
--- a/java-chassis-reference/zh_CN/build-provider/springmvc.md
+++ b/java-chassis-reference/zh_CN/build-provider/springmvc.md
@@ -2,13 +2,13 @@
## 概念阐述
-ServiceComb支持SpringMVC注解,允许使用SpringMVC风格开发微服务。建议参照着项目 [SpringMVC](https://github.com/apache/incubator-servicecomb-java-chassis/tree/master/samples/springmvc-sample)进行详细阅读
+ServiceComb支持SpringMVC注解,允许使用SpringMVC风格开发微服务。建议参照着项目 [SpringMVC](https://github.com/apache/servicecomb-java-chassis/tree/master/samples/springmvc-sample)进行详细阅读
## 开发示例
-### 步骤 1定义服务接口。
+### 步骤 1定义服务接口(可选,方便使用RPC方式调用)
-根据开发之前定义好的契约,编写Java业务接口,代码如下。定义接口不是必须的,但是 一个好习惯,可以简化客户端使用RPC方式编写代码。
+定义接口不是必须的,但是 一个好习惯,可以简化客户端使用RPC方式编写代码。
```java
public interface Hello {
@@ -19,7 +19,7 @@
-### 步骤 2实现服务。
+### 步骤 2实现服务
使用Spring MVC注解开发业务代码,Hello的服务实现如下。在服务的实现类上打上注解@RestSchema,指定schemaId,schemaId必须保证微服务范围内唯一。
@@ -41,7 +41,7 @@
}
```
-### 步骤 3发布服务
+### 步骤 3发布服务 (可选,默认会扫描main函数所在的package)
在`resources/META-INF/spring`目录下创建`springmvcprovider.bean.xml`文件,命名规则为`\*.bean.xml`,配置spring进行服务扫描的base-package,文件内容如下:
@@ -60,7 +60,7 @@
### 步骤 4启动provider 服务
-进行主要相关配置初始化。
+下面的代码使用Log4j作为日志记录器。开发者可以方便使用其他日志框架。
```java
public class SpringmvcProviderMain {
@@ -72,20 +72,6 @@
}
```
-## 涉及API
-
-Spring MVC开发模式当前支持org.springframework.web.bind.annotation包下的如下注解,所有注解的使用方法参考[Spring MVC官方文档](https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html)。
-
-### 表1-1 Spring MVC注解支持汇总
-
-| 注解 | 位置 | 描述 |
-| :--- | :--- | :--- |
-| RequestMapping | schema/operation | 支持标注path/method/produces三种数据,operation默认继承schema上的produces |
-| PathVariable | parameter | 从path中获取参数 |
-| RequestParam | parameter | 从query中获取参数 |
-| RequestHeader | parameter | 从header中获取参数 |
-| RequestBody | parameter | 从body中获取参数,每个operation只能有一个body参数 |
-
## Query参数聚合为POJO对象
### 使用说明
@@ -180,3 +166,78 @@
"cse://provider-service/hello/sayHello?name=Bob&age=22",
String.class); // 调用效果与RPC方式相同
```
+
+## ServiceComb支持的Spring MVC标签说明
+
+ServiceComb支持使用Spring MVC提供的标签\(org.springframework.web.bind.annotation\)来声明REST接口,但是两者是独立的实现,而且有不一样的设计目标。CSE的目标是提供跨语言、支持多通信协议的框架,因此去掉了Spring MVC中一些对跨语言支持不是很好的特性,也不支持特定运行框架强相关的特性,比如直接访问Servlet协议定义的HttpServletRequest。ServiceComb没有实现@Controller相关功能, 只实现了@RestController,即通过MVC模式进行页面渲染等功能都是不支持的。
+
+下面是一些具体差异。
+
+* 常用标签支持
+
+下面是CSE对于Spring MVC常用标签的支持情况。
+
+### 表1-1 Spring MVC注解情况说明
+
+| 标签名称 | 是否支持 | 说明 |
+| :--- | :--- | :--- |
+| RequestMapping | 是 | 不允许制定多个Path,一个接口只允许一个Path |
+| GetMapping | 是 | |
+| PutMapping | 是 | |
+| PostMapping | 是 | |
+| DeleteMapping | 是 | |
+| PatchMapping | 是 | |
+| RequestParam | 是 | |
+| CookieValue | 是 | |
+| PathVariable | 是 | |
+| RequestHeader | 是 | |
+| RequestBody | 是 | 目前支持application/json,plain/text |
+| RequestPart | 是 | 用于文件上传的场景,对应的标签还有Part、MultipartFile |
+| ResponseBody | 否 | 返回值缺省都是在body返回 |
+| ResponseStatus | 否 | 可以通过ApiResponse指定返回的错误码 |
+| RequestAttribute | 否 | Servlet协议相关的标签 |
+| SessionAttribute | 否 | Servlet协议相关的标签 |
+| MatrixVariable | 否 | |
+| ModelAttribute | 否 | |
+| ControllerAdvice | 否 | |
+| CrossOrigin | 否 | |
+| ExceptionHandler | 否 | |
+| InitBinder | 否 | |
+
+* 服务声明方式
+
+Spring MVC使用@RestController声明服务,而ServiceComb使用@RestSchema声明服务,并且需要显示的使用@RequestMapping声明服务路径,以区分该服务是采用Spring MVC的标签还是使用JAX RS的标签。
+
+```
+@RestSchema(schemaId = "hello")
+@RequestMapping(path = "/")
+```
+
+Schema是CSE的服务契约,是服务运行时的基础,服务治理、编解码等都基于契约进行。在跨语言的场景,契约也定义了不同语言能够同时理解的部分。
+
+最新版本也支持@RestController声明,等价于@RestSchma(schemaId="服务的class名称"),建议用户使用@RestSchema显示声明schemaId,在管理接口基本的配置项的时候,更加直观。
+
+* 数据类型支持
+
+采用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)
+```
+
+ServiceComb会根据接口定义生成契约,从上面的接口定义,如果不结合实际的实现代码或者额外的开发文档说明,无法直接生成契约。也就是站在浏览器的REST视角,不知道如何在body里面构造消息内容。ServiceComb不建议定义接口的时候使用抽象类型、接口等。
+
+为了支持快速开发,ServiceComb的数据类型限制也在不停的扩充,比如支持HttpServletRequest,Object等。但是实际在使用的时候,他们与WEB服务器的语义是不一样的,比如不能直接操作流。因此建议开发者在ServiceComb的使用场景下,尽可能使用契约能够描述的类型,让代码阅读性更好。
+
+ServiceComb在数据类型的支持方面的更多说明,请参考: [接口定义和数据类型](/build-provider/interface-constraints.md)
+
+* 其他
+更多开发过程中碰到的问题,可以参考[案例](https://bbs.huaweicloud.com/blogs/8b8d8584e70d11e8bd5a7ca23e93a891)。开发过程中存在疑问,也可以在这里进行提问。
+