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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM