JavaWeb(一)Servlet中的request與response


一、HttpServletRequest概述

1.1、HttpServletRequest簡介

  HttpServletRequest對象代表 客戶端的請求,當客戶端通過HTTP協議訪問服務器時,HTTP請求頭中的所有信息都封裝在這個對象中,開發人員通過這個對象的方法,可以獲得客戶這些信息。
  request就是 將請求文本封裝而成的對象,所以通過request能獲得請求文本中的所有內容,請求頭、請求體、請求行
    

二、詳解HttpServletRequest

2.1、請求行

  舉例: Get  http://localhost:8080/day09/servlet/req1?username=zs  http/1.1
  相關方法:
    getMethod();     獲得請求方式
    getRequestURL();    返回客戶端發出請求時的完整URL。
    getRequestURI();    返回請求行中的資源名部分。
    getContextPath();    當前應用的虛擬目錄 
    getQueryString() ;    返回請求行中的參數部分。
//        getMethod(); 獲得請求方式
//        ***getRequestURL();返回客戶端發出請求時的完整URL。
//        ***getRequestURI(); 返回請求行中的資源名部分。
//        *****getContextPath(); 當前應用的虛擬目錄 /day09_01_HttpServletRequest
//        getQueryString() ; 返回請求行中的參數部分。
        
        System.out.println(request.getMethod());//  GET
        System.out.println(request.getRequestURL()); // http://localhost:8080/day09_01_HttpServletRequest/servlet/demo1
        System.out.println(request.getRequestURI()); //   /day09_01_HttpServletRequest/servlet/demo1
        System.out.println(request.getContextPath()); //  /day09_01_HttpServletRequest
        System.out.println(request.getQueryString()); //  username=tom
舉例

   舉例二:Get  http://localhost:6060/Web_Servlet/ServletTest3?username=faker&password=mid  http/1.1

  相關方法:

    getRequestURI();
    getRequestURL();
    getProtocol(); 
    getScheme();
    getServerName();
    getServerPort();
    getContextPath();
    getServletPath();
    getQueryString();
    getRemoteAddr(); 

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.統一資源標記符   /Web_Servlet/ServletTest3
        String uri = req.getRequestURI();
        System.out.println(uri);
        //2.統一資源定位符    http://localhost:6060/Web_Servlet/ServletTest3 
        StringBuffer url = req.getRequestURL();
        System.out.println(url);
        //3.協議和版本    HTTP/1.1
        String potocol = req.getProtocol();
        System.out.println(potocol);
        //4.協議    http
        String scheme = req.getScheme();
        System.out.println(scheme);
        //5.主機(域名)  localhost,如果你使用的是ip地址,就顯示ip地址
        String serverName = req.getServerName();
        System.out.println(serverName);
        //6.端口  6060(這是我自己修改了的端口,默認是8080)
        int port = req.    getServerPort();
        System.out.println(port);
        //7.發布到tomcat下的項目名稱  /Web_Servlet
        String contextPath = req.getContextPath();
        System.out.println(contextPath);
        //8.servlet路徑    /ServletTest3 
        String servletPath = req.getServletPath();
        System.out.println(servletPath);
        //9.獲取所有請求參數,即?之后所有東西。    username=faker&password=mid
        String queryString = req.getQueryString();
        System.out.println(queryString);
        //10.遠程主機的ip地址    0:0:0:0:0:0:0:1
        String remoteAddr = req.getRemoteAddr();
        System.out.println(remoteAddr);
        
        
    }
舉例二

2.2、請求頭  

  我們可以查看任意一個網頁,它都是有請求頭的。

  

  相關方法: 

    String getHeader(String name) 根據頭名稱得到頭信息值

    long getDateHeader(java.lang.String name) 獲得指定頭內容Date

    int getIntHeader(java.lang.String name)  獲得指定頭內容int

    Enumeration getHeaderNames() 得到所有頭信息name
    Enumeration getHeaders(String name) 根據頭名稱得到相同名稱頭信息值

  舉例1:Enumeration getHeaderNames() 得到所有頭信息name 

