表單form的提交和servlet的取值

表單form的提交和servlet的取值

1、前言

對於後端開發來講,常常要和前端進行聯繫的兩個面就是:一、表單form提交至servlet。二、ajax提交至servlet進行處理。javascript

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

一、一箇中文亂碼的坑

在表單傳值和後臺進行交流的時候,一個最大的坑就是中文的亂碼問題了。這個坑的具體分析不過多闡述,最佳實踐就是: 使用post 方式進行數據的提交,後臺設置字符集過濾器,對requestresponse 的字符集都設置爲utf-8前端

二、表單form的enctype字段

HTML表單如何打包數據文件是由enctype這個屬性決定的。enctype有如下幾種取值:java

  • application/x-www-form-urlencoded在發送數據以前,編碼全部字符(空格被編碼爲’+’,特殊字符被編碼爲ASCII十六進制字符,中文會被編碼,英文不會)。此時,數據是以編碼後的字符串形式進行傳輸。
  • multipart/form-data 不對字符編碼。在使用包含文件上傳控件的表單時,必須使用該值。此時,數據是以二進制流的形式進行傳輸。
  • text/plain 空格轉換爲 「+」 加號,但不對特殊字符編碼。

默認值是enctype=application/x-www-form-urlencoded,因此表單的內容會按URL規則編碼,而後根據表單的提交方法:jquery

  • method="get" ,編碼後的表單內容附加在請求鏈接後
  • method="post" ,編碼後的表單內容做爲post請求的正文內容

2、使用action 的表單

前端的表單,在填寫了數據以後將數據發送給後端進行處理。這裏,咱們所指的表單意爲經過action 字段進行提交,經過ajax 模擬提交的狀況放在下一大點中討論。web

而這裏的表單又分爲2種狀況:ajax

  1. 表單form單純的只有數據項,只提交文本數據,一般是key-value 的形式,對於複選框亦如此。
  2. 表單form既有文本數據項,又有文件數據,即包含<input type="file" ...> 字段。

一、只提交文本數據的表單

例如表單:spring

<form action="/webapp/formServlet" method="post">
    <input type="text" name="username">
    <!-- 單選框 -->
    <input type="radio" name="sex" value="male">male
    <input type="radio" name="sex" value="female">female
    <!-- 下拉框 -->
    <select name="education">
        <option value="primary">primary</option>
        <option value="middle">middle</option>
        <option value="high">high</option>
    </select>
    <!-- 複選框 -->
    <input type="checkbox" name="hobby" value="basket">basket
    <input type="checkbox" name="hobby" value="tennis">tennis
    <input type="checkbox" name="hobby" value="football">football
    <input type="submit" value="提交">
</form>

在servlet中獲取數據:apache

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=222json

傳輸方式: 數據傳輸方式method : 若是使用get ,那麼該字符串會追加到請求的url地址後面;而若是使用post ,那麼打開調試臺,查看Form Data 項也能夠查看到字符串。

這種表單提交數據的方式最爲簡單。

二、提交文本數據和文件數據的表單

例如表單:

<form action="/webapp/formServlet" method="post" enctype="multipart/form-data">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="file" name="file">
    <input type="submit" value="提交">
</form>

在servlet中獲取數據以及保存文件:

由於傳輸過來的是二進制流,所以沒法使用getParameter() 等現成的方法來獲取值。推薦使用apache upload 框架來進行數據的讀取操做。固然,servlet也有原生的方法來獲取,參考(https://docs.oracle.com/javae... 、(https://docs.oracle.com/javae...

解讀

傳輸方式: 由於是二進制流, 因此method 只能使用post 進行提交,沒法使用get

三、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技術。

3、使用ajax技術,模擬表單提交

前言:

咱們先聊一聊ajax技術,ajax是發起一個http請求,固然能夠攜帶數據,這個數據是以字符串的形式來傳輸的。固然,這個請求被髮送至servlet進行處理,servlet返回處理後的信息,這個信息被ajax的回調函數所接受,而後ajax就能夠進行相應的操做了。

當使用ajax時,能夠沒有表單的存在,由於咱們不須要action 了,咱們只須要獲得要傳輸的數據便可。同時,對於type="submit" 字段也要當心設置,由於咱們其實能夠不設置該值,或者在js事件中進行表單提交的判斷。

區別:

ajax的過程和表單提交幾乎差很少,不一樣的是:ajax發出的http請求並非瀏覽器發出的請求,所以servlet是沒有辦法影響頁面的跳轉的 ,因此要想進行頁面的跳轉只能是ajax的回調函數中進行處理。而且大多數時候,servlet的處理也會返回json 數據至前臺。這裏的話,就涉及到json 數據的反序列化和java 對象(或者是MapList )的序列化了。

緩存: ajax發出的請求一般會被瀏覽器緩存,所以咱們能夠應該拒絕緩存。一般是在url地址後面追加一個隨機字符參數,而使用jquery的ajax能夠設置cache:false 這個屬性就ok了。

jquery的ajax:

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

一、一個提交後頁面自動刷新的坑

有時候,在點擊提交以後,頁面會自動刷新,咱們沒法查看相關的數據,這是一個大坑。正確的解決方法,使用<input type="button" value="提交" /> 這個按鈕來進行事件綁定並提交。固然,這是針對ajax來用的。

二、 僅發送請求至servlet,接收返回數據

當咱們不須要發送數據的時候,其實只須要在一個js的事件中使用ajax就能夠了,不須要表單。這種方式實際用的比較少。

一個觸發ajax的按鈕:

<button id="bt_1">ajax_1</button>

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();

三、 攜帶文本數據,發送請求至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的代碼中,有幾個參數比較重要。

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

這個參數是指明提交的數據的數據類型,不指明的話,默認是:

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

而指明瞭數據格式爲json 的話,在後臺有些框架能夠直接獲取,好比說springmvc。

注意: 一旦使用了指明瞭數據類型是json以後,就應該使用JSON.stringify() 方法來處理json數據。在後臺的處理程序中就沒法使用getParameter() 方法來獲取值了。

二、 dataType:"json"

這個參數是指明返回的數據的數據類型,不指明的話,默認是:"text"

四、 攜帶文本數據和文件數據,發送請求至servlet,接收返回數據

一樣的一句話,只要涉及到文件數據,那麼就是二進制流傳輸,是沒法使用getParameter() 直接獲取數據的。而且再囉嗦一句,之因此推薦使用ajax,就是由於它能夠作到頁面不跳轉的提交。

4.1 使用FormData對象

咱們仍是能夠選擇是否使用表單,這也無所謂。當multiple="multiple" 時,能夠一次上傳多個文件。

表單:

<form id="form_1">
    <input type="text" name="user" id="user">
    <input type="file" name="file" multiple="multiple" id="file">
    <input type="button" id="sub" value="submit it"/>
</form>

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,

4、謝幕

關於前端的表單提交數據至後臺servlet的總結就先告一段落了。內容上能夠分紅2塊,一是直接使用action 的表單提交,二是使用ajax 技術模擬的表單提交。而在數據上又能夠分紅2塊,一是隻含有文本數據,而是含有上傳文件。

相關文章
相關標籤/搜索