什么是REST

  • 全称:表述性状态转移 (Representational State Transfer), 将资源的状态以最适合客户端或服务端的形式从服务器端转移到客户端(或者反过来)。
  • 面向资源,而不是面向行为
  • 资源通过URL进行识别和定位,
  • 一般URL中都使用名词,不使用动词
  • 对资源采取的行为使用HTTP方法来定义,如GET, POST, DELETE, PUT

Spring MVC REST API示例

以用户增删改查为例,设计 REST API.

这里,我们主要关注Spring Mvc中的Controller的设计:

UserController类:

@RestController
@RequestMapping(value = "/users")
public class UserController extends BaseController
{
@Autowired
    private IUserService userService;
...
}

这里使用了@RestController注解,Spring将会为该Controller的所有处理方法应用消息转换功能,因此我们可以不必为每个方法都添加@ResponseBody。

Spring支持多种资源表述形式(JSON/XML/HTML...),不过一般使用JSON形式。

查询所有用户

对应请求的URL示例(无分页):http://localhost:8080/webbf/users

对应的URL示例(有分页):http://localhost:8080/webbf/users?offset=0&limit=10

使用的HTTP方法:GET

如果查询不到用户,返回状态码204,No Content

否则,返回状态码200, OK,返回的数据类型为 application/json;charset=utf-8

    @RequestMapping(method = RequestMethod.GET, produces = "application/json; charset=utf-8")
