什么是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. Thread.Sleep(0) vs Sleep(1) vs Yeild

    本文将要提到的线程及其相关内容,均是指 Windows 操作系统中的线程,不涉及其它操作系统. 文章索引 核心概念 Thread.Yeild       Thread.Sleep(0) Thread. ...

  2. 精通Perl(第2版)

    精通Perl(第2版)(通往Perl大师之路必读经典书籍,体现了一种编程思维,能够帮你解决很多实际的问题) [美]brian d foy(布瑞恩·D·福瓦)著   王兴宇 刘宸宇 译 ISBN 978 ...

  3. GitHub实战系列~3.提交github的时候过滤某些文件 2015-12-10

    GitHub实战系列汇总:http://www.cnblogs.com/dunitian/p/5038719.html ———————————————————————————————————————— ...

  4. UEditor编辑器使用示例

    1. UEditor下载 UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码. 下载链接:http ...

  5. Redis数据结构详解之Set(三)

    序言 在Redis中,Set和list都是字符串序列,非常相似,不同之处在于Set是用哈希表来保持字符串的唯一性,没有先后顺序,不像list一样,可以在首尾增删数据.但是set也有自己的相应处理命令来 ...

  6. 原创:CSS3技术-雪碧图自适应缩放与精灵动画方案

    花了一个礼拜完成了慕课网定制的七夕主题效果,其中有一个没实现好的功能,就是雪碧图的自适应缩放 ps: 以下实现都是基于移动端的处理 原图如下: 人物是采用的是雪碧图,通过坐标绝对数据取值 问题很明显, ...

  7. 【原】Masonry+UIScrollView的使用注意事项

    [原]Masonry+UIScrollView的使用注意事项 本文转载请注明出处 —— polobymulberry-博客园 1.问题描述 我想实现的使用在一个UIScrollView依次添加三个UI ...

  8. SQL Server-聚焦过滤索引提高查询性能(十)

    前言 这一节我们还是继续讲讲索引知识,前面我们讲了聚集索引.非聚集索引以及覆盖索引等,在这其中还有一个过滤索引,通过索引过滤我们也能提高查询性能,简短的内容,深入的理解,Always to revie ...

  9. PhoneGap/cordvoa如何添加Media插件

    phonegap由2.7升级到3.7之前,只要引入一个cordova.js,就可以了.现在由于所用的插件,都需要用模块的形式进行按需加载,自然就没有以前那么安逸了. 例如,如果要在安卓平台添加一个音频 ...

  10. 在CentOS 7上安装.NET Core R2跑Hello World

    前言 在上个月.NET Core出了最新版本预览版,只是在Window系统上试验了一下.原本想等发布正式版的时候在linux系统上试试,可能还需要一段时间,刚好有空可以折腾一下. 由于之前安装的Ubu ...