Request與Response

一.Request

1.什么是Request

由于Http協(xié)議比較復(fù)雜, 所以在API中提供了 HttpServletRequest (繼承自ServletRequest) 來封裝 Http 請求消息;

2.Request的作用

獲取客戶端的請求信息;

2.1 獲取請求行

@WebServlet("/demo1")
public class ServletDem01 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //使用request對象獲取請求行的信息
        //1. 獲取請求的方式(可能會用)
        String method = req.getMethod();
        System.out.println("method = " + method); // method = GET

        //2. 獲取客戶端的ip地址
        String remoteAddr = req.getRemoteAddr();
        System.out.println("remoteAddr = " + remoteAddr); // 0:0:0:0:0:0:0:1 ipv6地址

        //3. 獲取項(xiàng)目部署的路徑
        String contextPath = req.getContextPath();
        System.out.println("contextPath = " + contextPath); // /rzc

        //4. 獲取請求的url: 統(tǒng)一資源定位符 http://localhost:8080/requestDemo/demo01
        StringBuffer requestURL = req.getRequestURL();
        System.out.println("requestURL = " + requestURL); // http://localhost:8080/rzc/demo1

        //5. 獲取請求的uri: 統(tǒng)一資源標(biāo)識符,在url的基礎(chǔ)上省略了服務(wù)器路徑"http://loaclhost:8080"
        String requestURI = req.getRequestURI();
        System.out.println("requestURI = " + requestURI); // /rzc/demo1
    }
}
  • getServerPort(); 獲取服務(wù)端的端口
  • getQueryString(); 獲取請求參數(shù)(get請求的,URL的?后面的. eg:username=zs&password=123456)

2.2 獲取請求頭

請求頭包含的信息比較多, 需要用的時(shí)候可以通過 getHeader(String name) 函數(shù)來獲取;

  • User-Agent: 瀏覽器信息
  • Referer: 來自哪個(gè)網(wǎng)站(防盜鏈)

2.3 獲取請求體

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注冊頁面</title>
</head>
<body>
    <form action="/rzc/demo3" method="post">
        用戶名<input type="text" name="username"><br>
        密碼<input type="text" name="password"><br>
        性別<input type="radio" name="gender" value="male">男
        <input type="radio" name="gender" value="female">女
        <br>
        興趣愛好
        <input type="checkbox" name="hobby" value="basketball">籃球
        <input type="checkbox" name="hobby" value="football">足球
        <input type="checkbox" name="hobby" value="ppball">乒乓球
        <input type="checkbox" name="hobby" value="yumaoball">羽毛球
        <br>
        <input type="submit" value="注冊">
    </form>
</body>
</html>
@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 根據(jù)參數(shù)名,獲取一個(gè)參數(shù)值
        String username = req.getParameter("username");
        System.out.println("username = " + username);

        //2. 根據(jù)參數(shù)名,獲取多個(gè)參數(shù)值:比如說注冊時(shí)候的興趣愛好的復(fù)選框
        String[] hobbies = req.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println("hobby = " + hobby);
        }

        //3. 獲取所有的請求參數(shù)
        //getParameterMap()獲取所有請求參數(shù),請求參數(shù)的參數(shù)名就是map的key,請求參數(shù)的參數(shù)值就是map的value
        Map<String, String[]> parameterMap = req.getParameterMap();
        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
        for (Map.Entry<String, String[]> entry : entries) {
            String key = entry.getKey();
            String[] values = entry.getValue();
            for (String value : values) {
                System.out.println("key+\"=\"+value = " + key + "=" + value);
            }
        }
    }
}
使用BeanUtils封裝這些參數(shù)對象
    1.需要依賴BeanUtils的jar包
    2.Java Bean文件中的屬性名需要和參數(shù)名一一對應(yīng);
    BeanUtils.copyProperties(user,parameterMap);
    // BeanUtils.populate(user,parameterMap);

2.4 請求轉(zhuǎn)發(fā)

/**
 * 1. 請求轉(zhuǎn)發(fā)的效果的跳轉(zhuǎn), 跳轉(zhuǎn)到其他頁面,或者跳轉(zhuǎn)到其它的servlet
 * 2. 請求轉(zhuǎn)發(fā)的跳轉(zhuǎn), 只能是跳轉(zhuǎn)到本項(xiàng)目的資源
 * 3. 請求轉(zhuǎn)發(fā)的原理是: 服務(wù)器進(jìn)行轉(zhuǎn)發(fā)操作,將這次請求發(fā)給目標(biāo)地址,由服務(wù)器向目標(biāo)地址響應(yīng)資源
 */
@WebServlet("/demo5")
public class ServletDemo5 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 訪問此 Servlet 將跳轉(zhuǎn)到 /register.html
//        req.getRequestDispatcher("/register.html").forward(req,resp);

        // 訪問此 Servlet 將跳轉(zhuǎn)到訪問 /demo3
        req.getRequestDispatcher("/demo3").forward(req,resp);
    }
}