Enumeration<String> headerNames = req.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String key = (String)headerNames.nextElement();
            String value = req.getHeader(key);
            System.out.println(key+"="+value);
        } 

  結果:

    

  舉例2:Enumeration getHeaders(String name) 根據頭名稱得到相同名稱頭信息值

        Enumeration<String> headers = req.getHeaders("accept-language");
        while(headers.hasMoreElements()){
            String key = (String)headers.nextElement();
            String value = req.getHeader(key);
            System.out.println(key+"==="+value);
            
        }

  結果:

    

2.3、請求體(請求正文)

  1)與表單獲取相關的方法

  方法:    

    String getParameter(name)   根據表單中name屬性的名,獲取value屬性的值方法
    String[] getParameterValues(String name)  專為復選框取取提供的方法
    getParameterNames()   得到表單提交的所有name的方法
    Map<String , String[]> getParameterMap()   得到表單提交的所有值的方法 //做框架用,非常實用
    getInputStream    以字節流的方式得到所有表單數據

  舉例:   

<form action="/day09_01_HttpServletRequest/servlet/demo3" method="get">
        用戶名:<input type="text" name="userName"/><br/>
        密碼:<input type="password" name="pwd"/><br/>
        性別:<input type="radio" name="sex" value="" checked="checked"/><input type="radio" name="sex" value=""/>女  <br/>
        愛好 :
            <input type="checkbox" name="hobby" value="籃球"/>籃球
            <input type="checkbox" name="hobby" value="唱歌"/>唱歌
            <input type="checkbox" name="hobby" value="編碼"/>編碼
            <br/>
        所在城市:
        <select name="city">
            <option>------請選擇------</option>
            <option value="bj">北京</option>
            <option value="sh">上海</option>
            <option value="gz">廣州</option>
        </select>
        <br/>
        
        <input type="submit" value="注冊"/>
    </form>
舉例

  測試1使用方法:   

    <input type="text" name="username" />
     getParameter(name) 根據表單中name屬性的名,獲取value屬性的值方法 
    getParameterValues(String name)專業為復選框取取提供的方法
//獲取表單數據
        
        //根據表單中name屬性的名,獲取value屬性的值方法 
        String userName = request.getParameter("userName");
        String pwd = request.getParameter("pwd");
        String sex = request.getParameter("sex");
        String[] hobbys = request.getParameterValues("hobby");
        
        String city = request.getParameter("city");
        
        userName = new String(userName.getBytes("iso-8859-1"),"UTF-8");
        System.out.println(userName);
        System.out.println(pwd);
        System.out.println(sex);
        
        for (int i = 0;hobbys!=null && i < hobbys.length; i++) {
            System.out.print(hobbys[i]+"\t");
        }
        System.out.println();
        
        System.out.println(city);
測試一

   測試2使用方法:

     getParameterNames() 得到表單提交的所有name的方法 

    getParameterValues(String name)專業為復選框取取提供的方法

