ServiceComb支持开发者使用JAX-RS注解,使用JAX-RS模式开发服务。
根据开发之前定义好的契约,编写Java业务接口,代码如下。定义接口不是必须的,但是 一个好习惯,可以简化客户端使用RPC方式编写代码。
public interface Hello { String sayHi(String name); String sayHello(Person person); }
使用JAX-RS注解开发业务代码,Hello的服务实现如下:
@RestSchema(schemaId = "jaxrsHello") @Path("/jaxrshello") @Produces(MediaType.APPLICATION_JSON) public class JaxrsHelloImpl implements Hello { @Path("/sayhi") @POST @Override public String sayHi(String name) { return "Hello " + name; } @Path("/sayhello") @POST @Override public String sayHello(Person person) { return "Hello person " + person.getName(); } /** * 这个方法是实现类特有的,因此对它的远程调用会有所不同. * 具体可以参考 jaxrs-consumer */ @Path("/saybye") @GET public String sayBye() { return "Bye !"; } }
在resources/META-INF/spring目录下创建jaxrsHello.bean.xml文件,配置spring进行服务扫描的base-package,文件内容如下。(注意修改package名称为正确名称)
<?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:p=" http://www.springframework.org/schema/p " xmlns:util=" http://www.springframework.org/schema/util " xmlns:cse=" http://www.huawei.com/schema/paas/cse/rpc " 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 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.jaxrs.provider"/> </beans>
public class JaxrsProviderMain{ public static void main(String[] args) throws Exception { Log4jUtils.init(); BeanUtils.init(); } }
JAX-RS开发模式当前支持如下注解,所有注解的使用方法参考JAX-RS官方文档。
注解 | 位置 | 描述 |
---|---|---|
javax.ws.rs.Path | schema/operation | URL路径 |
javax.ws.rs.Produces | schema/operation | 方法支持的编解码能力 |
javax.ws.rs.DELETE | operation | http method |
javax.ws.rs.GET | operation | http method |
javax.ws.rs.POST | operation | http method |
javax.ws.rs.PUT | operation | http method |
javax.ws.rs.QueryParam | parameter | 从query string中获取参数 |
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
、InvocationContext
类型参数时,默认为body类型参数,一个方法最多只支持一个body类型参数。
用户可以使用@BeanParam注解将多个参数聚合到一个JavaBean中,通过将@QueryParam等参数注解打在此JavaBean的属性或setter方法上来声明参数,从而简化业务接口的参数表。可以参考JAX-RS的官方说明:https://docs.oracle.com/javaee/7/api/javax/ws/rs/BeanParam.html
ServiceComb现在也支持类似的用法,该用法的要求如下:
void
@JsonIgnore
忽略掉@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(); } }
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; // 其他方法忽略 }
# 忽略契约的其他部分 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端RPC开发模式:
public interface HelloServiceIntf { String sayHello(String name, int age); }
String result = helloService.sayHello("Bob", 22); // result的值为"Hello, your name is Bob, and age is 22"
String result = restTemplate.getForObject( "cse://provider-service/hello/sayHello/Bob?age=22", String.class); // 调用效果与RPC方式相同