1. 程式人生 > 實用技巧 >【Servlet】Servlet基礎、實戰

【Servlet】Servlet基礎、實戰

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建立與銷燬。