//獲取所有的表單name的名子
        Enumeration names = request.getParameterNames();
        while(names.hasMoreElements()){
            String name = (String) names.nextElement();//得到每一個name名
            String[] values = request.getParameterValues(name);//根據name名,得到value值
            for (int i = 0;values!=null && i < values.length; i++) {
                System.out.println(name+"\t"+values[i]);
測試二    

   測試3使用方法:

    getParameterMap 到表單提交的所有值的方法   //做框架用,非常實用

try {
            User u = new User();
            System.out.println("封裝數據前:"+u);
            //獲取表單數據
            Map<String,String[]> map = request.getParameterMap();
            
            for (Map.Entry<String, String[]> m : map.entrySet()) {
                String name = m.getKey();
                String[] value = m.getValue();
                
                //創建一屬性描述器
                PropertyDescriptor pd = new PropertyDescriptor(name, User.class);
                //得到setter屬性
                Method setter = pd.getWriteMethod();
                
                if(value.length==1){
                    setter.invoke(u, value[0]);//給一個值的變量賦值
                }else{
                    setter.invoke(u, (Object)value);//相關於給復選框賦值
                }
            }
            
            System.out.println("封裝數據后:"+u);
        } catch (Exception e) {
            e.printStackTrace();
        }
測試三

  測試4使用方法:

    getInputStream  以字節流的方式得到所有表單數據

request.setCharacterEncoding("UTF-8");
        //獲取表單數據
        ServletInputStream sis = request.getInputStream();
        int len = 0;
        byte[] b = new byte[1024];
        while((len=sis.read(b))!=-1){
            //System.out.println(new String(new String(b,0,len).getBytes(),"utf-8"));
            System.out.println(new String(b, 0, len, "UTF-8"));
        }
        
        sis.close();
測試四

   2)與操作非表單數據相關的方法(request也是一個域對象)

  方法:

    void setAttribute(String name, Object value);
    Object getAttribute(String name);
    Void removeAttribute(String name);

  3)與請求轉發相關的方法

  方法: 

    //得到請求轉發或請求包含的協助對象
    RequestDispatcher getRequestDispatcher(String path)
    forward(ServletRequest request, ServletResponse response) //轉發的方法
    include(ServletRequest request, ServletResponse response) //請求包含

  注意:    

    include()方法的處理流程:
      一是:如果目標組件為Servlet或JSP,就執行它們,並把它們產生的響應正文添加到源組件的響應結果中;
      如果目標組件為HTML文檔,就直接把文檔的內容添加到源組件的響應結果中。
      二是:返回到源組件的服務方法中,繼續執行后續代碼塊。
    特點:
      一是:源組件與被包含的目標組件的輸出數據都會被添加到響應結果中。
      二是:在目標組件中對響應狀態代碼或者響應頭所做的修改都會被忽略。

   使用:

    //path:轉發后跳轉的頁面,這里不管用不用"/"開頭,都是以web項目根開始,因為這是請求轉發,請求轉發只局限與在同一個web項目下使用,所以這里一直都是從web項目根下開始的。 

    request.getRequestDispatcher(String path).forward(request,response);     

    web項目根:

      開發:G:\Workspaces\test01\WebRoot\..

      運行時:D:\java\tomcat\apache-tomcat-7.0.53\webapps\test01\..

    web站點根:

      運行時:D:\java\tomcat\apache-tomcat-7.0.53\webapps\..

     從這里可以看出,web項目根就是從該web項目名開始,所以我們請求轉發時,只需要接着項目名后面需要訪問的路徑寫就行了。

    特點:瀏覽器中url不會改變,也就是瀏覽器不知道服務器做了什么,是服務器幫我們跳轉頁面的,並且在轉發后的頁面,能夠繼續使用原先的request,因為是原先的request,所以request域中的屬性都可以繼續獲取到。

  4)與編碼相關的方法  

    //解決post方式編碼
      request.setCharacterEncoding("UTF-8"); //告訴服務器客戶端什么編碼,只能處理post請求方式 
    //解決get方式編碼
      String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”);

三、reqeust的常見應用

3.1、各種表單輸入項數據的獲取

  text、password、radio、checkbox、file、select、textarea、 hidden
  image、button給js編程用
  請求參數的中文亂碼問題 
  瀏覽器是什么編碼就以什么編碼傳送數據 
  解決:request.setCharacterEncoding(“UTF-8”);//POST有效
        new String(username.getBytes(“ISO-8859-1”),“UTF-8”);//GET方式

3.2、request對象實現請求轉發

  請求轉發指一個web資源收到客戶端請求后,通知服務器去調用另外一個web資源進行處理
  request對象提供了一個getRequestDispatcher方法,該方法返回一個RequestDispatcher對象,調用這個對象的forward方法可以實現請求轉發。
  request對象同時也是一個域對象,開發人員通過request對象在實現轉發時,把數據通過request對象帶給其它web資源處理

四、HttpServletResponse概述

