restful-api最佳实践
Best-practices-for-a-pragmatic-restful-api 先阅读文档:http://www.oschina.net/translate/best-practices-for-a-pragmatic-restful-api 理解restful api设计理念 我们公司的所有微服务接口都放在 "api.998jk.com/微服务名"下 微服务内部api设计规范为:业务域/访问级别, 与best-practices-for-a-pragmatic-restful-api的区别是加入了一级访问级别,例如: 简单列表接口 /chatMessage/pb GET方式,提交参数page,pageSize,total 复杂查询接口 /chatMessage/pb/search POST方式,提交参数为json RequestBody,根据各个接口不同自行定义 查询单条接口 /chatMessage/pb/123 GET方式,123为id 删除单条接口 /chatMessage/pt/123 DELETE方式,123为id 更新单条接口 /chatMessage/pt/123 PUT方式,提交参数为json RequestBody,根据各个接口不同自行定义 上述示例 完整路径为:api.998jk.com/微服务名/chatMessage/xxx 访问级别: pb(public) 公开,对外对内没有任何限制; pt(protected)受保护,对外受保护,对内没有任何限制。需要header中含有authorization 值为"Bearer token令牌"。在api gateway会获取该token, 并且在header中设置uid 值为该令牌的用户id。 df(default) 默认,对外加密,对内没有任何限制。继承protected限制。并且在api gateway会对返回结果加密,客户端需要对结果解密后使用。加密后json如下: {"encrypted":"返回结果加密后的字符串"} pv(private) 私有的,对外无法访问,对内没有任何限制。继承default限制。 暴露的restful服务需采用JAX-RS标准注解,无需springMVC controller 直接暴露service,需要使用swagger注解以便自动产生restful api文档。示例如下 packagecharles.sc.provider.service; importcharles.sc.provider.entity.ChatMessage; importcom.jztey.framework.mvc.Paging; importcom.jztey.framework.mvc.RestfulPagingResult; importcom.jztey.framework.mvc.RestfulResult; importio.swagger.annotations.Api; importio.swagger.annotations.ApiOperation; importio.swagger.annotations.ApiParam; importorg.springframework.cloud.netflix.feign.FeignClient; importjavax.validation.Valid; importjavax.ws.rs.*; importjavax.ws.rs.core.MediaType; /** *CreatedbyCharleson2016/8/15. */ @FeignClient(value="provider-service") @Path("/chatMessage") @Produces(MediaType.APPLICATION_JSON) @Api(tags={"聊天消息接口"}) publicinterfaceChatMessageService{ @Path("/pb") @GET @ApiOperation(value="聊天记录列表",response=RestfulPagingResultChatMessage.class) RestfulPagingResult<ChatMessage>findPage(@QueryParam("id")intpage,@QueryParam("pageSize")intpageSize,@QueryParam("total")inttotal); @Path("/pt/{id:\\d+}") @GET @ApiOperation(value="按id查询聊天记录",response=RestfulResultChatMessage.class) RestfulResult<ChatMessage>find(@PathParam("id")Longid); @Path("/pb/search") @POST @ApiOperation(value="搜索聊天记录",response=RestfulPagingResultChatMessage.class) RestfulPagingResult<ChatMessage>search(Paging<ChatMessage>paging); @Path("/pt") @POST @ApiOperation(value="添加聊天记录",response=RestfulResultChatMessage.class) RestfulResult<ChatMessage>insert(@HeaderParam("uid")Longuid,@ApiParam@ValidChatMessagechatMessage); @Path("/pt/{id:\\d+}") @DELETE @ApiOperation(value="按id删除聊天记录",response=RestfulResultChatMessage.class) RestfulResult<ChatMessage>delete(@HeaderParam("uid")Longuid,@PathParam("id")Longid); @Path("/pt/{id:\\d+}") @PUT @ApiOperation(value="修改聊天记录",response=RestfulResultChatMessage.class) RestfulResult<ChatMessage>update(@HeaderParam("uid")Longuid,@PathParam("id")Longid,@ApiParam@ValidChatMessagechatMessage); classRestfulResultChatMessageextendsRestfulResult<ChatMessage>{ } classRestfulPagingResultChatMessageextendsRestfulPagingResult<ChatMessage>{ } } packagecharles.sc.provider.service; importcharles.sc.provider.entity.ChatMessage; importcom.jztey.framework.mvc.Paging; importcom.jztey.framework.mvc.RestfulPagingResult; importcom.jztey.framework.mvc.RestfulResult; importorg.springframework.stereotype.Service; importjava.util.ArrayList; importjava.util.List; /** *CreatedbyCharleson2016/8/16. */ @com.alibaba.dubbo.config.annotation.Service @Service publicclassChatMessageServiceImplextendsBaseService<ChatMessage>implementsChatMessageService{ @Override publicRestfulPagingResult<ChatMessage>findPage(intpage,intpageSize,inttotal){ System.out.println("get"); //统一使用查询接口 Paging<ChatMessage>paging=newPaging<>(page,pageSize); paging.setTotal(total); returnthis.search(paging); } @Override publicRestfulResult<ChatMessage>find(Longid){ System.out.println("getById"); returnnewRestfulResult(newChatMessage(id,"fu","tu","msg","mi",System.currentTimeMillis(),System.currentTimeMillis(),ChatMessage.STATUS_NO_PROCESS)); } @Override publicRestfulPagingResult<ChatMessage>search(Paging<ChatMessage>paging){ System.out.println("search"); List<ChatMessage>entityList=newArrayList<>(); entityList.add(newChatMessage(1L,"fu","tu","msg","mi",System.currentTimeMillis(),System.currentTimeMillis(),ChatMessage.STATUS_NO_PROCESS)); entityList.add(newChatMessage(2L,"fu2","tu2","msg2","mi2",System.currentTimeMillis(),System.currentTimeMillis(),ChatMessage.STATUS_NO_PROCESS)); if(-1==paging.getTotal()){//total没有传上来 //查询total paging.setTotal(100); } returnnewRestfulPagingResult(entityList,paging.getTotal()); } @Override publicRestfulResult<ChatMessage>insert(Longuid,ChatMessagechatMessage){ System.out.println("insertuid:"+uid); returnnewRestfulResult<>(chatMessage); } @Override publicRestfulResult<ChatMessage>delete(Longuid,Longid){ System.out.println("deleteuid:"+uid); returnnewRestfulResult(newChatMessage(id,"fu","tu","msg","mi",System.currentTimeMillis(),System.currentTimeMillis(),ChatMessage.STATUS_NO_PROCESS)); } @Override publicRestfulResult<ChatMessage>update(Longuid,Longid,ChatMessagechatMessage){ System.out.println("updateuid:"+uid); returnnewRestfulResult<>(chatMessage); } } 完整代码参考:http://gitlab.998jk.com/heying/spring-cloud 本文转自yushiwh 51CTO博客,原文链接:http://blog.51cto.com/yushiwh/1942254,如需转载请自行联系原作者