什么是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. 小丁是怎样入门git的

    0x01前言 既然没有华丽的出场,那就平凡的分享,首先我要说明一点本篇文章针对Git初学者,对我自己学Git的资源的整合,其实本篇索引应该在我写Git系列文章的时候就紧跟着放上索引的,由于时间问题没有 ...

  2. TODO:字节的那点事Go篇

    TODO:字节的那点事Go篇 (本文go version go1.7.3 darwin/amd64) 在Golang中string底层是由byte数组组成的. fmt.Println(len(&quo ...

  3. 无需编译、快速生成 Vue 风格的文档网站

    无需编译.快速生成 Vue 风格的文档网站 https://docsify.js.org/#/#coverpage https://github.com/QingWei-Li/docsify/

  4. Oozie分布式任务的工作流——邮件篇

    在大数据的当下,各种spark和hadoop的框架层出不穷.各种高端的计算框架,分布式任务如乱花般迷眼.你是否有这种困惑!--有了许多的分布式任务,但是每天需要固定时间跑任务,自己写个调度,既不稳定, ...

  5. ASP.NET MVC5+EF6+EasyUI 后台管理系统(2)-easyui构建前端页面框架[附源码]

    系列目录 前言 为了符合后面更新后的重构系统,本文于2016-10-31日修正一些截图,文字 我们有了一系列的解决方案,我们将动手搭建新系统吧. 后台系统没有多大的UI视觉,这次我们采用的是标准的左右 ...

  6. ASP.NET Core管道深度剖析(1):采用管道处理HTTP请求

    之所以称ASP.NET Core是一个Web开发平台,源于它具有一个极具扩展性的请求处理管道,我们可以通过这个管道的定制来满足各种场景下的HTTP处理需求.ASP. NET Core应用的很多特性,比 ...

  7. Web缓存杂谈

    一.概述 缓存通俗点,就是将已经得到的‘东东’存放在一个相对于自己而言,尽可能近的地方,以便下次需要时,不会再二笔地跑到起始点(很远的地方)去获取,而是就近解决,从而缩短时间和节约金钱(坐车要钱嘛). ...

  8. 多线程同步工具——LockSupport

    用例1:子线程等待主线程发放许可! public static void main(String[] args) { Thread thread = new Thread(){ public void ...

  9. Java内存模型深度解析:总结--转

    原文地址:http://www.codeceo.com/article/java-memory-7.html 处理器内存模型 顺序一致性内存模型是一个理论参考模型,JMM和处理器内存模型在设计时通常会 ...

  10. ASP.NET Core 整合Autofac和Castle实现自动AOP拦截

    前言: 除了ASP.NETCore自带的IOC容器外,我们还可以使用其他成熟的DI框架,如Autofac,StructureMap等(笔者只用过Unity,Ninject和Castle). 1.ASP ...