public ResponseEntity<List<User>> getUserList(
@RequestParam(value = "offset", defaultValue = "0") long offset,
@RequestParam(value = "limit", defaultValue = MAX_LONG_AS_STRING) long limit)
{
Map<String, Object> param = new HashMap<String, Object>();
param.put("offset", offset);
param.put("limit", limit);
List<User> userList = userService.query(param);
if (userList.size() == 0)
{
return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<User>>(userList, HttpStatus.OK);
}

查询单个用户

对应请求的URL示例:http://localhost:8080/webbf/users/1

使用的HTTP方法:GET

如果查询不到用户,返回状态码404,Not Found

否则,返回状态码200, OK,返回的数据类型为 application/json;charset=utf-8

    @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
public ResponseEntity<User> getUserById(@PathVariable Long id)
{ User user = userService.findById(id);
if (user == null)
{
return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<User>(userService.findById(id), HttpStatus.OK);
}

删除用户

对应请求的URL示例:http://localhost:8080/webbf/users/1

使用的HTTP方法:DELETE

如果查询不到被删除的用户,返回状态码404,Not Found

否则,删除成功,返回状态码204, No Content

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = "application/json; charset=utf-8")
public ResponseEntity<User> deleteUser(@PathVariable Long id)
{
User user = userService.findById(id);
if (user == null)
{
return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
userService.deleteUser(id);
return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
}

保存用户

对应请求的URL示例:http://localhost:8080/webbf/users

请求体:

{
    "name":"1",
    "address":"aa"
}

Content-Type: application/json

使用的HTTP方法:POST

响应的body为新创建的用户;

响应头的Location:http://localhost:8080/webbf/users/60

//如果用户已存在,返回状态码,409, Conflict

保存成功,返回状态码201, Created,返回的数据类型为 application/json;charset=utf-8

    @RequestMapping(method = RequestMethod.POST, consumes = "application/json; charset=utf-8")
public ResponseEntity<User> saveUser(@RequestBody User user, UriComponentsBuilder ucb)
{ // if (userService.isUserExist(user)) {
// System.out.println("A User with name " + user.getName() +
// " already exist");
// return new ResponseEntity<User>(user, HttpStatus.CONFLICT);
// }
User saved = userService.saveUser(user); HttpHeaders headers = new HttpHeaders();
URI locationUri = ucb.path("/users/").path(String.valueOf(saved.getId())).build().toUri();
headers.setLocation(locationUri); ResponseEntity<User> responseEntity = new ResponseEntity<User>(saved, headers,
HttpStatus.CREATED);
return responseEntity;
}

修改用户

对应请求的URL示例:http://localhost:8080/webbf/users/1

请求体:

{
    "name":"1",
    "address":"aa"
}

Content-Type: application/json

使用的HTTP方法:PUT

响应的body为新创建的用户;

如果查询不到被修改的用户,返回状态码404,Not Found

保存成功,返回状态码201, Created,返回的数据类型为 application/json;charset=utf-8

    @RequestMapping(value = "/{id}", method = RequestMethod.PUT, consumes = "application/json; charset=utf-8")
public ResponseEntity<User> updateUser(@PathVariable("id") long id, @RequestBody User user)
{
User currentUser = userService.findById(id); if (currentUser == null)
{
return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
} currentUser.setId(id);
currentUser.setName(user.getName());
currentUser.setAddress(user.getAddress()); userService.updateUser(currentUser);
return new ResponseEntity<User>(currentUser, HttpStatus.OK);
}

异常处理

请求中发生异常,返回500 Internal Server Error。

    @ExceptionHandler(Exception.class)
@ResponseBody
public ResponseEntity<Exception> handleException(HttpServletRequest request, Exception e)
{
logger.error("Request FAILD, URL = {} method = {}", request.getRequestURI(), request.getMethod());
logger.error(e.toString(), e);
return new ResponseEntity<Exception>(e, HttpStatus.INTERNAL_SERVER_ERROR);
}

前端测试工具

因为我喜欢用fireFox, 所以我用restclient测试工具测试 REST API:

chrom的话,可以使用Postman。

修改用户测试

新增用户测试

查询单个用户

前端AJAX调用 REST API 示例

查询用户

      $.ajax({
async: false,
type : "get",
url : "/webbf/users",
data: {},
datatype : 'json', success : function(data,textStatus) {
this.trigger({userList:data});
}.bind(this), error: function(jqXHR, textStatus, errorThrown) {
alert(jqXHR.status + ' ' + jqXHR.responseText);
} });

删除用户

      $.ajax({
async: false,
type : "delete",
url : "/webbf/users/" + userId,
data: {},
datatype : 'json',
success : function(data) { alert("删除成功");
this.getAllUser(); }.bind(this), error: function(jqXHR, textStatus, errorThrown) {
alert(jqXHR.status + ' ' + jqXHR.responseText);
}
});

新增用户

      $.ajax({
async: false,
contentType: "application/json; charset=utf-8",
type : "post",
url : "/webbf/users",
data: JSON.stringify({name:userName,address:address}),
datatype : 'json',
success : function(data) { alert("操作成功");
this.openAddModal(false);
this.getAllUser(); }.bind(this), error: function(jqXHR, textStatus, errorThrown) {
alert(jqXHR.status + ' ' + jqXHR.responseText);
}
});

参考资料

Spring in action 4

Spring 4 创建REST API的更多相关文章

  1. 使用Spring MVC创建 REST API

    1.REST的基础知识 当谈论REST时,有一种常见的错误就是将其视为“基于URL的Web服务”——将REST作为另一种类型的远程过程调用(remote procedurecall,RPC)机制,就像 ...

  2. 第16章-使用Spring MVC创建REST API

    1 了解REST 1.1 REST的基础知识 REST与RPC几乎没有任何关系.RPC是面向服务的,并关注于行为和动作:而REST是面向资源的,强调描述应用程序的事物和名词. 为了理解REST是什么, ...

  3. 利用spring boot创建java app

    利用spring boot创建java app 背景 在使用spring框架开发的过程中,随着功能以及业务逻辑的日益复杂,应用伴随着大量的XML配置和复杂的bean依赖关系,特别是在使用mvc的时候各 ...

  4. Spring Boot 处理 REST API 错误的正确姿势

    摘要:如何正确的处理API的返回信息,让返回的错误信息提供更多的含义是一个非常值得做的功能.默认一般返回的都是难以理解的堆栈信息,然而这些信息也许对于API的客户端来说有可能并没有多大用途,并没有多大 ...

  5. spring如何创建RESTful Service

    REST REST,是指REpresentational State Transfer,有个精辟的解释什么是RESTful, 看url就知道要什么 看method就知道干什么 看status code ...

  6. 使用Spring MVC开发RESTful API

    第3章 使用Spring MVC开发RESTful API Restful简介 第一印象 左侧是传统写法,右侧是RESTful写法 用url描述资源,而不是行为 用http方法描述行为,使用http状 ...

  7. Spring mvc创建的web项目,如何获知其web的项目名称,访问具体的链接地址?

    Spring mvc创建的web项目,如何获知其web的项目名称,访问具体的链接地址? 访问URL:  http://localhost:8090/firstapp/login 在eclipse集成的 ...

  8. ASP.NET 5系列教程 (六): 在 MVC6 中创建 Web API

    ASP.NET 5.0 的主要目标之一是统一MVC 和 Web API 框架应用. 接下来几篇文章中您会了解以下内容: ASP.NET MVC 6 中创建简单的web API. 如何从空的项目模板中启 ...

  9. spring cloud教程之使用spring boot创建一个应用

    <7天学会spring cloud>第一天,熟悉spring boot,并使用spring boot创建一个应用. Spring Boot是Spring团队推出的新框架,它所使用的核心技术 ...

随机推荐

  1. MVVM大比拼之AngularJS源码精析

    MVVM大比拼之AngularJS源码精析 简介 AngularJS的学习资源已经非常非常多了,AngularJS基础请直接看官网文档.这里推荐几个深度学习的资料: AngularJS学习笔记 作者: ...

  2. EasyPR--开发详解(7)字符分割

    大家好,好久不见了. 一转眼距离上一篇博客已经是4个月前的事了.要问博主这段时间去干了什么,我只能说:我去“外面看了看”. 图1 我想去看看 在外面跟几家创业公司谈了谈,交流了一些大数据与机器视觉相关 ...

  3. JavaScript dom 标签属性

    节点: 平时开发中常用的节点是: 元素节点:nodeType值是 1    --> <a>,<p>...... 属性节点:nodeType值是 2    --> t ...

  4. .NET 程序集单元测试工具 SmokeTest 应用指南

    Smoke Test(冒烟测试),也称Regression Test(回归测试),是对软件的安装和基本功能的测试.一般地我们使用脚本来实现Smoke Test的自动化,可借用虚拟机的snapshot机 ...

  5. 1.Kali安装到移动硬盘或者U盘中~Linux系通用方法(包括Android)

    0.1.保证这个服务必须启动(虚拟机服务最好都启动) 0.2.看看U盘接口类型是否对应 1.安装第一步 2.安装第二步,选择kali镜像 3.设置存放位置(上面的名字无所谓,最后不会用它的,虚拟机只是 ...

  6. 锋利的jQuery--jQuery与DOM对象的互相转换,DOM的三种操作(读书笔记一)

    1.jQuery对象就是通过jQuery包装DOM对象后产生的对象.   2.jQuery对象和DOM对象的相互转换.   良好的书写风格: var $input=$("input" ...

  7. Android开发之Activity的生命周期以及加载模式

    本篇博客就来好好的搞一下Activity的生命周期,如果搞过iOS的小伙伴的话,Activity的生命周期和iOS中ViewController的生命周期非常类似.生命周期,并不难理解.一个人的生命周 ...

  8. C++服务器开发之笔记三

    为什么需要原子性操作? 我们考虑一个例子:(1)x++这个常见的运算符在内存中是怎样操作的?从内存中读x的值到寄存器中,对寄存器加1,再把新值写回x所处的内存地址 若是有两个线程同时对同一个变量++, ...

  9. spring boot(三):Spring Boot中Redis的使用

    spring boot对常用的数据库支持外,对nosql 数据库也进行了封装自动化. redis介绍 Redis是目前业界使用最广泛的内存数据存储.相比memcached,Redis支持更丰富的数据结 ...

  10. Oracle数据库文件路径变更

    环境:RHEL 6.4 + Oracle 11.2.0.3 情景一:只是部分普通数据文件迁移,可以在线操作. 1.将对应表空间offline,移动数据文件到新路径 2.数据文件alter databa ...