- rest风格:被推荐各个微服务系统之间用于交互的方式
- 每一个资源对应着一个网站
- 资源网址 是一个名词,而不是动词
- 简易参数通过网址 进行传递
- http://localhost:8080/user/1
- user名词,代表用户信息
- 1 是用户编号,获取用户id为1的资源
rest概述
-
roy thomas fielding在 2000年 博士论文提出的
-
fielding是 http 1.0 和 1.1的主要设计者,apache 服务器软件的作者,apache 第一任主席
-
将他对 互联网 软件的架构原则,命名为:rest (representationnal state transfer)
-
representationnal state transfer 表现状态转换
-
首先需要有资源才能表现 (资源)
-
有了资源也要根据需要以 合适的形式 表现资源 (表现层)
-
资源可以 新增 修改 删除 (状态转换)
-
资源:
- 系统权限用户 角色 菜单
- 媒体类型 文本 图片 歌曲
- 具体存在的对象,可以用URL,统一资源定位器 指向它
- 每一个资源 都会 对应一个 独一无二的URI,URI 可以称为端点 end Point
-
表现层:
- 如何表现这个资源, json xml 一幅图片
-
状态转换:
- 资源并不是 一成不变的,资源经历:创建,访问,修改,删除
- http协议,是一个没有状态的协议,只能在服务端保存,http中存在多种动作来对应这些变化。
-
result风格的特点
- 每个资源通过 单独唯一的 URI 进行标识
- 客户端和服务端相互传递资源,而资源以某种表现层 得以展示
- 客户端通过 HTTP协议所定义的动作 对资源进行操作。
http的动作
-
rest风格 通过http的行为去操作资源
-
创建 修改 访问 删除 转换
- get (visit) 访问
- post (create) 用来创建新的资源
- put (update) 修改,需要把资源的所有属性,一并提交
- patch (update) 修改已经存在的资源,只需要将部分资源属性提交。(这个动作并不普及,java还不能完全支持它)
- delete 从服务器将资源删除
-
对于 http协议 ,还有另外两种不常用的动作行为
- head 获取资源的元数据 content-type
- options 提供资源 可供 客户端修改的属性信息
- 实用价值不大
-
rest风格的URI设计
- get /user/1
-
get /users/{username}/{note}
- post /user/{username}/{sex}/{note}
-
put /user/{id}/{username}/{sex}/{note}
- patch /user/{id}/{userName} 修改局部
-
URI 不能出现动词,对于参数 主要通过 URI设计去获取
- 对于参数 超过 5个 ,用 JSON 传递。(我觉得超过4个就用json)
rest风格误区
- 不应该出现动词。 get /user/get/1 修改为 /user/1
- 不应该有版本号。 get /v1/user/1 。应该 设置http请求头, Accept:version=1.0
- put users?userName=user_name¬e=note。建议 /users/{userName}/{note} 参数比较多用 json
spring MVC 开发 rest风格端点
-
在 4.3 之后,更多的注解 引入 使得 REST 风格的开发 更为便捷
-
@RequestMapping
-
@GetMapping
-
@PostMapping
-
@PutMapping 提交所有资源
-
@PatchMapping 提交部分资源
-
@DeleteMapping
-
简单参数,通过URL直接传递
-
@PathVariable
-
@RequestBody 多个用json
- MVC 通过, MappingJackson2HttpMessageConverter
-
@RestConteroller 整个控制器 都默认转换为 json数据
-
请求一幅图片,一段视频。 Spring提供 协商资源的视图解析器 ContentNegotiatingViewResolver
使用 Spring开发 rest风格的端点
-
dao使用的是 PO (persisent Object),直接对应数据库的表
-
@Alias("user") public class User { private Long id; private String userName; private String note; private SexEnum sex=null; }
-
po sex是枚举类型的
-
-
前端难以理解,所以有了 VO
-
public class User { private Long id; private String userName; private String note; private String sexName; private int sexCode; }
-
把枚举类转换成 字符串 和 代码
-
通用工具类
public enum SexEnum {
MALE(0, "男"),
FEMALE(1, "女");
private int code;
private String name;
SexEnum(int code, String name) {
this.code = code;
this.name = name;
}
public static SexEnum getSexEnum(int code) {
for (SexEnum sex : SexEnum.values()) {
if (sex.getCode() == code) {
return sex;
}
}
return null;
}
}
// 转换Vo变为PO
private User changeToPo(UserVo userVo) {
User user = new User();
user.setId(userVo.getId());
user.setUserName(userVo.getUserName());
user.setSex(SexEnum.getSexEnum(userVo.getSexCode()));
user.setNote(userVo.getNote());
return user;
}
// 转换PO变为VO
private UserVo changeToVo(User user) {
UserVo userVo = new UserVo();
userVo.setId(user.getId());
userVo.setUserName(user.getUserName());
userVo.setSexCode(user.getSex().getCode());
userVo.setSexName(user.getSex().getName());
userVo.setNote(user.getNote());
return userVo;
}
// 将PO列表转换为VO列表
private List<UserVo> changeToVoes(List<User> poList) {
List<UserVo> voList = new ArrayList<>();
for (User user : poList) {
UserVo userVo = changeToVo(user);
voList.add(userVo);
}
return voList;
}
// 结果VO
public class ResultVo {
private Boolean success = null;
private String message = null;
public ResultVo() {
}
public ResultVo(Boolean success, String message) {
this.success = success;
this.message = message;
}
}
插入 controller 和 js
@Controller
public class UserController {
// 用户服务接口
@Autowired
private UserService userService = null;
// 映射JSP视图
@GetMapping("/restful")
public String index() {
return "restful";
}
@PostMapping("/user")
@ResponseBody
public User insertUser(@RequestBody UserVo userVo) {
User user = this.changeToPo(userVo);
return userService.insertUser(user);
}
}
function post() {
var params = {
'userName': 'user_name_new',
'sexCode' : 1,
'note' : "note_new"
}
$.post({
url : "./user",
// 此处需要告知传递参数类型为JSON,不能缺少
contentType : "application/json",
// 将JSON转化为字符串传递
data : JSON.stringify(params),
// 成功后的方法
success : function(result) {
if (result == null || result.id == null) {
alert("插入失败");
return;
}
alert("插入成功");
}
});
}
得到 get和 js
// 获取用户
@GetMapping(value = "/user/{id}")
@ResponseBody
public UserVo getUser(@PathVariable("id") Long id) {
User user = userService.getUser(id);
return changeToVo(user);
}
@GetMapping("/users/{userName}/{note}/{start}/{limit}")
@ResponseBody
public List<UserVo> findUsers(
@PathVariable("userName") String userName,
@PathVariable("note") String note,
@PathVariable("start") int start,
@PathVariable("limit") int limit) {
List<User> userList = userService.findUsers(userName, note, start, limit);
return this.changeToVoes(userList);
}//如果参数多于 5个,就用json传递
function get() {
$.get("./user/1", function(user, status) {
if (user == null) {
alert("结果为空")
} else {
alert("用户信息为"+JSON.stringify(user));
}
});
}
get();
function findUsers() {
$.get("./users/u/n/0/5", function(user, status) {
if (user == null) {
alert("结果为空")
} else {
alert("用户信息为:"+JSON.stringify(user));
}
});
}
findUsers();
修改
@PutMapping("/user/{id}")
@ResponseBody
public User updateUser(@PathVariable("id") Long id, @RequestBody UserVo userVo) {
User user = this.changeToPo(userVo);
user.setId(id);
userService.updateUser(user);
return user;
}
function updateUser() {
var params = {
'userName' : 'user_name_1_update',
'sexCode' : 1,
'note' : "note_new_1"
}
$.ajax({
url : "./user/1",
// 此处告知使用PUT请求
type : 'PUT',
// 此处需要告知传递参数类型为JSON,不能缺少
contentType : "application/json",
// 将JSON转化为字符串传递
data : JSON.stringify(params),
success : function(user, status) {
if (user == null) {
alert("结果为空")
} else {
alert(JSON.stringify(user));
}
}
});
}
updateUser();
//jquery 不存在put,用 ajax替代
修改局部
//一些重要的java类 可能还不能够支持它
function updateUserName() {
$.ajax({url:"./user/1/user_name_patch",
type:"PATCH",
success: function(result, status) {
if (result == null) {
alert("结果为空")
} else {
alert(result.success? "更新成功" : "更新失败");
}
}
})
}
updateUserName();
@PatchMapping("/user/{id}/{userName}")
@ResponseBody
public ResultVo changeUserName(@PathVariable("id") Long id,
@PathVariable("userName") String userName) {
int result = userService.updateUserName(id, userName);
ResultVo resultVo = new ResultVo(result>0,
result > 0 ? "更新成功" : "更新用户【" + id + "】失败。");
return resultVo;
}
删除
@DeleteMapping("/user/{id}")
@ResponseBody
public ResultVo deleteUser(@PathVariable("id") Long id) {
int result = userService.deleteUser(id);
ResultVo resultVo = new ResultVo(result>0,
result > 0 ? "更新成功" : "更新用户【" + id + "】失败。");
return resultVo;
}
function deleteUser() {
$.ajax({
url : "./user/1",
type :'DELETE',
success : function(result) {
if (result == null) {
alert("结果为空")
} else {
alert(result.success? "删除成功" : "删除失败");
}
}});
}
deleteUser();
表单提交修改
@PatchMapping("/user/name")
@ResponseBody
public ResultVo changeUserName2(Long id, String userName) {
int result = userService.updateUserName(id, userName);
ResultVo resultVo = new ResultVo(result>0,
result > 0 ? "更新成功" : "更新用户名【" + id + "】失败。");
return resultVo;
}
// 映射JSP视图
@GetMapping("/user/name")
public String changeUserName() {
return "change_user_name";
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>表单定义HTTP动作</title>
</head>
<body>
<form id="form" action="./name" method="post">
<table>
<tr>
<td>用户编号</td>
<td><input id="id" name="id" /></td>
</tr>
<tr>
<td>用户名称</td>
<td><input id="userName" name="userName" /></td>
</tr>
<tr>
<td></td>
<td align="right"><input id="submit" name="submit"
type="submit" /></td>
</tr>
</table>
<input type="hidden" name="_method" id="_method" value="PATCH" />
</form>
</body>
</html>
1.form 定义为post
2.form 中还存在 一个命令为 _method 。
这样就能定位到了
@RestController
@RestController
public class UserController2 {
// 用户服务接口
@Autowired
private UserService userService = null;
// 映射JSP视图
@GetMapping(value = "/restful2")
public ModelAndView index() {
ModelAndView mv = new ModelAndView("restful");
return mv;
}
// 获取用户
@GetMapping(value = "/user2/{id}")
public UserVo getUser(@PathVariable("id") Long id) {
User user = userService.getUser(id);
return changeToVo(user);
}
}
- JSP 也要渲染的话,就不能直接返回字符串了
渲染结果
-
还有 PDF,Excel 等媒体类型 MediaType
-
一种:@ResponseBody,用Ioc容器中 HttpMessageConverter 接口实现类的 MappingJackson2HttpMessageConverter
-
一种:ModelAndView mv = new ModelAndView(“restful”); 使用ModelAndView捆绑视图
-
HttpMessageConverter 接口有两个实现类:StringHttpMessageConverter 和 MappingJackson2HttpMessageConverter
-
HttpMessageConverter 定义了:boolean canWrite(Class<?> var1, @Nullable MediaType var2); 。MediaType 是可以传入的媒体类型。MVC在执行控制器方法后,会变量HttpMessageConverter 接口的实现类。并使用canWrite 判断是否拦截控制器的返回
-
@RequestMapping GetMapping 还存在 consumes和produces
-
consumes 代表限制该方法 接收什么类型的请求体 (body)。消费者。action是消费 前端的请求
-
produces 代表限定返回的媒体类型。 action是提供者。仅当 request请求头中 (Accept ) 类型中包含 该指定类型才返回。
-
@RestController public class UserController2 { // 获取用户 @GetMapping(value = "/user2/{id}") public UserVo getUser(@PathVariable("id") Long id) { User user = userService.getUser(id); return changeToVo(user); } @GetMapping(value = "/user2/name/{id}", // 接受任意类型的请求体 consumes = MediaType.ALL_VALUE, // 限定返回的媒体类型为文本 produces = MediaType.TEXT_PLAIN_VALUE) public String getUserName(@PathVariable("id") Long id) { User user = userService.getUser(id); // 返回字符 return user.getUserName(); } } @GetMapping(value = "/user2/name/{id}", // 接受任意类型的请求体 consumes = MediaType.ALL_VALUE, // 限定返回的媒体类型为文本 produces = MediaType.TEXT_PLAIN_VALUE)
-
@RestController 默认方法标注为:application/json;charset=UTF-8
-
getUser方法结束后,遍历 HttpMessageConverter 接口有两个实现类:StringHttpMessageConverter 和 MappingJackson2HttpMessageConverter 。MappingJackson2HttpMessageConverter 的 canWrite方法 返回true
-
就将启用这个转换器 将其装换成 json 数据集
-
getUserName consumes为接收所有的请求体 body。所以可接收任何的请求体。 结果声明为 了 普通文本(会修改默认的json类型)。会被 StringHttpMessageConverter 拦截。 转为一个简单的字符串
-
-
-
-
对于没有 HttpMessageConverter 机制 没有处理的数据模型,它会 流转到视图解析器(ViewResolver)。ModelAndView mv = new ModelAndView(“restful”); Spring对rest支持中,还提供 协商视图解析器 contentNegotiatingViewResolver 。控制器找不到HttpMessageConverter ,就会流转到他那里。解析到这个view类,然后返回,找到视图解析器 如: InternalResourceViewResolver ,对jsp渲染
-
视图解析器
- BeanName ViewResolver 根据请求URI名称找到 对应的视图
- View Resolver Composite 视图解析器组合
- InternalResourceView 逻辑视图解析器,最常用。子类有 JstlViewResolver
处理 http 状态码,异常 和 响应头
-
没有找到资源,或者发生异常。
-
返回给前端 http状态码 和 错误消息
-
spring提供 实体类封装类 ResponseEntiry 和 注解 @ResponseStatus
-
封装错误消息 和 状态码,通过 @ResponseStatus 配置指定的响应码给 客户端
-
200 代表请求成功
-
201 代表新增资源成功
-
http响应头加入属性 响应码
-
-
@PostMapping(value = "/user2/entity") public ResponseEntity<UserVo> insertUserEntity( @RequestBody UserVo userVo) { User user = this.changeToPo(userVo); userService.insertUser(user); UserVo result = this.changeToVo(user); //定义hearder HttpHeaders headers = new HttpHeaders(); String success = (result == null || result.getId() == null) ? "false" : "true"; // 设置响应头,比较常用的方式 headers.add("success", success); // 下面是使用集合(List)方式,不是太常用 // headers.put("success", Arrays.asList(success)); // 返回创建成功的状态码 return new ResponseEntity<UserVo>(result, headers, HttpStatus.CREATED); } @PostMapping(value = "/user2/annotation") // 指定状态码为201(资源已经创建) @ResponseStatus(HttpStatus.CREATED) public UserVo insertUserAnnotation(@RequestBody UserVo userVo) { User user = this.changeToPo(userVo); userService.insertUser(user); UserVo result = this.changeToVo(user); return result; }
-
function postStatus() { // 请求体 var params = { 'userName': 'user_name_new', 'sexCode' : 1, 'note' : "note_new" } var url = "./user2/annotation"; // var url = "./user2/annotation"; $.post({ url : url, // 此处需要告知传递参数类型为JSON,不能缺少 contentType : "application/json", // 将JSON转化为字符串传递 data : JSON.stringify(params), // 成功后的方法 success : function(result, status, jqXHR) { // 获取响应头 var success = jqXHR.getResponseHeader("success"); // 获取状态码 var status = jqXHR.status; alert("响应头参数是:" + success+",状态码是:" + status); if (result == null || result.id == null) { alert("插入失败"); return; } alert("插入成功"); } }); } { "id": 6, "userName": "我的测试2", "sexCode": 1, "sexName": "女", "note": "我的测试备注2" } 上面两个返回都一样。 第一个header头会返回success 为true。status 都会返回201
异常处理
- 异常可以用 @ControllerAdvice (定义控制器通知) 和 @ExceptionHandler (异常发生的处理方法)
异常处理类
-
public class NotFoundException extends RuntimeException { private static final long serialVersionUID = 1L; // 异常编码 private Long code; // 异常自定义信息 private String customMsg; public NotFoundException() { } public NotFoundException(Long code, String customMsg) { super(); this.code = code; this.customMsg = customMsg; } }
-
找不到用户的时候,抛出此异常,在 控制器通知 @controller Advice中 来处理这些异常
-
使用:@ExceptionHandler 。Boot 里面自带 BasicErrorController
异常处理的通知
//控制器通知
@ControllerAdvice(
// 指定拦截包的控制器
basePackages = { "com.springboot.chapter11.controller.*" },
// 限定被标注为@Controller或者@RestController的类才被拦截
annotations = { Controller.class, RestController.class })
public class VoControllerAdvice {
// 异常处理,可以定义异常类型进行拦截处理
@ExceptionHandler(value = NotFoundException.class)
// 以JSON表达方式响应
@ResponseBody
// 定义为服务器错误状态码
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//500
public Map<String, Object> exception(HttpServletRequest request, NotFoundException ex) {
Map<String, Object> msgMap = new HashMap<>();
// 获取异常信息
msgMap.put("code", ex.getCode());
msgMap.put("message", ex.getCustomMsg());
return msgMap;
}
}
{
"code": 1,
"message": "找不到用户【1000】信息"
}
测试action
@GetMapping(value="/user/exp/{id}",
// 产生JSON数据集
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
// 响应成功
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public UserVo getUserForExp(@PathVariable("id") Long id) {
User user = userService.getUser(id);
// 如果找不到用户,则抛出异常,进入控制器通知
if (user == null) {
throw new NotFoundException(1L, "找不到用户【" + id +"】信息");
}
UserVo userVo = changeToVo(user);
return userVo;
}
dao代码
@Mapper
public interface UserDao {
public User getUser(Long id);
public int insertUser(User user);
public List<User> findUsers(@Param("userName") String userName, @Param("note") String note, @Param("start") int start, @Param("limit") int limit);
public int updateUser(User user);
public int updateUserName(@Param("id") Long id, @Param("userName") String userName);
public int deleteUser(Long id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.springboot.chapter11.dao.UserDao">
<resultMap type="user" id="userMapper">
<result column="id" property="id"/>
<result column="user_name" property="userName"/>
<result column="sex" property="sex" typeHandler="com.springboot.chapter11.typeHandler.SexTypeHandler"/>
<result column="note" property="note"/>
</resultMap>
<select id="getUser" resultMap="userMapper">
select id, user_name, sex, note from t_user where id = #{id}
</select>
<select id="findUsers" resultMap="userMapper">
select id, user_name, sex, note from t_user
<where>
<if test="userName != null"> and user_name like concat('%', #{userName}, '%')</if>
<if test="note != null"> and note like concat('%', #{note}, '%')</if>
</where>
limit #{start}, #{limit}
</select>
<insert id="insertUser" parameterType="user" useGeneratedKeys="true" keyProperty="id">
insert into t_user(user_name, sex, note) values(#{userName}, #{sex, typeHandler=com.springboot.chapter11.typeHandler.SexTypeHandler}, #{note})
</insert>
<update id="updateUser" parameterType="user">
update t_user
<set>
<if test="userName != null"> user_name = #{userName},</if>
<if test="sex != null"> sex = #{sex, typeHandler=com.springboot.chapter11.typeHandler.SexTypeHandler},</if>
<if test="note != null">note = #{note}</if>
</set>
where id= #{id}
</update>
<update id="updateUserName">
update t_user set user_name = #{userName} where id = #{id}
</update>
<delete id="deleteUser" parameterType="long">
delete from t_user where id = #{id}
</delete>
</mapper>
解析器
@MappedTypes(SexEnum.class)
@MappedJdbcTypes(JdbcType.INTEGER)
public class SexTypeHandler extends BaseTypeHandler<SexEnum> {
@Override
public SexEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
int code = rs.getInt(columnName);
return SexEnum.getSexEnum(code);
}
@Override
public SexEnum getNullableResult(ResultSet rs, int index) throws SQLException {
int code = rs.getInt(index);
return SexEnum.getSexEnum(code);
}
@Override
public SexEnum getNullableResult(CallableStatement cs, int index) throws SQLException {
int code = cs.getInt(index);
return SexEnum.getSexEnum(code);
}
@Override
public void setNonNullParameter(PreparedStatement ps, int index, SexEnum sex, JdbcType jdbcType) throws SQLException {
ps.setInt(index, sex.getCode());
}
}
客户端请求 TestTemplate
-
每个微服务都会暴露 Rest风格的URI 请求,给别的微服务系统所调用
-
为了方便相互调用 给予了模板类 RestTemplate (还有声明式调用)
-
产品 用户 财务 交易 分别作为一个单独的系统
-
交易系统:希望得到 产品 ,用户 ,和 财务的信息
-
有 webService 和 远程调用 (RPC)
-
推荐使用 REST风格 来完成系统之间的交互
-
会带来并发的过程导致数据的不一致,分布式数据库事务
-
在 Spring 5 所推出的 WebFlux 中,还有 WebClient
-
RestTemplate底层是: HttpURLConnection实现的
最简单的查询
// 获取用户
public static UserVo getUser(Long id) {
// 创建一个RestTemplate对象
RestTemplate restTmpl = new RestTemplate();
// 消费服务,第一个参数为url,第二个是返回类型,第三个是URI路径参数
UserVo userVo = restTmpl.getForObject(
"http://localhost:8080/user/{id}", UserVo.class, id);
// 打印用户名称
System.out.println(userVo.getUserName());
return userVo;
}
- 实际服务器只会返回Json类型的数据给我们,RestTemplate 会转成java
多个参数,简介写法
public static List<UserVo> findUser(String userName,
String note, int start, int limit) {
RestTemplate restTmpl = new RestTemplate();
// 使用Map进行封装多个参数,以提高可读性
Map<String, Object> params = new HashMap<String, Object>();
params.put("userName", "user");
params.put("note", "note");
params.put("start", start);
params.put("limit", limit);
// Map中的key和URI中的参数一一对应
String url = "http://localhost:8080/users/{userName}/{note}/{start}/{limit}";
// 请求后端
ResponseEntity<List> responseEntity = restTmpl.getForEntity(url, List.class, params);
List<UserVo> userVoes = responseEntity.getBody();
return userVoes;
}
- 先将map封装起来,
json请求
// 新增用户
public static User insertUser(UserVo newUserVo) {
// 请求头
HttpHeaders headers = new HttpHeaders();
// 设置请求内容为JSON类型
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
// 创建请求实体对象
HttpEntity<UserVo> request = new HttpEntity<>(newUserVo, headers);
RestTemplate restTmpl = new RestTemplate();
// 请求时传递请求实体对象,并返回回填id的用户
User user = restTmpl.postForObject("http://localhost:8080/user", request, User.class);
System.out.println(user.getId());
return user;
}
/**
* A String equivalent of {@link MediaType#APPLICATION_JSON_UTF8}.
*相当于{@link MediaType#APPLICATION_JSON_UTF8}的字符串。
* @deprecated as of 5.2 in favor of {@link #APPLICATION_JSON_VALUE}
* @deprecated as 5.2赞成{@link #APPLICATION_JSON_VALUE}
* since major browsers like Chrome
*主要浏览器如Chrome
* <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=438464">
* now comply with the specification</a> and interpret correctly UTF-8 special
*现在符合规范</a>和正确解释UTF-8特殊
* characters without requiring a {@code charset=UTF-8} parameter.
*不需要{@code字符集=UTF-8}参数的字符。
*/
@Deprecated
public static final String APPLICATION_JSON_UTF8_VALUE = "application/json;charset=UTF-8";
public static final String APPLICATION_JSON_VALUE = "application/json";
删除
public static void deleteUser(Long id) {
RestTemplate restTmpl = new RestTemplate();
restTmpl.delete("http://localhost:8080/user/{id}", id);
}
- restTemplate 是用 HttpURLConnection 的,不支持 PATCH
- PATCH 是对 PUT的补充,
获取响应头,状态码,和 资源交换
public static User insertUserEntity(UserVo newUserVo) {
// 请求头
HttpHeaders headers = new HttpHeaders();
// 请求类型
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
// 绑定请求体和头
HttpEntity<UserVo> request = new HttpEntity<>(newUserVo, headers);
RestTemplate restTmpl = new RestTemplate();
// 请求服务器
ResponseEntity<User> userEntity = restTmpl.postForEntity(
"http://localhost:8080/user2/entity", request, User.class);
// 获取响应体
User user = userEntity.getBody();
// 获取响应头
HttpHeaders respHeaders = userEntity.getHeaders();
// 获取响应属性
List<String> success = respHeaders.get("success");
// 响应的HTTP状态码
int status = userEntity.getStatusCodeValue();
System.out.println(user.getId());
return user;
}
-
ResponseEntity userEntity = restTmpl.postForEntity()
-
包含响应体 和 状态码 和 响应头
-
exchange 资源交换使用:
public static User useExchange(UserVo newUserVo, Long id) { // 请求头 HttpHeaders headers = new HttpHeaders(); // 请求类型 headers.setContentType(MediaType.APPLICATION_JSON_UTF8); // 绑定请求体和头 HttpEntity<UserVo> request = new HttpEntity<>(newUserVo, headers); RestTemplate restTmpl = new RestTemplate(); String url = "http://localhost:8080/user2/entity"; // 请求服务器 ResponseEntity<User> userEntity = restTmpl.exchange(url, HttpMethod.POST, request, User.class); // 获取响应体 User user = userEntity.getBody(); // 获取响应头 HttpHeaders respHeaders = userEntity.getHeaders(); // 响应头属性 List<String> success = respHeaders.get("success"); // 响应的HTTP状态码 int status = userEntity.getStatusCodeValue(); System.out.println(user.getId()); // 修改URL获取资源 url = "http://localhost:8080/user/{id}"; // 传递URL地址参数 ResponseEntity<UserVo> userVoEntity = restTmpl.exchange(url, HttpMethod.GET, null, UserVo.class, id); // 获取响应体 UserVo userVo = userVoEntity.getBody(); System.out.println(userVo.getUserName()); return user; }
- 更多的时候,还是用 PostForEntity 和 getForEntity方法