Servlet

2020-08-09 09:09:41

Servlet

zzj

一、HTTP協定

用戶端發給伺服器的叫請求協定,伺服器發送給用戶端的叫響應協定

1.1 書寫格式

http://12.0.0.1:8080/s01/ser01?name=zs

上面格式的名稱分別爲:http協定,伺服器ip,伺服器埠號,專案路徑,資源路徑,要傳入的屬性值。

1.2 http協定的特點

  • 支援c/s模式
  • 簡單快速,靈活
  • 無連線,http1.1 版本之後支援可持續連線,現在一般都是這個版本
  • 無狀態

1.3 http請求與響應

請求由三部分組成:請求行、請求頭、請求正文。

響應由三部分組成:狀態行、響應頭、響應正文。

1.4 訊息頭

請求頭

  • Referer:該請求頭指明請求從哪裏來,可以通過這個看到當前網頁的父類別網頁

響應頭

  • Location:地址,重定向到一個新的地址,常用於更新域名。
  • Refresh:自動跳轉

二、Tomcat伺服器

2.1 Tomcat的特點

  • 是複合javaee web標準的最小的web容器
  • 技術先進、效能穩定、免費,屬於輕量級應用伺服器。

2.2 Tomcat的埠

Tomcat的埠是可以更改的,在Tomcat安裝目錄下的conf資料夾中找到server.xml檔案,預設是8080。

2.3 Tomcat的優化

  • 指定使用NIO(同步非阻塞)模型來接受HTTP請求(Tomcat 8預設NIO)
  • Tomcat以JNI的形式呼叫Apache HTTP伺服器的核心動態鏈接庫來處理檔案讀取或網路傳輸操作,從而大大的提高Tomcat對靜態檔案的處理效能
  • 給Tomcat設定HTTP壓縮功能
  • 關閉DNS查詢

三、Servlet的實現

3.1 servlet定義

  • servlet物件由servlet容器建立。常見的容器有:tomcat,jetty等等
  • Servlet是一個介面

3.2 servlet版本

  • 3.0之前需要使用者手動設定web.xml,優勢在於解決寫死,但是檔案臃腫。
  • 3.0之後使用註解@WebServlet(「資源路徑」),優勢在於設定簡單。

3.3 servlet的實現

  1. 繼承HttpServlet,重新裏面的service方法。
  2. 在類上面設定註解:@WebServlet(「資源路徑」)。
  3. 發佈專案到Tomcat中。
  4. 存取方式:http://localhost:8080/s01/ser01 最後兩個爲自己設定的專案地址和類的資源地址。
@WebServlet("/ser02")
public class Servlet02 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("你好。。。");
    }
}

3.4 servlet的生命週期

  • init:範例與初始化時期,第一次請求資源的時候執行,只要不重新啓動伺服器,那麼只會執行一次。
  • service:服務階段,執行service()方法,每存取一次就會執行一次。
  • destory:銷燬階段,servlet伺服器正常關閉的時候執行,只會執行一次。

四、HttpServletRequest物件

**作用:**接受用戶端發送過來的請求資訊。

它是ServletRequest的子介面

4.1 獲取請求參數

方法:request.getParameter(「名稱」);

//通過表單進行提交
String name = request.getParameter("userName");
System.out.println(name);
System.out.println(request.getParameter("userPwd"));

4.2 請求亂碼問題

 //解決請求亂碼問題
request.setCharacterEncoding("UTF-8");

 //同時設定伺服器端與用戶端的編碼格式
response.setContentType("text/html;charset=UTF-8");

4.3 請求轉發

是伺服器端跳轉,位址列不發生改變,只有一次請求,request作用域數據可以共用,請求轉發只能轉發到當前專案下的資源。

// 請求轉發到頁面
req.getRequestDispatcher("login.jsp").forward(req,resp);

// 請求到相同項目下的Servlet
req.getRequestDispatcher("ser07").forward(req,resp);

4.4 request作用域

在同一次請求中有效,只能request使用。

//設定域物件內容
request.setAttribute("msg","使用者名稱不能爲空");

//獲取域物件內容
request.getAttribute("msg");

//刪除域物件
request.removeAttribute("msg");

五、HttpServletResponse物件

作用:伺服器端向用戶端輸出數據。

5.1 響應數據

方法:getWriter():字元流,只能響應回字元

​ getOutputStream():位元組流,能響應回一切數據

注意:兩個不能同時使用;

​ 使用字元流往用戶端輸出中文的時候會出現亂碼情況,這個時候就要手動設定編碼格式: response.setContentType(「text/html;charset=UTF-8」);

//同時設定伺服器端與用戶端的編碼格式
resp.setContentType("text/html;charset=UTF-8");

//字元輸出流
PrintWriter writer=resp.getWriter();
writer.write("<h2>Hello 中國</h2>");
writer.flush();
writer.close();

//直接輸出流
/*ServletOutputStream out=resp.getOutputStream();
  out.write("<h2>Hello 中國</h2>".getBytes());
  out.flush();
  out.close();*/

