探索Android軟鍵盤的疑難雜癥 深入探討Android異步精髓Handler 詳解Android主流框架不可或缺的基石 站在源碼的肩膀上全解Scroller工作機制
Android多分辨率適配框架(1)— 核心基礎 Android多分辨率適配框架(2)— 原理剖析 Android多分辨率適配框架(3)— 使用指南
自定義View系列教程00–推翻自己和過往,重學自定義View 自定義View系列教程01–常用工具介紹 自定義View系列教程02–onMeasure源碼詳盡分析 自定義View系列教程03–onLayout源碼詳盡分析 自定義View系列教程04–Draw源碼分析及其實踐 自定義View系列教程05–示例分析 自定義View系列教程06–詳解View的Touch事件處理 自定義View系列教程07–詳解ViewGroup分發Touch事件 自定義View系列教程08–滑動沖突的產生及其處理
在前幾篇博客中我們學習了Tomcat,Http,Servlet,HttpServletResponse在此基礎上我們來深入學習Servlet的請求即HttpServletRequest
HttpServletRequest代表客戶端的請求,當客戶端通過HTTP協議訪問服務器時與請求相關的所有信息都將被封裝在這個對象中,所以我們可通過該對象獲得客戶端的相關信息。
常用的方法如下:
getRequestURL():返回客戶端發出請求時的完整URLgetRequestURI():返回請求行中的資源名部分getContextPath():返回請求的上下文路徑getQueryString():返回請求行中的參數部分getParameter():返回參數中的具體值getRemoteAddr():返回發出請求的客戶端的ip地址getRemoteHost():返回發出請求的客戶端的完整主機名getRemotePort():返回客戶端所使用的網絡端口號getMethod():返回客戶端使用的請求方式getHeaderNames():返回此請求包含的所有頭的名稱getHeader():返回指定的請求頭的值請看如下示例:
/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;import java.io.IOException;import java.util.Enumeration;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class TestServlet extends HttpServlet { @Override PRotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { getRequestInfo(request); getRequestHeader(request); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } //獲取與請求相關的信息 private void getRequestInfo(HttpServletRequest request){ String method=request.getMethod(); StringBuffer requestURL = request.getRequestURL(); String requestURI = request.getRequestURI(); String contextPath = request.getContextPath(); String queryString = request.getQueryString(); String name=request.getParameter("name"); String remoteAddr = request.getRemoteAddr(); String remoteHost = request.getRemoteHost(); int remotePort = request.getRemotePort(); System.out.println("----> method="+method); System.out.println("----> requestURL="+requestURL); System.out.println("----> requestURI="+requestURI); System.out.println("----> contextPath="+contextPath); System.out.println("----> queryString="+queryString); System.out.println("----> remoteAddr="+remoteAddr); System.out.println("----> remoteHost="+remoteHost); System.out.println("----> remotePort="+remotePort); } //獲取請求的Header中的信息 private void getRequestHeader(HttpServletRequest request){ Enumeration<String> headerNames = request.getHeaderNames(); while(headerNames.hasMoreElements()){ String headKey=headerNames.nextElement(); String headValue=request.getHeader(headKey); System.out.println(headKey+":"+headValue); } }}代碼寫好了,我們現在通過瀏覽器發出請求:
http://localhost:8081/TestServlet03/helloServlet?name=lucy
在Console中觀察輸入結果:
—-> method=GET —-> requestURL=http://localhost:8081/TestServlet03/helloServlet —-> requestURI=/TestServlet03/helloServlet —-> contextPath=/TestServlet03 —-> queryString=name=lucy —-> name=lucy —-> remoteAddr=127.0.0.1 —-> remoteHost=127.0.0.1 —-> remotePort=63484 host:localhost:8081 connection:keep-alive cache-control:max-age=0 accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 upgrade-insecure-requests:1 user-agent:Mozilla/5.0 (Windows NT 10.0;Win64; x64)Chrome/47.0.2526.111 accept-encoding:gzip, deflate, sdch accept-language:zh-CN,zh;q=0.8
嗯哼,結合這些輸出結果再回過頭看這些方法就能有更好的體會。在此,再次強調一下:請注意getRequestURL()和getRequestURI()以及getContextPath()、getQueryString()這四個方法的區別
getRequestURL()返回的是請求的路徑,但是不含請求的參數部分getRequestURI()返回請求行中的資源名部分,但是不含有請求的主機和端口以及請求的參數部分getContextPath()返回請求的上下文,即/+項目名稱,比如此處的/TestServlet03在前幾篇博客中我們學習了Tomcat,Http,Servlet,HttpServletResponse在此基礎上我們來深入學習Servlet的請求即HttpServletRequest
在剛才的示例中,我們利用getParameter()獲取GET請求中請求參數中的具體值,那么在POST請求時又該怎么獲取傳遞給服務端的值呢?請看如下示例
先準備一個表單:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Welcome</title></head><body> <form action="/TestServlet03/form" method="post"> 用 戶:<input type="text" name="username"/> <br/><br/> 密 碼:<input type="passWord" name="password"/> <br/><br/> 性 別:<input type="radio" name="gender" value="男" />男 <input type="radio" name="gender" value="女" checked="checked"/>女 <br/><br/> 愛 好:<input type="checkbox" name="hobby" value="攝影"/>攝影 <input type="checkbox" name="hobby" value="唱歌"/>唱歌 <input type="checkbox" name="hobby" value="拍照"/>拍照 <br/><br/> 城 市: <select name="city"> <option>------請選擇------</option> <option value="dj">東京</option> <option value="db">大阪</option> <option value="xt">仙臺</option> </select> <br/><br/> <input type="submit" value="歡迎注冊VIP會員"/> </form></body></html>再實現服務端的代碼:
/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;import java.io.IOException;import java.util.Enumeration;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class TestForm extends HttpServlet{ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { testForm1(request); } private void testForm1(HttpServletRequest request)throws ServletException,IOException { request.setCharacterEncoding("UTF-8"); Enumeration<String> parameterNames = request.getParameterNames(); while(parameterNames.hasMoreElements()){ String name = parameterNames.nextElement(); String[] values = request.getParameterValues(name); for(int i=0;values!=null&&i<values.length;i++){ System.out.println("name="+name+" "+"value="+values[i]); } } }}代碼解析如下:
利用setCharacterEncoding()設置編碼方式利用getParameterNames()獲取所有請求參數的名稱,請參見代碼第28行 對于此處的表單POST提交而言傳遞的參數的名稱分別為username,password,gender,hobby,city獲取每個參數對于的值,請參見代碼第29-35行嗯哼,現在我們通過瀏覽器來發起一個請求:
在Console觀察打印信息:
name=username value=杉原杏璃 name=password value=123456789 name=gender value=女 name=hobby value=攝影 name=hobby value=拍照 name=city value=dj
在實際開發中,我們可能需要將這些傳遞給服務端的信息封裝成實體,請看如下示例:
先準備一個實體Entity:
/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;import java.io.Serializable;import java.util.Arrays;public class User implements Serializable{ private String username; private String password; private String gender; private String[] hobby; private String city; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String[] getHobby() { return hobby; } public void setHobby(String[] hobby) { this.hobby = hobby; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "User [username=" + username + ", password=" + password + ", gender=" + gender + ", hobby=" + Arrays.toString(hobby) + ", city=" + city + "]"; }}請注意,該實體中字段的名字必須與表單中各個name的值相對應
再來看服務端的代碼:
private void testForm2(HttpServletRequest request)throws ServletException,IOException { try { request.setCharacterEncoding("UTF-8"); User user = new User(); Map<String,String[]> parameterMap = request.getParameterMap(); for (Map.Entry<String, String[]> map : parameterMap.entrySet()) { String name = map.getKey(); String[] values = map.getValue(); PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, User.class); Method method = propertyDescriptor.getWriteMethod(); if(values.length==1&&!name.equals("hobby")){ method.invoke(user, values[0]); }else{ method.invoke(user, (Object)values); } } System.out.println("------> "+user); } catch (Exception e) { e.printStackTrace(); } }代碼解析如下:
利用getParameterMap()得到請求中所有的參數及其對應的值,請參見代碼第5行 注意:有的參數只有一個值,比如該示例中的username;有的參數會有多個值,比如該示例中的hobby獲取每個參數及其對應的值,請參見代碼第7-8行反射出每個參數在實體中的setter()方法,請參見代碼第9-10行設置每個參數對應的值,請參見代碼第11-15行我們知道:
利用response.sendRedirect()實現請求的重定向利用request.getRequestDispatcher().forward()實現請求的轉發請注意它們的區別:
重定向時瀏覽器中的地址欄會發生變化,但是請求轉發時瀏覽器中地址欄不會發生改變。從本質上來講:重定向是兩次不同的請求,而請求轉發只向服務端的發送了一次請求由服務端的內部實現請求的跳轉。重定向可以跳轉到應用的外部,而重定向的范圍只能是應用的內部請求轉發可利用request.setAttribute()將數據傳遞到下一個Servlet且下一個Servlet可用request.getAttribute()取出數據;但是重定向不可以也沒有道理這么做。至于為什么,請參考第一點。新聞熱點
疑難解答