4.1、HttpServletResponse簡介

  Web服務器收到客戶端的http請求,會針對每一次請求,分別創建一個用於代表請求的request對象、和代表響應的response對象。
  request和response對象即然代表請求和響應,那我們要獲取客戶機提交過來的數據,只需要找request對象就行了。要向容器輸出數據,只需要找response對象就行了。
  HttpServletResponse對象代表服務器的響應。這個對象中封裝了向客戶端發送數據、發送響應頭,發送響應狀態碼的方法。
  

4.2、HttpServletResponse細節  

  getOutputStream和getWriter方法分別用於得到輸出二進制數據、輸出文本數據的ServletOuputStream、Printwriter對象。

  getOutputStream和getWriter這兩個方法互相排斥,調用了其中的任何一個方法后,就不能再調用另一方法。 會拋異常。

  Servlet程序向ServletOutputStream或PrintWriter對象中寫入的數據將被Servlet引擎從response里面獲取,Servlet引擎將這些數據當作響應消息的正文,
  然后再與響應狀態行和各響應頭組合后輸出到客戶端。

  Serlvet的service方法結束后,Servlet引擎將檢查getWriter或getOutputStream方法返回的輸出流對象是否已經調用過close方法,
  如果沒有,Servlet引擎將調用close方法關閉該輸出流對象。

五、詳解HttpServletResponse

5.1、響應行

  響應狀態行    HTTP/1.1  200 OK

  常見的響應狀態碼:    

  200 OK
    一切正常,對GET和POST請求的應答文檔跟在后面
  3XX  用於已經移動的文件並且充被包含在定位頭信息中指定新的地址消息
    302 Found
    類似於301,但新的URL應該被視為臨時性的替代,而不是永久性的。
  4XX  用於指出客戶端的錯誤
    404 Not Found  無法找到指定位置的資源 
  5XX   用於支持服務器錯誤
    500 Internal Server Error   服務器遇到了意料不到的情況,不能完成客戶的請求
  方法:
    setStatus(int sc) 設置響應狀態碼

5.2、響應頭

  常見的響應頭  
        Accept:指示HTTP響應可以接收的文檔類型集
        Accept-Charset:告知客戶可以接收的字符集
        Accept-Encoding:所有響應的字符編碼集
        Content-Type:響應體的MIME類型
        Content-Language:響應體的語言類型
        Content-Length:響應體的長度和字節數
        Expires:通知客戶端過期時間,防止客戶瀏覽器使用本地緩存副本
        Cookie:包含保存到客戶端的Cookie集
        Redirect:提供指定重定向,可以不向瀏覽器輸出響應內容,而是直接重新請求到另一個URL地址,實現重定向響應,即是一種自動定向。 
  方法:
    setHeader(String name, String value) 設置響應頭信息
    舉例:
      response.setHeader(java.lang.String name, java.lang.String value) 設置指定的頭,一般常用。 
    //告知瀏覽器使用什么碼表
    response.setHeader("content-type", "text/html;charset=UTF-8");
    代替了:
      //告訴服務器應用使用UTF-8解析文本
        response.setCharacterEncoding("UTF-8");
        //告訴客戶端要使用什么編碼
        response.setHeader("content-type", "text/html;charset=UTF-8");
      
      
       //告知客戶端不緩存
      response.setHeader("pragma", "no-cache");
      response.setHeader("cache-control", "no-cache");
      response.setDateHeader("expires", 0);
 
      //設置每隔3秒就自動刷新一次
      response.setHeader("Refresh",3);

