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


    结合此篇参考Spring框架学习笔记(9)——API接口设计相关知识及具体编码实现

    在使用Spring Boot进行接收参数的时候,发现了许多问题,之前一直都很忙,最近才稍微有空研究一下此问题。

    网上的大多数文章,只讲Spring Boot如何实现接受参数,却不讲如何在客户端调用,本篇使用Jsoup、okhttp3和postwoman测试工具进行截图,讲解如何在服务器实现接口,同时在客户端如何发起请求并传参

    四种请求方式介绍

    可能刚入门Web开发的大家会有疑惑?不是只有get和post这两种?

    最近几年好像流行restful风格的接口,里面有多种方式,按照功能进行区分

    不过,目前常用的就只有下面这四个方式get、post、put、delete

    本质上除了get,其他凡是都是post方式衍生出来的版本,调用的时候只需要修改方法名即可(具体可查看post方式中的代码例子)

    get方式

    介绍

    如下图,我写了一个接口

    由于是本地部署,ip为localhost,contextpath名为requestdemo,端口默认为8080,所以访问的url就为http://localhost:8080/requestdemo/api/user/users

    由于我们使用了@RequestMapping注解,所以,不过使用什么方式都可以访问到数据,如下图,切换为post方式访问

    如果想要指定get方式,可以使用@GetMapping注解,GetMapping注解其实是相当于这样的写法@RequestMapping("users",method = [(RequestMethod.GET)]),注解中method属性接收的是数组参数

    指定了get方式,使用其他的post方式、put方式等都是返回不了数据的,报405错误代码,如下图

    接收数据

    @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
    

    下面报错的截图也是充分说明了这一点

    客户端代码发起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())
    	}
    })
    

    post方式

    @RequestParam注解

    @RequestParam用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式GET、POST。

    有如下的接口:

    @PostMapping("update")
    fun update(@RequestParam map: HashMap<String,String>) {
    	//输出传入的key和value
    	for (mutableEntry in map) {
    		println(mutableEntry.key + "=" + mutableEntry.value)
    	}
    }
    

    PS:不能省略RequestParam注解,否则服务器后端接收不到数据

    使用postwoman测试接口:

    注意,这种方式的数据格式是表单数据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<String,String>,或者键值对,上面的例子可以改成下面的代码

    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字符串数据转为实体类

    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的值为其他形式即可

    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来进行构建数据,具体可以自行操作一下,这里就不再演示了

    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方法添加即可,下图是可选的数值:

    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应该这样进行请求:

    Jsoup代码:

    //我这里不加头部,也可以获取到数据
    val postUrl = "https://www.lanzous.com/ajaxm.php"
    val params = LinkedHashMap<String, String>()
    params["action"] = "downprocess"
    params["sign"] = sign
    params["ves"] = "1"
    
    val result = Jsoup.connect(postUrl)
    		.data(params)
    		.post()
    		.html()
    

    参考

    post frombody
    SpringBoot 出现 Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
    OKHTTP3 简单使用(三) POST方法

  • 相关阅读:
    DDoS攻击
    CSRF攻击
    正向代理和反向代理
    DNS协议
    四次挥手
    Nginx重要概念之lingering_close
    Nginx重要概念之pipeline
    Nginx重要概念之keepalive
    http1.0、http1.1、http2.0三者的区别
    Vue axios封装二
  • 原文地址:https://www.cnblogs.com/stars-one/p/12506469.html
Copyright © 2020-2023  润新知