(轉)表單form的提交和servlet的取值


轉發博客原址:https://segmentfault.com/a/1190000015718785

表單form的提交和servlet的取值

一、前言

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

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

1、一個中文亂碼的坑

在表單傳值和后台進行交流的時候,一個最大的坑就是中文的亂碼問題了。這個坑的具體分析不過多闡述,最佳實踐就是: 使用post 方式進行數據的提交,后台設置字符集過濾器,對requestresponse 的字符集都設置為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種情況:

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

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

例如表單:

<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中獲取數據:

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、提交文本數據和文件數據的表單

例如表單:

<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

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 對象(或者是MapList )的序列化了。

緩存: 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、一個提交后頁面自動刷新的坑

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

2、 僅發送請求至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();

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處理代碼:(接收數據,返回數據)


免責聲明!

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



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