5.2 響應亂碼

直接使用:response.setContentType(「text/html;charset=UTF-8」);可以同時解決請求亂碼和響應亂碼問題。

5.3 重定向

伺服器端指導,用戶端跳轉行爲;位址列發生改變,存在兩次請求,request作用域不共用。

// 重定向到頁面
resp.sendRedirect("login.jsp");

// 請求到相同項目下的Servlet
resp.sendRedirect("ser07");

//重定向可以跳轉到百度
resp.sendRedirect("http://www.baidu.com");

六、請求轉發與重定向的區別

請求轉發 重定向
伺服器端跳轉 伺服器端指導用戶端跳轉
請求一次 請求兩次
位址列不變 位址列改變
共用request作用域 不共用request作用域
只能轉發到同一專案下的資源 可以重定向到任意地方

七、Cookie物件

cookie是由伺服器端建立,儲存在用戶端的,是瀏覽器技術,比如說記住密碼等。預設情況下關閉瀏覽器則cookie被銷燬。

7.1 cookie的建立與發送

在伺服器端建立,建立好之後發送給用戶端。

Cookie cookie=new Cookie("uName","zhangsan");
responce.addCookie(cookie);

Cookie cookie2=new Cookie("uPwd","123456");
responce.addCookie(cookie2);

7.2 伺服器端獲取cookie值

通過遍歷用戶端回傳的cookie陣列實現。

//獲取cookie陣列
Cookie[] cookies = request.getCookies();
// 判斷陣列是否爲空
if (cookies != null && cookies.length > 0) {
    // 遍歷cookie陣列並輸出
    for (Cookie cookie : cookies){
        System.out.println(cookie.getName());
        System.out.println(cookie.getValue());
    }
}

7.3 設定cookie失效時間

  • 正整數

    ​ 表示存放在本地磁碟當中,存活指定秒數。

  • 負整數

    ​ 表示只在瀏覽器中存活,關閉瀏覽器失效。

  • ​ 表示刪除cookie。

Cookie cookie=new Cookie("aa","AA");

//cookie.setMaxAge(-1);

cookie.setMaxAge(20);
resp.addCookie(cookie);

//設定七天失效
Cookie cookie1 = new Cookie("name", "張三");
cookie1.setMaxAge(7*24*60*60);

resp.addCookie(cookie1);

8.4 cookie的路徑

情況一:在當前專案中的資源可以存取(預設)

Cookie cookie1 = new Cookie("a1","A1");
cookie1.setPath("/s03"); //可以不設定,預設
resp.addCookie(cookie1);

情況二:在指定專案中的資源可以存取 (只能在專案名是/s04的專案下的資源能存取)

Cookie cookie2 = new Cookie("a2","A2");
cookie2.setPath("/s04");
resp.addCookie(cookie2);

情況三:在當前伺服器中任意資源都可存取 (只要是放在同一伺服器下的資源)

Cookie cookie3 = new Cookie("a3","A3");
cookie3.setPath("/");
resp.addCookie(cookie3);

情況四:在指定專案下的指定資源可以存取

Cookie cookie4 = new Cookie("a4","A4");
cookie4.setPath("/s04/cook02");
resp.addCookie(cookie4);

注意:若存取的路徑包含了其它cookie的路徑的時候,這個時候就會同時獲取兩個cookie,例如:路徑爲"/s04/cook02"的cookie可以包含路徑爲"/s04"的cookie。

8.5 cookie中注意點

  1. cookie儲存在當前瀏覽器中。不能跨瀏覽器,不能跨電腦。

  2. cookie存在中文問題。若cookie中存在中文不解碼的話會出現亂碼問題。(不過這種方式已經過期了,一般不會存在這種情況,使用者名稱或密碼之類的一般都不會爲中文)

    建立cookie時,要編碼:

    String name="姓名";
    String value="張三";
    name = URLEncoder.encode(name);
    value = URLEncoder.encode(value);
    Cookie cookie=new Cookie(name,value);
    resp.addCookie(cookie);
    

    獲取cookie時要解碼:

    Cookie[] cookies = req.getCookies();
    if(cookies!=null && cookies.length>0){
        for (Cookie cookie:cookies){
            String name = URLDecoder.decode(cookie.getName());
            String value = URLDecoder.decode(cookie.getValue());
            System.out.println("鍵:" + name  + ",值:" + value);
        }
    }
    
  3. cookie同名問題。新的cookie會覆蓋原有的cookie。

  4. 瀏覽器中存放cookie是有一定上限的。

八、HttpSession物件

HttpSession是一個純粹的介面,不存在父介面,它的底層是cookie,使用request.getSession();方法獲取當前對談的session物件。

//若session物件存在,則獲取;session物件不存在,則建立
HttpSession session=request.getSession();

8.1 JSESSIONID對談識別符號

