RESTful风格探讨

72 阅读5分钟

认识RESTful

我最开始接触到RESTful风格是工作早几年在工作当中看到行业内交流出现了RESTful风格API的新闻,当时懵懵懂懂的知道了大概,实际没怎么运用上,然后大部分人后续主要用于面试当中的回答面试官问题。

RESTful的由来

为什么RESTful叫RESTFul,而不是 restful 或者是 Restful REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的,Roy Thomas Fielding是一个很重要的人,他是HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。 所以,他的这篇论文一发表,就引起了很多人的关注,并且立即对互联网开发产生了深远的影响。 Roy Thomas Fielding将他对互联网软件的架构原则,定名为REST,也就是REpresentational State Transfer(3个单词的首字母)的缩写,一般翻译为"表现层状态转化"或者是”表述性状态转移"。

如果我们想理解RESTful架构风格,则需要先理解RESTful这个单词的组成。

  • 资源(Resources):REST的名称是"表现层状态转化",其实是资源(Resources)的"表现层状态转化"。这里所谓的"资源",其实就是网络上存储的一个具体信息或数据,它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的数据。我们可以用一个URI(统一资源标识符)指向这些资源,每种资源都对应一个特定的URI。要获取这个资源,通过访问它对应的URI就可以了,因此该URI就代表了每一个资源的地址或独一无二的识别符号。
  • 表述性(REpresentational):"资源"是一种信息实体,它可以有多种外在的表现形式,我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。REST 资源实际上可以用各种形式来进行表现,比如文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现,我们可以使用最适合资源的任意形式。
  • 状态(State):当使用 REST 的时候,我们更关注资源的状态而不是对资源采取的行为。
  • 转义(Transfer): REST 涉及到转移资源数据,它以某种表述性形式从一个应用转移到另一个应用。

如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer),而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。

RESTful的历史

Restful早在2000-2002年出现,现在已经过去20多年,早已不是什么新鲜东西,但是仍然是许多公司面试官拿出来提问的话题,所以它的影响还是挺深远的,包括我自己,也会偶尔提问是否知道RESTful API风格。

在工作中,我们早已经习惯性的编写controller里面的接口,要么是GET,要么就是POST,很少用到PUT,DELETE,或者是少见的PATCH方式请求。 并且在流水线的编程中,大家的接口命名都是有点怎么方便怎么来命令,或者是先沿着已有的接口名称来命名,于是在每个人参与每个不同的项目中都会多少掺杂点个人理解或者是个人认知的命名在里面,长久一来,项目接口的命名就会堆积,然后不太利于维护和阅读。

所以我觉得应该有一套大家约定的规则来做这个事情,不要求完美,但尽可能的向这个约定的方向靠齐。 这里可能又会引申出,写代码本身是一种创造性的东西,在各种框框条条的限制下,这个人感觉就是流水线的一个单位,但是又不可避免规则来约束。包括生活等等方面......

案例对比

@RestController
@RequestMapping("/api/quartz")
public class QuartzController {

    @Autowired
    private QuartzService quartzService;



    @RequestMapping(value = "", method = RequestMethod.GET)
    public Result<List<T>> getScheduleList() throws Exception {
        return Result.success();
    }


    @RequestMapping(value = "/pause", method = RequestMethod.PUT)
    public Result<String> pauseScheduleJob(@RequestBody QuartzReqDto quartzReqDto) throws Exception {
        return Result.success();
    }
    
    @RequestMapping(value = "/resume", method = RequestMethod.PUT)
    public Result<String> resumeJob(@RequestBody QuartzReqDto quartzReqDto) throws Exception {
    	return Result.success();
    }

    @RequestMapping(value = "", method = RequestMethod.DELETE)
    public Result<Boolean> deleteScheduleJob(@RequestBody QuartzReqDto quartzReqDto) throws Exception {
    	return Result.info();
    }


    @RequestMapping(value = "/exists", method = RequestMethod.GET)
    public Result<String> checkExistsScheduleJob(String jobName, String jobGroup) throws Exception {
    	return Result.info();
    }
    

    @RequestMapping(value = "", method = RequestMethod.PUT)
    public Result<String> updateScheduleCronJob(@RequestBody QuartzReqDto quartzReqDto) throws Exception {
        return Result.info();
    }


    @RequestMapping(value = "", method = RequestMethod.POST)
    public Result<String> createScheduleCronJob(@RequestBody QuartzReqDto quartzReqDto) throws Exception {
        return Result.info("create success");
    }


    @RequestMapping(value = "detail", method = RequestMethod.GET)
    public Result<T> getQuartzInfoDetail (String jobName, String jobGroup) throws Exception {
        return Result.success();
    }


}

总结

接口路径:

/api/quartz GET
/api/quartz POST
/api/quartz/pause PUT
/api/quartz/resume PUT
/api/quartz/exists GET
/api/quartz PUT

以前的接口写法可能是这样的:

/addNew?name=xxx
/queryList?q1=&q2=
/queryPage?pageIndex=&pageSize=
/saveCar

这样一看,确实RESTful风格的接口比较清爽,简洁; 有些习惯性的写法就直接写 /addQuartz, /updateInfo, /checkJob, /saveNew 等等,虽然这样命名没错,但是我觉得整体不太好,但是实际工作中,确实是不少这样的现象,总的来说,虽然大家都是边做边学,但是偶尔尝试新的方式应该是挺不错的,我觉得现在就是挺缺少创新的,新鲜的东西,敢于冒险我觉得挺重要(我自己的一点废话......)

CRUD动作HTTP方法
CreatePOST
ReadGET
UpdatePUT或者PATCH
DeleteDELETE

部分资料来源于网络各路大牛,在此表示感谢。