【二】HttpServletRequest & HttpServletResponse

1. ServletContext

Servlet 上下文

每個web工程都只有一個ServletContext對象。 說白了也就是不管在哪個Servlet里面,獲取到的這個類的對象都是同一個。

1.1 有什么作用?

  • 1.1.1 獲取全局配置參數(shù)
<!-- 配置參數(shù) -->
  <context-param>
    <param-name>address</param-name>
    <param-value>shanghai</param-value>
  </context-param>
ServletContext servletContext = getServletContext();
String value = servletContext.getInitParameter("address");
System.out.println("address =" + value);
  • 1.1.2 獲取web工程中的資源
    a.先獲取路徑,在獲取流對象
/**
     * 先獲取路徑,在獲取流對象
     * @throws FileNotFoundException
     * @throws IOException
     */
    private void test01() throws FileNotFoundException, IOException {
        // 獲取ServletContext對象
        ServletContext context = getServletContext();
        //獲取給定的文件在服務(wù)器上面的絕對路徑剥险。
        String path = context.getRealPath("file/config.properties");
        System.out.println("path="+path);
//      path=/Users/Ben/Library/apache-tomcat-7.0.92/wtpwebapps/Demo03/file/config.properties

        // 1. 創(chuàng)建屬性對象
        Properties properties = new Properties();
        InputStream is = new FileInputStream(path);
        properties.load(is);

        // 3. 獲取name屬性的值
        String name = properties.getProperty("name");

        System.out.println("name=" + name);
    }

b.根據(jù)相對路徑,直接獲取流對象

/**
     * 根據(jù)相對路徑宪肖,直接獲取流對象
     */
    private void test02() {
        try {
            // 獲取ServletContext對象
            ServletContext context = getServletContext();
            
            // 1. 創(chuàng)建屬性對象
            Properties properties = new Properties();
            InputStream is = context.getResourceAsStream("file/config.properties");
            properties.load(is);
            // 3. 獲取name屬性的值
            String name = properties.getProperty("name");
            System.out.println("name22=" + name);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

c.根據(jù)classloader去獲取工程下的資源 類加載器(JDBC)

/**
     * 根據(jù)classloader去獲取工程下的資源    類加載器(JDBC)
     */
    private void test03() {
        try {
            // 1. 創(chuàng)建屬性對象
            Properties properties = new Properties();
            InputStream is = this.getClass().getClassLoader().getResourceAsStream("../../file/config.properties");
            properties.load(is);
            // 3. 獲取name屬性的值
            String name = properties.getProperty("name");
            System.out.println("name333333=" + name);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 1.1.3 存取數(shù)據(jù)表制,Servlet間共享數(shù)據(jù) 域?qū)ο?br> a.定義一個登陸的html頁面, 定義一個form表單
<!--    
    A路徑: Servlet的路徑
        http://localhost:8080/Demo4/login
    
    B路徑: 當(dāng)前這個html的路徑:
        http://localhost:8080/Demo4/login.html -->
    <form action="login" method="get">
        賬號:<input type="text" name="username"/><br>
        密碼:<input type="text" name="password"/><br>
        <input type="submit" value="登錄"/>
    </form>

b.定義一個Servlet控乾,名為LoginServlet么介,用戶登錄之后,成功跳到成功的html蜕衡,并做一個登錄次數(shù)統(tǒng)計的需求壤短。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        
        //1. 獲取數(shù)據(jù)
        String userName = request.getParameter("username");
        String password = request.getParameter("password");
        
        System.out.println("userName="+userName+"==password="+password);
        //2. 校驗數(shù)據(jù)
        
        //向客戶端輸出內(nèi)容
        PrintWriter pw = response.getWriter();
        
        if("admin".equals(userName) && "123".equals(password)){
            //System.out.println("登錄成功");
            pw.write("login success..");
            //成功就跳轉(zhuǎn)到login_success.html
            
            //1. 成功的次數(shù)累加
            
            //獲取以前存的值 , 然后在舊的值基礎(chǔ)上  + 1 
            Object obj = getServletContext().getAttribute("count") ; 
            
            //默認(rèn)就是0次
            int totalCount = 0 ;
            if(obj != null){
                totalCount = (int) obj;
            }
            
            System.out.println("已知登錄成功的次數(shù)是:"+totalCount);
            
            //給這個count賦新的值
            getServletContext().setAttribute("count", totalCount+1);
            
            
            //2. 跳轉(zhuǎn)到成功的界面 
            //設(shè)置狀態(tài)碼? 重新定位 狀態(tài)碼
            response.setStatus(302);
            //定位跳轉(zhuǎn)的位置是哪一個頁面。
            response.setHeader("Location", "login_success.html");
        }else{
            pw.write("login failed..");
        }
        
    }

1.2 ServletContext 何時創(chuàng)建久脯, 何時銷毀?

服務(wù)器啟動的時候纳胧,會為托管的每一個web應(yīng)用程序,創(chuàng)建一個ServletContext對象
從服務(wù)器移除托管帘撰,或者是關(guān)閉服務(wù)器跑慕。

1.3 ServletContext 的作用范圍

只要在這個項目里面,都可以取摧找。 只要同一個項目核行。 A項目 存, 在B項目取蹬耘,是取不到的芝雪? ServletContext對象不同。

2. HttpServletRequest

這個對象封裝了客戶端提交過來的一切數(shù)據(jù)

2.1 可以獲取客戶端請求頭信息

//得到一個枚舉集合  
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = (String) headerNames.nextElement();
            String value = request.getHeader(name);
            System.out.println(name+"="+value);
            
        }

2.2 獲取客戶端提交過來的數(shù)據(jù)

String name = request.getParameter("name");
        String address = request.getParameter("address");
        System.out.println("name="+name);
        System.out.println("address="+address);

        -------------------------------------------------

        //name=zhangsan&name=lisi&name=wangwu 一個key可以對應(yīng)多個值综苔。

        Map<String, String[]> map = request.getParameterMap();
        
        Set<String> keySet = map.keySet();
        Iterator<String> iterator = keySet.iterator();
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            System.out.println("key="+key + "--的值總數(shù)有:"+map.get(key).length);
            String value = map.get(key)[0];
            String value1 = map.get(key)[1];
            String value2 = map.get(key)[2];
            
            System.out.println(key+" ======= "+ value + "=" + value1 + "="+ value2);
        }

