亲宝软件园·资讯

展开

探究Spring Boot中的接收参数问题与客户端发送请求传递数据

Stars-one 人气:0
结合此篇参考[Spring框架学习笔记(9)——API接口设计相关知识及具体编码实现](https://www.cnblogs.com/stars-one/p/12305429.html) 在使用Spring Boot进行接收参数的时候,发现了许多问题,之前一直都很忙,最近才稍微有空研究一下此问题。 网上的大多数文章,只讲Spring Boot如何实现接受参数,却不讲如何在客户端调用,**本篇使用Jsoup、okhttp3和postwoman测试工具进行截图,讲解如何在服务器实现接口,同时在客户端如何发起请求并传参** ## 四种请求方式介绍 可能刚入门Web开发的大家会有疑惑?不是只有get和post这两种? 最近几年好像流行restful风格的接口,里面有多种方式,按照功能进行区分 不过,目前常用的就只有下面这四个方式**get、post、put、delete** 本质上除了get,其他凡是都是post方式衍生出来的版本,调用的时候只需要修改方法名即可(具体可查看post方式中的代码例子) ## get方式 ### 介绍 如下图,我写了一个接口 ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316172211569-1276607179.png) 由于是本地部署,ip为`localhost`,contextpath名为`requestdemo`,端口默认为`8080`,所以访问的url就为`http://localhost:8080/requestdemo/api/user/users` ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316172504331-1062121966.png) 由于我们使用了`@RequestMapping`注解,所以,不过使用什么方式都可以访问到数据,如下图,切换为post方式访问 ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316172537729-1301065146.png) 如果想要指定get方式,可以使用`@GetMapping`注解,GetMapping注解其实是相当于这样的写法`@RequestMapping("users",method = [(RequestMethod.GET)])`,注解中method属性接收的是数组参数 指定了get方式,使用其他的post方式、put方式等都是返回不了数据的,报405错误代码,如下图 ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316173053178-1572600377.png) ### 接收数据 ``` @GetMapping("select") fun selectByPk(@RequestParam("id") ids:Int):User { println(ids) return User("zhangsan",19) } @GetMapping("select1") fun selectByPk1(ids:Int) { println(ids) } ``` 第一种方式客户端应该这样调用,输入网址即可 ``` http://localhost:8080/requestdemo/api/user/select?id=1 ``` 第二种参数没有注解,所以spring boot默认以变量名作为参数,所以应该是这样调用 ``` http://localhost:8080/requestdemo/api/user/select1?ids=1 ``` 下面报错的截图也是充分说明了这一点 ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316190306762-139092185.png) ### 客户端代码发起get请求 客户端发起get请求用代码写就比较简单,只要我们把url拼接好即可 **Jsoup:** Jsoup中的get方法是返回一个Document(网页对象,之后可进行css筛选来找到指定节点,从而获取内容) ``` //需要ignoreContentType,忽略content-type,否则会报错,拿不到服务器返回的数据 val doc= Jsoup.connect("http://localhost:8080/requestdemo/api/user/select?id=1") .ignoreContentType(true) .get() //输出服务器返回json数据 println(doc.body().text()) ``` **Okhttp3:** ``` val client = OkHttpClient() val request = Request.Builder() .url("http://localhost:8080/requestdemo/api/user/select?id=1") .get() .build() val call = client.newCall(request) call.enqueue(object :Callback{ override fun onFailure(call: Call, e: IOException) { } override fun onResponse(call: Call, response: Response) { println(response.body()?.string()) } }) ``` ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316192611280-1392580729.png) ## post方式 ### @RequestParam注解 @RequestParam用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式GET、POST。 有如下的接口: ``` @PostMapping("update") fun update(@RequestParam map: HashMap) { //输出传入的key和value for (mutableEntry in map) { println(mutableEntry.key + "=" + mutableEntry.value) } } ``` **PS:不能省略RequestParam注解,否则服务器后端接收不到数据** 使用postwoman测试接口: ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316193732904-371653861.png) 注意,这种方式的数据格式是表单数据**application/x-www-form-urlencoded** **Jsoup:** ``` val dataMap = hashMapOf("name" to "zhangsag","age" to 11.toString()) val doc= Jsoup.connect("http://localhost:8080/requestdemo/api/user/update") .ignoreContentType(true) .data(dataMap) .post() //输出结果 println(doc.body().text()) ``` Jsoup中的data方法可以接受Map,或者键值对,上面的例子可以改成下面的代码 ``` val doc= Jsoup.connect("http://localhost:8080/requestdemo/api/user/update") .ignoreContentType(true) .data("name","zhangsan") .data("age",12.toString()) .post() //输出结果 println(doc.body().text()) ``` **Okhttp3:** ``` fun sendPostRequest(){ val url ="http://localhost:8080/requestdemo/api/user/update" val client = OkHttpClient() val formBodyBuilder = FormBody.Builder() formBodyBuilder.add("names", "zhangsxx") formBodyBuilder.add("ages", "19") val request = Request.Builder() .url(url) .post(formBodyBuilder.build()) .build() val call = client.newCall(request) call.enqueue(object : Callback{ override fun onFailure(call: Call, e: IOException) { } override fun onResponse(call: Call, response: Response) { } } ) } ``` 这里有个小问题没搞明白,如果接口是下面这样,客户端应该如何传递数据?我试了几种方法,都是报错,**说是无法把String类型转为User类型**,是不是这种方法是不能传递的? 有路过的大神希望可以帮忙解答一下 ``` @PostMapping("update2") fun update2(@RequestParam user: User) { println(user.toString()) } ``` ### @RequestBody注解 有时候,我们需要传递一个json字符串,就需要用到此注解 @RequestBody接受的是一个json对象的字符串,而不是Json对象 有下面的一个接口: ``` @PostMapping("update1") fun update1(@RequestBody user:User) { println(user.toString()) } ``` 我们在客户端传递了json数据,之后spring boot就会自动调用jackson框架,把json字符串数据转为实体类 ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316195539824-47648368.png) ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316195512909-23406201.png) **Jsoup:** ``` val json = "{\"name\":\"zhangs\",\"age\":18}" val doc= Jsoup.connect("http://localhost:8080/requestdemo/api/user/update1") .requestBody(json) .header("content-type","application/json") .post() ``` jsoup中需要添加请求头来声明传递json字符串数据,举一反三,传递其他形式只需要更改content-type的值为其他形式即可 ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316201802184-70317853.png) **OkHttp3:** ``` val json = "{\"name\":\"zhangs\",\"age\":18}" val client = OkHttpClient() val request = Request.Builder() .url("http://localhost:8080/requestdemo/api/user/update1") .post(RequestBody.create(MediaType.parse("application/json"),json)) .build() val call = client.newCall(request) call.enqueue(object :Callback{ override fun onFailure(call: Call, e: IOException) { } override fun onResponse(call: Call, response: Response) { println(response.body()?.string()) } }) ``` 这里与上面的okhttp有所类似,就是post方法里面的参数的数据不一样 @RequestParam -> application/x-www-form-urlencoded -> FormBody @RequestBody -> application/json -> RequestBody 举一反三,如果是xml格式或者是二进制格式,应该使用RequestBody来进行构建数据,具体可以自行操作一下,这里就不再演示了 ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316200934685-1435365228.png) ### put、delete方式如何写 Jsoup: ``` val json = "{\"name\":\"zhangs\",\"age\":18}" val doc= Jsoup.connect("http://localhost:8080/requestdemo/api/user/update1") .requestBody(json) .header("content-type","application/json") .method(xx) .post() ``` 在method方法添加即可,下图是可选的数值: ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200316201300984-1866043043.png) Okhttp3中,只需要把post方法更改为put或者delete方法即可 ``` val json = "{\"name\":\"zhangs\",\"age\":18}" val client = OkHttpClient() val request = Request.Builder() .url("http://localhost:8080/requestdemo/api/user/update1") //put或delete .put(RequestBody.create(MediaType.parse("application/json"),json)) .build() val call = client.newCall(request) call.enqueue(object :Callback{ override fun onFailure(call: Call, e: IOException) { } override fun onResponse(call: Call, response: Response) { println(response.body()?.string()) } }) ``` ## ajax请求转代码(补充) **如有下面的ajax代码:** ``` var sg = 'UDZRb1loVWQFDAI9BTVcYFc6ADRTNQo8UWBQY1I5ASYBdVU_aXTEAYQdpBGEGagI2Vj4HO1Q7VmI_c'; $.ajax({ type : 'post', url : '/ajaxm.php', data : { 'action':'downprocess','sign':sg,'ves':1 }, dataType : 'json', success:function(msg){ var date = msg; ... ``` **在postwoman应该这样进行请求:** ![](https://img2020.cnblogs.com/blog/1210268/202003/1210268-20200310230525146-1580128319.png) **Jsoup代码:** ``` //我这里不加头部,也可以获取到数据 val postUrl = "https://www.lanzous.com/ajaxm.php" val params = LinkedHashMap() params["action"] = "downprocess" params["sign"] = sign params["ves"] = "1" val result = Jsoup.connect(postUrl) .data(params) .post() .html() ``` ## 参考 [post frombody](http://jessehu.cn/2019/01/08/okhttp3/okhttp03/) [SpringBoot 出现 Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported](https://blog.csdn.net/feiyst/articlehttps://img.qb5200.com/download-x/details/88431621) [OKHTTP3 简单使用(三) POST方法](http://jessehu.cn/2019/01/08/okhttp3/okhttp03/)

加载全部内容

相关教程
猜你喜欢
用户评论