- 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方法