2.5 作為域?qū)ο?/h3>
/**
 * request 作為域?qū)ο笤诓煌腟ervlet之間進(jìn)行數(shù)據(jù)的共享,它只能在同一次請求中進(jìn)行數(shù)據(jù)共享
 * request 域?qū)ο笾挥泻驼埱筠D(zhuǎn)發(fā)一起使用才有意義
 */
@WebServlet("/demo6")
public class ServletDemo6 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("name","ccs");
        req.getRequestDispatcher("/demo7").forward(req,resp);
    }
}
@WebServlet("/demo7")
public class ServletDemo7 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object name = req.getAttribute("name");
        System.out.println("name=="+name);
    }
}

二.Response

1.什么是Repsonse

由于Http協(xié)議比較復(fù)雜, 所以在API中提供了 HttpServletResponse (繼承自ServletResponse) 來封裝 Http 響應(yīng)消息;

2.Response的作用

響應(yīng)客戶端的請求

2.1 設(shè)置響應(yīng)行信息

/**
 * response 設(shè)置響應(yīng)行的信息
 * setStatus設(shè)置響應(yīng)狀態(tài)碼
 * 200 響應(yīng)成功
 * 302 重定向
 * 304 訪問緩存
 * 403 沒有權(quán)限訪問
 * 404 客戶端錯(cuò)誤
 * 500 服務(wù)器錯(cuò)誤
 */
@WebServlet("/demo8")
public class ServletDemo8 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(403);
    }
}

2.2 設(shè)置響應(yīng)頭信息以及重定向

/**
 * 常用的響應(yīng)頭,需要使用其它的響應(yīng)頭可以去文檔中查找
 * Refresh 定時(shí)跳轉(zhuǎn)
 * Location 重定向地址
 * Content-Disposition 告訴瀏覽器下載
 * Content-Type 設(shè)置響應(yīng)內(nèi)容的MiME類型(服務(wù)器告訴瀏覽器內(nèi)容的類型)
 */
@WebServlet("/demo9")
public class ServletDemo9 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Refresh 定時(shí)跳轉(zhuǎn)
        // resp.setHeader("Refresh","3,http://www.baidu.com");

        // Location 重定向地址
        resp.setStatus(302);
        resp.setHeader("Location","/rzc/register.html");
        // resp.sendRedirect("/rzc/register.html");
        // resp.sendRedirect("http://www.baidu.com");
    }
}

2.3 設(shè)置響應(yīng)體信息

@WebServlet("/demo9")
public class ServletDemo9 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //給客戶端響應(yīng)一張圖片
        //1. 讀取b.jpg圖片,將其轉(zhuǎn)換成字節(jié)輸入流,使用ServletContext
//        ServletContext servletContext = getServletContext();
//        InputStream is = servletContext.getResourceAsStream("b.jpg");
//
//        //2. 使用字節(jié)輸出流,將is中的字節(jié)都輸出到瀏覽器
//        ServletOutputStream os = resp.getOutputStream();
//
//        /*byte[] buffer = new byte[1024];
//        int len = 0;
//        while ((len = is.read(buffer)) != -1){
//            os.write(buffer,0,len);
//        }*/
//        IOUtils.copy(is,os);
//        os.close();
//        is.close();

        // 給客戶端響應(yīng)一段字符串
        resp.setContentType("text/html;charset=UTF-8");

        //要向?yàn)g覽器輸出響應(yīng)體的信息,需要通過流來進(jìn)行操作
        //第一種:字符串,輸出文本內(nèi)容
        PrintWriter writer = resp.getWriter();
        //使用字符流往瀏覽器輸出文本
        //1. writer()方法,只能輸出字符串,如果輸出int、float等等類型的話,則會有問題
        writer.write("你好世界");
        //2. print()方法,可以輸出數(shù)字、字符串
        //writer.print(8);
    }
}

三.請求轉(zhuǎn)發(fā)與重定向的區(qū)別

1.跳轉(zhuǎn)的發(fā)起者不同
    請求轉(zhuǎn)發(fā)的跳轉(zhuǎn)發(fā)起者:是服務(wù)器去重新找到資源響應(yīng)給瀏覽器
    重定向的跳轉(zhuǎn)發(fā)起者:是服務(wù)器響應(yīng)給瀏覽器一個(gè)新的地址,兩次都是瀏覽器;
2.瀏覽發(fā)起的請求次數(shù)不同
    請求轉(zhuǎn)發(fā):只會請求一次;
    重定向:會請求二次;
3.能夠跳轉(zhuǎn)到的資源
    請求轉(zhuǎn)發(fā):只能是服務(wù)器本項(xiàng)目中的資源;
    重定向:可以是任意地址;
4.地址樣的地址是否發(fā)生改變
    請求轉(zhuǎn)發(fā):沒有發(fā)生改變;
    重定向:會發(fā)生改變

四.路徑問題