5.3、響應正文

  常用方法:

    getWrite(); 字符輸出流
    getOutputStream(); 字節輸出流
    setCharacterEncoding(String charset) 告知服務器使用什么編碼
    setContentType(String type)

 5.4、重定向

  1)重定向運行原理  

    重定向機制的運作流程
    第一步:用戶在瀏覽器端輸入特定URL,請求訪問服務器端的某個組件
    第二步:服務器端的組件返回一個狀態碼為302的響應結果。
    第三步:當瀏覽器端接收到這種響應結果后,再立即自動請求訪問另一個web組件
    第四步:瀏覽器端接收到來自另一個web組件的響應結果。
    HttpServeltResponse的sendRedirect(String location)用於重定向

   2)具體實現

  方式一:手動方案

    response.setStatus(302);  //狀態碼302就代表重定向

    response.setHeader("location","http://www.baidu.com");

  方式二:使用封裝好的,通過response.sendRedirect("http://www.baidu.com");

    特點:服務器告訴瀏覽器要跳轉的頁面,是瀏覽器主動去跳轉的頁面,瀏覽器知道,也瀏覽器的地址欄中url會變,是瀏覽器重新發起一個請求到另外一個頁面,所以request是重新發起的,跟請求轉發不一樣

    注意:response.sendRedirect(path);  //

    第一種:response.sendRedirect("/test01/MyServlet01");  //使用了"/"開頭,說明是從web站點根開始,所以需要寫test01/MyServlet01

    第二種:response.sendRedirect("MyServlet01");  //沒有使用"/"開頭,說明是從web項目根開始,那么就無需寫test01了

    注意:重定向沒有任何局限,可以重定向web項目內的任何路徑,也可以訪問別的web項目中的路徑,並且這里就用"/"區分開來如果使用了"/"開頭,就說明我要重新開始定位了,不訪問剛才的web項目,自己寫項目名,

       如果沒有使用"/"開始,那么就知道是訪問剛才那個web項目下的servlet,就可以省略項目名了。就是這樣來區別。 

六、Response常見應用

6.1、向客戶端輸出中文數據

  1)用OutputStream(字節流)發送數據:
    response.getOutputStream().write(“中國”.getBytes());//以默認編碼發送數據
    response.getOutputStream().write("中國".getBytes("UTF-8"));//以UTF-8編碼發送數據,瀏覽器(默認用GB2312)會出現亂碼
 
  解決辦法:
    通過更改瀏覽器的編碼方式:IE/”查看”/”編碼”/”UTF-8”(不可取)
    通過設置響應頭告知客戶端編碼方式:response.setHeader(“Content-type”, “text/html;charset=UTF-8”);//告知瀏覽器數據類型及編碼
    通過meta標簽模擬請求頭:out.write("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />".getBytes());
    通過以下方法:response.setContentType("text/html;charset=UTF-8");
 
  2)用PrintWriter(字符流)發送數據:
    示例:response.getWriter().write(“中國” );有沒有亂碼?
    原因:以默認編碼發送數據 ISO-8859-1(沒有中國二字編碼),此時會發生亂碼
  解決辦法:
    setCharacterEncoding(“UTF-8”);
    //更改編碼為UTF-8
    response.setHead(“Context-type”,”text/html;charset=UTF-8”);
    //告訴客戶端編碼方式
  注意:不要忘記告訴客戶端的編碼方式。
    由於經常改動編碼,response提供了一種更簡單的方式
    response. setContentType(“text/html;charset=UTF-8”); 其作用相當於以上兩條代碼。

6.2、文件下載

//通過路徑得到一個輸入流
        String path = this.getServletContext().getRealPath("/WEB-INF/classes/美女.jpg");
        FileInputStream fis = new FileInputStream(path);
        //創建字節輸出流
        ServletOutputStream sos = response.getOutputStream();
        
        //得到要下載的文件名
        String filename = path.substring(path.lastIndexOf("\\")+1);
        
        //設置文件名的編碼
        filename = URLEncoder.encode(filename, "UTF-8");//將不安全的文件名改為UTF-8格式
        
        //告知客戶端要下載文件
        response.setHeader("content-disposition", "attachment;filename="+filename);
        response.setHeader("content-type", "image/jpeg");
        
        //執行輸出操作
        int len = 1;
        byte[] b = new byte[1024];
        while((len=fis.read(b))!=-1){
            sos.write(b,0,len);
        }
        
        sos.close();
        fis.close();
代碼示例

 6.3、生成驗證碼

  之后我會詳細介紹

6.4、定時刷新頁面

  利用Refresh刷新到其他組件。模擬注冊頁面,注冊處理交由一個Servlet,在Servlet處理完成后,顯示注冊成功並轉向主頁。(meta也可實現)

  

 

喜歡就點個“推薦”哦!

 


免責聲明!

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



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