第二章: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”)如何设计的文章,然而 ...
随机推荐
- 白话SpringCloud | 第四章:服务消费者(RestTemple+Ribbon+Feign)
前言 上两章节,介绍了下关于注册中心-Eureka的使用及高可用的配置示例,本章节开始,来介绍下服务和服务之间如何进行服务调用的,同时会讲解下几种不同方式的服务调用. 一点知识 何为负载均衡 实现的方 ...
- MongoDB集群怎样去访问?
上一章节简单介绍了MONGODB的集群搭建.相信大家都已经很熟悉了.集群搭建完接下来应该考虑我们的程序应该怎样去访问他. 怎么读写数据等操作.下面把我在工作中的一些用法列出来供大家作为参考. 官网的链 ...
- HyperLink 控件
yperLink就是一个可以用后台代码控制生成的超链接 1,声明,创建 2,设定text 3,设定navigateurl 4,将他添加到某个容器中 为什么没有保留第一次添加的连接? l 按钮1:向pa ...
- SQLAlchemy的使用---M2M增删改查
from sqlalchemy.orm import sessionmaker from sqlalchemy_M2M import engine, Girls, Boys Session = ses ...
- Windows 10:开机显示C:\WINDOWS\system32\config\systemprofile\Desktop不可用 的解决方法
今晨起来开机,开完机一看,弹出啦一个框框上面写着“C:\WINDOWS\system32\config\systemprofile\Desktop不可用...” 当我点击了确定之后,发现屏幕一片黑,只 ...
- iDempiere 使用指南 MRP/生产插件 LiberoMFG 源码安装
Created by 蓝色布鲁斯,QQ32876341,blog http://www.cnblogs.com/zzyan/ iDempiere官方中文wiki主页 http://wiki.idemp ...
- Git 几个重要操作指令对比
1.git merge 和 git rebase https://blog.csdn.net/wh_19910525/article/details/7554489 http://gitbook.li ...
- 01_JMS概述
[以前的通信技术的局限性] 在大规模和复杂的分布式系统中,传统的RMI.DCOM等中间件通信技术逐渐有了局限性,如下: 1.同步通信:客户发出调用后,必须等待服务对象完成处理并返回结果才能继续执行. ...
- TextView来实现跑马灯的效果
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- ViewPager+fragment的使用
如图我在一个继承FragmentActivity的类中嵌套了3个fragment分别能实现3个不同的界面,默认展现第一个,在第一个的fragment中有个ViewPager在ViewPager中嵌套了 ...