2.3 獲取中文數(shù)據(jù)亂碼問題

客戶端提交數(shù)據(jù)給服務(wù)器端惩系,如果數(shù)據(jù)中帶有中文的話,有可能會出現(xiàn)亂碼情況如筛,那么可以參照以下方法解決蛆挫。

  • 如果是GET方式
  1. 代碼轉(zhuǎn)碼
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("userName="+username+"==password="+password);
//get請求過來的數(shù)據(jù),在url地址欄上就已經(jīng)經(jīng)過編碼了妙黍,所以我們?nèi)〉降木褪莵y碼,
//tomcat收到了這批數(shù)據(jù)瞧剖,getParameter 默認(rèn)使用ISO-8859-1去解碼
//先讓文字回到ISO-8859-1對應(yīng)的字節(jié)數(shù)組 拭嫁, 然后再按utf-8組拼字符串
username = new String(username.getBytes("ISO-8859-1") , "UTF-8");
System.out.println("userName="+username+"==password="+password);
  1. 可以在tomcat里面做設(shè)置處理 conf/server.xml 加上URIEncoding="utf-8"
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>
  • 如果是POST方式
這個說的是設(shè)置請求體里面的文字編碼。  get方式抓于,用這行做粤,有用嗎? ---> 沒用
request.setCharacterEncoding("UTF-8");
這行設(shè)置一定要寫在getParameter之前捉撮。

3.HttpServletResponse

負(fù)責(zé)返回數(shù)據(jù)給客戶端。

  • 輸出數(shù)據(jù)到頁面上
