【Servlet】Servlet基礎、實戰
阿新 • • 發佈:2020-09-08
Servlet
1).TomCat伺服器
常見軟體伺服器產品: tomcat apache提供,java程式碼編寫.(執行以來jvm環境); apache apache提供.LAMP軟體架構.(Linux Apache MySQL PHP) Nginx 伺服器反向代理和負載均衡,叢集伺服器. TomCat使用: ①部署靜態資源. a在tomcat的webapps下新建資料夾(代表web專案) b將資源放入web資料夾中. ②啟動tomcat `startup.bat` ③瀏覽器訪問 常見異常: ①埠被佔用 異常資訊: socket bind faild / JVM Bind 原因: tomcat使用埠被佔用. 解決辦法: 修改tomcat/conf/server.xml `<connector port="埠">` ②404 異常資訊: 客戶端請求的資源找不到? 原因: 地址請求的資源和真正伺服器的資源路徑不符.(不存在, 路徑寫錯了) 解決辦法: 按照請求路徑和資源部署路徑一個一個校對. URL: URL: 統一資源定位符. 注意: 伺服器端每個資源(HTML CSS 圖片 視訊 程式其他資源),都有一個唯一的訪問路徑. URL: http://ip:port/專案名/資源路徑. 應用: 瀏覽器位址列 URI: `/專案名/資源路徑` 本tomcat內部資源路徑 應用: form a link img <img src="/專案名/圖片資源路徑"/> <form action="/專案名..."> </form> <a href="/專案名/資源路徑"></a> url-pattern: `/資源路徑` 本專案內部資源
2).Servlet初始、及常見異常
概念: 一段Java程式,可以執行在tomcat端. 語法: Servlet標準.(介面) JavaEE標準(servlet-api.jar) 介面: interface Servlet{ init(){servlet物件建立的自動呼叫} destroy(){servlet物件銷燬的自動呼叫} service(){//使用者訪問tomcat伺服器的該程式,呼叫service方法. // 使用者請求後,執行的程式碼. } } JavaEE提供類: HttpServlet 實現了Servlet介面. 自定義tomcat執行程式碼: public class MyServlet extends HttpServlet{ public void service(){ //覆蓋servlet的service方法. } } 開發第一個Servlet程式: 需求: 顯示當前系統時間? Servlet開發的具體步驟: ①手動部署servlet程式 編寫Servlet程式 匯入servlet-api的jar.(編寫編譯java程式使用) public class FirstServlet extends HttpServlet{ public void service(){ // 1. 獲得當前系統時間 // 2. 將時間返回給瀏覽器(響應給瀏覽器) //列印一字串 PrintWriter pw = resp.getWriter(); pw.println(“這是一個字串”); } } ②將servlet部署tomcat 在tomcat/webapps下建立資料夾(web專案) 在專案下建立建立WEB-INF/classes,將程式碼帶包拷貝在classes下面 ③在web.xml描述(全類名+訪問路徑) 註冊servlet資訊: <servlet> <servlet-name>&名字&</servlet-name> <servlet-class>全類名</servlet-class> </servlet> 對映servlet訪問路徑 <servlet-mapping> <servlet-name>&名字&</servlet-name> <url-pattern>/servlet訪問路徑</url-pattern> </servlet-mapping> ④啟動tomcat ⑤訪問servlet,檢視執行響應的結果. `http:ip:port/專案名/web.xml註冊的servlet的訪問url-pattern` `http://localhost:8989/web/firstDate` 常見異常[重點] ①405 `Method Not Allowed` 原因: 方法呼叫錯誤 解決辦法: a. 方法名是否錯誤. b. service方法內,不能呼叫父類的方法. ②訪問servlet變成下載 響應型別設定有問題 `resp.setContentType("text/html;charset=UTF-8");` ③servlet修改後,沒有變化. 原因: servlet程式碼修改,tomcat需要重啟,才能生效. ④500錯誤: a. classNotFundException: web.xml的servlet的全類名寫錯. b. 服務端java程式碼執行異常. ⑤404 錯誤; 瀏覽器訪問地址: 不存在 地址寫錯(瀏覽器位址列, url-pattern不一致,) tomcat啟動就報錯(tomcat啟動失敗)
3).Servlet在MyEclipse中部署、Servlet執行原理、請求引數及請求方式
(1)MyEclipse開發部署Servlet ①新建web project > 建立web.xml > 自動建立好對應的目錄結構(WEB-INF classes web.xml) ②編寫servlet ③編寫web.xml ④部署 servers--tomcat8.x---右鍵---add deployment--選擇專案部署 Servlet生命週期 [面試]: 概念: servlet建立時機和活躍使用時機,銷燬時機. interface Servlet{ init(){} //物件建立執行 service(){} //瀏覽器請求到servlet,提供服務的執行的方法. destroy(){} //物件銷燬執行. } ① servlet建立 第一個瀏覽器訪問servlet,物件會被建立 一個Servlet類只會建立一個servlet物件. ②servlet服務 瀏覽器每次訪問都會呼叫service方法. ③servlet銷燬 tomcat關閉,銷燬servlet物件 重點: Servlet物件只有一個單例項,面向多執行緒(使用者)訪問,**執行緒不安全**. ①如果servlet有屬性, service方法中對屬性的操作,加鎖. ②要求: Servlet中不要新增資料屬性 (2)Servlet執行原理 瀏覽器向tomcat發出url的http請求: http://ip:port/web專案名/servlet的url-pattern tomcat伺服器: ①獲得url的專案名, 從本tomcat下的webapps下找到對應資料夾. ②根據url中servlet的url-pattern,從web.xml找到 servlet-name, 找到servlet-class被訪問的servlet的全類名 ③Class<?> clazz = Class.forName("Servlet的全類名");//獲得servlet的類物件. ④Servlet servlet = (Servlet)clazz.newInstance();//創建出了類的物件(Servlet), tomcat內部管理servlet Map<String,Servlet> map = ....; map.put("url-pattern",servlet); ⑤tomcat先呼叫 `servlet.init()`方法,(servlet第一被訪問) map.contains("url-pattern")//--true; ⑥`servlet.service(req,resp)`呼叫servlet的service方法; ⑦伺服器將響應結果返回給瀏覽器. ⑧瀏覽器發出第二次請求. ⑨tomcat會直接根據url-pattern,找到servlet物件,呼叫servlet.service方法. map.get("url中的url-pattern"); (3)Servlet請求引數 概念: 瀏覽器請求servlet攜帶的資料,叫做請求引數 Servlet接收請求引數: `request.getParameter("表單元素的name")//接收名字對應單個數據的引數` `request.getParameterValues("表單元素的name")//獲得一個名字對應多個值,返回值String[]` (4)瀏覽器請求Servlet的方式 ①瀏覽器位址列。也可以新增資料例如xxxx/xxxxxx/xxxx?username=“值”&password=“值” ②form表單(的action)請求Servlet `<form action="servlet的路徑(URI)">` ③超連結的href. `<a href="servlet的路徑(URI)"></a>` 補充小技巧: 使用瀏覽器監控瀏覽發出請求的請求引數 (F12除錯) 名字=值;
4).請求引數亂碼問題、Servlet請求轉發、Request作用域、請求重定向(Redirect)、總結跳轉方式
(1)請求引數亂碼問題
①Post提交亂碼:
瞭解: tomcat接收資料預設編碼: `ISO-8859-1`
接收: req.setCharacterEncoding("UTF-8")
傳送: resp.setContentType(“text/html;charset=UTF-8”);
注意: 設定編碼,在接收請求引數之前設定
② Get提交亂碼:
方式:
form action="" method="get"
超連結攜帶的資料.
瀏覽器傳送請求引數
修改tomcat的conf/server.xml中`<connector URIEncoding=”UTF-8” />`
(2)Servlet各司其職
請求轉發(foward)
作用: **多個Servlet配合完成一個功能**
核心特點:
①是伺服器(當前web專案)內部發送的流程跳轉*
②forward請求轉發連線的多個servlet,處於一個請求過程中.
程式碼:
RequestDispatcher rdp = request.getRequestDispatcher("轉發後的下一個servlet的url-pattern/其他資源的url-pattern路徑");//獲得轉發器.
rdp.forward(req,resp);//foward轉發.呼叫轉發動作.
補充:
跳轉情況:
`servlet-->Servlet`
`servlet--->HTML(JSP)`
(3)Request作用域
概念: JavaEE提供的儲存資料(命名屬性)的空間.
命名屬性: 名字---值
生命週期: 一次請求過程.[備註:請求轉發的servlet正好處於一次請求過程]
存: `request.setAttribute("名字",值/資料/物件/xxx)`
取: `request.getAttribute("名字")`
(4)請求重定向(Redirect)
核心特點:
①伺服器(web應用)外部跳轉。
②通知瀏覽器,自動去請求下一個要跳轉的頁面或者Servlet(不需要使用者操作)
③重定向連線的servlet或者資源,處於兩個不同的請求過程。
④請求重定向後的頁面和瀏覽器的地址一致。
程式碼實現:
resp.sendRedirect("/專案名/資源路徑url-pattern");
//通知瀏覽器自動請求"/專案名/資源路徑url-pattern"
(5)總結跳轉方式
請求轉發(foward) 請求重定向(Redirect)
原理(本質) 伺服器(Web專案)內部跳轉 伺服器(Web專案)外部跳轉
請求過程 1個請求過程 2個不同的請求過程
瀏覽器顯示和地址 不一致 一致
作用域 可以使用request作用域傳值 不能使用request作用域傳值 [瞭解:地址?拼接資料]
應用 servlet--->傳遞資料,使用request作用域,請求轉發。一個業務功能中的多個資源要處於一個請求過程中,使用請求轉發;servlet跳轉的下一個資源屬於另一個業務功能,使用請求重定向。
5).會話技術(Cookie、HttpSession)、Session實現原理、解決瀏覽器禁用Cookie後Session失效問題
會話技術
http協議: 無狀態協議,(協議本身不會記錄任何資訊,兩次資訊傳輸之間沒有任何關係)
概念: 客戶端(瀏覽器)會話技術。
應用場景: 瀏覽器記錄 登入驗證 驗證碼 購物車(閹割版)
另一種解釋: 瀏覽器和伺服器之間,多次互動依然儲存資料(狀態)的一種機制。(每個瀏覽器一份)
(1)Cookie
概念: 伺服器儲存在瀏覽器上的一小段字串[key=value]
工作機制:
①伺服器tomcat建立
②儲存在瀏覽器
③瀏覽器每次訪問伺服器,都會將伺服器(web專案)儲存在本瀏覽器上的cookie傳送到伺服器上。(傳送當前伺服器儲存的cookie)
編碼實現:
①建立:
Cookie cookie = new Cookie("key","value");
②將cookie存入瀏覽器
response.addCookie(cookie);// 將cookie隨著響應返回給瀏覽器.
③其他方法(設定生命週期,設定存活多久)
cookie.setMaxAge(存活時間秒);
④獲得瀏覽器請求攜帶的cookie資訊?
Cookie[] cs = req.getCookies();
cs[0].getName(); //cookie的key
cs[0].getValue(); //cookie的value
總結Cookie的特點
①存在瀏覽器上的一小段字串
>缺點: (資料不太安全)
>優點: 分擔伺服器的壓力。(不會佔用伺服器的任何資源)
②cookie只能儲存字串,不能儲存中文。
③cookie生命週期: (跨多次請求)
設定: setMaxAge(秒)
10 存活10s
0 刪除cookie
-1 設定cookie瀏覽器關閉之前。
預設: 瀏覽器關閉,cookie丟失。
④cookie和瀏覽器(使用者)一一對應。
(2)HttpSession
概念: 伺服器會話技術。
核心工作機制: 伺服器為每個**瀏覽器分配的一個一一**對應的儲存空間。
詳細: 瀏覽器第一次訪問web應用伺服器,伺服器分配一個session物件,該瀏覽器第二次後再訪問,伺服器直接將原有sessino物件分配給該瀏覽器。
HttpSession的特點:
①存放在伺服器
②每個瀏覽器和session一一對應
③HttpSession的生命週期誇多次請求依然存在。
HttpSession 相關的API:
①屬性: id.
②獲得session: `request.getSession()`
瀏覽器第一次訪問: 建立session物件。
瀏覽器第二 三...次訪問: 獲得原有的session物件給你。
HttpSession作用
**作用域,儲存命名屬性**
存:`session.setAttribute("name",值)`
取: `session.getAttribute("name")`
移除:`session.removeAttribute("name")`
特點:
①瀏覽器一一對應
②跨多次請求依然存在
③存放在伺服器
應用場景(強制登入/登入驗證):
需求:某些資源(HTML,Servlet)的訪問需要使用者登入之後才能訪問,否則,強制使用者去登入頁面登入?
基本思路: web專案伺服器記住使用者(登入)
Session失效時機(補充):
①瀏覽器關閉,session失效。
②session預設保留30分鐘。 【瀏覽器和伺服器之間,超過30分鐘沒有請求】
--當前專案的web.xml中修改
<session-config>
<session-timeout>60</session-timeout>
</session-config>
③主動失效: `session.invalidate()` 將所有Session失效
應用: 使用者退出登入:
`session.removeAttribute("user")`
`sesssion.invalidate()`
Cookie和Session對比[筆試]
Session和Cookie的相同點
和瀏覽器一一對應。
生命週期跨多次請求依然存。
Session和Cookie的不同點:
Cookie:
存在瀏覽器
cookie只能儲存字串,不能存漢字.(缺點)
cookie資料容易通過瀏覽器直接檢視,不太安全。(缺點)
Session:
存在於伺服器端
session可以存物件,可以存入任何型別。(優點)
session資料儲存伺服器,相對安全。(優點)
session中資料過多,侵佔伺服器記憶體資源(對伺服器執行造成壓力)[缺點]
應用場景分析:
使用者私密資訊(Session)
使用者瀏覽器過的商品資訊(cookie儲存)
(3)Session實現原理
機制:
瀏覽器第一請求伺服器web專案,會為該瀏覽器建立一個session物件。獲得session的id,並且將id以cookie的形式寫回到瀏覽器。以後每次瀏覽器,請求伺服器都會自動攜帶該cookie(JsessionId)資訊,tomcat通過獲得cookie中名字為jesessionid的cookie的value值,和內部所有的session物件匹配,找到對應的session對該瀏覽器使用。
內部程式碼咋實現(區域性程式碼):
①瀏覽器第一請求伺服器:
HttpSession session = new XxxxSession();
String id = session.getId();
//將session儲存在伺服器記憶體中(集合)
Map<String,HttpSession> map = new ConcurrentHashMap<String,HttpSession>();
map.put(id,session);
Cookie ck = new Cookie("jsessionid",id);
resp.addCookie(ck);
②瀏覽器第二次(以後)請求伺服器
Cookie[] cks = req.getCookies();
for(Cookie c:cks){
if(c.getName().equals("jsessionid")){
String sessionId = c.getValue();
//根據sessionid找到對應的session物件
HttpSession session = map.get(sessionId);
}
}
(4)使用者禁用Cookie (瞭解)
導致session失效,解決辦法?
總結:
對所有超連結+表單等一切請求伺服器的url路徑,全部進行url重寫。
方法: `String 重寫後的url = resp.encodeUrl(原url地址)`
糾錯: `重寫url;jsessionid=1234asdf1234`;
6).Filter過濾器
Filter過濾器: Servlet中提供的技術,可以過濾瀏覽器發出的請求,並且決定放行請求還是中斷請求。
編碼步驟:
①自定義一個java類,實現Filter介面
public class EncodingFilter implements Filter{
init(){}
destroy(){}
//請求經過filter要執行的程式碼
doFilter(FilterChain chain){
//放行請求之前
chain.doFilter(req,resp);//放行請求。中斷:不要呼叫
//響應回來的程式碼,例如:資源的控制
}
}
②在web.xml中註冊資訊
<!-- 註冊filter資訊 -->
<filter>
<filter-name>filter名字</filter-name>
<filter-class>filter全限定名</filter-class>
</filter>
<filter-mapping>
<filter-name>filter名字</filter-name>
<url-pattern>/被過濾請求的servlet或者html等資源的url-pattern</url-pattern>
</filter-mapping>
生命週期(瞭解):
①建立: tomcat啟動
②銷燬:tomcat關閉
Filter的url-pattern的寫法:
①寫多個<url-pattern>資源</url-pattern>
②`/*`---過濾所有請求(統配) <url-pattern>/*</url-pattern>
③`*.do`---過濾請求以.do的請求,在要過濾的servlet的全類名後加”.do”
然後配置filter:<url-pattern>*.do</url-pattern>
④`/xxxxooaa/*` ----過濾路徑中的url-pattern部分,以/xxxxxooaa開頭的請求
<url-pattern>/目錄/*</url-pattern>
應用:
可以為所有servlet設定編碼格式
7).ServletContext容器、監聽器(ServletContextListener/HttpSessionListener/ServletRequestListener)
(1)ServletContext
(容器)作用域: 一個web應用只有一個ServletContext物件。
建立:tomcat啟動建立 銷燬: tomcat關閉
程式設計:
① 獲得servletContext物件:
`ServletContext ctx = session.getServletContext()`
② 存: `ctx.setAttribute("name",值)`
③ 取: `ctx.getAttribute("name")`
④移除: `ctx.removeAttribute("name")`
全域性引數:
web.xml啟動載入完畢會將資訊存入servletContext
1. 在web.xml書寫常亮配置
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
2. 從servletContext中獲得常亮配置
String value = ctx.getInitParameter("encoding"); //“UTF-8”
web應用內流的相對路徑:
`String 真實路徑 = ctx.getRealPath("/專案名下的相對路徑")`
專案名的動態獲取(補充):
String ctxtPath = request.getContextPath();// "/專案名"
使用: 跳轉路徑: /專案名
(2)監聽器
事件程式設計模型
概念:
事件源: 發生事件的物件本身,源頭。
事件: 具體發生事情事件。
監聽器: 監聽事件源上發生的具體的事件,如果發生,會觸發對應的程式碼執行。
監聽器:
SerletContextListener: 監聽ServletContext物件的建立和銷燬
HttpSessionListener: 監聽HttpSession物件建立和銷燬
ServletRequestListner: 監聽ServletRequest物件建立和銷燬。
編碼:
①自定義一個類實現ServletContextListener:
public class MyContextListener implements ServletContextListener{
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("context----銷燬!!!!!!!!!!!!");
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("context----建立!!!!!!!!!!!!");
}}
②web.xml註冊:
<listener><listener-class>全類名</listener></listener>
應用:
需求: 監控線上使用者數量?
在HttpSession監聽器中,監聽session建立與銷燬。