RestTemplate的exchange()方法,解决put和delete请求拿不到返回值的问题
嗷嗷待哺的controller(被调用provider的controller方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //测试get少量参数 @RequestMapping (value = "detailsGetD" ,method = RequestMethod.GET) public String test05(Integer id,String name){ System.out.println( "GET-" +id+ "-" +name); return "error" ; } //测试post @RequestMapping (value = "detailsPostD" ,method = RequestMethod.POST) public String test06(Integer id,String name){ System.out.println( "POST-" +id+ "-" +name); return "error" ; } //测试put @RequestMapping (value = "detailsPutD" ,method = RequestMethod.PUT) public String test07(Integer id,String name){ System.out.println( "PUT-" +id+ "-" +name); return "error" ; } //测试delete @RequestMapping (value = "detailsDeleteD" ,method = RequestMethod.DELETE) public String test08(Integer id,String name){ System.out.println( "DELETE-" +id+ "-" +name); return "error" ; } |
consumer的调用传参(url拼接少量参数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //get传递单参 ResponseEntity<String> resp = restTemplate.exchange( "http://localhost:8080/detailsGetD?id={id}&name={name}" , HttpMethod.GET, null , String. class , 1 , "zsw" ); //post传递单参 ResponseEntity<String> resp = restTemplate.exchange( "http://localhost:8080/detailsPostD?id={id}&name={name}" , HttpMethod.POST, null , String. class , 1 , "zsw" ); //put传递单参 Map<String,Object> map= new HashMap<>(); map.put( "id" , 1 ); map.put( "name" , "zsw" ); ResponseEntity<String> resp = restTemplate.exchange( "http://localhost:8080/detailsPutD?id={id}&name={name}" , HttpMethod.PUT, null , String. class ,map); //delete传递单参 Map<String,Object> map= new HashMap<>(); map.put( "id" , 1 ); map.put( "name" , "zsw" ); ResponseEntity<String> resp = restTemplate.exchange( "http://localhost:8080/detailsDeleteD?id={id}&name={name}" , HttpMethod.DELETE, null , String. class ,map); //返回内容 String result = resp.getBody(); System.out.println(result); |
使用map和直接写参数都可以。
再介绍一下传json对象。
首先登场的是provider方controller。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //测试get @RequestMapping (value = "detailsGet" ,method = RequestMethod.GET) public String test01( @RequestBody Detail detail){ System.out.println( "GET-" +detail); return "error" ; } //测试post @RequestMapping (value = "detailsPost" ,method = RequestMethod.POST) public String test02( @RequestBody Detail detail){ System.out.println( "POST-" +detail); return "error" ; } //测试put @RequestMapping (value = "detailsPut" ,method = RequestMethod.PUT) public String test03( @RequestBody Detail detail){ System.out.println( "PUT-" +detail); return "error" ; } //测试delete @RequestMapping (value = "detailsDelete" ,method = RequestMethod.DELETE) public String test04( @RequestBody Detail detail){ System.out.println( "DELETE-" +detail); return "error" ; } |
我们再来看consumer的选手,传参json对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | String json = "{\"author\":\"zsw\",\"createdate\":1582010438846,\"id\":1,\"summary\":\"牡丹\",\"title\":\"菏泽\"}" ; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<String> entity = new HttpEntity<>(json,headers); ResponseEntity<String> resp = restTemplate.exchange( "http://localhost:8080/detailsPost" , HttpMethod.POST, entity, String. class ); HttpStatus statusCode = resp.getStatusCode(); // 获取响应码 int statusCodeValue = resp.getStatusCodeValue(); // 获取响应码值 HttpHeaders headers1 = resp.getHeaders(); // 获取响应头 System.out.println( "statusCode:" + statusCode); System.out.println( "statusCodeValue:" + statusCodeValue); System.out.println( "headers:" + headers1); //或者直接传对象,底层自己处理 Detail detail= new Detail(); detail.setId(1L); detail.setSummary( "牡丹" ); detail.setTitle( "菏泽" ); detail.setAuthor( "zsw" ); detail.setCreatedate( new Timestamp( new Date().getTime())); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<Detail> entity = new HttpEntity<>(detail,headers); ResponseEntity<String> resp = restTemplate.exchange( "http://localhost:8080/detailsDelete" , HttpMethod.DELETE, entity, String. class ); //拿到返回值 String result = resp.getBody(); System.out.println(result); return result; |
post、put、delete请求都可以用这种方法。但是测试get时就不行了直接报错:org.springframework.web.client.HttpClientErrorException: 400 null(错误请求,服务器不理解请求的语法),get请求不支持这种方式的传参,get请求只能将请求参数拼接URI
后边,而不能单独传递request body参数,除非你改用POST
。如果用resuful风格,必须要get传参对象,也不是没有办法的。根据(https://blog.belonk.com/c/http_resttemplate_get_with_body.html)这篇文章,小弟把情况摸清楚了,上手!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | import com.alibaba.fastjson.JSON; import com.github.pagehelper.PageInfo; import com.zhou.entity.Detail; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpUriRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.*; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.stereotype.Repository; import org.springframework.web.client.RestTemplate; import java.net.URI; import java.util.HashMap; import java.util.List; import java.util.Map; @Repository public class DetailMapper { public String test(){ RestTemplate restTemplate1 = new RestTemplate(); restTemplate1.setRequestFactory( new HttpComponentsClientHttpRequestWithBodyFactory()); String json = "{\"author\":\"zsw\",\"createdate\":1582010438846,\"id\":1,\"summary\":\"牡丹\",\"title\":\"菏泽\"}" ; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<String> entity = new HttpEntity<>(json,headers); ResponseEntity<String> resp = restTemplate1.exchange( "http://localhost:8080/detailsGet" , HttpMethod.GET, entity, String. class ); String result = resp.getBody(); System.out.println(result); return result; } private static final class HttpComponentsClientHttpRequestWithBodyFactory extends HttpComponentsClientHttpRequestFactory { @Override protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) { if (httpMethod == HttpMethod.GET) { return new HttpGetRequestWithEntity(uri); } return super .createHttpUriRequest(httpMethod, uri); } } private static final class HttpGetRequestWithEntity extends HttpEntityEnclosingRequestBase { public HttpGetRequestWithEntity( final URI uri) { super .setURI(uri); } @Override public String getMethod() { return HttpMethod.GET.name(); } } } |
大致就是这个样子。对于没接触过httpclient的我,有些类不能导包,属实有的懵。百度百度百度。。。 找到httpclient的maven的依赖,下载导包,成功!启动项目:无法访问org.apache.http.annotation.ThreadSafe,找不到org.apache.http.annotation.ThreadSafe的类文件 ???,我记忆中没有用过这个类,全局搜索一下也找不到(ctrl+shift+f - 查询自己写的代码)。继续百度,说httpclient4.5.2版本和httpcore4.4.4版本更配哦,maven自动下载的httpcore4.4.13,今天这个maven咋回事(好感-1),参考(https://www.jianshu.com/p/f35eac56c334)文章,最终的pom文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | <?xml version= "1.0" encoding= "UTF-8" ?> <project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion> 4.0 . 0 </modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version> 2.1 . 12 .RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.zhou</groupId> <artifactId>news-consumer</artifactId> <version> 0.0 . 1 -SNAPSHOT</version> <name>news-consumer</name> <description>Demo project for Spring Boot</description> <properties> <java.version> 1.8 </java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional> true </optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional> true </optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 分页 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version> 1.2 . 3 </version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version> 1.2 . 13 </version> </dependency> <!-- Apache Commons IO --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version> 4.5 . 2 </version> </dependency> <!-- Apache Commons IO --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version> 4.4 . 4 </version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> |
重新启动,访问,拿到参数。
附上github地址:https://github.com/wwck-zsw/RestTemplate
参考链接:
https://segmentfault.com/a/1190000021123356
https://www.cnblogs.com/jnba/p/10522608.html(灵感来源)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了