1request概述html
request是Servlet.service()方法的一個參數,類型爲javax.servlet.http.HttpServletRequest。在客戶端發出每一個請求時,服務器都會建立一個request對象,並把請求數據封裝到request中,而後在調用Servlet.service()方法時傳遞給service()方法,這說明在service()方法中能夠經過request對象來獲取請求數據。java
request的功能能夠分爲如下幾種:瀏覽器
l 封裝了請求頭數據;安全
l 封裝了請求正文數據,若是是GET請求,那麼就沒有正文;服務器
l request是一個域對象,能夠把它當成Map來添加獲取數據;app
l request提供了請求轉發和請求包含功能。post
2request域方法學習
request是域對象!在JavaWeb中一共四個域對象,其中ServletContext就是域對象,它在整個應用中只建立一個ServletContext對象。request其中一個,request能夠在一個請求中共享數據。編碼
一個請求會建立一個request對象,若是在一個請求中經歷了多個Servlet,那麼多個Servlet就可使用request來共享數據。如今咱們還不知道如何在一個請求中經歷之個Servlet,後面在學習請求轉發和請求包含後就知道了。url
下面是request的域方法:
l
void setAttribute(String name, Object value):用來存儲一個對象,也能夠稱之爲存儲一個域屬性,例如:servletContext.setAttribute(「xxx」, 「XXX」),在request中保存了一個域屬性,域屬性名稱爲xxx,域屬性的值爲XXX。請注意,若是屢次調用該方法,而且使用相同的name,那麼會覆蓋上一次的值,這一特性與Map相同;
l Object getAttribute(String name):用來獲取request中的數據,當前在獲取以前須要先去存儲才行,例如:String value = (String)request.getAttribute(「xxx」);,獲取名爲xxx的域屬性;
l void removeAttribute(String name):用來移除request中的域屬性,若是參數name指定的域屬性不存在,那麼本方法什麼都不作;
l Enumeration getAttributeNames():獲取全部域屬性的名稱;
3request獲取請求頭數據
request與請求頭相關的方法有:
l String getHeader(String name):獲取指定名稱的請求頭;
l Enumeration getHeaderNames():獲取全部請求頭名稱;
l int getIntHeader(String name):獲取值爲int類型的請求頭。
4request獲取請求相關的其它方法
request中還提供了與請求相關的其餘方法,有些方法是爲了咱們更加便捷的方法請求頭數據而設計,有些是與請求URL相關的方法。
l int getContentLength():獲取請求體的字節數,GET請求沒有請求體,沒有請求體返回-1;
l String getContentType():獲取請求類型,若是請求是GET,那麼這個方法返回null;若是是POST請求,那麼默認爲application/x-www-form-urlencoded,表示請求體內容使用了URL編碼;
l String getMethod():返回請求方法,例如:GET
l Locale getLocale():返回當前客戶端瀏覽器的Locale。java.util.Locale表示國家和言語,這個東西在國際化中頗有用;
l String getCharacterEncoding():獲取請求編碼,若是沒有setCharacterEncoding(),那麼返回null,表示使用ISO-8859-1編碼;
l void setCharacterEncoding(String code):設置請求編碼,只對請求體有效!注意,對於GET而言,沒有請求體!!!因此此方法只能對POST請求中的參數有效!
l String getContextPath():返回上下文路徑,例如:/hello
l String getQueryString():返回請求URL中的參數,例如:name=zhangSan
l String getRequestURI():返回請求URI路徑,例如:/hello/oneServlet
l StringBuffer getRequestURL():返回請求URL路徑,例如:http://localhost/hello/oneServlet,即返回除了參數之外的路徑信息;
l String getServletPath():返回Servlet路徑,例如:/oneServlet
l String getRemoteAddr():返回當前客戶端的IP地址;
l String getRemoteHost():返回當前客戶端的主機名,但這個方法的實現仍是獲取IP地址;
l String getScheme():返回請求協議,例如:http;
l String getServerName():返回主機名,例如:localhost
l int getServerPort():返回服務器端口號,例如:8080
System.out.println("request.getContentLength(): " + request.getContentLength()); System.out.println("request.getContentType(): " + request.getContentType()); System.out.println("request.getContextPath(): " + request.getContextPath()); System.out.println("request.getMethod(): " + request.getMethod()); System.out.println("request.getLocale(): " + request.getLocale());
System.out.println("request.getQueryString(): " + request.getQueryString()); System.out.println("request.getRequestURI(): " + request.getRequestURI()); System.out.println("request.getRequestURL(): " + request.getRequestURL()); System.out.println("request.getServletPath(): " + request.getServletPath()); System.out.println("request.getRemoteAddr(): " + request.getRemoteAddr()); System.out.println("request.getRemoteHost(): " + request.getRemoteHost()); System.out.println("request.getRemotePort(): " + request.getRemotePort()); System.out.println("request.getScheme(): " + request.getScheme()); System.out.println("request.getServerName(): " + request.getServerName()); System.out.println("request.getServerPort(): " + request.getServerPort()); |
4.1 案例:request.getRemoteAddr():封IP
可使用request.getRemoteAddr()方法獲取客戶端的IP地址,而後判斷IP是否爲禁用IP。
String ip = request.getRemoteAddr(); System.out.println(ip); if(ip.equals("127.0.0.1")) { response. getWriter().print("您的IP已被禁止!"); } else { response.getWriter().print("Hello!"); } |
5request獲取請求參數
最爲常見的客戶端傳遞參數方式有兩種:
l 瀏覽器地址欄直接輸入:必定是GET請求;
l 超連接:必定是GET請求;
l 表單:能夠是GET,也能夠是POST,這取決與<form>的method屬性值;
GET請求和POST請求的區別:
l GET請求:
Ø 請求參數會在瀏覽器的地址欄中顯示,因此不安全;
Ø 請求參數長度限制長度在1K以內;
Ø GET請求沒有請求體,沒法經過request.setCharacterEncoding()來設置參數的編碼;
l POST請求:
Ø 請求參數不會顯示瀏覽器的地址欄,相對安全;
Ø 請求參數長度沒有限制;
<a href="/hello/ParamServlet?p1=v1&p2=v2">超連接</a> <hr/> <form action="/hello/ParamServlet" method="post"> 參數1:<input type="text" name="p1"/><br/> 參數2:<input type="text" name="p2"/><br/> <input type="submit" value="提交"/> </form> |
|
下面是使用request獲取請求參數的API:
l String getParameter(String name):經過指定名稱獲取參數值;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String v1 = request.getParameter("p1"); String v2 = request.getParameter("p2"); System.out.println("p1=" + v1); System.out.println("p2=" + v2); }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String v1 = request.getParameter("p1"); String v2 = request.getParameter("p2"); System.out.println("p1=" + v1); System.out.println("p2=" + v2); } |
l String[] getParameterValues(String name):當多個參數名稱相同時,可使用方法來獲取;
<a href="/hello/ParamServlet?name=zhangSan&name=liSi">超連接</a> |
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String[] names = request.getParameterValues("name"); System.out.println(Arrays.toString(names)); } |
l Enumeration getParameterNames():獲取全部參數的名字;
<form action="/hello/ParamServlet" method="post"> 參數1:<input type="text" name="p1"/><br/> 參數2:<input type="text" name="p2"/><br/> <input type="submit" value="提交"/> </form> |
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Enumeration names = request.getParameterNames(); while(names.hasMoreElements()) { System.out.println(names.nextElement()); } } |
l Map getParameterMap():獲取全部參數封裝到Map中,其中key爲參數名,value爲參數值,由於一個參數名稱可能有多個值,因此參數值是String[],而不是String。
<a href="/day05_1/ParamServlet?p1=v1&p1=vv1&p2=v2&p2=vv2">超連接</a> |
Map<String,String[]> paramMap = request.getParameterMap(); for(String name : paramMap.keySet()) { String[] values = paramMap.get(name); System.out.println(name + ": " + Arrays.toString(values)); } |
p2: [v2, vv2] p1: [v1, vv1] |
6 請求轉發和請求包含
不管是請求轉發仍是請求包含,都表示由多個Servlet共同來處理一個請求。例如Servlet1來處理請求,而後Servlet1又轉發給Servlet2來繼續處理這個請求。
6.1 請求轉發
在AServlet中,把請求轉發到BServlet:
public class AServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("AServlet"); RequestDispatcher rd = request.getRequestDispatcher("/BServlet"); rd.forward(request, response); } } |
public class BServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("BServlet"); } } |
Aservlet BServlet |
6.2 請求包含
在AServlet中,把請求包含到BServlet:
public class AServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("AServlet"); RequestDispatcher rd = request.getRequestDispatcher("/BServlet"); rd.include(request, response); } } |
public class BServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("BServlet"); } } |
Aservlet BServlet |
6.3 請求轉發與請求包含比較
l 若是在AServlet中請求轉發到BServlet,那麼在AServlet中就不容許再輸出響應體,即不能再使用response.getWriter()和response.getOutputStream()向客戶端輸出,這一工做應該由BServlet來完成;若是是使用請求包含,那麼沒有這個限制;
l 請求轉發雖然不能輸出響應體,但仍是能夠設置響應頭的,例如:response.setContentType(」text/html;charset=utf-8」);
l 請求包含大可能是應用在JSP頁面中,完成多頁面的合併;
l 請求請求大可能是應用在Servlet中,轉發目標大可能是JSP頁面;
6.4 請求轉發與重定向比較
l 請求轉發是一個請求,而重定向是兩個請求;
l 請求轉發後瀏覽器地址欄不會有變化,而重定向會有變化,由於重定向是兩個請求;
l 請求轉發的目標只能是本應用中的資源,重定向的目標能夠是其餘應用;
l 請求轉發對AServlet和BServlet的請求方法是相同的,即要麼都是GET,要麼都是POST,由於請求轉發是一個請求;
l 重定向的第二個請求必定是GET;