springmvc/springboot开发restful API
非rest的url写法:
查询 GET /user/query?name=tom
详情 GET /user/getinfo?id=
创建 POST /user/create?name=tom
修改 POST /user/update?id=&name=tom
删除 GET /user/delete?id=
rest风格的写法
查询 GET /user?name=tom
详情 GET /user/
创建 POST /user
修改 PUT /user
删除 DELETE /user/
rest接口设计参考:https://github.com/huobiapi/API_Docs/wiki/REST_api_reference
https://github.com/huobiapi/API_Docs
coinflext api: https://github.com/coinflex-exchange/API
1、Rest概念,来自百度百科
REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。
目前在三种主流的Web服务实现方案中,因为REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。
2、RESTful API的要求
1)用URL描述资源;
2)使用HTTP方法描述行为;使用HTTP状态码来表示不同的结果;
3)使用json来交互数据;
4)RESTful只是一种风格,并不是强制的标准。
总结:使用URL定位资源,使用HTTP方法操作资源。
GET 用来获取资源;
POST 用来新建资源(也可以用于更新资源);
PUT 用来更新资源;
DELETE 用来删除资源
3、Glory of REST
REST是一种软件接口设计的模型。REST 成熟度模型:(搜索关键字:steps toward the glory of REST)

level0: 使用http作为传输方式;
level1: 引入资源概念,每个资源都有对应的URL;
level2: 使用http方法进行不同的操作,使用http状态码来表示不同的结果。
level3: 使用超媒体,在资源的表达中包含了链接信息。
4、springmvc/springboot开发restful API
IndexController
@RestController
public class IndexController {
@Autowired
private UserService userService; @GetMapping("/user/{id}")
public Object getUserById(@PathVariable Integer id) {
return userService.getUserById(id);
}
}
测试结果:

5、使用MockMVC 编写测试用例(单元测试)
参考:https://www.cnblogs.com/xy-ouyang/p/10681965.html
选中IndexController,右键/new/Junit Test Case


