最近開發(fā)一個(gè)SpringMVC的老項(xiàng)目時(shí)遇到一個(gè)棘手的問題,在我們后臺(tái)有一個(gè)訂單在支付成功之后會(huì)通過回調(diào)地址到我們后臺(tái)的一個(gè)接口,起初我用的是下面的方式直接獲取參數(shù)的:
public void handleNotify(HttpServletRequest request) {
String orderId = request.getParameter("orderId");
...
}
但是測(cè)試結(jié)果大失所望,結(jié)果居然是空的,后面參考了第三方的接口,使用了下面的方式獲取數(shù)據(jù):
public String getString(HttpServletRequest request) {
StringBuilder builder = new StringBuilder();
String reqBody = null;
try (BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
String line = null;
while ((line = br.readLine()) != null) {
builder.append(line);
}
if (builder.length() < 1) {
return "";
}
reqBody = URLDecoder.decode(builder.toString(), "UTF-8");
return reqBody;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void handleNotify(HttpServletRequest request) {
String result = getString(request);
}
最終的結(jié)果數(shù)據(jù):
--------------------------5b3f5adfbc805c33Content-Disposition: form-data; name="callbacks"CODE_SUCCESS
--------------------------5b3f5adfbc805c33Content-Disposition: form-data; name="type"wechat
--------------------------5b3f5adfbc805c33Content-Disposition: form-data; name="total"2
--------------------------5b3f5adfbc805c33Content-Disposition: form-data; name="api_order_sn"19112919251299300001
--------------------------5b3f5adfbc805c33Content-Disposition: form-data; name="order_sn"191129-233113846570304
--------------------------5b3f5adfbc805c33Content-Disposition: form-data; name="sign"6424E18CEC1C32449D856436F6E2D087
--------------------------5b3f5adfbc805c33--
看了下數(shù)據(jù)這種數(shù)據(jù)結(jié)構(gòu)是一種multipart/form-data的格式,說明如下:
在最初的 http 協(xié)議中,沒有上傳文件方面的功能。 rfc1867為 http 協(xié)議添加了這個(gè)功能。客戶端的瀏覽器,如 Microsoft IE, Mozila, Opera 等,按照此規(guī)范將用戶指定的文件發(fā)送到服務(wù)器。服務(wù)器端的網(wǎng)頁程序,如 php, asp, jsp 等,可以按照此規(guī)范,解析出用戶發(fā)送來的文件。Microsoft IE, Mozila, Opera 已經(jīng)支持此協(xié)議,在網(wǎng)頁中使用一個(gè)特殊的 form 就可以發(fā)送文件。絕大部分 http server ,包括 tomcat ,已經(jīng)支持此協(xié)議,可接受發(fā)送來的文件。各種網(wǎng)頁程序,如 php, asp, jsp 中,對(duì)于上傳文件已經(jīng)做了很好的封裝。
注意 enctype="multipart/form-data", method=post, type="file" 。根據(jù) rfc1867, 這三個(gè)屬性是必須的。multipart/form-data 是新增的編碼類型,以提高二進(jìn)制文件的傳輸效率。
知道了什么格式之后,通過強(qiáng)大的網(wǎng)絡(luò)搜索引擎找到了最簡(jiǎn)單的方式:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
只需要在你的applicationContext.xml文件中配置上面的bean就可以解決這個(gè)問題了,之后我們依然可以使用最早的那種方式獲取數(shù)據(jù)。
看了下CommonsMultipartResolver里面的代碼實(shí)現(xiàn),這個(gè)類最終也會(huì)調(diào)用commons-fileupload.jar這個(gè)第三方工具實(shí)現(xiàn)表單和上傳文件的解析。
參考資料如下:
上傳文件multipart form-data boundary 說明
SpringMVC接收multipart/form-data傳輸?shù)臄?shù)據(jù)
Spring MVC獲取不到post提交的multipart/form-data格式的數(shù)據(jù)