關於HttpServletRequest的方法的使用

1 HttpServletRequest的功能

HttpServletRequestJavaWeb中非常重要的一個類。它是Servletservice()方法的參數之一!所以你必須必須要掌握它!

request的功能可以分爲以下幾種:

l         封裝了請求頭數據;

l         封裝了請求正文數據,如果是GET請求,那麼就沒有正文;

l         request是一個域對象,可以把它當成Map來添加獲取數據;

l         request提供了請求轉發和請求包含功能。

 

2 request獲取請求頭數據

String value = request.getHeader(“請求頭名稱”);

request對象可以用來獲取請求頭數據,當然,這些請求數據都是Tomcat封裝到request中去的。我們在service()方法中可以直接來獲取!

request與請求頭相關的方法有:

l         String getHeader(String name):獲取指定名稱的請求頭;

l         Enumeration getHeaderNames():獲取所有請求頭名稱;

l         int getIntHeader(String name):獲取值爲int類型的請求頭。

 

       response.setContentType("text/html;charset=utf-8");

       Enumeration names = request.getHeaderNames();

       while(names.hasMoreElements()) {

           String name = (String)names.nextElement();

           String value = request.getHeader(name);

           System.out.println(name +": " + value);

           response.getWriter().println(name +": " + value + "<br/>");

       }

 

3 request獲取請求相關的其它方法

request中還提供了與請求相關的其他方法,有些方法是爲了我們更加便捷的方法請求頭數據而設計,有些是與請求URL相關的方法。

l         int getContentLength():獲取請求正文的字節數,GET請求沒有正文,沒有正文返回-1

l         String getContentType():獲取請求類型,如果請求是GET,那麼這個方法返回null;如果是POST請求,那麼默認爲application/x-www-form-urlencoded,其它類型以後再學;

l         String getMethod():返回請求方法,例如:GET

l         Locale getLocale():返回當前客戶端瀏覽器支持的Localejava.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         int getRemotePort():返回客戶端的端口號,每次請求都會變;

l         String getSchema():返回請求協議,例如:http

l         String getServerName():返回主機名,例如:localhost

l         int getServerPort():返回服務器端口號,例如:80

 

http://localhost:8080/hello/a/b/c/d.jsp?mame=zhangSan

   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 request.getRemoteAddr():封IP

  可以使用request.getRemoteAddr()方法獲取客戶端的IP地址,然後判斷IP是否爲禁用IP。這種方式可以很方便的對多次密碼的用戶處理。

       String ip = request.getRemoteAddr();

       System.out.println(ip);

       if(ip.equals("127.0.0.1")) {

           response.sendError(500,"您的IP已被禁止!");

       } else {

           response.getWriter().print("Hello!");

       }

 

HttpServletRequest獲取參數

 

1 HttpServletRequest獲取參數方法

可以使用HttpServletRequest獲取客戶端的請求參數,相關方法如下:

l         String getParameter(String name):通過指定名稱獲取參數值;

l         String[] getParameterValues(String[] name):通過指定名稱獲取參數值數組,有可能一個名字對應多個值,例如表單中的多個複選框使用相同的name時;

l         Enumeration getParameterNames():獲取所有參數的名字;

l         Map getParameterMap():獲取所有參數對應的Map,其中key爲參數名,value爲參數值。

 

2 傳遞參數的方式

傳遞參數的方式:GETPOST

GET

l         地址欄中直接給出參數:http://localhost/param/ParamServlet?p1=v1&p2=v2

l         超鏈接中給出參數:<a href=” http://localhost/param/ParamServlet?p1=v1&p2=v2”>???</a>

l         表單中給出參數:<form method=”GET” action=”ParamServlet”>…</form>

 

POST

l         表單中給出參數:<form method=”POST” action=”ParamServlet”>…</form>

 

無論是GET還是POST,獲取參數的方法是相同的。

String s1 = request.getParameter(“p1”);//返回v1

String s2 = request.getParameter(“p2”);//返回v2

 

    <formaction="ParamServlet"method="post">

    <inputtype="text"name="p1"/><br/>

    <inputtype="text"name="p2"/><br/>

    <inputtype="submit"value="提交"/><br/>

    </form>

    <ahref="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);

       }

 

 

3 多值參數

例如在註冊表單中,如果讓用戶填寫愛好,那麼愛好可能就是多個。那麼hobby參數就會對應多個值:

    <formaction="ParamServlet"method="post">

       上網:<inputtype="checkbox"name="hobby"value="netplay"/><br/>

       踢球:<inputtype="checkbox"name="hobby"value="football"/><br/>

       看書:<inputtype="checkbox"name="hobby"value="read"/><br/>

       編程:<inputtype="checkbox"name="hobby"value="programme"/><br/>

    <inputtype="submit"value="提交"/><br/>

    </form>

       //獲取所有名爲hoby的參數值

       String[] hobbies = request.getParameterValues("hobby");

       System.out.println(Arrays.toString(hobbies));

 

 

4 獲取所有參數,並封裝到Map

  request.getParameterMap()方法返回Map類型,對應所有參數。其中Mapkey對應參數的名字;Mapvalue對應參數的值。

    <formaction="ParamServlet"method="post">

       姓名:<inputtype="text"name="name"/><br/>

       年齡:<inputtype="text"name="age"/><br/>

       性別:<inputtype="text"name="sex"/><br/>

    <inputtype="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

 

 

5 BeanUtils:使用Map創建Bean實例

我們知道,可以使用Map來創建Bean實例,我們也知道,可以把表單數據封裝到Map中返回。這樣我們就可以通過BeanUtils把表單數據封裝成Bean實例了。但要注意的是,必須要創建表單中參數的名稱與Bean的屬性名相同!!!

       try {

           Map<String,String[]> map = request.getParameterMap();

           Person person = new Person();

           BeanUtils.populate(person, map);[崔1] 

           System.out.println(person);

       } catch (IllegalAccessException e) {

           thrownew RuntimeException(e);

       } catch (InvocationTargetException e) {

           thrownew RuntimeException(e);

       }

 

 

6 單值參數,也可以使用request.getParameterValues(String)獲取

其實當參數的值是單個的時候,同樣可以使用request.getParameterValues(String)方法來獲取參數值,不過這個參數返回的值爲String[],這時我們需要再去獲取數組下標0的元素。

String name = request.getParameterValues(“name”)[0];

 

HttpServletRequest請求轉發

 

1        HttpServletRequest可以當作Map來用

JSP一共四個域對象(多出來一個PageContext,等第八天吧!)

Servlet中有三個對象是域對象,即在不同範圍內傳遞域變量:

l         HttpServletRequest:範圍爲請求,在同一請求範圍內傳遞屬性;

l         HttpSession:範圍是會話,在同一會話中傳遞屬性。當某個用戶打開某一網站的第一個頁面開始,直到關閉該網站的所有頁面結束,這是一個會話範圍;

l         ServletContext:範圍是Context,即項目。在同一個項目中,只有一個ServletContext

 

今天我們要使用的是HttpServletRequest的傳遞屬性功能。

所有域對象都有如下四個方法:

l         void setAttribute(String name, Object o):設置屬性,其中name爲屬性值,o爲屬性值;

l         void removeAttribute(String name):移除指定名字的屬性;

l         Object getAttribute(String name):獲取指定名稱的屬性;

l         Enumeration getAttibuteNames():獲取所有屬性名稱。

 

  注意,attributeparameter不同,attribute是我們自己設置的,而parameter是用戶通過表單、超鏈接中傳遞過來,然後由Tomcat封裝到request中的。說白一點,attribute是在服務器端組件中直接設置的,而parameter是由客戶端間接設置的。

 

2 在同一Servlet中測試域方法

       String name = request.getParameter("name")[崔2] ;

       request.setAttribute("name", name)[崔3] ;

       String aName = (String)request.getAttribute("name")[崔4] ;

       System.out.println(aName);

 

3 請求轉發

通常一個請求往往會涉及到多個Servlet,也就是說一個Servlet不只獨立完成一個請求,那麼就存在了請求轉發的“故事”。例如:登錄驗證Servlet在完成了驗證之後會把請求轉發給顯示主頁的Servlet

下面是一段“錯誤的轉發”:

publicclass AServletextends HttpServlet {

    protectedvoid doPost(HttpServletRequest req, HttpServletResponse resp)

           throws ServletException, IOException {

       System.out.println("AServlet的工作");

       Servlet bServlet = new BServlet();

       bServlet.service(req, resp);

    }

}

publicclass BServletextends HttpServlet {

    protectedvoid doPost(HttpServletRequest req, HttpServletResponse resp)

           throws ServletException, IOException {

       System.out.println("BServlet的工作");

    }

}

 

上面代碼中,AServlet會創建BServlet對象,然後去調用BServletservice()方法。這種方式確實可以調用BServlet,但這種方法的問題就太多太多了。

l         AServlet知道的太多了,它居然知道BServlet的存在;

l         BServletAServlet創建,不在是由Tomcat管理Servlet的生命週期;

 

