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文档。示例如下

package charles.sc.provider.service;

import charles.sc.provider.entity.ChatMessage;
import com.jztey.framework.mvc.Paging;
import com.jztey.framework.mvc.RestfulPagingResult;
import com.jztey.framework.mvc.RestfulResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.cloud.netflix.feign.FeignClient;

import javax.validation.Valid;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

/**
 * Created by Charles on 2016/8/15.
 */
@FeignClient(value = "provider-service")
@Path("/chatMessage")
@Produces(MediaType.APPLICATION_JSON)
@Api(tags = {"聊天消息接口"})
public interface ChatMessageService {
    @Path("/pb")
    @GET
    @ApiOperation(value = "聊天记录列表", response = RestfulPagingResultChatMessage.class)
    RestfulPagingResult<ChatMessage> findPage(@QueryParam("id") int page, @QueryParam("pageSize") int pageSize, @QueryParam("total") int total);

    @Path("/pt/{id:\\d+}")
    @GET
    @ApiOperation(value = "按id查询聊天记录", response = RestfulResultChatMessage.class)
    RestfulResult<ChatMessage> find(@PathParam("id") Long id);

    @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") Long uid, @ApiParam @Valid ChatMessage chatMessage);

    @Path("/pt/{id:\\d+}")
    @DELETE
    @ApiOperation(value = "按id删除聊天记录", response = RestfulResultChatMessage.class)
    RestfulResult<ChatMessage> delete(@HeaderParam("uid") Long uid, @PathParam("id") Long id);

    @Path("/pt/{id:\\d+}")
    @PUT
    @ApiOperation(value = "修改聊天记录", response = RestfulResultChatMessage.class)
    RestfulResult<ChatMessage> update(@HeaderParam("uid") Long uid, @PathParam("id") Long id, @ApiParam @Valid ChatMessage chatMessage);

    class RestfulResultChatMessage extends RestfulResult<ChatMessage> {
    }

    class RestfulPagingResultChatMessage extends RestfulPagingResult<ChatMessage> {
    }
}

 

package charles.sc.provider.service;

import charles.sc.provider.entity.ChatMessage;
import com.jztey.framework.mvc.Paging;
import com.jztey.framework.mvc.RestfulPagingResult;
import com.jztey.framework.mvc.RestfulResult;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Charles on 2016/8/16.
 */
@com.alibaba.dubbo.config.annotation.Service
@Service
public class ChatMessageServiceImpl extends BaseService<ChatMessage> implements ChatMessageService {

    @Override
    public RestfulPagingResult<ChatMessage> findPage(int page, int pageSize, int total) {
        System.out.println("get");
        // 统一使用查询接口
        Paging<ChatMessage> paging = new Paging<>(page, pageSize);
        paging.setTotal(total);

        return this.search(paging);
    }

    @Override
    public RestfulResult<ChatMessage> find(Long id) {
        System.out.println("getById");
        return new RestfulResult(new ChatMessage(id, "fu", "tu", "msg", "mi", System.currentTimeMillis(), System.currentTimeMillis(), ChatMessage.STATUS_NO_PROCESS));
    }

    @Override
    public RestfulPagingResult<ChatMessage> search(Paging<ChatMessage> paging) {
        System.out.println("search");
        List<ChatMessage> entityList = new ArrayList<>();

        entityList.add(new ChatMessage(1L, "fu", "tu", "msg", "mi", System.currentTimeMillis(), System.currentTimeMillis(), ChatMessage.STATUS_NO_PROCESS));
        entityList.add(new ChatMessage(2L, "fu2", "tu2", "msg2", "mi2", System.currentTimeMillis(), System.currentTimeMillis(), ChatMessage.STATUS_NO_PROCESS));

        if (-1 == paging.getTotal()) {    // total没有传上来
            // 查询total
            paging.setTotal(100);
        }
        return new RestfulPagingResult(entityList, paging.getTotal());
    }

    @Override
    public RestfulResult<ChatMessage> insert(Long uid, ChatMessage chatMessage) {
        System.out.println("insert uid:" + uid);
        return new RestfulResult<>(chatMessage);
    }

    @Override
    public RestfulResult<ChatMessage> delete(Long uid, Long id) {
        System.out.println("delete uid:" + uid);
        return new RestfulResult(new ChatMessage(id, "fu", "tu", "msg", "mi", System.currentTimeMillis(), System.currentTimeMillis(), ChatMessage.STATUS_NO_PROCESS));
    }

    @Override
    public RestfulResult<ChatMessage> update(Long uid, Long id, ChatMessage chatMessage) {
        System.out.println("update uid:" + uid);
        return new RestfulResult<>(chatMessage);
    }
}

完整代码参考:http://gitlab.998jk.com/heying/spring-cloud





      本文转自yushiwh 51CTO博客,原文链接:http://blog.51cto.com/yushiwh/1942254,如需转载请自行联系原作者