開啓了對談,用戶端就會建立一個JSESSIONID,並將它回傳給伺服器端。

  • 當jsessionid的值不存在,伺服器會新建一個對談,並生成新的sessionid,返回給瀏覽器。
  • 當jsessionid的值存在,伺服器會判斷sessionid是否存在。
    • 若不存在,伺服器會建立一個新的對談,並生成新的sessionid,返回給瀏覽器
    • 若存在,則使用當前已有的對談

8.2 session域物件

在一次對談中數據是可以共用的,使用請求轉發或者重定向都可以共用session域物件。可以有多次請求。

HttpSession session = req.getSession();
session.setAttribute("uName","admin");
//請求轉發
//req.getRequestDispatcher("sess03").forward(req,resp);
//重定向
resp.sendRedirect("sess03");
String uName =(String) req.getSession().getAttribute("uName");
System.out.println("Session:"+uName);

8.3 session物件的銷燬

  • 預設到期時間(預設最大不活動時間)

    Tomcat中預設是30分鐘失效,

    可以在Tomcat的解壓目錄conf目錄下,對應的web.xml中修改 ,單位是分鐘。

  • 手動設定最大不活動時間(單位:秒)

    獲取最大不活動時間 session.getMaxInactiveInterval();

    設定最大不不活動時間 session.setMaxInactiveInterval(秒數);

  • 手動銷燬

    session.invalidate();

  • 關閉瀏覽器

    session底層依賴cookie,cookie預設關閉瀏覽器失效

  • 關閉伺服器

HttpSession session = req.getSession();

int sec = session.getMaxInactiveInterval();
System.out.println("最大不活動時間:" + sec);

session.setMaxInactiveInterval(15);

session.invalidate();

**注:**當過了15秒沒有操作時,伺服器便會建立一個新的jsessionid,並將這個迴應給瀏覽器。

九、ServletContext物件

它又稱爲Application物件,當web容器啓動時就會建立這個物件。

9.1 ServletContext物件的獲取

  1. 通過request物件獲取

    ServletContext servletContext = request.getServletContext();
    
  2. 通過session物件獲取

    ServletContext servletContext = request.getSession().getServletContext();
    
  3. 通過servletConfig物件獲取

    ServletContext servletContext2 = getServletConfig().getServletContext();
    
  4. 直接獲取

    ServletContext servletContext3 = getServletContext();
    

9.2 常用方法

System.out.println("獲取伺服器的資訊: " + servletContext.getServerInfo());
System.out.println("獲取專案的真實路徑: " + servletContext.getRealPath("/"));

9.3 ServletContext域物件

只要伺服器不關閉,則該域中的數據一直共用。

ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("name","zhangsan");
String name = (String) servletContext.getAttribute("name");
servletContext.removeAttribute("name");

十、servlet的四大域物件

  1. page域物件

    pageContext:只在同一個頁面有效 。

  2. request域物件

    在一次請求中有效。請求轉發有效,重定向無效。

  3. session域物件

    在一次對談中有效。請求轉發和重定向都有效,session銷燬後無效。

  4. ServletContext域物件

    application在整個程式中有效。關閉伺服器之後無效。

十一、檔案的上傳與下載

11.1 檔案的上傳(用的較多)

11.1.1 前臺介面

表單的提交方式一定要爲post,還要設定enctype=「multipart/form-data」。

<form method="post" action="uploadServlet" enctype="multipart/form-data">
    姓名:<input type="text" name="uname"><br>
    檔案:<input type="file" name="myfile">
    <button>提交</button>
</form>

11.1.2 後臺實現

除了使用@WebServlet(「資源路徑」)的註解之外,還要使用@MultipartConfig表示檔案上傳。

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setCharacterEncoding("UTF-8");

    String uname = req.getParameter("uname"); // uname代表的是表單元素input的name屬性值
    System.out.println("姓名: " + uname);
    // 檔案上傳
    // request.getPart(name) 得到上傳的檔案物件,name代表的是file檔案域的name屬性值
    Part part = req.getPart("myfile");
    // 得到上傳的檔案的檔名
    String fileName = part.getSubmittedFileName();
    System.out.println(fileName);

    if(fileName!=null&&!"".equals(fileName)){
        // 設定得到檔案的 存放的路徑
        String realPath = req.getServletContext().getRealPath("/upload/");
        System.out.println(realPath);
        part.write(realPath+fileName);
    }
}

11.2 檔案下載

11.2.1 超鏈接下載(常用)

  • 瀏覽器遇到能夠識別的資源,會直接顯示;遇到不能識別的資源,則會進行下載。
  • 可以通過download屬性進行下載,如果未設定download屬性的屬性值,則下載名是檔名;
<a href="1.jpg">圖片</a>
    <a href="test.html">HTML</a>
    <a href="Q-Dir.exe - 快捷方式.lnk">快捷方式</a>
    <hr>
    <a href="1.jpg" download>圖片</a>
    <a href="1.jpg" download="aa.png">圖片</a>

    <br><br><hr>

    <form action="downloadServlet">
    檔名:<input type="text" name="fileName"> <button>下載</button>
    </form>