第二章: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”)如何设计的文章,然而 ...
随机推荐
- 表单提交前的confirm验证提示
今天要做一个修改提交前的提示,点击修改按钮进行提示,然后根据confirm的结果来决定是否提交;发现平时很常见的一个功能,自己不会.所以只能去晚上找资料了; 举例如下: <form action ...
- SpringBoot | 第二十七章:监控管理之Actuator使用
前言 随着我们服务越来越多,部署的环境也越来越繁多时,由于各服务都部署在不同的机器上,每当出现问题或者异常时,想快速进行问题的定位就变的麻烦了.所以,本章节开始,开始讲解SpringBoot的监控相关 ...
- D3(v5) in TypeScript 坐标轴之 饼状图生成
饼状图生成时依旧遇到了类型问题,记录如下: import * as d3 from 'd3'; import * as React from 'react'; class TestGraph exte ...
- 【Linux】网络性能测试工具iperf详细使用图文教程【转】
参考链接:https://www.cnblogs.com/yingsong/p/5682080.html Iperf是一个网络性能测试工具.Iperf可以测试TCP和UDP带宽质量. Iperf可以测 ...
- Advanced .NET Debugging: Managed Heap and Garbage Collection(转载,托管堆查内存碎片问题解决思路)
原文地址:http://www.informit.com/articles/article.aspx?p=1409801&seqNum=4 Debugging Managed Heap Fra ...
- 【数据库】6.0 MySQL入门学习(六)——MySQL启动与停止、官方手册、文档查询
1.0 MySQL主要有四种启动方式:直接启动.安全启动.服务启动.多实例启动. 直接启动: 服务器启动: 安全启动(最常用): 多实例启动: 2.0如何获得MySQL帮助 2.1官方手册 下面提供百 ...
- java参数传递之值传递
一 概述 1.什么是参数传递? 调用方法时向形参传递数据的过程叫做参数传递.在编程语言中有两种传递方式:值传递与引用传递.必须强调的是,这里提到的两种传递方式不是仅限于java使用到的传递方式,而是出 ...
- jquery.rotate.js可选抽奖次数和中奖内容的转盘抽奖demo
需求: 最多可以抽奖5次,而且,每次只会中“2000元理财金”或者“谢谢参与”,其它的不会抽中(哈哈,果然都是套路). 效果如下: 一.页面结构: <div class="g-cont ...
- linux配置IP
1.配置ip的几种方式: 1.使用ifconfig命令(临时配置,重启后失效) 2.使用setup工具(RedHat专有的,不过经本人测试,虚拟机装了centos,也有setup,也可以进行配置, ...
- Ruby系列文章之1---开发者应该熟悉的10个工具
1. Git Git是进入Ruby这个生态圈首先最应该学会的工具.几乎所有以Ruby开发出来的套件都放在Github上.也就是不管你要下载或修改协作都需要透过Git. 2. RVM Ruby有很多种i ...