测试用例代码:
package com.imooc.controller; import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext; /**
* @author oy
* @date 2019年6月22日 下午11:14:56
* @version 1.0.0
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class IndexControllerTest { @Autowired
private WebApplicationContext wac; private MockMvc mocMvc; @Before
public void setUp() throws Exception {
mocMvc = MockMvcBuilders.webAppContextSetup(wac).build();
} @Test
public void testGetUserById() throws Exception {
String mvcResult = mocMvc.perform(MockMvcRequestBuilders.get("/user/1")
.contentType(MediaType.APPLICATION_FORM_URLENCODED))
.andDo(MockMvcResultHandlers.print()) // 打印信息
.andExpect(MockMvcResultMatchers.status().isOk()) // 期望返回的状态码为200
.andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(2)) // 期望返回的json数据中有两个字段
.andExpect(MockMvcResultMatchers.jsonPath("$.username").value("张三")) // 期望返回的json数据中username字段的值为"张三"
.andReturn().getResponse().getContentAsString(); System.out.println("mvcResult: " + mvcResult);
}
}
控制台打印结果:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /user/1
Parameters = {}
Headers = {Content-Type=[application/x-www-form-urlencoded]} Handler:
Type = com.imooc.controller.IndexController
Method = public java.lang.Object com.imooc.controller.IndexController.getUserById(java.lang.Integer) Async:
Async started = false
Async result = null Resolved Exception:
Type = null ModelAndView:
View name = null
View = null
Model = null FlashMap:
Attributes = null MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body = {"username":"张三","password":"123"}
Forwarded URL = null
Redirected URL = null
Cookies = []
mvcResult: {"username":"张三","password":"123"}
测试用例的代码简洁写法:使用静态导入

package com.imooc.controller; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext; /**
* @author oy
* @date 2019年6月22日 下午11:14:56
* @version 1.0.0
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class IndexControllerTest { @Autowired
private WebApplicationContext wac; private MockMvc mocMvc; @Before
public void setUp() throws Exception {
mocMvc = MockMvcBuilders.webAppContextSetup(wac).build();
} @Test
public void testGetUserById() throws Exception {
String mvcResult = mocMvc.perform(get("/user/1")
.contentType(MediaType.APPLICATION_FORM_URLENCODED))
.andDo(print()) // 打印信息
.andExpect(status().isOk()) // 期望返回的状态码为200
.andExpect(jsonPath("$.length()").value(2)) // 期望返回的json数据中有两个字段
.andExpect(jsonPath("$.username").value("张三"))
.andReturn().getResponse().getContentAsString(); System.out.println("mvcResult: " + mvcResult);
}
}
6、@PageableDefault指定默认的分页参数

测试代码:
@RunWith(SpringRunner.class)
@SpringBootTest
public class IndexControllerTest { @Autowired
private WebApplicationContext wac; private MockMvc mocMvc; @Before
public void setUp() throws Exception {
mocMvc = MockMvcBuilders.webAppContextSetup(wac).build();
} @Test
public void testGetUserById() throws Exception {
String mvcResult = mocMvc.perform(get("/user/1")
// .param("page", "2")
// .param("size", "10")
// .param("sort", "id,desc")
.contentType(MediaType.APPLICATION_FORM_URLENCODED))
.andDo(print()) // 打印信息
.andExpect(status().isOk()) // 期望返回的状态码为200
.andExpect(jsonPath("$.length()").value(2)) // 期望返回的json数据中有两个字段
.andExpect(jsonPath("$.username").value("张三"))
.andReturn().getResponse().getContentAsString(); System.out.println("mvcResult: " + mvcResult);
}
}
IndexController
@RestController
public class IndexController {
@Autowired
private UserService userService; @GetMapping("/user/{id}")
public Object getUserById(@PathVariable Integer id,
@PageableDefault(page = 1, size = 10, sort = "id,asc") Pageable pageable) { String str = ReflectionToStringBuilder.toString(pageable, ToStringStyle.MULTI_LINE_STYLE);
System.out.println(str); return userService.getUserById(id);
}
}
控制台打印结果:
org.springframework.data.domain.PageRequest@7d522180[
sort=id,asc: ASC
page=1
size=10
]
7、测试用例中jsonpath的用法
github上面搜索jsonpath ==> https://github.com/json-path/JsonPath
8、@PathVariable 以及url映射中使用正则表达式
@GetMapping("/user/{id:\\d+}")
public Object getUserById(@PathVariable Integer id) {
return userService.getUserById(id);
}
此时,请求url为 /user/a 时,报404。
参考:
1)详解REST架构风格:http://www.uml.org.cn/zjjs/201805142.asp
2)REST,以及RESTful的讲解:https://blog.csdn.net/qq_21383435/article/details/80032375
springmvc/springboot开发restful API的更多相关文章
- ASP.NET Core Web API 开发-RESTful API实现
ASP.NET Core Web API 开发-RESTful API实现 REST 介绍: 符合REST设计风格的Web API称为RESTful API. 具象状态传输(英文:Representa ...
- flask开发restful api系列(8)-再谈项目结构
上一章,我们讲到,怎么用蓝图建造一个好的项目,今天我们继续深入.上一章中,我们所有的接口都写在view.py中,如果几十个,还稍微好管理一点,假如上百个,上千个,怎么找?所有接口堆在一起就显得杂乱无章 ...
- flask开发restful api
flask开发restful api 如果有几个原因可以让你爱上flask这个极其灵活的库,我想蓝图绝对应该算上一个,部署蓝图以后,你会发现整个程序结构非常清晰,模块之间相互不影响.蓝图对restfu ...
- SpringBoot 构建RestFul API 含单元测试
相关博文: 从消费者角度评估RestFul的意义 SpringBoot 构建RestFul API 含单元测试 首先,回顾并详细说明一下在快速入门中使用的 @Controller . @RestC ...
- 描述怎样通过flask+redis+sqlalchemy等工具,开发restful api
flask开发restful api系列(8)-再谈项目结构 摘要: 进一步介绍flask的项目结构,使整个项目结构一目了然.阅读全文 posted @ 2016-06-06 13:54 月儿弯弯02 ...
- 使用Spring MVC开发RESTful API
第3章 使用Spring MVC开发RESTful API Restful简介 第一印象 左侧是传统写法,右侧是RESTful写法 用url描述资源,而不是行为 用http方法描述行为,使用http状 ...
- flask开发restful api系列(7)-蓝图与项目结构
如果有几个原因可以让你爱上flask这个极其灵活的库,我想蓝图绝对应该算上一个,部署蓝图以后,你会发现整个程序结构非常清晰,模块之间相互不影响.蓝图对restful api的最明显效果就是版本控制:而 ...
- flask开发restful api系列(6)-配置文件
任何一个好的程序,配置文件必不可少,而且非常重要.配置文件里存储了连接数据库,redis的用户密码,不允许有任何闪失.要有灵活性,用户可以自己配置:生产环境和开发环境要分开,最好能简单的修改一个东西, ...
- flask开发restful api系列(1)
在此之前,向大家说明的是,我们整个框架用的是flask + sqlalchemy + redis.如果没有开发过web,还是先去学习一下,这边只是介绍如果从开发web转换到开发移动端.如果flask还 ...
随机推荐
- GitLab使用小结
对Git和GitLab的使用作一个小结 GitLab基于Git,可以作为团队开发项目使用,因此通常会有一个主分支master和其他分支,因此项目成员中任意一人不能随意push到主分支中,容易引起混乱: ...
- USACO4.3 Street Race【分析】
这道题,感觉不是很难,分析清楚之后非常简单.(标签都不知道怎么加) 读完题首先想到了分割点一定是必经点的一种特殊情况,如果分割点不是必经点的话,那么它就不能把这个图分成两半(存在不经过它的边沟通两半) ...
- 【VS开发】Caffelib中出现的问题:强制链接静态库所有符号(包括未被使用的)
C++程序在链接一个静态库时,如果该静态库里的某些方法没有任何地方调用到,最终这些没有被调用到的方法或变量将会被丢弃掉,不会被链接到目标程序中.这样做大大减小生成二进制文件的体积.但是,某些时候,即使 ...
- 小记-----如何把本地jar包加载到maven库中
1.从maven中央库下载下jar包
- 使用render函数渲染组件
使用render函数渲染组件:https://www.jianshu.com/p/27ec4467a66b
- RPC架构下org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
一.调用后台接口报错 网上有很多作者列出大部分原因: 1.实体类名对应配置文件名或者路径不一致 2.spring扫描路径不全 但是本人使用的是mtbatis逆向工程生成的实体类.接口与配置文件,所以不 ...
- PAT B1021 个位数统计 (15)
AC代码 #include <cstdio> #include <iostream> #include <cstring> using namespace std; ...
- shell简单脚本#1
判断/etc/inittab文件是否大于100行,如果大于,则显示”/etc/inittab is a big file.”否者显示”/etc/inittab is a small file.” #! ...
- 开发跨平台应用解决方案-uniapp 真心不错,支持一波
uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架,开发者编写一套代码,可编译到iOS.Android.微信小程序等多个平台. 用了mui,H5+一年多了,感觉dcloud 最近推出的 ...
- 解决Asp.net Core中chtml文档中文乱码的问题
原因 由于Visual Studio 2017在保存chtml时,文本格式非utf-8,所以导致中文会出现乱码情况. 解决办法 在工具->扩展与更新中添加插件"ForceUTF8 (w ...