WillemJiang closed pull request #29: Add description about SpringMVC's query 
object param and JAX-RS's BeanParam
URL: https://github.com/apache/incubator-servicecomb-docs/pull/29
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/java-chassis-reference/zh_CN/build-provider/jaxrs.md 
b/java-chassis-reference/zh_CN/build-provider/jaxrs.md
index 1ccada8..b004e33 100644
--- a/java-chassis-reference/zh_CN/build-provider/jaxrs.md
+++ b/java-chassis-reference/zh_CN/build-provider/jaxrs.md
@@ -98,11 +98,101 @@ JAX-RS开发模式当前支持如下注解,所有注解的使用方法参考[J
 | javax.ws.rs.PathParam | parameter | 从path中获取参数,必须在path中定义该参数 |
 | javax.ws.rs.HeaderParam | parameter | 从header中获取参数 |
 | javax.ws.rs.CookieParam | parameter | 从cookie中获取参数 |
+| javax.ws.rs.FormParam | parameter | 从form中获取参数 |
+| javax.ws.rs.BeanParam | parameter | 
用于参数聚合,允许在一个JavaBean的属性上打上参数标记以将多个参数聚合为一个JavaBean |
 
 > **说明:**
 >
-> * 当方法参数没有注解,且不为HttpServletRequest类型参数时,默认为body类型参数,一个方法只支持最多一个body类型参数。
-> * 打在参数上面的注解建议显式定义出value值,否则将直接使用契约中的参数名,例如应该使用`@QueryParam\("name"\) String 
name`,而不是`@QueryParam String name`。
+> * 
当方法参数没有注解,且不为`HttpServletRequest`、`InvocationContext`类型参数时,默认为body类型参数,一个方法最多只支持一个body类型参数。
 
+## 使用@BeanParam聚合参数
 
+### 使用说明
 
+用户可以使用@BeanParam注解将多个参数聚合到一个JavaBean中,通过将@QueryParam等参数注解打在此JavaBean的属性或setter方法上来声明参数,从而简化业务接口的参数表。可以参考JAX-RS的官方说明:https://docs.oracle.com/javaee/7/api/javax/ws/rs/BeanParam.html
+
+ServiceComb现在也支持类似的用法,该用法的要求如下:
+1. 聚合参数所用的类型必须是标准的JavaBean,即类型的属性与getter、setter方法名称匹配,setter方法的返回类型为`void`
+2. 参数注解可以打在JavaBean的属性或setter方法上
+3. 允许通过@FormParam将多个上传文件参数聚合到JavaBean中
+4. 作为BeanParam的JavaBean内部如果有多余的属性,需要打上`@JsonIgnore`忽略掉
+5. body参数无法聚合进BeanParam
+6. Consumer端不支持将参数聚合为JavaBean发送,即仍然需要按照接口契约单独填写各个参数
+
+### 代码示例
+
+#### Provider端开发服务
+
+- Provider端业务接口代码:
+```java
+  @RestSchema(schemaId = "helloService")
+  @Path("/hello")
+  public class HelloService {
+    @Path("/sayHello/{name}")
+    @GET
+    public String sayHello(@BeanParam Person person) {
+      System.out.println("sayHello is called, person = [" + person + "]");
+      return "Hello, your name is " + person.getName() + ", and age is " + 
person.getAge();
+    }
+  }
+```
+- BeanParam参数定义:
+```java
+  public class Person {
+    private String name;
+    @QueryParam("age")
+    private int age;
+    @PathParam("name")
+    public void setName(String name) {
+      this.name = name;
+    }
+    @JsonIgnore // 忽略复杂属性
+    private List<Person> children;
+
+    // 其他方法忽略
+  }
+```
+- 接口契约:
+```yaml
+# 忽略契约的其他部分
+basePath: "/hello"
+paths:
+  /sayHello/{name}:
+    get:
+      operationId: "sayHello"
+      parameters:
+      - name: "name"
+        in: "path"
+        required: true
+        type: "string"
+      - name: "age"
+        in: "query"
+        required: false
+        type: "integer"
+        format: "int32"
+      responses:
+        200:
+          description: "response of 200"
+          schema:
+            type: "string"
+```
+
+#### Consumer端调用服务
+
+- consumer端RPC开发模式:
+  - Provider接口定义
+  ```java
+    public interface HelloServiceIntf {
+      String sayHello(String name, int age);
+    }
+  ```
+  - 调用代码
+  ```java
+    String result = helloService.sayHello("Bob", 22); // result的值为"Hello, your 
name is Bob, and age is 22"
+  ```
+- consumer端RestTemplate开发模式:
+  ```java
+    String result = restTemplate.getForObject(
+      "cse://provider-service/hello/sayHello/Bob?age=22",
+      String.class); // 调用效果与RPC方式相同
+  ```
diff --git a/java-chassis-reference/zh_CN/build-provider/springmvc.md 
b/java-chassis-reference/zh_CN/build-provider/springmvc.md
index 1bc428d..9f24be5 100644
--- a/java-chassis-reference/zh_CN/build-provider/springmvc.md
+++ b/java-chassis-reference/zh_CN/build-provider/springmvc.md
@@ -86,5 +86,97 @@ Spring MVC开发模式当前支持org.springframework.web.bind.annotation包下
 | RequestHeader | parameter | 从header中获取参数 |
 | RequestBody | parameter | 从body中获取参数,每个operation只能有一个body参数 |
 
+## Query参数聚合为POJO对象
 
+### 使用说明
 
+SpringBoot支持将Java业务接口中的多个query参数聚合为一个POJO类,SpringBoot原生用法示例如下:
+```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();
+  }
+}
+```
+其中,作为参数的`Person`类是一个标准的JavaBean,包含属性`name`和`age`。当服务接收到的请求时,SpringBoot会将query参数`name`和`age`聚合为Person对象传入业务接口。
+
+ServiceComb的SpringMVC开发模式现在也支持类似的用法,该用法的要求如下:
+1. POJO参数上不能有Spring的参数注解,否则ServiceComb不会将其作为聚合的query参数对象处理。
+2. 仅支持聚合query参数
+3. POJO参数类中的属性名与query参数名需要保持一致
+4. 
POJO参数中不支持复杂的属性,如其他POJO对象、List等。用户可以在这些复杂类型打上`@JsonIgnore`注解来让ServiceComb忽略这些复杂属性。
+5. 
consumer端不支持query参数聚合为POJO对象,调用服务时依然要按照契约发送请求。即provider端被聚合的POJO参数在契约中会被展开成一系列的query参数,consumer端需要在provider接口方法中依次定义这些query参数(RPC开发模式),或在发送请求时填入这些query参数(RestTemplate开发模式)。
+
+### 代码示例
+
+#### Provider端开发服务
+
+- Provider端业务接口代码:
+```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();
+    }
+  }
+```
+- POJO参数对象定义:
+```java
+  public class Person {
+    private String name;
+    private int age;
+    @JsonIgnore  // 复杂属性需要标记@JsonIgnore,否则启动时会报错
+    private List<Person> children;
+  }
+```
+- 接口契约:
+```yaml
+# 忽略契约的其他部分
+basePath: "/hello"
+paths:
+  /sayHello:
+    get:
+      operationId: "sayHello"
+      parameters:
+        # Person类的name属性和age属性作为契约中的query参数
+      - 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端调用服务
+
+- consumer端RPC开发模式:
+  - Provider接口定义
+  ```java
+    public interface HelloServiceIntf {
+      String sayHello(String name, int age);
+    }
+  ```
+  - 调用代码
+  ```java
+    String result = helloService.sayHello("Bob", 22); // result的值为"Hello, your 
name is Bob, and age is 22"
+  ```
+- consumer端RestTemplate开发模式:
+  ```java
+    String result = restTemplate.getForObject(
+      "cse://provider-service/hello/sayHello?name=Bob&age=22",
+      String.class); // 调用效果与RPC方式相同
+  ```


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to