什么是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. 轻量级表达式树解析框架Faller

    有话说 之前我写了3篇关于表达式树解析的文章 干货!表达式树解析"框架"(1) 干货!表达式树解析"框架"(2) 干货!表达式树解析"框架" ...

  2. ABP框架 - 实体

    文档目录 本节内容: 实体类 聚合根类 领域事件 约定的接口 审计 软删除 活跃/消极 实体 实体变化事件 IEntity 接口 实体是DDD一个核心的概念.Eric Evans是这么描述的:“一个对 ...

  3. 对百度的UEditor多图片上传的一些补充

    我已经写了一篇文章关于百度的UEditor提取多图片上传模块.如果还没有看过,请点击以下链接查看 http://www.cnblogs.com/luke1006/p/3719029.html 出差了两 ...

  4. 【饿了么】招聘Java开发工程师、架构师

    3年以上实际工作经验,本科及以上学历. 具有良好的编程基础( 比如熟悉HTTP.多线程.Socket.JVM.基本的数据结构和算法等). 熟悉Java语言以及相关的服务器(比如Tomcat).工具(M ...

  5. Oracle数据库自动备份SQL文本:Procedure存储过程,View视图,Function函数,Trigger触发器,Sequence序列号等

    功能:备份存储过程,视图,函数触发器,Sequence序列号等准备工作:--1.创建文件夹 :'E:/OracleBackUp/ProcBack';--文本存放的路径--2.执行:create or ...

  6. construction const parameter问题 构造函数const引用参数问题

    工程在window下编译没有任何问题, 但是在linux(CentOS6)下编译就老是报错 C++ 编译器已升级到最新版 6.1.0 错误如下: In file included /bits/stl_ ...

  7. ASP.NET MVC5+EF6+EasyUI 后台管理系统(49)-工作流设计-我的申请

    系列目录 提交一个表单后 我们需要一个管理的列表.我的申请,我的申请包含了提交内容的列表状态 状态分:过期,未审核,审核通过,驳回,废弃 列表对应代码 @using App.Admin; @using ...

  8. NodeJs对Mysql封装

    之前在学习NodeJs的时候,每次操作数据库都需要连接数据库然后开始写Sql操作,这样非常麻烦,然后自己对Mysql进行了封装,一共100多行代码. github地址: Mysql操作 我在里面对My ...

  9. SQL Tuning 基础概述03 - 使用sql_trace和10046事件跟踪执行计划

    1.使用sql_trace跟踪执行计划 1.1 当前session跟踪: alter session set sql_trace = true; //开始sql_trace alter session ...

  10. 浅谈css的伪元素::after和::before

    css中的::after和::before已经被大量地使用在我们日常开发中了,使用他们可以使我们的文档结构更加简洁.但是很多人对::after和::before仍不是特别了解,究竟他们是做什么的?如何 ...