一、REST——前后台间的通信方式
1、认识REST
REST是软件架构的规范体系结构,它将资源的状态以适合客户端的形式从服务器端发送到客户端(或相反方向)。**在REST中,通过URL进行资源定位,用HTTP动作(GET、POST等)描述操作,完成功能。
遵循RESTful风格,可以使得开发的接口通用。
2、REST的特征
- 客户-服务器:提供服务的服务器和使用服务的客户端需要被隔离对待。
- 无状态:服务器端不存储客户的请求中的信息,客户的每一个请求必须包含服务器处理该请求所需的所有信息,所有的资源都可以通过URI定位。
- 可缓存:服务器必须让客户知道请求是否可以被缓存。
- 统一接口:客户和服务器之间通信的方法必须统一,RESTful风格的数据元操作CRUD分别对应HTTP方法——GET来获取、POST用来新建资源、PUT用来更新资源,DELETE用来删除资源,这样就统一了数据操作的接口。
- HTTP状态码
3、HTTP方法与CRUD动作映射
RESTful风格使用同一个URL,通过约定不同的HTTP方法来实施不同的业务。
普通网页的CRUD和RESTful风格CRUD的区别
动作 | 普通CURD的URL | 普通CRUD的HTTP方法 | Restful的URL | Restful的CRUD的HTTP方法 |
---|---|---|---|---|
查询 | Article/id=1 | GET | Article/{id} | GET |
添加 | Article?title=xxx&body=xxx | GET/POST | Article | POST |
修改 | Article/update?id=xxx | GET | Article/{id} | PUT或PATCH |
删除 | Article/delete?id=xxx | GET | Article/{id} | DELETE |
4、实现RESTful风格的数据增加、删除、修改和查询
@RestController和@RequestMapping来实现
- Value:用来定制URI
- Method:用来定制HTTP请求方法
- 通过@PathVariable("")来获取参数
@RequestMapping(Value = "/{id}",method = RequestMethod.DELETE)
public String delete(@PathVariable("id") long id){
articleRespository.deleteById(id);
return "success";
}
二、设计统一的RESTful风格的数据接口
1、版本控制
①通过URL
-
二级目录的方式:
-
http://eg.com/api/v1 http://eg.com/api/v2
-
-
二级域名的方式:
-
http://v1.eg.com http://v2.eg.com
-
②通过自定义请求头:
自定义头(例如,Accept-version)允许在版本之间保留URL
③通过Accept标头
客户端在请求资源之前,必须要指定特定头,然后API接口负责确定要发送哪个版本的资源
2、过滤信息
如果记录数量很多,则服务器不可能一次都将它们返回给用户。API应该提供参数,实现分页返回结果。
- ?limit=10:指定返回记录的数量
- ?page=5&size=10:指定第几页,以及每页的记录数
- ?search_type=1:指定筛选条件
3、定义统一的返回的格式
为了保障前后端数据交互的顺畅,建议规范数据的返回,并采用固定的数据格式封装。
异常信息:
{
"code":10001,
"msg":"异常信息",
"data":null
}
成功信息:
{
"code":200,
"msg":"成功",
"data":{
"id":1,
"name":"longzhiran",
"age":2
}
}
4、实例:为手机APP、PC、H5网页提供统一风格的API
①实现响应的枚举类
public enum ExceptionMsg{
SUCCESS("200","操作成功"),
FAILED("999999","操作失败");
public ExceptionMsg(String code,String msg){
this.code = code;
this.msg = msg;
}
private String code;
private String msg;
}
②实现返回的实体对象
实现返回的对象实体,返回Code和Message
public class Response{
private String rspCode = "200";
prvate String rspMsg = "操作成功";
}
③封装返回的结果0
public class ResponseData extends Response{
private Object data;
public ResponseData(Object data){
this.data = data;
}
}
④统一处理异常
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.*;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@RestControllerAdvice
public class GlobalExceptionHandler {
// 日志记录工具
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MissingServletRequestParameterException.class)
public Map<String, Object> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
logger.error("缺少请求参数", e);
Map<String, Object> map = new HashMap<String, Object>();
map.put("rspCode", 400);
map.put("rspMsg", e.getMessage());
//发生异常进行日志记录,写入数据库或者其他处理,此处省略
return map;
}
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class)
public Map<String, Object> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
logger.error("参数解析失败", e);
Map<String, Object> map = new HashMap<String, Object>();
map.put("rspCode", 400);
map.put("rspMsg", e.getMessage());
//发生异常进行日志记录,写入数据库或者其他处理,此处省略
return map;
}
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
logger.error("参数验证失败", e);
BindingResult result = e.getBindingResult();
FieldError error = result.getFieldError();
String field = error.getField();
String code = error.getDefaultMessage();
String message = String.format("%s:%s", field, code);
Map<String, Object> map = new HashMap<String, Object>();
map.put("rspCode", 400);
map.put("rspMsg", message);
//发生异常进行日志记录,写入数据库或者其他处理,此处省略
return map;
}
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(BindException.class)
public Map<String, Object> handleBindException(BindException e) {
logger.error("参数绑定失败", e);
Map<String, Object> map = new HashMap<String, Object>();
BindingResult result = e.getBindingResult();
FieldError error = result.getFieldError();
String field = error.getField();
String code = error.getDefaultMessage();
String message = String.format("%s:%s", field, code);
map.put("rspCode", 400);
map.put("rspMsg",message);
//发生异常进行日志记录,写入数据库或者其他处理,此处省略
return map;
}
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ConstraintViolationException.class)
public Map<String, Object> handleServiceException(ConstraintViolationException e) {
logger.error("参数验证失败", e);
Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
ConstraintViolation<?> violation = violations.iterator().next();
String message = violation.getMessage();
Map<String, Object> map = new HashMap<String, Object>();
map.put("rspCode", 400);
map.put("rspMsg", message);
//发生异常进行日志记录,写入数据库或者其他处理,此处省略
return map;
}
/**
* 400 - Bad Request
*/
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ValidationException.class)
public Map<String, Object> handleValidationException(ValidationException e) {
logger.error("参数验证失败", e);
Map<String, Object> map = new HashMap<String, Object>();
map.put("rspCode", 400);
map.put("rspMsg", e.getMessage());
//发生异常进行日志记录,写入数据库或者其他处理,此处省略
return map;
}
/**
* 405 - Method Not Allowed
*/
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public Map<String, Object> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
logger.error("不支持当前请求方法", e);
Map<String, Object> map = new HashMap<String, Object>();
map.put("rspCode", 405);
map.put("rspMsg", e.getMessage());
//发生异常进行日志记录,写入数据库或者其他处理,此处省略
return map;
}
/**
* 415 - Unsupported Media Type
*/
@ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
public Map<String, Object> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
logger.error("不支持当前媒体类型", e);
Map<String, Object> map = new HashMap<String, Object>();
map.put("rspCode", 415);
map.put("rspMsg", e.getMessage());
//发生异常进行日志记录,写入数据库或者其他处理,此处省略
return map;
}
/**
* 自定义异常类
*/
@ResponseBody
@ExceptionHandler(BusinessException.class)
public Map<String, Object> businessExceptionHandler(BusinessException e) {
logger.error("自定义业务失败", e);
Map<String, Object> map = new HashMap<String, Object>();
map.put("rspCode", e.getCode());
map.put("rspMsg", e.getMessage());
//发生异常进行日志记录,写入数据库或者其他处理,此处省略
return map;
}
/**
* 获取其它异常。包括500
*
* @param e
* @return
* @throws Exception
*/
@ExceptionHandler(value = Exception.class)
public Map<String, Object> defaultErrorHandler(Exception e) {
logger.error("Exception", e);
Map<String, Object> map = new HashMap<String, Object>();
map.put("rspCode", 500);
map.put("rspMsg", e.getMessage());
//发生异常进行日志记录,写入数据库或者其他处理,此处省略
return map;
}
}
⑤编写测试控制器
@RestController
public class TestController {
@RequestMapping("/BusinessException")
public String testResponseStatusExceptionResolver(@RequestParam("i") int i){
if (i==0){
throw new BusinessException(600,"自定义业务错误");
}
throw new ValidationException();
}
}
运行项目,访问localhost:8080/BusinessException?i=1
⑥实现数据的增加、删除、修改和查询的控制器
entity.Article
@Entity
@Table(name = "artitcle")
@Data
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String title;
private String body;
}
repository.ArticleRepository
import com.example.demo.entity.Article;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface ArticleRepository extends JpaRepository<Article,Long>, JpaSpecificationExecutor<Article> {
Article findById(long id);
}
result.ExceptionMsg
package com.example.demo.result;
//实现响应的枚举类
public enum ExceptionMsg {
SUCCESS("200", "操作成功"),
FAILED("999999","操作失败"),
ParamError("000001", "参数错误!"),
FileEmpty("000400","上传文件为空"),
LimitPictureSize("000401","图片大小必须小于2M"),
LimitPictureType("000402","图片格式必须为'jpg'、'png'、'jpge'、'gif'、'bmp'")
;
private ExceptionMsg(String code, String msg) {
this.code = code;
this.msg = msg;
}
private String code;
private String msg;
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
result.ResponseData
package com.example.demo.result;
//返回结果数据格式封装
public class ResponseData extends Response {
private Object data;
public ResponseData(Object data) {
this.data = data;
}
public ResponseData(ExceptionMsg msg) {
super(msg);
}
public ResponseData(String rspCode, String rspMsg) {
super(rspCode, rspMsg);
}
public ResponseData(String rspCode, String rspMsg, Object data) {
super(rspCode, rspMsg);
this.data = data;
}
public ResponseData(ExceptionMsg msg, Object data) {
super(msg);
this.data = data;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
@Override
public String toString() {
return "ResponseData{" +
"data=" + data +
"} " + super.toString();
}
}
/*return new ResponseData(ExceptionMsg.SUCCESS,"你好");*/
ArticleController
import com.example.demo.entity.Article;
import com.example.demo.repository.ArticleRepository;
import com.example.demo.result.ExceptionMsg;
import com.example.demo.result.Response;
import com.example.demo.result.ResponseData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("article")
public class ArticleController {
protected Response result(ExceptionMsg msg){
return new Response(msg);
}
protected Response result(){
return new Response();
}
@Autowired
private ArticleRepository articleRepository;
@Autowired
RestTemplateBuilder restTemplateBuilder;
@RequestMapping(value = "/", method = RequestMethod.GET)
public ResponseData getArticleList() {
List<Article> list = new ArrayList<Article>(articleRepository.findAll());
return new ResponseData(ExceptionMsg.SUCCESS,list);
}
//增
@RequestMapping(value = "/", method = RequestMethod.POST)
public ResponseData add(Article article) {
articleRepository.save(article);
// return "{success:true,message: \"添加成功\" }";
return new ResponseData(ExceptionMsg.SUCCESS,article);
}
//删
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public Response delete(@PathVariable("id") long id) {
/* RestTemplate client= restTemplateBuilder.build();
String uri = "http://localhost:8080" + "/{id}";
Map map= new HashMap();
map. put ("orderid",id);
Void article = client.delete(uri,map,id);*/
articleRepository.deleteById(id);
return result(ExceptionMsg.SUCCESS);
//return new ResponseData(ExceptionMsg.SUCCESS,"");
}
//改
@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public ResponseData update(Article model) {
articleRepository.save(model);
return new ResponseData(ExceptionMsg.SUCCESS,model);
}
//查
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ResponseData findArticle(@PathVariable("id") Integer id) throws IOException {
Article article = articleRepository.findById(id);
if (article != null) {
return new ResponseData(ExceptionMsg.SUCCESS,article);
}
return new ResponseData(ExceptionMsg.FAILED,article);
}
//查
@RequestMapping(value = "/re/{id}", method = RequestMethod.GET)
public Article findArticled(@PathVariable("id") Integer id) throws IOException {
RestTemplate client= restTemplateBuilder.build();
String uri = "http://localhost:8080/article/"+id;
System.out.println(uri);
Article article = client.getForObject (uri,Article.class,id) ;
return article;
}
}
通过PostMan测试接口即可,这里持久层模板用的是JPA。
三、用Swagger实现接口文档
1、配置Swagger
①添加Swagger依赖
在pom.xml文件中加入Swagger2的依赖
<!--Swagger依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--Swagger-UI依赖 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
②创建Swagger配置类
创建Swagger配置类,完成相关的配置项。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
/**
* Swagger 配置文件
*/
@Configuration
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(" RESTful APIs")
.description("RESTful APIs")
.termsOfServiceUrl("http://localhost:8080/")
.contact("long")
.version("1.0")
.build();
}
}
代码解释:
- @Configuration:让Spring来加载该配置类
- @EnableSwagger2:启用Swagger2.createRestApi函数创建Docket的Bean
- apiInfo():用来展示该APi的基本信息
- select():返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现。
- apis(RequestHandlerSelectors.basePackage()):配置包扫描路径。Swagger会扫描包下所有Controller定义的API,并产生文档内容。如果不想产生API,则使用注解@ApiIgnore。
2、编写接口文档
在完成了上述的配置之后,即生成了文档,但是这样生成的文档主要针对请求本身,而描述自动根据方法等名产生,对用户并不友好。所以,通常需要自己增加一些说明以丰富文档内容。可以通过一下注解来加以说明。
- @Api:描述类/接口的主要用途
- @ApiOperation:描述方法用途,给API增加说明
- @ApiImplcitParam:描述方法的参数,给参数增加说明
- @ApiImplicitParams:描述方法的参数(Multi-Params),给参数增加说明
- @ApiIgnore:忽略某类/方法/参数的文档
@RestController
public class HelloWorldController {
@ApiOperation(value = "hello", notes = "notes ")
@RequestMapping("/hello")
public String hello() throws Exception {
return "HelloWorld ,Spring Boot!";
}
//使用该注解忽略这个API
@ApiIgnore
@RequestMapping(value = "/ignoreApi")
public String ignoreApi() {
return "HelloWorld ,Spring Boot!";
}
四、用RestTemplate发送请求
在Java应用程序中访问RESTful服务,可以使用Apache的HttpClient来实现。不过次方法使用起来太过于繁琐,Spring提供了一种简单便捷的模板类——RestTemplate来进行操作。
RestTemplate用于同步Client端的核心类,简化与HTTP服务的通信。在默认情况下,RestTemplate默认依赖JDK的HTTP连接工具。亦可以通过setRequestFactory属性切换到不同的HTTP源,比如Apache HttpComponents、Netty和OkHttp。
RestTemplate默认使用HttpMessageConverter将HTTP消息转换成POJO,或从POJO转换成HTTP消息,默认情况下会注册MIME类型的转换器,但也可以通过setMessageConverters注册其他类型的转换器。
1、用RestTemplate发送GET请求
可以通过getForEntity和getForObject两种方式
①创建测试实体
public class User {
private long id;
private String name;
public User() {
}
public User(long id, String name) {
this.id = id;
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
②创建测试的API
package com.example.demo.controller;
import com.example.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
@RestController
public class TestController {
@RequestMapping(value = "/getparameter", method = RequestMethod.GET)
public User getparameter(User user) {
return user;
}
@RequestMapping(value = "/getuser1", method = RequestMethod.GET)
public User user1() {
return new User(1, "zhonghua");
}
@RequestMapping(value = "/postuser", method = RequestMethod.POST)
public User postUser(User user) {
System.out.println("name:" + user.getName());
System.out.println("id:" + user.getId());
return user;
}
}
③使用getForEntity测试
a.返回String,不带参数的例子。
package com.example.demo.controller;
import com.example.demo.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.*;
@SpringBootTest
@RunWith(SpringRunner.class)
public class GetTest {
@Autowired
RestTemplateBuilder restTemplateBuilder;
//返回String,不带参数
@Test
public void nparameters() {
RestTemplate client= restTemplateBuilder.build();
ResponseEntity<String> responseEntity = client.getForEntity("http://localhost:8080/getuser1", String.class);
System.out.println(responseEntity.getBody());
}
}
运行测试单元,控制台输出结果:
{"id":1,"name":"zhonghua"}
b.返回String,带参数的例子。
@Test
public void withparameters1() {
RestTemplate client= restTemplateBuilder.build();
ResponseEntity<String> responseEntity = client.getForEntity("http://localhost:8080/getparameter? name={1}&id={2}", String.class, "hua",2);
System.out.println(responseEntity.getBody());
}
运行测试单元,控制台输入结果:
{"id":2,"name":"hua"}
//返回String,带参数
@Test
public void withparameters2() {
RestTemplate client= restTemplateBuilder.build();
Map<String, String> map = new HashMap<>();
map.put("name", "zhonghuaLong");
ResponseEntity<String> responseEntity = client.getForEntity("http://localhost:8080/getparameter?name={name}&id=3", String.class, map);
System.out.println(responseEntity.getBody());
}
使用name={name}这种形式。最后一个参数是一个map,map的key即为前边占位符的名字,map的value为参数值。
c.返回对象
@Test
public void restUser1() {
RestTemplate client= restTemplateBuilder.build();
ResponseEntity<User> responseEntity = client.getForEntity("http://localhost:8080/getuser1", User.class);
System.out.println(responseEntity.getBody().getId());
System.out.println(responseEntity.getBody().getName());
}
④使用getForObject
getForObject函数是对getForEntity函数的进一步封装。如果只关注返回消息体的内容,而对其他信息都不关注,则可以使用getForObject。
@Test
public void getForObject() {
RestTemplate client= restTemplateBuilder.build();
User user = client.getForObject("http://localhost:8080/getuser1", User.class);
System.out.println(user.getName());
}
2、用RestTemplate发送POST请求
POST请求可以通过postForEntity、postForObject、postForLocation、exchange四种方法来发起。
注意:用上述三种方法传递参数的时候,Map不能被定义为HashMap、LinkedHashMap,而应该被定义为LinkedMultiValueMap,这样参数才能成功传递到后台
①使用postForEntity
package com.example.demo.controller;
import com.example.demo.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import static org.junit.Assert.*;
@SpringBootTest
@RunWith(SpringRunner.class)
public class PostTest {
@Autowired
RestTemplateBuilder restTemplateBuilder;
RestTemplate restTemplate = new RestTemplate();
@Test
public void postForEntity() {
//RestTemplate client= restTemplateBuilder.build();
// 封装参数,千万不要替换为Map与HashMap,否则参数无法传递
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
paramMap.add("name", "longzhiran");
paramMap.add("id", 4);
/* User user = new User();
user.setName("hongwei");
user.setId(4);*/
//方法的第一参数表示要调用的服务的地址
//方法的第二个参数表示上传的参数
//方法的第三个参数表示返回的消息体的数据类型
ResponseEntity<User> responseEntity = restTemplate.postForEntity("http://localhost:8080/postuser", paramMap, User.class);
System.out.println( responseEntity.getBody().getName());
}
}
- restTemplate.postForEntity("url",paramMap,User.class):参数分别表示要调用的服务的地址、上传的参数、返回的消息体的数据类型。
②使用postForObject
@Test
public void postForObject() {
// 封装参数,千万不要替换为Map与HashMap,否则参数无法传递
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
paramMap.add("name", "longzhonghua");
paramMap.add("id", 4);
RestTemplate client = restTemplateBuilder.build();
String response = client.postForObject("http://localhost:8080/postuser", paramMap, String.class);
System.out.println(response);
}
③使用postForexchange
@Test
public void postForexchange() {
// 封装参数,千万不要替换为Map与HashMap,否则参数无法传递
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
paramMap.add("name", "longzhonghua");
paramMap.add("id", 4);
RestTemplate client = restTemplateBuilder.build();
HttpHeaders headers = new HttpHeaders();
//headers.set("id", "long");
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String, Object>> (paramMap,headers);
ResponseEntity<String> response = client.exchange("http://localhost:8080/postuser", HttpMethod.POST,httpEntity,String.class,paramMap);
System.out.println(response.getBody());
}
④使用postForLocation
它用于提交数据,并获取返回的URI。一般登录注册都是POST请求,操作完成之后,跳转到某个页面,这种场景就可以使用postForLocation。所以,先要添加处理登录的API:
@ResponseBody
@RequestMapping(path = "success")
public String loginSuccess(String name, Integer id) {
return "welcome " + name;
}
@RequestMapping(value = "/post", method = RequestMethod.POST)
public String post(HttpServletRequest request, @RequestParam(value = "name", required = false) String name,
@RequestParam(value = "password", required = false) String password, @RequestParam(value = "id", required = false) Integer id, HttpServletResponse response) {
// 如果获取的值为“null”,则需要把URI添加到response信息的header中。添加方法为:“response.addHeader("Location",uri)”
response.addHeader("Location", "success?name=" + name + "&id=" + id + "&status=success");
return "redirect:/success?name=" + name + "&id=" + id + "&status=success";
// return "redirect:/success?name=" + URLEncoder.encode(name, "UTF-8") + "&id=" + id + "&status=success";
}
然后使用postForLocation请求
@Test
public void postForLocation() {
// 封装参数,千万不要替换为Map与HashMap,否则参数无法传递
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<String, Object>();
paramMap.add("name", "longzhonghua");
paramMap.add("id", 4);
RestTemplate client = restTemplateBuilder.build();
URI response = client.postForLocation("http://localhost:8080/post",paramMap);
System.out.println(response);
}