完整路徑, 相對路徑, 絕對路徑; 完整路徑, 是一個(gè)完整的訪問地址, 可以在不同的項(xiàng)目中訪問; 而相對路徑與絕對路徑都是針對相同項(xiàng)目而言的;

1.完整Url地址

url的組成部分:

例如 http://localhost:8080/rzc/jstl/jstl_test01.jsp

  • http:// 表示協(xié)議是http協(xié)議
  • localhost 表示主機(jī)地址,就是ip地址
  • :8080 表示服務(wù)器的端口號 (通過端口號可以找到服務(wù)端程序的進(jìn)程);
  • rzc 表示項(xiàng)目的虛擬路徑(部署路徑), 這個(gè)在 idea 中一般為項(xiàng)目名, 可以設(shè)置成不包含這個(gè)路徑的訪問地址;
  • jstl/jstl_test01.jsp 表示項(xiàng)目上的具體的動(dòng)態(tài)或靜態(tài)資源;

什么時(shí)候會使用完整的url

  • 瀏覽器地址欄直接訪問;

  • 一個(gè)項(xiàng)目中,訪問另一個(gè)項(xiàng)目中的資源;

2.相對路徑

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>路徑相關(guān)測試</title>
</head>
<body>
<h1>hello world....</h1>
    <!--
        目標(biāo)資源的url: http://localhost:8080/rzc/demo2
        當(dāng)前資源的url: http://localhost:8080/rzc/pages/path.html
        相對路徑的優(yōu)劣:
            1. 優(yōu)勢: 無論部署的項(xiàng)目名怎么改變,我的路徑都不需要改變
            2. 劣勢: 如果當(dāng)前資源的位置發(fā)生改變,那么相對路徑就必定要發(fā)生改變
    -->
    <a href="../demo2">訪問ServletDemo2</a>
</body>
</html>

3.絕對路徑

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>路徑相關(guān)測試</title>
</head>
<body>
<h1>hello world....</h1>
<!--
    目標(biāo)資源的url: http://localhost:8080/rzc/demo2
    當(dāng)前資源的url: http://localhost:8080/rzc/pages/path.html
      
    絕對路徑: 不是請求轉(zhuǎn)發(fā)的情況, "/項(xiàng)目部署路徑/資源路徑"
        1. 優(yōu)勢: 無論當(dāng)前資源的位置怎么發(fā)生改變,絕對路徑都是不變的
        2. 劣勢: 如果項(xiàng)目名發(fā)生改變,那么絕對路徑必須改變
-->
<a href="/rzc/demo02">訪問ServletDemo02</a>
</body>
</html>

五.案例代碼

1.文件下載案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>下載頁面</title>
</head>
<body>
    <a href="/downloadDemo/download?fileName=a.jpg">下載a.jpg</a><br>
    <a href="/downloadDemo/download?fileName=b.jpg">下載b.jpg</a><br>
    <a href="/downloadDemo/download?fileName=WEB01.zip">下載WEB01.zip</a><br>
    <a href="/downloadDemo/download?fileName=美女.jpg">下載美女.jpg</a><br>
    <a href="/downloadDemo/download?fileName=霉女.jpg">下載霉女.jpg</a>
</body>
</html>
/**
 * 瀏覽器訪問DownloadServlet,如果是圖片直接在瀏覽器上顯示了,現(xiàn)在需要下載這張圖片
 * 使用 Content-Disposition 響應(yīng)頭,讓瀏覽器進(jìn)行文件的下載
 * 當(dāng)文件名是中文的時(shí)候,瀏覽器下載無法顯示中文 URLEncoder
 * file文件應(yīng)該在web目錄下
 */
@WebServlet("/demo10")
public class DownLoadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");

        //獲取請求參數(shù)fileName的值
        String fileName = req.getParameter("fileName");

        //讀取對應(yīng)的文件
        InputStream is = req.getServletContext().getResourceAsStream("file/"+fileName);

        //告訴瀏覽器文件的MIME類型(可以不寫)
        String mimeType = getServletContext().getMimeType(fileName);
        System.out.println("mimeType = " + mimeType);
        resp.setHeader("Content-Type",mimeType);

        //使用字節(jié)輸出流,將文件輸出給瀏覽器
        ServletOutputStream os = resp.getOutputStream();

        //響應(yīng)頭中是無法識別中文的,所以有中文的文件名,在下載的時(shí)候顯示會出現(xiàn)問題
        //將文件名進(jìn)行編碼轉(zhuǎn)換,將中文轉(zhuǎn)換成英文
        String encodeFileName = URLEncoder.encode(fileName, "UTF-8");

        //在輸出內(nèi)容之前,進(jìn)行響應(yīng)頭的設(shè)置,設(shè)置Content-Disposition響應(yīng)頭,讓瀏覽器下載文件
        resp.setHeader("Content-Disposition", "attachment;filename=" + encodeFileName);

        IOUtils.copy(is, os);

        os.close();
        is.close();
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容