@ApiOperation
标签给重载的接口指定唯一 的 operation id (对应于 nickname 属性)。示例代码如下:@Path("/sayHi") @GET @Produces("text/plain;charset=UTF-8") @ApiOperation(value = "", nickname = "sayHi") public String sayHello() { return "ApiOperationJaxrsSchema#sayHello"; } @Path("/sayHello") @GET @Produces("application/json;charset=UTF-8") @ApiOperation(value = "", nickname = "sayHello") public String sayHello(@ApiParam("name") String name) { return name; }
Interface
或者 Abstract Class
。因为这些类型 无法正确的生成 swagger 描述。如果必须使用这些类型,可以考虑接口定义使用 Object 规避,客户端可以对返回值结果 自行进行 json 转换。@PostMapping(path = "holderUser") public Holder<User> holderUser(@RequestBody Holder<User> input) { Assert.isInstanceOf(Holder.class, input); Assert.isInstanceOf(User.class, input.value); return input; } @GetMapping(path = "/genericParams") @ApiOperation(value = "genericParams", nickname = "genericParams") public List<List<String>> genericParams(@RequestParam("code") int code, @RequestBody List<List<String>> names) { return names; }
未指定泛型类型是不允许的。比如:
@GetMapping(path = "/genericParams") @ApiOperation(value = "genericParams", nickname = "genericParams") public List genericParams(@RequestParam("code") int code, @RequestBody List names) { return names; }
如果业务必须使用泛型,并且不能确定类型,可以考虑接口定义使用 Object 规避,客户端可以对返回值结果 自行进行 json 转换。
@ApiOperation(value = "", hidden = true) public void hidden() { }
在迁移改造的过程中,比如将 HSF 和 Dubbo 的内部 RPC 接口改造为 java-chassis 的 RPC 接口,可能还有更加复杂 的情况,比如:
@HSFProvider(MyInterface.class) public MyService extends AbstractMyService implements MyInterface
如果直接改造为
@RpcSchema(schemaId = "MyService") public MyService extends AbstractMyService implements MyInterface
那么 AbstractMyService
的公共方法也会发布为 RPC 接口, 而 HSF 和 dubbo 则不会。 这种情况建议增加 一个类,而将原来的接口声明为服务类来处理, 比如:
@Service("MyService") public MyService extends AbstractMyService implements MyInterface @RpcSchema(schemaId = "MyServiceImpl") public MyServiceImpl implements MyInterface { @Autowired @Qualifier("MyService") MyInterface service; public String hello(String name) { return service.hello(name); } }
@ApiResponse(code = 201, response = Integer.class, message = "") public int test(int x) { return 100; }
对于其他返回值,可以通过抛出自定义的 InvocationException 实现,例如:
@Path("/errorCode") @POST @ApiResponses({ @ApiResponse(code = 200, response = MultiResponse200.class, message = ""), @ApiResponse(code = 400, response = MultiResponse400.class, message = ""), @ApiResponse(code = 500, response = MultiResponse500.class, message = "")}) public MultiResponse200 errorCode(MultiRequest request) { if (request.getCode() == 400) { MultiResponse400 r = new MultiResponse400(); r.setCode(400); r.setMessage("bad request"); throw new InvocationException(javax.ws.rs.core.Response.Status.BAD_REQUEST, r); } else if (request.getCode() == 500) { MultiResponse500 r = new MultiResponse500(); r.setCode(500); r.setMessage("internal error"); throw new InvocationException(javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR, r); } else { MultiResponse200 r = new MultiResponse200(); r.setCode(200); r.setMessage("success result"); return r; } }
Q: 如何定制自己微服务的日志配置?
config/log4j.properties和config/log4j.*.properties
, 从搜索出的文件中切出\*
的部分,进行alpha排序,然后按顺序加载,最后合成的文件作为log4j的配置文件。Q: 当服务配置了多个transport的时候,在运行时是怎么选择使用哪个transport的?
A: ServiceComb的consumer、transport、handler、producer之间是解耦的,各功能之间通过契约定义联合在一起工作的,即: consumer使用透明rpc,还是springmvc开发与使用highway,还是RESTful在网络上传输没有关系与producer是使用透明rpc,还是jaxrs, 或者是springmvc开发,也没有关系handler也不感知,业务开发方式以及传输方式。consumer访问producer,在运行时的transport选择上, 总规则为:cnsumer的transport与producer的endpoint取交集,如果交集后,还有多个transport可选择,则轮流使用,分解开来,存在以下场景:
当一个微服务producer同时开放了highway以及RESTful的endpoint
如果consumer想固定使用某个transport访问producer,可以在consumer进程的microservice.yaml中配置,指定transport的名称:
servicecomb: references: <service_name>: transport: highway
当一个微服务producer只开放了highway的endpoint
当一个微服务producer只开放了RESTful的endpoint
Q: ServiceComb微服务框架服务调用是否使用长连接?
Q: 服务断连服务中心注册信息是否自动删除
Q: 如果使用tomcat方式集成ServiceComb微服务框架,如何实现服务注册
Q: 如果使用tomcat方式集成ServiceComb微服务框架,服务注册的时候如何将war包部署的上下文注册到服务中心
A: 发布服务接口的时候需要将war包部署的上下文(context)放在baseurl最前面,这样才能保证注册到服务中心的路径是完整的路径(包含了上下文)。示例:
@path(/{context}/xxx) class ServiceA
Q: ServiceComb微服务框架如何实现数据多个微服务间透传
A: 透传数据塞入:
CseHttpEntity<xxxx.class> httpEntity = new CseHttpEntity<>(xxx); //透传内容 httpEntity.addContext("contextKey","contextValue"); ResponseEntity<String> responseEntity = RestTemplateBuilder.create() .exchange("cse://springmvc/springmvchello/sayhello",HttpMethod.POST,httpEntity,String.class);
透传数据获取:
@Override @RequestMapping(path="/sayhello",method = RequestMethod.POST) public String sayHello(@RequestBody Person person,InvocationContext context){ //透传数据获取 context.getContext(); return "Hello person " + person.getName(); }
Q: ServiceComb body Model部分暴露
A: 一个接口对应的body对象中,可能有一些属性是内部的,不想开放出去,生成schema的时候不要带出去,使用:
@ApiModelProperty(hidden = true)
Q: 服务超时设置
A: 在微服务描述文件(microservice.yaml)中添加如下配置:
servicecomb: request: timeout: 30000
Q: URL 地址就可以唯一定位,为什么要加上一个schema?
Q: rest客户端调用的时候,实际上只带上了服务名和URL,并不需要指定schema id的, 而实际上根据这个URL也能找到具体契约的,所以指定schema id作用何在?
Q: Transport是个什么概念?用来干什么的?
Q: ServiceComb和服务中心是怎么交互的?
Q: 有类似dubbo那种治理中心吗?
Q: service path怎么理解?
Q: 浏览器能直接访问微服务Endpoint吗?
Q: 契约生成时,需要强制带上版本号和语言吗?
Q: 如果同时引入了transport-rest-servlet
和transport-rest-vertx
的依赖,那么它怎么决定采用哪一个?
Q: qps流控设计时是出于什么场景考虑的?
Q: 如果服务端是链式调用,即类似a->b->c,那设置了qps 流控会不会造成水管粗细不均的事情?
Q: 如何在契约DTO中忽略中指定的属性?
A: 可以使用@JsonIgnore注解标记需要忽略的属性, 例如:
public class OutputForTest{ @JsonIgnore private String outputId = null; private String inputId = null; ... }