相关文章
|
11天前
|
缓存 监控 API
构建高效可扩展的RESTful API:后端开发的实践指南
【4月更文挑战第26天】在现代Web开发中,构建一个高效、可扩展且易于维护的RESTful API是后端工程师必须面对的挑战。本文将深入探讨如何利用最佳实践和流行技术,设计出符合REST架构原则的服务端接口。我们将重点讨论API版本控制、资源路由、数据库优化、缓存策略以及安全性考虑等方面,旨在为开发者提供一套综合性解决方案,帮助其提升API的性能与可靠性。
|
7天前
|
JSON API 数据处理
【Swift开发专栏】Swift中的RESTful API集成实战
【4月更文挑战第30天】本文探讨了在Swift中集成RESTful API的方法,涉及RESTful API的基础概念,如HTTP方法和设计原则,以及Swift的网络请求技术,如`URLSession`、`Alamofire`和`SwiftyJSON`。此外,还强调了数据处理、错误管理和异步操作的重要性。通过合理利用这些工具和策略,开发者能实现高效、稳定的API集成,提升应用性能和用户体验。
|
7天前
|
缓存 监控 JavaScript
Node.js中构建RESTful API的最佳实践
【4月更文挑战第30天】本文介绍了在Node.js中构建RESTful API的最佳实践:选择合适的框架(如Express、Koa)、设计清晰的API接口(遵循HTTP动词和资源路径)、实现认证授权(JWT、OAuth 2.0)、错误处理、限流缓存、编写文档和测试,以及监控性能优化。这些实践有助于创建健壮、可维护和易用的API。
|
7天前
|
存储 关系型数据库 Go
【Go语言专栏】基于Go语言的RESTful API开发
【4月更文挑战第30天】本文介绍了使用Go语言开发RESTful API的方法,涵盖了路由、请求处理、数据存储和测试关键点。RESTful API基于HTTP协议,无状态且使用标准方法表示操作。在Go中,通过第三方库如`gorilla/mux`进行路由映射,使用`net/http`处理请求,与数据库交互可选ORM库`gorm`,测试则依赖于Go内置的`testing`框架。Go的简洁性和并发性使得它成为构建高效API的理想选择。
|
7天前
|
机器学习/深度学习 算法 安全
深度学习在图像识别中的应用与挑战构建高效可扩展的RESTful API:后端开发的实战指南
【4月更文挑战第30天】 随着计算机视觉技术的飞速发展,深度学习在图像识别领域取得了显著的成果。本文将探讨深度学习技术在图像识别中的应用及其所面临的挑战。首先,我们将介绍深度学习的基本原理和关键技术,然后分析其在图像识别中的优势和应用案例。最后,我们将讨论当前深度学习在图像识别领域所面临的主要挑战和未来的发展趋势。
|
8天前
|
XML JSON API
【PHP开发专栏】PHP RESTful API设计与开发
【4月更文挑战第29天】本文探讨了在Web开发中流行的前后端分离模式,重点介绍了RESTful API的设计与实现。REST是一种基于HTTP协议的架构风格,核心概念包括资源、表述和状态转换。RESTful API设计遵循无状态、统一接口等原则,使用GET、POST、PUT、DELETE等HTTP方法执行操作,并通过状态码和JSON/XML传输数据。在PHP中实现RESTful API,可通过定义路由、创建控制器、处理请求和响应,同时注意安全性措施,如使用HTTPS。文中还提供了一个用户管理API的实战示例,以帮助读者更好地理解和应用RESTful API。
|
8天前
|
缓存 监控 API
|
12天前
|
缓存 安全 API
构建高效可扩展的RESTful API:后端架构的艺术
【4月更文挑战第25天】 在数字化时代的浪潮中,一个稳定、高效且易于扩展的后端系统是企业成功的关键。本文将探讨如何构建一个满足现代业务需求的RESTful API。我们将深入分析关键设计原则,如模块化、服务分层、缓存策略以及数据库优化,并讨论这些原则如何融入实际开发流程中。通过具体案例和最佳实践,我们的目标是为读者提供一套实用的工具和方法,以支持他们自己的后端开发工作。
|
15天前
|
缓存 JSON 负载均衡
构建高效RESTful API的最佳实践
【4月更文挑战第22天】在当今互联网应用的开发中,后端系统的核心通常体现在API的设计和实现上。一个设计良好、性能优异的RESTful API能够极大地提升应用的响应速度及用户体验。本文将探讨在构建高效RESTful API时应当遵循的一系列最佳实践,包括合理的数据结构设计、缓存策略、负载均衡技术以及API版本管理等。通过这些实践,可以确保API服务的高性能与易维护性,并适应不断变化的业务需求。
|
19天前
|
JSON API 数据库
解释如何在 Python 中实现 Web 服务(RESTful API)。
在Python中实现Web服务(RESTful API)涉及选择框架(如Flask、Django、FastAPI),定义路由及处理函数(对应HTTP请求方法),处理请求,构建响应和启动服务器。以下是一个使用Flask的简单示例:定义用户列表,通过`@app.route`装饰器设置GET和POST请求处理函数,返回JSON响应,并用`app.run()`启动服务器。实际API会包含更复杂的逻辑和错误处理。
16 1