//以字符流的方式寫數(shù)據(jù)    
//response.getWriter().write("<h1>hello response...</h1>");
//以字節(jié)流的方式寫數(shù)據(jù) 
response.getOutputStream().write("hello response2222...".getBytes());

3.1 響應(yīng)的數(shù)據(jù)中有中文巾遭,那么有可能出現(xiàn)中文亂碼

  • 以字符流輸出

response.getWriter()

//1. 指定輸出到客戶端的時候肉康,這些文字使用UTF-8編碼
response.setCharacterEncoding("UTF-8");
//2. 直接規(guī)定瀏覽器看這份數(shù)據(jù)的時候灼舍,使用什么編碼來看。
response.setHeader("Content-Type", "text/html; charset=UTF-8");
response.getWriter().write("我愛java...");
  • 以字節(jié)流輸出

response.getOutputStream()

//1. 指定瀏覽器看這份數(shù)據(jù)使用的碼表
response.setHeader("Content-Type", "text/html;charset=UTF-8");
//2. 指定輸出的中文用的碼表
response.getOutputStream().write("我愛java和PHP..".getBytes("UTF-8"));
  • 不管是字節(jié)流還是字符流骑素,直接使用一行代碼就可以了。
response.setContentType("text/html;charset=UTF-8");
然后在寫數(shù)據(jù)即可。

4.文件下載

  • 下載html代碼
<br>手動編碼提供下載末捣。:<br>
    <a href="Demo01?filename=aa.jpg">aa.jpg</a><br>
    <a href="Demo01?filename=bb.txt">bb.txt</a><br>
    <a href="Demo01?filename=cc.rar">cc.rar</a><br>
  • Servlet代碼
public class Demo01 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        
        //1. 獲取要下載的文件名字 aa.jpg  --- inputStream
        String fileName = request.getParameter("filename");
        
        /*
         * 如果文件的名字帶有中文,那么需要對這個文件名進(jìn)行編碼處理
         * 如果是IE 箩做,或者  Chrome (谷歌瀏覽器) 莽红,使用URLEncoding 編碼
         * 如果是Firefox 卒茬, 使用Base64編碼
         */
        //獲取來訪的客戶端類型
        String clientType = request.getHeader("User-Agent");

        if(clientType.contains("Firefox")){
//          fileName = DownLoadUtil.base64EncodeFileName(fileName);
        }else{
            //IE ,或者  Chrome (谷歌瀏覽器) 圃酵,
            //對中文的名字進(jìn)行編碼處理
            fileName = URLEncoder.encode(fileName,"UTF-8");
        }
        
        
        //2. 獲取這個文件在tomcat里面的絕對路徑地址
        String path = getServletContext().getRealPath("download/"+fileName);
        
        //讓瀏覽器收到這份資源的時候, 以下載的方式提醒用戶郭赐,而不是直接展示薪韩。 
        response.setHeader("Content-Disposition", "attachment; filename="+fileName);
        
        //3. 轉(zhuǎn)化成輸入流
        InputStream is = new FileInputStream(path);
        OutputStream os = response.getOutputStream();
        
        int len = 0 ;
        byte[]buffer = new byte[1024];
        while( (len = is.read(buffer)) != -1){
            os.write(buffer, 0, len);
        }
        
        os.close();
        is.close();
    
    }

5.重定向和請求轉(zhuǎn)發(fā)(登錄成功跳轉(zhuǎn)成功界面)

public class LoginServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");
        
        String userName = request.getParameter("username");
        String password = request.getParameter("password");
        
        if("admin".equals(userName) && "123".equals(password)){
            //response.getWriter().write("登錄成功");
            /*
             * 早期的寫法:
             * response.setStatus(302);
            response.setHeader("Location", "login_success.html");*/
            
            //重定向?qū)懛ǎ?重新定位方向  /根目錄 
            response.sendRedirect("login_success.html");
            
            
            //請求轉(zhuǎn)發(fā)的寫法:
//          request.getRequestDispatcher("login_success.html").forward(request, response);
        }else{
            response.getWriter().write("登錄失敗");
        }
    }

