天天看點

form表單送出數組java,表單form的送出和servlet的取值

表單form的送出和servlet的取值

一、前言

對于後端開發來說,經常要和前端進行聯系的兩個面就是:1、表單form送出至servlet。2、ajax送出至servlet進行處理。

顯然,有必要對這兩個常用的功能進行一次梳理。

1、一個中文亂碼的坑

在表單傳值和背景進行交流的時候,一個最大的坑就是中文的亂碼問題了。這個坑的具體分析不過多闡述,最佳實踐就是: 使用post 方式進行資料的送出,背景設定字元集過濾器,對request、response 的字元集都設定為utf-8 。

2、表單form的enctype字段

HTML表單如何打包資料檔案是由enctype這個屬性決定的。enctype有以下幾種取值:

application/x-www-form-urlencoded在發送資料之前,編碼所有字元(空格被編碼為’+’,特殊字元被編碼為ASCII十六進制字元,中文會被編碼,英文不會)。此時,資料是以編碼後的字元串形式進行傳輸。

multipart/form-data 不對字元編碼。在使用包含檔案上傳控件的表單時,必須使用該值。此時,資料是以二進制流的形式進行傳輸。

text/plain 空格轉換為 “+” 加号,但不對特殊字元編碼。

預設值是enctype=application/x-www-form-urlencoded,是以表單的内容會按URL規則編碼,然後根據表單的送出方法:

method="get" ,編碼後的表單内容附加在請求連接配接後

method="post" ,編碼後的表單内容作為post請求的正文内容

二、使用action 的表單

前端的表單,在填寫了資料之後将資料發送給後端進行處理。這裡,我們所指的表單意為通過action 字段進行送出,通過ajax 模拟送出的情況放在下一大點中讨論。

而這裡的表單又分為2種情況:

表單form單純的隻有資料項,隻送出文本資料,通常是key-value 的形式,對于複選框亦如此。

表單form既有文本資料項,又有檔案資料,即包含 字段。

1、隻送出文本資料的表單

例如表單:

male

female

primary

middle

high

basket

tennis

football

在servlet中擷取資料:

String username = request.getParameter("username");

String sex = request.getParameter("sex");

String education = request.getParameter("education");

String[] hobby = request.getParameterValues("hobby");

解讀

資料編碼: 對于純文字的表單,其字段enctype=application/x-www-form-urlencoded 是預設值,表示表單的資料進行url編碼,如:表單的資料被編碼成username=123&password=222 。

傳輸方式: 資料傳輸方式method : 如果使用get ,那麼該字元串會追加到請求的url位址後面;而如果使用post ,那麼打開調試台,檢視Form Data 項也可以檢視到字元串。

這種表單送出資料的方式最為簡單。

2、送出文本資料和檔案資料的表單

例如表單:

在servlet中擷取資料以及儲存檔案:

因為傳輸過來的是二進制流,是以無法使用getParameter() 等現成的方法來擷取值。推薦使用apache upload 架構來進行資料的讀取操作。當然,servlet也有原生的方法來擷取,參考(https://docs.oracle.com/javae... 、(https://docs.oracle.com/javae... 。

解讀

傳輸方式: 因為是二進制流, 是以method 隻能使用post 進行送出,無法使用get 。

3、servlet的處理再談一談

既然我們在servlet中可以擷取到表單傳過來的值了,那麼我們的傳回又應該是什麼樣的呢?對于使用action 送出的表單,我們的servlet必須将請求轉發或者使用重定向,以此進行頁面的切換(跳轉)。如果想攜帶新的資料,隻能在請求轉發的request 對象上進行資料的添加。

請求轉發:

request.setAttribute("msg","登入成功!"); // 攜帶資料

request.getRequestDispatcher("/success.jsp").forward(request,response);

重定向:

response.sendRedirect("/webapp/success.jsp");

解讀

很明顯,直接使用action 送出是很不好的。因為在送出至servlet時,位址欄的路徑會變成指向servlet的路徑,而這時候,如果使用請求轉發的話,那麼位址欄的路徑并不會改變,這樣就不是很優雅。而如果使用重定向的話,就無法攜帶資料,對于常見的登入驗證(需要錯誤資訊)就無法完成了。另一個缺點就是,無論是請求轉發還是重定向,原本填寫的表單資料都被清空,這樣是極為糟糕的。

表單送出的最常見場景,往往就是使用者登入或者是檔案上傳,這些都需要伺服器做出回報,鑒于上面所說的缺點,我們就不會使用action 的表單,而是使用更為強大ajax技術。

三、使用ajax技術,模拟表單送出

前言:

我們先聊一聊ajax技術,ajax是發起一個http請求,當然可以攜帶資料,這個資料是以字元串的形式來傳輸的。當然,這個請求被發送至servlet進行處理,servlet傳回處理後的資訊,這個資訊被ajax的回調函數所接受,然後ajax就可以進行相應的操作了。

當使用ajax時,可以沒有表單的存在,因為我們不需要action 了,我們隻需要得到要傳輸的資料即可。同時,對于type="submit" 字段也要小心設定,因為我們其實可以不設定該值,或者在js事件中進行表單送出的判斷。

差別:

ajax的過程和表單送出幾乎差不多,不同的是:ajax發出的http請求并不是浏覽器發出的請求,是以servlet是沒有辦法影響頁面的跳轉的 ,是以要想進行頁面的跳轉隻能是ajax的回調函數中進行處理。并且大多數時候,servlet的處理也會傳回json 資料至前台。這裡的話,就涉及到json 資料的反序列化和java 對象(或者是Map 、List )的序列化了。

緩存: ajax發出的請求通常會被浏覽器緩存,是以我們可以應該拒絕緩存。通常是在url位址後面追加一個随機字元參數,而使用jquery的ajax可以設定cache:false 這個屬性就ok了。

jquery的ajax:

因為原生的ajax技術代碼較多,是以我們使用jquery封裝好的ajax函數來講解其用法。在jQuery中,$.ajax() 方法屬于最底層的方法,第2層是$.load(),$.get(),和$.post(),第3層是$.getScript()和$.getJSON() 方法。第2、3層都是調用了第1層來實作的。

1、一個送出後頁面自動重新整理的坑

有時候,在點選送出之後,頁面會自動重新整理,我們無法檢視相關的資料,這是一個大坑。正确的解決方法,使用 這個按鈕來進行事件綁定并送出。當然,這是針對ajax來用的。

2、 僅發送請求至servlet,接收傳回資料

當我們不需要發送資料的時候,其實隻需要在一個js的事件中使用ajax就可以了,不需要表單。這種方式實際用的比較少。

一個觸發ajax的按鈕:

ajax_1

jquery代碼:(請求servlet,接收傳回資料)

var bt_1=$("#bt_1");

bt_1.on("click",function () {

$.ajax({

url:"/webTest/ajax1", // 請求的servlet

type:"post", // 因為沒有攜帶資料,無所謂

async: true, // 異步

cache: false, // 不許緩存

success:function(data){ // 請求成功,200

console.log(data);

},

error:function(error){ // 請求失敗

console.log(error);

}

})

})

servlet處理代碼:(傳回資料)

PrintWriter out = null;

try {

out = response.getWriter(); // 打開response的輸入流

} catch (IOException e) {

e.printStackTrace();

}

out.print("I give u a feedback"); // 寫入資訊到response

out.close();

3、 攜帶文本資料,發送請求至servlet,接收傳回資料

有的時候,我們需要攜帶一些資料,可以是常見的表單,也可以是一些零散的資料。在這種情況下,我們需要将資料封裝成json 資料格式進行傳輸。

3.1 第一種封裝的json 資料:對象形式

jquery代碼:

var sub=$("#sub");

sub.on("click",function () {

$.ajax({

url:"/webTest/ajax2",

type:"post",

async:true,

cache: false,

data: { // json資料(注意,不能使用JSON.stringify()方法,否則出錯)

"username": "liSi",

"password": "ps"

},

success:function(data){

console.log(data);

},

error:function(error){

console.log(error);

}

})

})

servlet處理代碼:(接收資料,傳回資料)

String username = request.getParameter("username");

String password = request,getParameter("password");

PrintWriter out = null;

try {

out = response.getWriter(); // 打開response的輸入流

} catch (IOException e) {

e.printStackTrace();

}

out.print("I give u a feedback"); // 寫入資訊到response中

out.close();

解讀

在這種情況下,封裝的json資料因為比較簡單,是以資料被編碼成字元串發送至servlet,就和之前使用action 的表單送出文本資料的情況一樣。

注意,一旦json 資料複雜一點點,如{"username":"liSi","hobby":{"todya":"ttennis"}} ;就無法使用getParameter("hobby") 來擷取資料了,這也是下面要将的第二種封裝的json 資料。顯然,這種封裝的json 資料的擷取,是一種特殊情況,在大多數不複制的情況是一種很好的方式。

技巧

當我們使用了表單的時候,如果我們隻是想傳輸表單的值,那麼就沒有必要手工取值化成json形式,jquery提供了相應的方法來簡化操作。當然,隻是針對文本資料而言。

jquery代碼1:

var data_json = $("#form_1").serialize();

data: data_json,

這裡通過序列化函數,會自動把表單的資料轉化為字元串形式(url),也就是和action 表單送出一緻的效果。在servlet中可以直接通過getParameter() 方法來擷取參數。

jquery代碼2:

var data_json = $("#form_1").serializeArray();

data: data_json,

這裡通過序列化函數,會自動把表單的資料轉化為json資料格式,省去了手工封裝成json的過程。

3.2 第二種封裝的json 資料:數組形式

一旦json 資料變複雜,那麼在servlet中就無法通過getParameter() 擷取資料了。這個時候我們需要把json 資料先字元串化,使得json 在傳輸的時候就是原資料(打開調試台看到的Form Data 就和json 原資料一樣)。

jquery代碼:

var sub=$("#sub");

var data_json=[{"sex": '男',"submit":"111"},{"sex": '女',"submit":"222"}];

sub.on("click",function () {

$.ajax({

url:"/webTest/ajax2",

type:"post",

async:true,

cache: false,

data: JSON.stringify(data_json), // 先序列化json資料

success:function(data){

console.log(data);

},

error:function(error){

console.log(error);

}

})

})

在這裡,json 資料就是比較複雜的了,我們要先使用JSON.stringify() 序列化json 資料。

servlet代碼:

BufferedReader reader = request.getReader(); // 擷取請求的輸出流

String jsonData = "";

jsonData += reader.readLine();

reader.close();

// 擷取到一緻的json資料

System.out.println(json); // [{"sex": '男',"submit":"111"},{"sex": '女',"submit":"222"}]

java操作json 資料:

對于得到的json 資料,我們需要反序列,把我們需要的值給取出來。通常是使用json 的解析庫,如GSON、fastJson等。這裡我們使用GSON來講解。

由于篇幅的原因,GSON 操作json 資料,序列化與反序列化的内容在另一章中進行講解。總之,我們可以操作任何複雜的json 資料,并且從中取出我們需要的屬性。

解讀

得益于json 資料格式,使得前後端之間的資料交流變得十分友善。具體如何在java中操作json,請看有關于json的文章。

3.3 jquery的ajax 技術參數解讀

在ajax的代碼中,有幾個參數比較重要。

1、 contentType: "application/json;charset=utf-8"

這個參數是指明送出的資料的資料類型,不指明的話,預設是:

Content-Type: application/x-www-form-urlencoded; charset=UTF-8 。

而指明了資料格式為json 的話,在背景有些架構可以直接擷取,比如說springmvc。

注意: 一旦使用了指明了資料類型是json之後,就應該使用JSON.stringify() 方法來處理json資料。在背景的處理程式中就無法使用getParameter() 方法來擷取值了。

2、 dataType:"json"

這個參數是指明傳回的資料的資料類型,不指明的話,預設是:"text" 。

4、 攜帶文本資料和檔案資料,發送請求至servlet,接收傳回資料

同樣的一句話,隻要涉及到檔案資料,那麼就是二進制流傳輸,是無法使用getParameter() 直接擷取資料的。并且再啰嗦一句,之是以推薦使用ajax,就是因為它可以做到頁面不跳轉的送出。

4.1 使用FormData對象

我們還是可以選擇是否使用表單,這也無所謂。當multiple="multiple" 時,可以一次上傳多個檔案。

表單:

jquery代碼:

var formData = new FormData();

var name = $("input").val();

// formData對象放入值

formData.append("name",name);

formData.append("file",$("#file")[0].files[0]); // 隻選擇第一個檔案

$.ajax({

url : Url,

type : 'POST',

data : formData,

processData : false, // 告訴jQuery不要去處理發送的資料

contentType : false, // 告訴jQuery不要去設定Content-Type請求頭

success:function(data){

console.log(data);

},

error:function(error){

console.log(error);

}

});

當然,我們可以直接傳入表單對象。這樣更加快速。

var form_1 = document.getElementById("form_1");

var formData = new FormData(form_1);

data: formData,

四、謝幕

關于前端的表單送出資料至背景servlet的總結就先告一段落了。内容上可以分成2塊,一是直接使用action 的表單送出,二是使用ajax 技術模拟的表單送出。而在資料上又可以分成2塊,一是隻含有文本資料,而是含有上傳檔案。