所以我們在AServlet中不知道BServlet的存在,在AServlet中只知道一個servletName(對應<servlet-name>),然後使用Tomcat的方式,通過servletName完成轉發。

如果在AServlet中需要保存數據給BServlet,那麼可以使用request.setAttribute()方法來設置,然後在BServlet中就可以通過request.getAttribute()方法獲取了。

AServlet中獲取請求轉發器:

RequestDispatcher rd = request.getRequestDispatcher(“/BServlet”);

RequestDispatcher就是請求轉發器了,獲取它需要使用request對象的getRequestDispatcher()方法,該方法的參數就是BServletweb.xml文件中的配置名:<servlet-name>BServlet</servlet-name>

這只是獲取了轉發器,還沒有轉發。轉發需要調用RequestDispatcher對象的forward()方法,該方法需要傳遞requestresponse兩個參數。

       // AServlet內容

Person person = new Person();[崔5] 

       try {

           BeanUtils.populate(person, request.getParameterMap());[崔6] 

       } catch (IllegalAccessException e) {

           thrownew RuntimeException(e);

       } catch (InvocationTargetException e) {

           thrownew RuntimeException(e);

       }

       request.setAttribute("person", person);[崔7] 

       RequestDispatcher rd = request.getRequestDispatcher("/BServlet");[崔8] 

       rd.forward(request, response);[崔9] 

       // BServlet內容

Person person = (Person)request.getAttribute("person");[崔10] 

       response.getWriter().print("BServlet:" + person +"<br/>")[崔11] ;

       System.out.println("BServlet: " + person)[崔12] ;

 

 

l         一個請求;

l         在一個請求中可能會執行多個Servlet

l         多個Servlet中可以共享request

l         多個Servlet中只有最後可以用來向客戶端響應;

l         其他Servlet如果響應了,有兩種可能:

Ø         數據只寫入到緩衝區中,沒有到客戶端,在轉必之前,Tomcat會清空這些數據;

Ø         數據已經發送到客戶端,Tomcat會拋出異常,不再轉發。

n         緩衝區滿了,就會自動發送到客戶端;

n         調用response.flushBuffer()

n         調用PrintWriter.flush()

 

4 請求包含

請求包含與請求轉發非常相似,區別在與轉發時AServlet中的響應正文會被清除,只會留下BServlet中的響應正文,但請求包含會保留AServlet中的響應。

請求包含需要調用RequestDispatcher對象的include()方法。請求包含基本上與轉發是相同的,區別在與請求包含時,在AServlet中存在響應正文會保留下來,而請求轉發會清除AServlet所做的響應正文內容。

 

       Person person = new Person();

       try {

           BeanUtils.populate(person, request.getParameterMap());

       } catch (IllegalAccessException e) {

           thrownew RuntimeException(e);

       } catch (InvocationTargetException e) {

           thrownew RuntimeException(e);

       }

       PrintWriter out = response.getWriter();

       //轉發之前的響應,不會被髮送到客戶端瀏覽器上去。

       out.println("AServlet: " + person);[崔13] 

       request.setAttribute("person", person);

       RequestDispatcher rd = request.getRequestDispatcher("/BServlet");

       rd.include(request, response);[崔14] 

       Person person = (Person)request.getAttribute("person");

       PrintWriter out = response.getWriter();

       out.print("BServlet:" + person +"<br/>");

       System.out.println("BServlet: " + person);

AServlet: Person [name=zhangSan, age=23, sex=male]

BServlet:Person [name=zhangSan, age=23, sex=male]

 

5 理解請求轉發和請求包含

細心的童鞋們已經發現了,當從AServlet轉發到BServlet後,在客戶端的瀏覽器地址欄中的URL還是AServlet,而不是BServlet。也就是說,請求轉發這個“故事”瀏覽器並不知道!!!

你可以把請求轉發當作是一個請求內部調用了多個Servletservice()方法完成的,而客戶端只是發送了一個請求而已。


 [崔1]使用Map中的鍵值爲person的屬性賦值。

 [崔2]獲取名爲name的請求參數

 [崔3]設置名爲name的屬性,其值是請求參數

 [崔4]獲取名爲name的屬性。注意,因爲返回值類型爲Object,所以需要強轉

 [崔5]創建Person實例

 [崔6]把請求參數保存到Person實例中。

 [崔7]轉發前把person保存起來

 [崔8]獲取轉發器,要轉發的目的地是BServlet

 [崔9]完成轉發

 [崔10]BServlet獲取AServlet中設置的數據

 [崔11]向客戶端輸出

 [崔12]向服務器控制檯打印

 [崔13]添加響應正文內容

 [崔14]請求轉發到BServlet

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章