請求:獲取資源。在 BS 架構中,就是客戶端瀏覽器向服務器端發出詢問,請求獲取資源html
請求對象:就是在項目當中用於發送請求的對象java
咱們經常使用的對象就是ServletRequest和HttpServletRequest,它們的區別就是是否和HTTP協議有關web
先了解便可,接下來咱們會一步一步介紹apache
獲取路徑方法windows
getQueryString,獲取請求的數據,好比url問號後邊的數據數組
URI是以一種抽象的,高層次概念定義統一資源標識,而URL則是具體的資源標識的方式瀏覽器
URI比URL範圍大,URL是URI的一種緩存
url?後邊的請求參數,也能夠叫作查詢字符串 (請求動做是查詢,把請求參數做爲查詢關鍵字)tomcat
重點方法:getContextPath,getQueryString,getRequestURI服務器
案例:新建項目request_demo,新建類com.itheima.servlet.ServletDemo01
這裏的項目須要是java ee 8 ,咱們要用註解註冊Servlet
package com.itheima.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
獲取路徑的相關方法
*/
訪問
獲取請求頭
有的請求頭是有多個值,因此能夠經過getHeaders方法獲取
好比:accept-encoding,他的值就有多個:gzip,deflate,br
案例:新建ServletDemo02
package com.itheima.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/*
獲取請求頭信息的相關方法
*/
訪問
獲取請求頭參數
若是請求參數只有一個值,經過getParameter獲取,好比:text
若是請求參數有多個值,經過getParameterValues獲取,好比:checkbox
重點掌握:getParameter,getParameterMap
案例:新建web/register.html
新建ServletDemo03
package com.itheima.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
/*
獲取請求參數信息的相關方法
*/
訪問
咱們經過上面的方法能夠獲取到請求參數,可是若是參數過多,在進行傳遞時,方法的形參定義將會變得很是難看
此時咱們應該用一個對象來描述這些參數,它就是實體類。這種類的定義,從基礎階段咱們就開始使用了
在基礎階段,咱們作過一個學生管理系統,用到了一個Student的類,它就是用於描述一個學生的實體類
咱們如今要作的就是把表單中提交過來的數據填充到實體類中
案例:新建com.itheima.bean.Student
package com.itheima.bean;
import java.util.Arrays;
public class Student {
private String username;
private String password;
private String[] hobby;
public Student() {
}
public Student(String username, String password, String[] hobby) {
this.username = username;
this.password = password;
this.hobby = hobby;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String[] getHobby() {
return hobby;
}
public void setHobby(String[] hobby) {
this.hobby = hobby;
}
新建ServletDemo04
package com.itheima.servlet;
import com.itheima.bean.Student;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
封裝對象-手動方式
*/
修改register.html
<form action="/request/servletDemo04">
訪問
問題:若是獲取的參數有10個,那麼就須要寫十次String xx= req.getParameter("xx");
,這樣太麻煩
那咱們就能夠採用反射封裝對象方式
此種封裝的使用要求是,表單<input>
標籤的name屬性取值,必須和實體類中定義的屬性名稱一致
案例:新建ServletDemo05
package com.itheima.servlet;
import com.itheima.bean.Student;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;
/*
封裝對象-反射方式(使用反射+內省實現數據模型的封裝)
* 內省:是sun公司推出的一套簡化反射操做的規範。把javabean中的屬性都封裝成一個屬性描述器。
* 屬性描述器中會有字段信息,get和set方法(取值或存值)
*/
修改register.html
<form action="/request/servletDemo05" >
訪問
上述的操做仍是都太麻煩,能不能直接調用現成的工具呢?
能夠,使用apache的beanutils包
copy jar包
「day03_請求響應\資料\beanutils的jar包」下全部的包,copy到「項目/web/WEB-INF/libs」下
而後添加到項目引用庫
案例:新建ServletDemo06
package com.itheima.servlet;
import com.itheima.bean.Student;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
/*
封裝對象-工具類方式
*/
修改register.html
<form action="/request/servletDemo06">
訪問 : 經過register.html點擊註冊以後,跳轉過去發現報錯
報錯信息說是,找不到BeanUtils
咱們剛剛不是添加到項目引用庫中了麼?注意咱們如今的項目是須要部署到tomcat的,項目中有了,可是部署到tomcat的war包中尚未,因此須要特殊處理一下:
File - Project Structure
訪問
除了上述方式能夠獲取請求信息,還能夠經過流來獲取
BufferedReader瞭解便可
ServletInputStream經常使用於獲取圖片,文件 ***
案例:新建ServletDemo07
package com.itheima.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
流對象獲取數據
*/
修改 register.html
<!--若是是字符流,post請求方式-->
<form action="/request/servletDemo07" method="post">
訪問
流方式獲取到的中文,會進行編碼,因此看到的姓名是編碼後的
GET 方式
沒有亂碼問題。在 Tomcat 8.5 版本後已經解決
POST 方式
有亂碼問題。能夠經過 setCharacterEncoding() 方法來解決
案例:ServletDemo08
package com.itheima.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
中文亂碼
*/
修改register.html
<form action="/request/servletDemo08" method="post" >
訪問
解決亂碼,修改
//設置編碼格式
req.setCharacterEncoding("UTF-8");
GET方式請求的正文是在地址欄中,在Tomcat8.5版本及之後,Tomcat服務器已經幫咱們解決了,因此不會有亂碼問題了。
而若是咱們使用的不是Tomcat服務器,或者Tomcat的版本是8.5之前,那麼GET方式仍然會有亂碼問題,解決方式以下:(如下代碼瞭解便可,由於咱們如今使用的是Tomcat9.xx版本)
/** * 在Servlet的doGet方法中添加以下代碼 */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * GET方式:正文在地址欄 * username=%D5%C5%C8%FD * %D5%C5%C8%FD是已經被編過一次碼了 * * 解決辦法: * 使用正確的碼錶對已經編過碼的數據進行解碼。 * 就是把取出的內容轉成一個字節數組,可是要使用正確的碼錶。(ISO-8859-1) * 再使用正確的碼錶進行編碼 * 把字節數組再轉成一個字符串,須要使用正確的碼錶,是看瀏覽器當時用的是什麼碼錶 */ String username = request.getParameter("username"); byte[] by = username.getBytes("ISO-8859-1"); username = new String(by,"GBK"); //輸出到瀏覽器:注意響應的亂碼問題已經解決了 response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.write(username); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }
請求到ServletA,實現的功能,須要用到ServletB,那這時候就能夠在ServletA將請求轉發到ServletB
那ServletB中可能會用到ServletA中的數據,那這時候就涉及到數據共享了
在這裏若是使用應用域來共享數據,就有點浪費了,由於咱們只是在此次請求中須要共享數據,不是整個應用
因此就用到了請求域
請求轉發:客戶端的一次請求到達後,發現須要藉助其餘 Servlet 來實現功能
特色:
瀏覽器地址欄不變
域對象中的數據不丟失
負責轉發的 Servlet 轉發先後的響應正文會丟失 (ServletA的響應正文會丟失,由ServletB響應客戶端)
由轉發的目的地來響應客戶端
應用場景:若是一次請求中這個servlet沒法單獨完成任務,這時會將這個請求轉發給另外一個servlet
若是這兩個servlet須要共享數據,咱們通常使用請求域
請求轉發,不會丟失請求域數據,因此共享數據,都使用請求域
請求轉發API
dispatcher:[dɪˈspætʃə(r)].調度
forward:向前,(按新地址)轉寄; 發送
getRequestDispatcher('轉發的url')
案例:新建ServletDemo09
package com.itheima.servlet; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* 請求轉發 */ @WebServlet("/servletDemo09") public class ServletDemo09 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //設置共享數據 req.setAttribute("encoding","gbk"); //獲取請求調度對象 RequestDispatcher rd = req.getRequestDispatcher("/servletDemo10"); //實現轉發功能 rd.forward(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
新建ServletDemo10
package com.itheima.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* 請求轉發 */ @WebServlet("/servletDemo10") public class ServletDemo10 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //獲取共享數據 Object encoding = req.getAttribute("encoding"); System.out.println(encoding); System.out.println("servletDemo10執行了..."); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
訪問
響應:回饋結果。在 BS 架構中,就是服務器給客戶端瀏覽器反饋結果
響應對象:就是在項目中用於發送響應的對象
響應對象也是是Servlet規範中定義的,它包括了協議無關的和協議相關的
協議無關的對象標準是:ServletResponse接口
協議相關的對象標準是:HttpServletResponse接口
咱們課程中涉及的響應對象都是和HTTP協議相關的。即便用的是HttpServletResponse接口的實現類
405:請求方式不支持,例如:通常是後臺只支持post請求,而發起的請求確實get請求,這時候就會提示405
狀態碼首位含義:
狀態碼 | 說明 |
---|---|
1xx | 消息 |
2xx | 成功 |
3xx | 重定向 |
4xx | 客戶端錯誤 |
5xx | 服務器錯誤 |
在HttpServletResponse接口中提供了不少方法,接下來咱們經過API文檔,來了解一下這些方法
先了解便可,接下來咱們會一步一步介紹
字節流響應API
字節流,經常使用於處理圖片,文件
新建項目:response_demo,設置虛擬路徑/response
新建類:com.itheima.servlet.ServletDemo01
package com.itheima.servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* 字節流響應消息及亂碼的解決 */ @WebServlet("/servletDemo01") public class ServletDemo01 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /* 項目中經常使用的編碼格式是u8,而瀏覽器默認使用的編碼是gbk。致使亂碼! */ //1. 獲取字節流輸出對象 ServletOutputStream sos = resp.getOutputStream(); //2. 定義一個消息 String str = "你好"; //經過字節流對象輸出 sos.write(str.getBytes());//getBytes不帶參數,默認獲取操做系統的編碼集(咱們安裝的都是中文windows,因此係統編碼集是gbk) //sos.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
訪問
谷歌瀏覽器,沒有亂碼(這是由於谷歌瀏覽器的默認編碼是gbk)
可是谷歌瀏覽器想查看編碼,須要安裝插件,因此咱們再來看ie(發現默認是gb2312(gbk))
但其實,咱們的代碼都應該是utf-8編碼格式,只不過是getBytes默認處理了,纔沒有出現亂碼
代碼格式是utf-8,可是到瀏覽器gbk上爲啥不是亂碼,這是由於getBytes方法默認處理了,getBytes默認與操做系統的編碼格式一致,而操做系統編碼是gbk,因此getBytes處理成gbk了
那如何出現亂碼呢?修改代碼:
sos.write(str.getBytes("UTF-8"));
訪問
解決亂碼
/* 項目中經常使用的編碼格式是u8,而瀏覽器默認使用的編碼是gbk。致使亂碼! 解決方式一:修改瀏覽器的編碼格式(不推薦,不能讓用戶作修改的動做) 解決方式二:經過輸出流寫出一個標籤:<meta http-equiv='content-type' content='text/html;charset=UTF-8'> 解決方式三:response.setHeader("Content-Type","text/html;charset=UTF-8"); 指定響應頭信息 解決方式四:response.setContentType("text/html;charset=UTF-8"); */ //sos.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes()); //resp.setHeader("Content-Type","text/html;charset=UTF-8"); resp.setContentType("text/html;charset=UTF-8");//經常使用第四種,告知瀏覽器採用utf-8編碼方式
訪問
字符流API
字符流,經常使用於處理文字
案例:新建ServletDemo02
package com.itheima.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /* 字符流響應消息及亂碼的解決 */ @WebServlet("/servletDemo02") public class ServletDemo02 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1. 準備一個消息 String str = "你好"; //2. 獲取字符流對象 PrintWriter pw = resp.getWriter(); //3. 經過字符流輸出 pw.write(str); //pw.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
訪問
解決
//解決中文亂碼 resp.setContentType("text/html;charset=UTF-8");
訪問
解決亂碼總結
若是是響應解決亂碼問題,通常思路就是讓瀏覽器與代碼中的編碼風格保持一致(utf-8)
resp.setContentType("text/html;charset=UTF-8");
若是請求中解決亂碼,將gbk編碼的中文信息轉換爲utf-8
//設置編碼格式 (將瀏覽器默認編碼gbk的中文信息,轉換爲utf-8的信息) req.setCharacterEncoding("UTF-8");
建立字節輸入流對象,關聯讀取的圖片路徑
經過響應對象獲取字節輸出流對象
循環讀取和寫出圖片
案例:新建ServletDemo03
package com.itheima.servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; /* 響應圖片到瀏覽器 */ @WebServlet("/servletDemo03") public class ServletDemo03 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1. 建立字節輸入流對象,關聯圖片路徑 String realPath = getServletContext().getRealPath("/img/hm.png"); System.out.println(realPath); BufferedInputStream bis = new BufferedInputStream(new FileInputStream(realPath)); //注意:不能直接指定圖片路徑,須要同getRealPath獲取,由於項目還要發佈,咱們須要獲取到發佈以後的圖片路徑 //BufferedInputStream bis = new BufferedInputStream(new FileInputStream(/img/hm.png)); //2. 獲取字節輸出流對象 ServletOutputStream sos = resp.getOutputStream(); //3. 循環讀寫 byte[] arr = new byte[1024]; int len; while((len = bis.read(arr)) != -1) { sos.write(arr,0,len); } bis.close(); sos.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
將今天資料「\day03_請求響應\資料\img」這個文件夾,copy到web目錄下
訪問
緩存:對於不常常變化的數據,咱們能夠設置合理緩存時間,以免瀏覽器頻繁請求服務器。以此來提升效率
緩存API
案例:新建ServletDemo04
package com.itheima.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* 緩存 */ @WebServlet("/servletDemo04") public class ServletDemo04 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String news = "這是一條很火爆的新聞~~"; //設置緩存時間:1小時的緩存時間 //參數1:Expires : 失效的意思 //參數2:當前時間+1小時毫秒值(意思就是在1小時以後過時) resp.setDateHeader("Expires",(System.currentTimeMillis()+1*60*60*1000L)); //設置編碼格式 resp.setContentType("text/html;charset=UTF-8"); //寫出數據 resp.getWriter().write(news); System.out.println("aaa"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
第一次訪問:發現執行了Servlet,而且打印了aaa
此時,這個Servlet已經被緩存下來了
第二次訪問
而且控制檯沒有打印aaa
定時刷新:過了指定時間後,頁面自動進行跳轉
定時刷新API
案例:新建ServletDemo05
package com.itheima.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* 定時刷新 */ @WebServlet("/servletDemo05") public class ServletDemo05 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String news = "您的用戶名或密碼錯誤,3秒後自動跳轉到登陸頁面..."; //設置編碼格式 resp.setContentType("text/html;charset=UTF-8"); //寫出數據 resp.getWriter().write(news); //設置響應消息頭定時刷新 //Refresh:刷新 //第二個參數第一部分:3,3設以後 //第二個參數第二部分:跳轉到哪一個路徑 //resp.setHeader("Refresh","3;URL=/response/login.html"); resp.setHeader("Refresh","3;URL="+req.getContextPath()+"/login.html"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
將以前的login.html複製到這個項目:web/login.html
訪問:3s以後自動跳轉到login.html
案例:新建ServletDemo06
package com.itheima.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* 請求重定向 */ @WebServlet("/servletDemo06") public class ServletDemo06 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //設置請求域數據 req.setAttribute("username","zhangsan"); //設置重定向 resp.sendRedirect(req.getContextPath() + "/servletDemo07"); //resp.sendRedirect("/response/servletDemo07"); // resp.sendRedirect("https://www.baidu.com"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
新建ServletDemo07,獲取共享數據
package com.itheima.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* 請求重定向 */ @WebServlet("/servletDemo07") public class ServletDemo07 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("servletDemo07執行了..."); Object username = req.getAttribute("username");//獲取不到 System.out.println(username); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
訪問:沒法獲取共享數據打印null
兩次請求驗證
重定向與轉發的區別
重定向:
兩次請求
地址欄發生變化
不可使用request域共享數據 (既然是兩次請求,那確定不能使用請求域中共享的數據)
能夠重定向到其餘服務器的url
轉發:
一次請求
地址欄不發生變化
可使用request域共享數據
只能轉發到本身服務器內部的url
案例:新建ServletDemo08
package com.itheima.servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; /* 文件下載 */ @WebServlet("/servletDemo08") public class ServletDemo08 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.建立字節輸入流,關聯讀取的文件 //獲取文件的絕對路徑 String realPath = getServletContext().getRealPath("/img/hm.png"); //建立字節輸出流對象 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(realPath)); //2.設置響應頭支持的類型 應用支持的類型爲字節流 /* Content-Type 消息頭名稱 支持的類型 application/octet-stream 消息頭參數 應用類型爲字節流 */ resp.setHeader("Content-Type","application/octet-stream"); //3.設置響應頭如下載方式打開 以附件形式處理內容 /* Content-Disposition 消息頭名稱 處理的形式 attachment;filename= 消息頭參數 附件形式進行處理;指定下載文件名稱 */ resp.setHeader("Content-Disposition","attachment;filename=hm.png"); //4.獲取字節輸出流對象 ServletOutputStream sos = resp.getOutputStream(); //5.循環讀寫文件 byte[] arr = new byte[1024]; int len; while((len = bis.read(arr)) != -1) { sos.write(arr,0,len); } //6.釋放資源 bis.close(); //sos.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
訪問
建立一個 web 項目 : reqresp_test,虛擬目錄/stu
在 web 目錄下建立一個 index.html,包含兩個超連接標籤(添加學生、查看學生)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>學生管理系統首頁</title> </head> <body> <a href="/stu/addStudent.html">添加學生</a> <a href="/stu/listStudentServlet">查看學生</a> </body> </html>
在 web 目錄下建立一個 addStudent.html,用於實現添加功能的表單頁面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加學生</title> </head> <body> <form action="/stu/addStudentServlet" method="get" autocomplete="off"> 學生姓名:<input type="text" name="username"> <br> 學生年齡:<input type="number" name="age"> <br> 學生成績:<input type="number" name="score"> <br> <button type="submit">保存</button> </form> </body> </html>
在 src 下建立一個 com.itheima.bean.Student 類,用於封裝學生信息
package com.itheima.bean; public class Student { private String username; private int age; private int score; public Student() { } public Student(String username, int age, int score) { this.username = username; this.age = age; this.score = score; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } }
實現步驟
建立 AddStudentServlet 類。繼承 HttpServlet
重寫 doGet 和 doPost 方法
獲取表單中的數據
將獲取到的數據封裝成 Student 對象
將 Student 對象中的數據保存到 d:\stu.txt 文件中
經過定時刷新功能完成對瀏覽器的響應
新建:AddStudentServlet
package com.itheima.servlet; import com.itheima.bean.Student; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; /* 實現添加功能 */ @WebServlet("/addStudentServlet") public class AddStudentServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.獲取表單中的數據 String username = req.getParameter("username"); String age = req.getParameter("age"); String score = req.getParameter("score"); //2.建立學生對象並賦值 Student stu = new Student(); stu.setUsername(username); stu.setAge(Integer.parseInt(age)); stu.setScore(Integer.parseInt(score)); //3.將學生對象的數據保存到d:\\stu.txt文件中 BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\stu.txt",true)); bw.write(stu.getUsername() + "," + stu.getAge() + "," + stu.getScore()); bw.newLine(); bw.close(); //4.經過定時刷新功能響應給瀏覽器 resp.setContentType("text/html;charset=UTF-8"); resp.getWriter().write("添加成功。2秒後自動跳轉到首頁..."); resp.setHeader("Refresh","2;URL=/stu/index.html"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
訪問
實現步驟
建立 ListStudentServlet 類。繼承 HttpServlet
重寫 doGet 和 doPost 方法
經過字符輸入流讀取 d:\stu.txt 文件中的數據
將讀到的數據封裝到 Student 對象中
將多個 Student 對象保存到集合中
遍歷集合,將數據響應到瀏覽器
新建ListStudentServlet
package com.itheima.servlet; import com.itheima.bean.Student; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; /* 實現查看功能 */ @WebServlet("/listStudentServlet") public class ListStudentServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.建立字符輸入流對象,關聯讀取的文件 BufferedReader br = new BufferedReader(new FileReader("d:\\stu.txt")); //2.建立集合對象,用於保存Student對象 ArrayList<Student> list = new ArrayList<>(); //3.循環讀取文件中的數據,將數據封裝到Student對象中。再把多個學生對象添加到集合中 String line; while((line = br.readLine()) != null) { //張三,23,95 Student stu = new Student(); String[] arr = line.split(","); stu.setUsername(arr[0]); stu.setAge(Integer.parseInt(arr[1])); stu.setScore(Integer.parseInt(arr[2])); list.add(stu); } //4.遍歷集合,將數據響應給瀏覽器 resp.setContentType("text/html;charset=UTF-8"); //獲取輸出流對象 PrintWriter pw = resp.getWriter(); for(Student s : list) { pw.write(s.getUsername() + "," + s.getAge() + "," + s.getScore()); pw.write("<br>"); } // 注意:其實這個代碼寫複雜了。文本中的數據,與最終輸出到瀏覽器的數據如出一轍 // 因此徹底能夠讀出來的line,經過pw直接寫便可,不須要封裝List<student> } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
訪問