--------------------------HttpServletRequest參數獲取,HttpServletRequest詳解---------------------------------
HttpServletRequest獲取參數(重要)
1 HttpServletRequest獲取參數方法
可以使用HttpServletRequest獲取客戶端的請求參數,相關方法如下:
- String getParameter(String name):通過指定名稱獲取參數值;
- String[] getParameterValues(String name):通過指定名稱獲取參數值數組,有可能一個名字對應多個值,例如表單中的多個複選框使用相同的name時;
- Enumeration getParameterNames():獲取所有參數的名字;
- Map getParameterMap():獲取所有參數對應的Map,其中key爲參數名,value爲參數值。
2 傳遞參數的方式
傳遞參數的方式:GET和POST。
GET:
- 地址欄中直接給出參數:http://localhost/param/ParamServlet?p1=v1&p2=v2;
- 超鏈接中給出參數:<a href=” http://localhost/param/ParamServlet?p1=v1&p2=v2”>???</a>
- 表單中給出參數:<form method=”GET” action=”ParamServlet”>…</form>
- Ajax暫不介紹
POST:
- 表單中給出參數:<form method=”POST” action=”ParamServlet”>…</form>
- Ajax暫不介紹
3. 單值參數的接收
單值參數包括單選,單值下拉框,文本,隱藏域
無論是GET還是POST,獲取參數的方法是相同的。
String s1 = request.getParameter(“p1”);//返回v1
String s2 = request.getParameter(“p2”);//返回v2
<form action="ParamServlet" method="post"> <input type="text" name="p1"/><br/> <input type="text" name="p2"/><br/> <input type="submit" value="提交"/><br/> </form> <a href="ParamServlet?p1=v1&p2=v2">Param</a> |
String s1 = request.getParameter("p1"); String s2 = request.getParameter("p2"); response.getWriter().print("p1 = " + s1 + "<br/>"); response.getWriter().print("p2 = " + s2 + "<br/>"); |
Enumeration names = request.getParameterNames(); while(names.hasMoreElements()) { String name = (String)names.nextElement(); String value = request.getParameter(name); System.out.println(name + " = " + value); } |
4 多值參數接收
多值參數主要就是多選checkbox
例如在註冊表單中,如果讓用戶填寫愛好,那麼愛好可能就是多個。那麼hobby參數就會對應多個值:
<form action="ParamServlet" method="post"> 上網:<input type="checkbox" name="hobby" value="netplay" /><br/> 踢球:<input type="checkbox" name="hobby" value="football" /><br/> 看書:<input type="checkbox" name="hobby" value="read" /><br/> 編程:<input type="checkbox" name="hobby" value="programme" /><br/> <input type="submit" value="提交"/><br/> </form> |
// 獲取所有名爲hoby的參數值 String[] hobbies = request.getParameterValues("hobby"); System.out.println(Arrays.toString(hobbies)); |
request.getParameterMap()方法返回Map類型,對應所有參數。其中Map的key對應參數的名字;Map的value對應參數的值。
<form action="ParamServlet" method="post"> 姓名:<input type="text" name="name"/><br/> 年齡:<input type="text" name="age"/><br/> 性別:<input type="text" name="sex"/><br/> <input type="submit" value="提交"/><br/> </form> |
Map<String,String[]> map = request.getParameterMap(); Set<String> keys = map.keySet(); for(String key : keys) { String[] value = map.get(key); System.out.println(key + " = " + value[0]); } |
sex = male name = zhangSan age = 23 |
單值參數,也可以使用request.getParameterValues(String)獲取,其實當參數的值是單個的時候,同樣可以使用request.getParameterValues(String)方法來獲取參數值,不過這個參數返回的值爲String[],這時我們需要再去獲取數組下標0的元素。
String name = request.getParameterValues(“name”)[0]; |
在知道name的情況下,獲取單值和多值的代碼示例:
代碼1.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h1>request接收參數</h1> <a href="/request_demo2/hello?name=likunpeng&age=30">訪問1.html</a> <hr/> <h1>表單方式來提交數據</h1> <form action="/request_demo2/hello" method="get"> 姓名:<input name="name" type="text"> <br/> 年齡:<input name="age" type="text"> <br/> 性別:<input name="gender" type= "radio" value="1">男 <input name="gender" type="radio" value="0">女 <br/> 職位:<select name="job"> <option value="1">講師</option> <option value="2">架構師</option> </select> <br/> 簡介:<br/> <textarea name="introduce" rows="10" cols="30"></textarea> <br/> 愛好:<input name="favor" type="checkbox" value="1">籃球 <input name="favor" type="checkbox" value="2">足球 <input name="favor" type="checkbox" value="3">游泳 <br/> <input type="submit" value="提交"> </form> </body> </html> |
HelloServlet代碼:
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//根據請求中的key來獲得值 //單值接收 String name = request.getParameter("name"); System.out.println(name); String age = request.getParameter("age"); System.out.println(age); String gender = request.getParameter("gender"); System.out.println(gender); String job = request.getParameter("job"); System.out.println(job); String introduce = request.getParameter("introduce"); System.out.println(introduce);
//以下方式不適合接收多選,只能接收到多選中的第一個 //String favor = request.getParameter("favor"); //多值接收 String[] favors = request.getParameterValues("favor"); for (String favo : favors) { System.out.print(favor+"、"); } }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }
} |
結果圖
-------------------------------------------------------------------------------------------------------------
在不知道name的情況下,通過request中的getParameterNames方法來獲取文本域中的值:
新建一個servlet
public class HelloServlet1 extends HttpServlet { /** * getParameterNames用於獲得表單中文本域的所有的name,適合動態表單 */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲得表單中所有的文本域的name Enumeration<String> parameteNames = request.getParameterNames(); while(parameteNames.hasMoreElements()){ //獲得每個文本域的name String parameteName = parameteNames.nextElement(); //根據文本域的name來獲取值 //因爲無法判斷文本域是否是單值或者雙值,所以我們全部使用雙值接收 String[] parameteValues = request.getParameterValues(parameteName); //輸出文本域的name System.out.print(parameteName+":"); for (String parameteValue : parameteValues) { //輸出文本域的值 System.out.print(parameteValue+" "); } //換行 System.out.println(); } }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }
} |
-------------------------------------------------------------------
Request中getParameterMap使用介紹:
Servlet代碼示例:
public class HelloServlet2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲得表單中所有文本域的name和值,以Map方式來存取 Map map = request.getParameterMap(); //獲得Map集合中所有的key,就是表單中文本域的集合 Set<String> keys = map.keySet(); for (String name : keys) { //獲得文本域的值 String[] values = (String[])map.get(name); //打印文本域名字 System.out.print(name+":"); for (String value : values) { //打印文本域中的值 System.out.print(value+" "); } //打印換行 System.out.println(); } } } |
5.Request的獲得中文亂碼處理
設置eclipse所使用的編碼:
Request接收參數時有get和post兩種請求方式,但是處理中文的編碼卻不一樣,我們在做項目時會全站都採用統一的編碼,最常用的就是UTF-8,在UTF-8編碼的項目中的
- 當我們使用Post請求時:
處理POST編碼問題!
我們知道,請求信息中,只有POST存在正文,所謂POST參數編碼就是就是請求正文的編碼。
默認情況下,使用getParameter()獲取POST請求參數時,使用的是ISO-8859-1編碼。
String name = request.getParameter("name"); name = new String(name.getBytes("ISO-8859-1"), "UTF-8"); System.out.println(name); |
因爲在獲取參數時已經被錯誤的編碼了,但因爲我們知道,亂碼的兩個原因:本來是使用UTF-8編碼的,還錯誤的使用了ISO-8859-1編碼。所以我們可以先使用ISO-8859-1獲取字節數組,然後再使用正確的UTF-8編碼得到字符串,這樣就沒問題了。
request的setCharacterEncodng()可以設置編碼,當然這必須在調用所有的getParameter()方法之前調用request的setCharacterEncodng()方法來設置編碼,這樣,就不會使用ISO解讀字節串了,而是使用你給定的編碼來解讀。
request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); System.out.println(name); |
對於每個請求,只需要調用request的setCharacterEncodng()一次,然後所有getParameter()都會使用這個編碼來解讀參數。但要注意,只對請求正文有效,即POST參數。
字符串編碼案例介紹:
public class test {
public static void main(String[] args) throws UnsupportedEncodingException { //獲取一個ISO-8869-1編碼的字符串 String s = new String("李昆鵬".getBytes(),"ISO-8859-1"); //指定s的編碼格式爲ISO-8859-1,s的解碼格式爲默認格式UTF-8,s1的編碼格式爲默認格式UTF-8 String s1 = new String(s.getBytes("ISO-8859-1")); //指定s的編碼格式爲ISO-8859-1,s的解碼格式爲默認格式UTF-8,s1的編碼格式爲指定格式UTF-8 String s2 = new String(s.getBytes("ISO-8859-1"),"UTF-8"); //指定s的編碼格式爲默認格式UTF-8,s的解碼格式爲默認格式UTF-8,s1的編碼格式爲指定格式UTF-8 String s3 = new String(s.getBytes(),"UTF-8"); //請看輸出結果 System.out.println(s); //ææé¹ System.out.println(s1);//李昆鵬 System.out.println(s2);//李昆鵬 System.out.println(s3);//ææé¹ } } |
Post方式處理中文亂碼第一種方式:
public class HelloServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); String introduce = request.getParameter("introduce"); //以下輸出字符串會出現亂碼 System.out.println(name); System.out.println(introduce); //將name編碼通過string構造器從ISO-8859-1變成UTF-8解碼 name = new String(name.getBytes("ISO-8859-1"),"UTF-8"); introduce = new String(introduce.getBytes("ISO-8859-1"),"UTF-8"); System.out.println(name); System.out.println(introduce); } } |
Post方式處理中文亂碼第二種方式: 使用request中的setCharacterEncoding(“UTF-8”)方法(建議使用)
public class HelloServlet1 extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //設置request編碼爲UTF-8 request.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); String introduce = request.getParameter("introduce"); System.out.println(name); System.out.println(introduce); }
} |
當我們採用get請求時
上述的post的處理方式不再生效
- 第一種方式:
我們可以採用字符串轉碼的方式來處理
String s = request.getParameter(“s”);
s = new String(s.getBytes(“iso-8859-1”), “utf-8”);
- 第二種方式:
GET參數不在請求正文中,而是在URL中。所以不能使用request的setCharacterEncodng()來設置GET參數的編碼。
處理GET參數編碼可以有兩種方式:第一種是設置<Connector>元素的URIEncoding屬性的值爲UTF-8。即conf\server.xml中的<Connector>元素的URIEncoding屬性。
一旦設置了這個屬性,那麼對於GET參數就直接是UTF-8編碼的了。但是,<Connector>元素來說,對整個Tomcat都是有效的!
- 第三種JavaScript對超鏈接做URL編碼
處理這個問題的辦法是把GET請求中的參數使用JavaScript做URL編碼,URL編碼後的內容就不再是中文了,這樣IE6也就不會丟失字節了。
<a href="#" onclick="click1()">ff</a> <script type="text/javascript"> function click1(){ var path = encodeURI(encodeURI("servlet/RequestDemo?namea=任亮")); location.href = path; } </script> |
http://localhost/encoding/EncodingServlet?name=%E5%A4%A7%E5%AE%B6%E5%A5%BD |
在使用URL編碼後,大家好已經變成了%E5%A4%A7%E5%AE%B6%E5%A5%BD。這樣就不會再丟失字節了。
String val = request.getParameter("namea"); val = URLDecoder.decode(val, "UTF-8"); System.out.println(val); |
代碼1.xml示例:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript"> function subreq(){ var path = encodeURI(encodeURI("/request_demo3/hello3?name=李昆鵬1")); window.location.href=path; } </script> </head> <body> <h1>request接收參數</h1> <a href="/request_demo2/hello?name=likunpeng&age=30">訪問1.html</a> <hr/> <h1>request處理post方式中文亂碼問題</h1> <form action="/request_demo3/hello1" method="post"> 姓名:<input name="name" type="text"> <br/> 年齡:<input name="age" type="text"> <br/> 簡介:<br/> <textarea name="introduce" rows="10" cols="30"></textarea> <br/> <input type="submit" value="提交"> </form> <hr/> <h1>request處理get方式中文亂碼問題</h1> <a href="/request_demo3/hello2?name=李昆鵬&introduce=你好">點擊Get請求</a> <br/> <a href="#" οnclick="subreq()">點擊Get請求1</a> </body> </html> |
HelloServlet3代碼示例:
public class HelloServlet3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //設置request編碼爲UTF-8 //在get方式請求中request.setCharacterEncoding("UTF-8");不再起作用 String name = request.getParameter("name"); //下面是第一種解決get方式中文亂碼問題 //name = new String(name.getBytes("ISO-8859-1"),"UTF-8"); //第二種方式在服務器配置文件server.xml的Connector元素中添加編碼屬性URIEncoding="UTF-8" //第三種方式利用javaScript解決中文亂碼問題 name = URLDecoder.decode(name,"UTF-8"); System.out.println(name); } } |
6. HttpServletRequest請求轉發(服務器端跳轉forward)
在Servlet中請求轉發是大量要使用的,因爲當我們訪問一個Servlet的時候通常會執行一些後臺的業務邏輯,然後跳轉到一個結果頁面,那麼跳轉到結果頁面的這個過程就是請求轉發,舉個例子我們做登錄的功能,我們填寫用戶名密碼然後提交到一個負責登錄的Servlet,Servlet爲我們做用戶名和密碼的校驗,如果我們都正確的話,我們就要跳轉到登錄的提示頁面,如果錯誤就要跳轉到登錄失敗的頁面。
Request的請求轉發也可以叫做服務器端的跳轉,雖然有頁面的跳轉但是我們會發現地址欄是不會有變化的。
request.getRequestDispatcher("/success.html").forward(request, response); |
我們不但可以跳轉到靜態頁面(後續主要講解是動態頁面我們通常會跳轉到一個jsp(jsp在Servlet之後產生)的提示頁面,因爲我們要返回的是動態頁面,所有html是不適合(後續講解))。還可以跳轉到Servlet,此時我們可以給request來設置當前域中的屬性值,在該域之內(當前請求完成之前)都能獲得到該屬性值。
request.setAttribute("name", "任亮"); request.getAttribute("name"); |
Servlet內部頁面跳轉代碼示例:
代碼1.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>請求轉發</title> </head> <body> <h1>請求轉發到success.html頁面</h1> <form action="/request_demo4/hello" method="post"> 姓名:<input name="name" type="text"> <br/> 年齡:<input name="age" type="text"> <br/> 簡介:<br/> <textarea name="introduce" rows="10" cols="30"></textarea> <br/> <input type="submit" value="提交"> </form> <h1>請求轉發到servlet</h1> <form action="/request_demo4/hello" method="post"> 姓名:<input name="name" type="text"> <br/> 年齡:<input name="age" type="text"> <br/> 簡介:<br/> <textarea name="introduce" rows="10" cols="30"></textarea> <br/> <input type="submit" value="提交"> </form> <hr/> </body> </html> |
HelloServlet代碼:
public class HelloServlet extends HttpServlet {
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /** * request請求轉發 * 服務器的頁面跳轉,地址欄不變 */ System.out.println("servlet被訪問"); //使用request.setAttribute來設置結果集 request.setAttribute("testAttribute", new String[]{"li","kun","peng"}); request.getRequestDispatcher("/hello1").forward(request, response); }
@Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response);
}
} |
HelloServlet1代碼:
public class HelloServlet1 extends HttpServlet {
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /** * request請求轉發 * 服務器的頁面跳轉,地址欄不變 */ System.out.println("servlet1被訪問"); String[] attributeValues = (String[])request.getAttribute("testAttribute"); for (String attributeValue : attributeValues) { System.out.println(attributeValue); } request.getRequestDispatcher("/success.html").forward(request, response); }
@Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response);
}
} |
7.request域的作用範圍
在上一講我們提及過ServletContext的概念,它也是一個域的對象,它的範圍非常大,是指定項目所有Servlet的公共的對象,隨着服務器的啓動而產生,服務器的停止而銷燬,那麼request的也是域對象,它的作用範圍小的多,它的範圍只在一次請求響應範圍之內,每一個線程的請求都會新產生一個HttpServletRequest和HttpServletResponse的對象