什么是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); } });