第二章:RESTful API
学习内容
使用Spring MVC编写Restful API
使用Spring MVC处理其他web应用常见的需求和场景
如何处理静态资源和异常,如何使用Spring MVC的拦截器,文件的上传下载,如何进行请求的异步开发
RESTful API开发常用辅助框架
Swagger-生成服务文档,WireMock-伪造服务
RESTful API介绍

特点:
1.用URL描述资源
2.使用HTTP方法描述行为,使用HTTP状态码来表示不同结果
增删改查对应POST、DELETE、PUT、GET,使用状态码来表示结果而不是用报文里面的内容。
3.使用json交互数据
4.RESTful只是一种风格,并不是强制标准
编写第一个RESTful API
使用注解声明RESTful API
常用注解
@RestController 标明此Controller提供RESTful API
@RequestMapping及其变体 映射http请求url到java方法
@RequestParam 映射请求参数到java方法的参数
@PageableDefault 指定分页参数的默认值
在RESTful API中传递参数
@RequestParam
required,name,defaultValue,required表示参数是否必须,name表示HTTP请求参数名,defaultValue表示未传参数时使用的默认值。
@RequestMapping(value = "/user", method = RequestMethod.GET)
public List<User> query(@RequestParam(required = true, name = "username", defaultValue = "Tom") String username) {
System.out.println(username);
List<User> users = new ArrayList<User>();
users.add(new User());
users.add(new User());
users.add(new User());
return users;
}
如果传递参数太多,Spring MVC可以自动将参数组装到对象中,可以声明一个类UserQueryCondition有多个属性。
public class UserQueryCondition {
private String username;
private int age;
private int ageTo;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getAgeTo() {
return ageTo;
}
public void setAgeTo(int ageTo) {
this.ageTo = ageTo;
}
}
@RequestMapping(value = "/user", method = RequestMethod.GET)
public List<User> query(UserQueryCondition condition) {
System.out.println(ReflectionToStringBuilder.toString(condition, ToStringStyle.MULTI_LINE_STYLE));
List<User> users = new ArrayList<User>();
users.add(new User());
users.add(new User());
users.add(new User());
return users;
}
@Test
public void whenQuerySuccess() throws Exception {
mockMvc.perform(get("/user")
.param("username", "jojo")
.param("age", "10")
.param("ageTo", "20")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()").value(3));
}
@PageableDefault
page,size,sort,表示默认查第几页,一页数据条数,排序
@RequestMapping(value = "/user", method = RequestMethod.GET)
public List<User> query(UserQueryCondition condition, @PageableDefault(page = 1, size = 10, sort = "username,asc") Pageable pageable) {
System.out.println(ReflectionToStringBuilder.toString(condition, ToStringStyle.MULTI_LINE_STYLE));
System.out.println(ReflectionToStringBuilder.toString(pageable, ToStringStyle.MULTI_LINE_STYLE));
List<User> users = new ArrayList<User>();
users.add(new User(1));
users.add(new User(2));
users.add(new User(3));return users;
}
@Test
public void whenQuerySuccess() throws Exception {
mockMvc.perform(get("/user")
.param("username", "jojo")
.param("age", "10")
.param("ageTo", "20")
.param("size", "5")
.param("page", "2")
.param("sort", "age,desc")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk());
}
编写用户详情服务
@PathVariable 映射url片段到java方法的参数
name,required,name要和url片段相同,required表示是否必须
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public User getInfo(@PathVariable(name = "id") String userid) {
User user = new User();
user.setId(userid);
user.setUsername("Tom");
return user;
}
@Test
public void whenGetInfoSuccess() throws Exception {
String result = mockMvc.perform(get("/user/1")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(jsonPath("$.username").value("Tom"))
.andReturn().getResponse().getContentAsString();
System.out.println(result);
}
在url片段的声明中使用正则表达式
@RequestMapping(value = "/user/{id:\\d+}", method = RequestMethod.GET)
public User getInfo(@PathVariable(name = "id") String userid) {
User user = new User();
user.setId(userid);
user.setUsername("Tom");
return user;
}
@Test
public void whenGetInfoFail() throws Exception {
mockMvc.perform(get("/user/a")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().is4xxClientError());
}
@JsonView控制json输出内容
假设query不想返回用户密码,getInfo时返回给前台用户密码,即在返回相同对象时控制返回哪些字段。
使用步骤:
1.使用接口声明多个视图 2.在值对象的get方法上指定视图 3.在Controller方法上指定视图
public class User {
public interface UserSimpleView {}; //视图1
public interface UserDetailView extends UserSimpleView {}; //视图2,因继承视图1,所以使用视图2也会显示视图1的属性
private String id;
private String username;
private int age;
private String password;
@JsonView(UserSimpleView.class)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@JsonView(UserSimpleView.class)
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@JsonView(UserSimpleView.class)
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@JsonView(UserDetailView.class)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@RequestMapping(value = "/user", method = RequestMethod.GET)
@JsonView(User.UserSimpleView.class)
public List<User> query(UserQueryCondition condition, @PageableDefault(page = 1, size = 10, sort = "username,asc") Pageable pageable) {
System.out.println(ReflectionToStringBuilder.toString(condition, ToStringStyle.MULTI_LINE_STYLE));
System.out.println(ReflectionToStringBuilder.toString(pageable, ToStringStyle.MULTI_LINE_STYLE));
List<User> users = new ArrayList<User>();
users.add(new User());
users.add(new User());
users.add(new User());
return users;
} @RequestMapping(value = "/user/{id:\\d+}", method = RequestMethod.GET)
@JsonView(User.UserDetailView.class)
public User getInfo(@PathVariable(name = "id") String userid) {
User user = new User();
user.setId(userid);
user.setUsername("Tom");
return user;
}
代码重构
1.将url相同部分提到类上声明
2.使用RequestMapping的变体GetMapping
@RestController
@RequestMapping("/user")
public class UserController { @GetMapping()
@JsonView(User.UserSimpleView.class)
public List<User> query(UserQueryCondition condition, @PageableDefault(page = 1, size = 10, sort = "username,asc") Pageable pageable) {
System.out.println(ReflectionToStringBuilder.toString(condition, ToStringStyle.MULTI_LINE_STYLE));
System.out.println(ReflectionToStringBuilder.toString(pageable, ToStringStyle.MULTI_LINE_STYLE));
List<User> users = new ArrayList<User>();
users.add(new User());
users.add(new User());
users.add(new User());
return users;
} @GetMapping("/{id:\\d+}")
@JsonView(User.UserDetailView.class)
public User getInfo(@PathVariable(name = "id") String userid) {
User user = new User();
user.setId(userid);
user.setUsername("Tom");
return user;
} }
第二章:RESTful API的更多相关文章
- 第二章 Stream API
引例: 1 List<String> strList = Arrays.asList("zhaojigang","nana","tiany ...
- HBase第二章 基本API
1.pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www ...
- HTML5 WebSocket 权威指南 学习一 (第二章 WebSocket API)
WebSocket 协议两种URL方案 ws 客户端和服务器之间的非加密流量 wss 客户端和服务器之间的加密流量 WebSocket Secure 表示使用传输层安全性(SSL)的WebSocket ...
- ArcGIS API for JavaScript 4.2学习笔记[10] 2D添加指北针widget、视图保存、视图padding(第二章完结)
这几个例子是第二章除了入门之外比较简单的几个,就做个合集,把最核心的代码(第二参数)和 引用放上来即可,不作多解释. 2D地图添加指北针widget 2D地图一般修正方向为正北方就需要这个widget ...
- ASP.NET Core 中文文档 第二章 指南 (09) 使用 Swagger 生成 ASP.NET Web API 在线帮助测试文档
原文:ASP.NET Web API Help Pages using Swagger 作者:Shayne Boyer 翻译:谢炀(kiler) 翻译:许登洋(Seay) 对于开发人员来说,构建一个消 ...
- ArcGIS API for JavaScript 4.2学习笔记[3] 官方第二章Mapping and Views概览与解释
目录如下: 连接:第二章 Mapping and Views 根据本人体会, [这一章节主要是介绍地图(Map)和视图(View)的.] 其中,Get started with MapView(2D) ...
- 基于轻量型Web服务器Raspkate的RESTful API的实现
在上一篇文章中,我们已经了解了Raspkate这一轻量型Web服务器,今天,我们再一起了解下如何基于Raspkate实现简单的RESTful API. 模块 首先让我们了解一下"模块&quo ...
- RESTful API 设计最佳实践
背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个"万能"的设计标准:如何鉴权?API ...
- ****RESTful API 设计最佳实践(APP后端API设计参考典范)
http://blog.jobbole.com/41233/ 背景 目前互联网上充斥着大量的关于RESTful API(为方便,下文中“RESTful API ”简写为“API”)如何设计的文章,然而 ...
随机推荐
- oracle dblink简介
database link概述 database link是定义一个数据库到另一个数据库的路径的对象,database link允许你查询远程表及执行远程程序.在任何分布式环境里,database都是 ...
- Cannot connect to VM com.sun.jdi.connect.TransportTimeoutException
Cannot connect to VM com.sun.jdi.connect.TransportTimeoutException 描述 在用eclipse进行debug的时候弹出了上面的错误,在s ...
- 使用c#正则验证关键字并找出匹配项
在.net里,使用类Regex可以正则验证一些关键字并取出匹配项. 1.使用Regex.IsMatch(string input, string pattern, RegexOptions ...
- android 短期计划
http://www.jianshu.com/p/2a9fcf3c11e4 http://www.jianshu.com/p/5f6d79323923 activity启动模式: http://www ...
- HTML代码中<%%>、<%=%>、<%:%>
<%%>之间可以写服务器端代码 比如 <% for(var i=0;i<10;i++){%> <%=%>获取后台的变量值,比如后台一个session[&quo ...
- WinSock WSAEventSelect 模型
在前面我们说了WSAAsyncSelect 模型,它相比于select模型来说提供了这样一种机制:当发生对应的IO通知时会立即通知操作系统,并调用对应的处理函数,它解决了调用send和 recv的时机 ...
- WSAAsyncSelect 消息模型
select 模型虽然可以管理多个socket,但是它涉及到一个时机的问题,select模型会针对所管理的数组中的每一个socket循环检测它管理是否在对应的数组中,从时间复杂度上来说它是O(n^2) ...
- CSS Hack兼容
CSS中有很多标签在不同浏览器中有不同的兼容性问题,问了让网页的功能更好的不同浏览器中显示正常, 需要通过hack的方式来解决浏览器兼容问题. CSS hack问题由来已久,目前我的了解甚少,以下是转 ...
- Canvas知识点汇总
本文主要记录Canvas基础知识汇总. 1.Canvas定义 <canvas> 元素是HTML5中的新元素,通过它可以在网页中绘制出所需的图形.<canvas>标签只是图形的容 ...
- 高效的jQuery代码编写技巧
缓存变量 DOM遍历是昂贵的,所以尽量将会重用的元素缓存. // 糟糕 h = $('#element').height(); $(); // 建议 $element = $('#element'); ...