目录
- 1、Restful简介
- 2、查询用户以及用户详情
- 2.1常用注解
- 2.2查询用户详情
- 3、处理创建请求
- 3.1@RequestBody注解
- 3.1.1用途
- 3.1.2语法规范
- 3.2日期类型的处理
- 3.3BindingResult
- 4、用户信息修改与删除
- 4.1用户信息修改
- 4.2案例
- 前端界面
- 后端控制器
1、Restful简介
Restful比较热门,,Spring的微服务是基于Restful风格搭建的框架。
Restful有一下几个特点:
- 使用URL描述资源。
- 使用HTTP方法描述行为,使用HTTP状态码来表示不同的结果。
- 使用JSON交互数据。
- Restful只是一种风格,不是强制标准。
2、查询用户以及用户详情
最简单的,最常用的GET请求,用于查询全部数据或者其中一条数据的详情。
2.1常用注解
常用注解 | 作用 |
@RestController | 表明此tController 提供的是Restful服务 |
@RequestMapping | 将URL映射到Java |
@RequestParam | 映射请求参数到Java上的参数 |
@PageableDefault | 指定分页参数的默认值 |
2.2查询用户详情
"/manage", method= {RequestMethod.GET}) | (value=|
public String list(String userId,Map<String,Object> map) { | |
if(userId==""||userId==null) { | |
map.put("userList", userService.getUserList()); | |
}else { | |
map.put("userList",userService.getUserById(Integer.parseInt(userId))); | |
} | |
return "user/list"; | |
} |
3、处理创建请求
3.1@RequestBody注解
3.1.1用途
用于接收前端传递给后端的json字符串中的数据。(处理json格式的数据)
@RequestBody用来接收前端传递给后端的json字符串中的数据,GET方式的请求一般通过URL中携带key-value参数,而@RequestBody接收的是请求体中的数据(json格式的数据,只有请求体中能保存json),所以使用@RequestBody接收数据的时候必须是POST方式等方式。
@RequestBody与@RequestParam()可以同时使用,但@RequestBody最多只能有一个,而@RequestParam()可以多个。
3.1.2语法规范
(Map map) | |
(Object object) |
(@RequestBody Map map)先对简单,将json解析成Map形式的key-value对,直接通过map.get(“KeyName”)就能拿到值了
(@RequestBody Object object) 通过json字符串中的key来匹配对应实体类的属性如果匹配一致且json中的该key对应的值符合实体类的对应属性的类型要求时,会调用实体类的setter方法将值注入到该属性。
例如
public Result deleteBookById( HashMap<String, String> map) { | |
this.bookService.deleteBookById(Long.parseLong(map.get("id"))); | |
return Result.createWithSuccessMessage(); | |
} | |
public Result updateBookById( Book book){ | |
Book record = this.bookService.updateBookById(book); | |
return Result.createWithModel(record); | |
} |
注意:
在(@RequestBody Object object)中,前端POST过来的数据会通过反序列数据到实体类中,并且在反序列的过程中会进行类型的转换。
在json中应该用null来代表空值,如果是"“(空字符串)会判断为空串,如果实体类属性是String类型的,那么接受到的就是”",如果实现类属性类型是Integer、Double等类型,那么接收到的就是null。
{ | |
name:"", | |
age:null | |
} |
(@RequestBody Object object)内部是通过传递过来的数据中的Key寻找setter方法,有则调用,无则不作任何操作(其实可以设计)。
如果通过Key匹配到setter方法,但是Value无法转换为对应的实例类属性的类型时,抛出异常。
3.2日期类型的处理
前端传入日期格式: yyyy-MM-dd HH:mm:ss,例如:2018-07-09 12:55:12(不使用时间戳,前后双方联调时查看起来更加友好)
后端返回日期格式: yyyy-MM-dd HH:mm:ss,例如:2018-07-09 12:55:12(不使用时间戳,前后双方联调时查看起来更加友好)
后端json序列化、反序列化框架: 定义任何一种高效的json工具都行,例如:Fastjson、Gson、Jackson lib
序列化、反序列化日期格式规范: pattern=”yyyy-MM-dd HH:mm:ss”,timezone = “GMT+8”,除特出场景可以使用pattern=”yyyy-MM-dd”,timezone = “GMT+8”
不要随意自定义convert处理日期格式以及其他特殊格式转换,应该交由基础框架组或架构组统一在框架层面解决,对业务开发透明,或者在有些小公司由Leader或高开来担当。
3.3BindingResult
/* | |
* 添加用户,使用@RequestBody将请求体映射到Action方法参数中 | |
* 使用@Valid注解验证请求参数的合法性 | |
* 使用BindingResult处理校验结果 | |
* @param user | |
* @param result | |
* @return | |
*/ | |
public User create( User user, BindingResult result){ | |
if(result.hasErrors()){ | |
result.getAllErrors().stream().forEach(error -> { | |
FieldError fieldError = (FieldError)error; | |
String message = fieldError.getField() + " " + error.getDefaultMessage(); | |
System.out.println(message); | |
}); | |
return null; | |
} | |
System.out.println(user.toString()); | |
user.setId(l); | |
return user; | |
} |
4、用户信息修改与删除
PUT和DELETE并不复杂,大家也熟悉,用于对后台数据的更新和删除。
4.1用户信息修改
对资源更新的请求方法通常是是PUT,但有时候也可能是POST。那么问题来了,都是更新资源区别在哪里?
PUT | POST |
在HTTP中PUT被定义为幂等的请求方法 | 而POST则不是 |
操作是作用于一个具体资源之上 | 作用于一个集合资源之上 |
URL在客户端确定使用PUT | URL在服务端确定使用POST |
比较直观的是资源URL的不同
4.2案例
前端界面
<html lang="en"> | |
<head> | |
<meta charset="UTF-"> | |
<title>Title</title> | |
<script src="../js/jquery.min.js"></script> | |
<script> | |
$(function () { | |
// 查询所有 | |
$('#btn').click(function () { | |
$.get('/employees', function (data) { | |
console.log(data); | |
}); | |
}); | |
// 查询一个 | |
$('#btn').click(function () { | |
$.get('/employees/', function (data) { | |
console.log(data); | |
}); | |
}); | |
// 添加 | |
$('#btn').click(function () { | |
$.post('/employees', "id=", function (data) { | |
console.log(data); | |
}); | |
}); | |
// 修改 | |
$('#btn').click(function () { | |
$.ajax({ | |
url: "/employees", | |
type: "PUT", | |
data: {id:, name: "小肥羊", age: 10}, | |
success: function (data) { | |
console.log(data); | |
} | |
}); | |
}); | |
// 删除 | |
$('#btn').click(function () { | |
$.ajax({ | |
url: "/employees/", | |
type: "DELETE", | |
data: {id:}, | |
success: function (data) { | |
console.log(data); | |
} | |
}); | |
}); | |
}); | |
</script> | |
</head> | |
<body> | |
<button id="btn">查询所有</button> | |
<button id="btn">查询一个</button> | |
<button id="btn">添加</button> | |
<button id="btn">修改</button> | |
<button id="btn">删除</button> | |
</body> | |
</html> |
后端控制器
package com.yy.web.controller; | |
import com.yy.domain.Employee; | |
import com.yy.util.JsonResult; | |
import org.springframework.stereotype.Controller; | |
import org.springframework.stereotype.Repository; | |
import org.springframework.web.bind.annotation.*; | |
import java.util.Arrays; | |
import java.util.List; | |
/** | |
* @program: restful-demo | |
* @ClassName: EmployeeController | |
* @description: | |
* @author: YanYang | |
* @create:-06-23 15:04 | |
**/ | |
public class EmployeeController { | |
/** | |
*个接口设计都是用相同资源,相同请求方法,此时 SpringMVC 无法识别, | |
* 认为是同一方法,报错:Ambiguous mapping. [模糊映射] | |
* | |
* RESTful 解决方案:使用 参数路径 方式 | |
* 具体实现:将参数作为请求映射路径一部分,[参与映射路径区分] | |
* 比如:查询指定 id 的员工信息接口设计 | |
* @RequestMapping(value = "/employees/{id}", method = RequestMethod.GET) | |
* 其中 "/employees/{id}" 参数路径,{id} 就是路径参数 | |
* | |
* 访问该接口时:http:localhost:/employees/1 其中 1 是 id 参数 | |
* 接口接收路径参数:使用 @PathVariable,表示将参数路径上的参数解析,并赋值给指定变量 | |
* 如果路径参数与变量名不一致,使用 @PathVariable("eid")明确指定 | |
* | |
*/ | |
// 查询所有(数据是模拟的) | |
// @RequestMapping(value = "/employees", method = RequestMethod.GET) | |
public List<Employee> list() { | |
return Arrays.asList(new Employee(L,"小肥羊", 10), new Employee(2L, "熊大", 11)); | |
} | |
// 查询单个(数据是模拟的) | |
// @RequestMapping(value = "/employees/{id}", method = RequestMethod.GET) | |
public Employee queryById( Long id) { | |
System.out.println("查询单个 = " + id); | |
return new Employee(L, "熊二", 8); | |
} | |
// 添加(数据是模拟的) | |
// @RequestMapping(value = "/employees", method = RequestMethod.POST) | |
public Employee add( Employee employee) { | |
System.out.println("添加 = " + employee.getId()); | |
return employee; | |
} | |
// 修改(数据是模拟的) | |
// @RequestMapping(value = "/employees", method = RequestMethod.PUT) | |
public Employee update( Employee employee) { | |
System.out.println("修改 = " + employee.getId()); | |
employee.setId(employee.getId()); | |
employee.setName(employee.getName()); | |
employee.setAge(employee.getAge()); | |
return employee; | |
} | |
// 删除(数据是模拟的) | |
// @RequestMapping(value = "/employees/{id}", method = RequestMethod.DELETE) | |
public String delete( Long id) { | |
System.out.println("删除 = " + id); | |
if (id != null && == id) { | |
return "删除成功"; | |
} | |
return "删除失败"; | |
} | |
} |