重定向說明

  1. 地址上顯示的是最后的那個資源的路徑地址
  2. 請求次數(shù)最少有兩次, 服務(wù)器在第一次請求后捌锭,會返回302 以及一個地址俘陷, 瀏覽器在根據(jù)這個地址,執(zhí)行第二次訪問观谦。
  3. 可以跳轉(zhuǎn)到任意路徑拉盾。 不是自己的工程也可以跳。
  4. 效率稍微低一點豁状, 執(zhí)行兩次請求捉偏。
  5. 后續(xù)的請求,沒法使用上一次的request存儲的數(shù)據(jù)泻红,或者 沒法使用上一次的request對象夭禽,因為這是兩次不同的請求。

請求轉(zhuǎn)發(fā)說明

  1. 地址上顯示的是請求servlet的地址谊路。 返回200 ok
  2. 請求次數(shù)只有一次讹躯, 因為是服務(wù)器內(nèi)部幫客戶端執(zhí)行了后續(xù)的工作。
  3. 只能跳轉(zhuǎn)自己項目的資源路徑 缠劝。
  4. 效率上稍微高一點潮梯,因為只執(zhí)行一次請求。
  5. 可以使用上一次的request對象惨恭。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末酷麦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子喉恋,更是在濱河造成了極大的恐慌沃饶,老刑警劉巖母廷,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異糊肤,居然都是意外死亡琴昆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門馆揉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來业舍,“玉大人,你說我怎么就攤上這事升酣∠夏海” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵噩茄,是天一觀的道長下面。 經(jīng)常有香客問我,道長绩聘,這世上最難降的妖魔是什么沥割? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任机杜,我火速辦了婚禮,結(jié)果婚禮上椒拗,老公的妹妹穿的比我還像新娘。我一直安慰自己陡叠,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著译红,像睡著了一般。 火紅的嫁衣襯著肌膚如雪侦厚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天刨沦,我揣著相機與錄音,去河邊找鬼想诅。 笑死岛心,一個胖子當(dāng)著我的面吹牛篮灼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诅诱,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼娘荡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起炮沐,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎祭阀,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體专控,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年伦腐,在試婚紗的時候發(fā)現(xiàn)自己被綠了失都。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡粹庞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出庞溜,到底是詐尸還是另有隱情,我是刑警寧澤流码,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站漫试,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏驾荣。R本人自食惡果不足惜普泡,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一典勇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧割笙,春花似錦、人聲如沸伤溉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至走净,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伏伯,已是汗流浹背橘洞。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工炸枣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人适肠。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓候引,卻偏偏與公主長得像,于是被迫代替她去往敵國和親澄干。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 本文內(nèi)容什么是Servlet與Servlet是如何執(zhí)行的了解Servlet實現(xiàn)關(guān)系手動和自動開發(fā)Servlet s...
    Vincilovfang閱讀 593評論 1 1
  • IOC 控制反轉(zhuǎn)容器控制程序?qū)ο笾g的關(guān)系傻寂,而不是傳統(tǒng)實現(xiàn)中疾掰,有程序代碼之間控制,又名依賴注入徐紧。All 類的創(chuàng)建炭懊,...
    irckwk1閱讀 934評論 0 0
  • 在一個方法內(nèi)部定義的變量都存儲在棧中拂檩,當(dāng)這個函數(shù)運行結(jié)束后,其對應(yīng)的棧就會被回收稻励,此時,在其方法體中定義的變量將不...
    Y了個J閱讀 4,413評論 1 14
  • 這部分主要是與Java Web和Web Service相關(guān)的面試題望抽。 96、闡述Servlet和CGI的區(qū)別? 答...
    雜貨鋪老板閱讀 1,400評論 0 10
  • 多讀文學(xué)作品煤篙,你就能通過作家特有的、細(xì)膩的心靈感觸和富有感染力的語言辑奈,是幫助我們保持心靈敏感不長老繭的最為有效的方式。
    你若安好便是幸福閱讀 66評論 0 0