最近開發(fā)一個SpringMVC的老項目時遇到一個棘手的問題,在我們后臺有一個訂單在支付成功之后會通過回調(diào)地址到我們后臺的一個接口,起初我用的是下面的方式直接獲取參數(shù)的:
public void handleNotify(HttpServletRequest request) {
String orderId = request.getParameter("orderId");
...
}
但是測試結(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ǎng)頁程序,如 php, asp, jsp 等,可以按照此規(guī)范,解析出用戶發(fā)送來的文件。Microsoft IE, Mozila, Opera 已經(jīng)支持此協(xié)議,在網(wǎng)頁中使用一個特殊的 form 就可以發(fā)送文件。絕大部分 http server ,包括 tomcat ,已經(jīng)支持此協(xié)議,可接受發(fā)送來的文件。各種網(wǎng)頁程序,如 php, asp, jsp 中,對于上傳文件已經(jīng)做了很好的封裝。
注意 enctype="multipart/form-data", method=post, type="file" 。根據(jù) rfc1867, 這三個屬性是必須的。multipart/form-data 是新增的編碼類型,以提高二進制文件的傳輸效率。
知道了什么格式之后,通過強大的網(wǎng)絡搜索引擎找到了最簡單的方式:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
只需要在你的applicationContext.xml文件中配置上面的bean就可以解決這個問題了,之后我們依然可以使用最早的那種方式獲取數(shù)據(jù)。
看了下CommonsMultipartResolver里面的代碼實現(xiàn),這個類最終也會調(diào)用commons-fileupload.jar這個第三方工具實現(xiàn)表單和上傳文件的解析。
參考資料如下:
上傳文件multipart form-data boundary 說明
SpringMVC接收multipart/form-data傳輸?shù)臄?shù)據(jù)
Spring MVC獲取不到post提交的multipart/form-data格式的數(shù)據(jù)