javascript
Java-Web JSP、Cookie和Session域对象
一、JSP入門
? ? 1.什么是JSP
????????JSP(Java Server Pages)是JavaWeb服務(wù)器端的動(dòng)態(tài)資源。它與html頁(yè)面的作用是相同的,顯示數(shù)據(jù)和獲取數(shù)據(jù)。
? ? 2.JSP的組成
????JSP = html + Java腳本(代碼片段) + JSP動(dòng)態(tài)標(biāo)簽
? ? 3.JSP語(yǔ)法
????? ? 3.1 JSP腳本
????????????? ? JSP腳本就是java代碼片段,分為三種:
????????(1)<%...%>:Java語(yǔ)句;
????????????????????????java代碼片段(常用),用于定義0~N條Java語(yǔ)句!方法內(nèi)能寫什么,它就可以放什么!
????????(2)<%=…%>:Java表達(dá)式;
????????????? ? ? ??? ? java表達(dá)式,用于輸出一條表達(dá)式(或變量)的結(jié)果。response.getWriter().print( ... );這里能放什么,它就可以放什么!
????????(3)<%!...%>:Java定義類成員;
? ????????????????????? 聲明,用來(lái)創(chuàng)建類的成員變量和成員方法(基本不用)
????? ? 3.2 多個(gè)<%...%>可以通用
????????????????在一個(gè)JSP中多個(gè)<%...%>是相通的。例如:
????????????? ? 循環(huán)打印表格:
<body><h1>表格</h1><table border="1" width="50%"><tr><th>序號(hào)</th><th>用戶名</th><th>密碼</th></tr><%for(int i = 0; i < 10; i++) { %><tr><td><%=i+1 %></td><td>user<%=i %></td><td><%=100 + 1 %></td></tr><%}%></table></body>? ? 4.JSP原理
????????JSP是一種特殊的Servlet,當(dāng)JSP頁(yè)面首次被訪問(wèn)時(shí),容器(Tomcat)會(huì)先把JSP編譯成Servlet,然后再去執(zhí)行Servlet。所以JSP其實(shí)就是一個(gè)Servlet!
? ? 5.JSP注釋
? ??? ? 格式:<%-- ... --%>
????????JSP是需要先編譯成.java,再編譯成.class的。其中<%-- ... --%>中的內(nèi)容在JSP編譯成.java時(shí)會(huì)被忽略的,即JSP注釋。
????????也可以在JSP頁(yè)面中使用html注釋:<!-- … -->,但這個(gè)注釋在JSP編譯成的.java中是存在的,它不會(huì)被忽略,而且會(huì)被發(fā)送到客戶端瀏覽器。但是在瀏覽器顯示服務(wù)器發(fā)送過(guò)來(lái)的html時(shí),因?yàn)?lt;!-- … -->是html的注釋,所以瀏覽器是不會(huì)顯示它的。
????6.JSP和Servlet的分工
????? * JSP:
????????????作為請(qǐng)求發(fā)起頁(yè)面,例如顯示表單、超鏈接。
????????????作為請(qǐng)求結(jié)束頁(yè)面,例如顯示數(shù)據(jù)。
????? * Servlet:
????????????作為請(qǐng)求中處理數(shù)據(jù)的環(huán)節(jié)。
????小案例演示:
????????客戶端請(qǐng)求該jsp頁(yè)面,輸出數(shù)字求和
<form method="post" action="/4.29/AServlet">請(qǐng)輸入數(shù)字:<input type="text" name="num1"/><br/>請(qǐng)輸入數(shù)字:<input type="text" name="num2"/><br/><input type="submit" value="求和" /></form>????? ? 該jsp將請(qǐng)求頁(yè)面發(fā)送到AServlet中,AServlet進(jìn)行數(shù)據(jù)的處理,然后轉(zhuǎn)發(fā)到showSum.jsp中public class AServlet extends HttpServlet {public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//獲取請(qǐng)求的參數(shù)String num1 = request.getParameter("num1");String num2 = request.getParameter("num2");//把字符串轉(zhuǎn)成Integer類型Integer num11 = Integer.valueOf(num1);Integer num22 = Integer.valueOf(num2);int sum = num11 + num22;//把相加的結(jié)果保存到request域?qū)ο笾衦equest.setAttribute("sum", sum);//轉(zhuǎn)發(fā)到showSum.jsp中request.getRequestDispatcher("/sum/showSum.jsp").forward(request,response);}}????showSum頁(yè)面獲取到request傳遞過(guò)來(lái)的sum值,并輸出在客戶端中 <%Integer sum=(Integer)request.getAttribute("sum"); %><h3>和為<%=sum %></h3>
二、Cookie
? ? 1.Cookie概述
????????Cookie就是一個(gè)鍵和一個(gè)值構(gòu)成的,隨著服務(wù)器端的響應(yīng)發(fā)送給客戶端瀏覽器。然后客戶端瀏覽器會(huì)把Cookie保存起來(lái),當(dāng)下一次再訪問(wèn)服務(wù)器時(shí)把Cookie再發(fā)送給服務(wù)器。
????????Cookie是由服務(wù)器創(chuàng)建,然后通過(guò)響應(yīng)發(fā)送給客戶端的一個(gè)鍵值對(duì)。客戶端會(huì)保存Cookie,并會(huì)標(biāo)注出Cookie的來(lái)源(哪個(gè)服務(wù)器的Cookie)。當(dāng)客戶端向服務(wù)器發(fā)出請(qǐng)求時(shí)會(huì)把所有這個(gè)服務(wù)器Cookie包含在請(qǐng)求中發(fā)送給服務(wù)器,這樣服務(wù)器就可以識(shí)別客戶端了!
? ? 2.Cookie規(guī)范
????????????Cookie大小上限為4KB;
????????????一個(gè)服務(wù)器最多在客戶端瀏覽器上保存20個(gè)Cookie
????????????一個(gè)瀏覽器最多保存300個(gè)Cookie;
????????注意,不同瀏覽器之間是不共享Cookie的。也就是說(shuō)在你使用IE訪問(wèn)服務(wù)器時(shí),服務(wù)器會(huì)把Cookie發(fā)給IE,然后由IE保存起來(lái),當(dāng)你在使用FireFox訪問(wèn)服務(wù)器時(shí),不可能把IE保存的Cookie發(fā)送給服務(wù)器。
? ? 3.Cookie與HTTP頭
????????Cookie是通過(guò)HTTP請(qǐng)求和響應(yīng)頭在客戶端和服務(wù)器端傳遞的:
????????Cookie:請(qǐng)求頭,客戶端發(fā)送給服務(wù)器端;
????????????格式:Cookie: a=A; b=B; c=C。即多個(gè)Cookie用分號(hào)離開;
????????????????Set-Cookie:響應(yīng)頭,服務(wù)器端發(fā)送給客戶端;
????????????????一個(gè)Cookie對(duì)象一個(gè)Set-Cookie:
????????????????????Set-Cookie: a=A
????????????????????Set-Cookie: b=B? ? 4.Cookie生命
????????可以通過(guò)setMaxAge(int)來(lái)設(shè)置Cookie的有效時(shí)間。
????????????cookie.setMaxAge(-1):cookie的maxAge屬性的默認(rèn)值就是-1,表示只在瀏覽器內(nèi)存中存活。一旦關(guān)閉瀏覽器窗口,那么cookie就會(huì)消失。
????????????cookie.setMaxAge(60*60):表示cookie對(duì)象可存活1小時(shí)。當(dāng)生命大于0時(shí),瀏覽器會(huì)把Cookie保存到硬盤上,就算關(guān)閉瀏覽器,就算重啟客戶端電腦,cookie也會(huì)存活1小時(shí);
????????????cookie.setMaxAge(0):cookie生命等于0是一個(gè)特殊的值,它表示cookie被作廢!也就是說(shuō),如果原來(lái)瀏覽器已經(jīng)保存了這個(gè)Cookie,那么可以通過(guò)Cookie的setMaxAge(0)來(lái)刪除這個(gè)Cookie。無(wú)論是在瀏覽器內(nèi)存中,還是在客戶端硬盤上都會(huì)刪除這個(gè)Cookie。?
? ? 5.Cookie的path
????????現(xiàn)在有WEB應(yīng)用A,向客戶端發(fā)送了10個(gè)Cookie,這就說(shuō)明客戶端無(wú)論訪問(wèn)應(yīng)用A的哪個(gè)Servlet都會(huì)把這10個(gè)Cookie包含在請(qǐng)求中!但是也許只有AServlet需要讀取請(qǐng)求中的Cookie,而其他Servlet根本就不會(huì)獲取請(qǐng)求中的Cookie。這說(shuō)明客戶端瀏覽器有時(shí)發(fā)送這些Cookie是多余的!
????????可以通過(guò)設(shè)置Cookie的path來(lái)指定瀏覽器,在訪問(wèn)什么樣的路徑時(shí),包含什么樣的Cookie。
????? ? (1)Cookie路徑與請(qǐng)求路徑的關(guān)系
????????當(dāng)瀏覽器訪問(wèn)服務(wù)器某個(gè)路徑時(shí),需要?dú)w還哪些Cookie給服務(wù)器呢?這由Cookie的path決定。
? ? ????瀏覽器訪問(wèn)服務(wù)器的路徑,如果包含某個(gè)Cookie的路徑,那么就會(huì)歸還這個(gè)Cookie。
? ?????????例如:
? ? ? ????aCookie.path=/day11_1/; bCookie.path=/day11_1/jsps/; cCookie.path=/day11_1/jsps/cookie/;
? ? ? ????????<> 訪問(wèn):/day11_1/index.jsp時(shí),歸還:aCookie
? ? ? ????????<> 訪問(wèn):/day11_1/jsps/a.jsp時(shí),歸還:aCookie、bCookie
? ? ? ????????<> 訪問(wèn):/day11_1/jsps/cookie/b.jsp時(shí),歸還:aCookie、bCookie、cCookie
? ? > Cookie的path默認(rèn)值:當(dāng)前訪問(wèn)路徑的父路徑。例如在訪問(wèn)/day11_1/jsps/a.jsp時(shí),響應(yīng)的cookie,那么這個(gè)cookie的默認(rèn)path為/day11_1/jsps/
????????(2)設(shè)置Cookie路徑
????????設(shè)置Cookie的路徑需要使用setPath()方法,例如:
????????????????????cookie.setPath(“/cookietest/servlet”);
如果沒(méi)有設(shè)置Cookie的路徑,那么Cookie路徑的默認(rèn)值當(dāng)前訪問(wèn)資源所在路徑,例如:
????訪問(wèn)http://localhost:8080/cookietest/AServlet時(shí)添加的Cookie默認(rèn)路徑為/cookietest;
????訪問(wèn)http://localhost:8080/cookietest/servlet/BServlet時(shí)添加的Cookie默認(rèn)路徑為/cookietest/servlet;
????訪問(wèn)http://localhost:8080/cookietest/jsp/BServlet時(shí)添加的Cookie默認(rèn)路徑為/cookietest/jsp;
? ? 6.Cookie中保存中文
????????Cookie的name和value都不能使用中文,如果希望在Cookie中使用中文,那么需要先對(duì)中文進(jìn)行URL編碼,然后把編碼后的字符串放到Cookie中。
????向客戶端響應(yīng)中添加Cookie
public class BServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response) {String name;try {name = URLEncoder.encode("姓名", "UTF-8");String value = URLEncoder.encode("張三", "UTF-8");Cookie c = new Cookie(name, value);c.setMaxAge(3600);response.addCookie(c);} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}} }????從客戶端請(qǐng)求中獲取Cookie
public class CServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=utf-8");Cookie[] cs = request.getCookies();if (cs != null) {for (Cookie cookie : cs) {String name = URLDecoder.decode(cookie.getName(), "UTF-8");String value = URLDecoder.decode(cookie.getValue(), "UTF-8");String s = name + ":" + value + "<br/>";response.getWriter().print(s);}}} }三、HttpSession
? ? 1.HttpSession概述
????? * HttpSession是由JavaWeb提供的,用來(lái)會(huì)話跟蹤的類。session是服務(wù)器端對(duì)象,保存在服務(wù)器端!!!
?? ? * HttpSession是Servlet三大域?qū)ο笾?request、session、application(ServletContext))。
????? * HttpSession底層依賴Cookie,或是URL重寫!
? ? 2.HttpSession的作用
? ????* 會(huì)話范圍:會(huì)話范圍是某個(gè)用戶從首次訪問(wèn)服務(wù)器開始,到該用戶關(guān)閉瀏覽器結(jié)束!
? ??????會(huì)話:一個(gè)用戶對(duì)服務(wù)器的多次連貫性請(qǐng)求!所謂連貫性請(qǐng)求,就是該用戶多次請(qǐng)求中間沒(méi)有關(guān)閉瀏覽器!
????? * 服務(wù)器會(huì)為每個(gè)客戶端創(chuàng)建一個(gè)session對(duì)象,session就好比客戶在服務(wù)器端的賬戶,它們被服務(wù)器保存到一個(gè)Map中,這個(gè)Map被稱之為session緩存!
? ????????? Servlet中得到session對(duì)象:HttpSession session = request.getSession();
? ????????? Jsp中得到session對(duì)象:session是jsp內(nèi)置對(duì)象之下,不用創(chuàng)建就可以直接使用!
????? * session域相關(guān)方法:
? ? ?????????void setAttribute(String name, Object value);
? ? ?????????Object getAttribute(String name);
? ? ?????????void removeAttribute(String name);
? ? 3.登陸案例
需要的頁(yè)面:
????login.jsp:登錄頁(yè)面,提供登錄表單;
????succ1.jsp:主頁(yè),顯示當(dāng)前用戶名稱,如果沒(méi)有登錄,退回到login頁(yè)面;
????LoginServlet:在login.jsp頁(yè)面提交表單時(shí),請(qǐng)求本Servlet。在本Servlet中獲取用戶名、密碼進(jìn)行校驗(yàn),如果用戶名、密碼錯(cuò)誤,顯示“用戶名或密碼錯(cuò)誤”,如果正確保存用戶名session中,然后重定向到succ1.jsp;
login.jsp
<!--獲取登陸過(guò)后給用戶名設(shè)置的Cookie值,下次方便登陸--><%String uname="";Cookie[] cookie=request.getCookies();if(cookie!=null){for(Cookie coo:cookie){if("username".equals(coo.getName())){uname=coo.getValue();}}}%> <!--獲取loginServlet發(fā)送過(guò)來(lái)的數(shù)據(jù)并顯示在瀏覽器上 --><h3>登陸界面</h3><br /> <% String message="";String judge=(String)request.getAttribute("judge");if(judge!=null){message=judge;}%><font color="red"><b><%=message%></b></font><form action="/4.29/loginServlet" method="post"><%-- 把cookie中的用戶名顯示到用戶名文本框中 --%>用戶名:<input type="text" name="username" value="<%=uname%>" /><br /> 密 碼:<input type="password" name="password" /><br /> <input type="submit" value="登陸" /></form>loginServlet
public class loginServlet extends HttpServlet {public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding("UTF-8");// 獲取表單提交的參數(shù)String username = request.getParameter("username");String password = request.getParameter("password");// 對(duì)帳號(hào)進(jìn)行校驗(yàn),成功的話if (!username.equals("hello")) {// 將帳號(hào)作為Cookie保存在瀏覽器中Cookie cookie = new Cookie("username", username);cookie.setMaxAge(60 * 60);response.addCookie(cookie);// 將獲取的參數(shù)存在session域中,方便succ1獲取HttpSession session = request.getSession();session.setAttribute("username", username);session.setAttribute("password", password);// 重定向到登陸成功頁(yè)面response.sendRedirect("/4.29/Login/succ1.jsp");// 失敗的話} else {// 保存錯(cuò)誤信息到request域中request.setAttribute("judge", "用戶名或密碼錯(cuò)誤。請(qǐng)重新輸入。");// 轉(zhuǎn)發(fā)到login.jsprequest.getRequestDispatcher("/Login/login.jsp").forward(request,response);}} }succ1.jsp
<%String username = (String) session.getAttribute("username");//獲取用戶名/*如果用戶名為null,向request域中保存錯(cuò)誤信息,轉(zhuǎn)發(fā)到login.jsp*/if (username == null) {request.setAttribute("judge", "您還沒(méi)有登陸");request.getRequestDispatcher("/Login/login.jsp").forward(request, response);return;}%><h2>歡迎回來(lái),<%=username%></h2>? ? 4.HttpSession原理
? * request.getSession()方法:
? ? > 獲取Cookie中的JSESSIONID:
? ? ? <> 如果sessionId不存在,創(chuàng)建session,把session保存起來(lái),把新創(chuàng)建的sessionId保存到Cookie中
? ? ? <> 如果sessionId存在,通過(guò)sessionId查找session對(duì)象,如果沒(méi)有查找到,創(chuàng)建session,把session保存起來(lái),把新創(chuàng)建的sessionId保存到Cookie中
? ? ? <> 如果sessionId存在,通過(guò)sessionId查找到了session對(duì)象,那么就不會(huì)再創(chuàng)建session對(duì)象了。
? ? ? <> 返回session
? ? > 如果創(chuàng)建了新的session,瀏覽器會(huì)得到一個(gè)包含了sessionId的Cookie,這個(gè)Cookie的生命為-1,即只在瀏覽器內(nèi)存中存在,如果不關(guān)閉瀏覽器,那么Cookie就一直存在。
? ? > 下次請(qǐng)求時(shí),再次執(zhí)行request.getSession()方法時(shí),因?yàn)榭梢酝ㄟ^(guò)Cookie中的sessionId找到session對(duì)象,所以與上一次請(qǐng)求使用的是同一session對(duì)象。??
? * 服務(wù)器不會(huì)馬上給你創(chuàng)建session,在第一次獲取session時(shí),才會(huì)創(chuàng)建!request.getSession();
? * request.getSession(false)、request.getSession(true)、request.getSession(),后兩個(gè)方法效果相同
? ? > 第一個(gè)方法:如果session緩存中(如果cookie不存在),不存在session,那么返回null,而不會(huì)創(chuàng)建session對(duì)象。
? ? 5.Session與瀏覽器
????????session保存在服務(wù)器,而sessionId通過(guò)Cookie發(fā)送給客戶端,但這個(gè)Cookie的生命不-1,即只在瀏覽器內(nèi)存中存在,也就是說(shuō)如果用戶關(guān)閉了瀏覽器,那么這個(gè)Cookie就丟失了。
????????當(dāng)用戶再次打開瀏覽器訪問(wèn)服務(wù)器時(shí),就不會(huì)有sessionId發(fā)送給服務(wù)器,那么服務(wù)器會(huì)認(rèn)為你沒(méi)有session,所以服務(wù)器會(huì)創(chuàng)建一個(gè)session,并在響應(yīng)中把sessionId中到Cookie中發(fā)送給客戶端。
????????你可能會(huì)說(shuō),那原來(lái)的session對(duì)象會(huì)怎樣?當(dāng)一個(gè)session長(zhǎng)時(shí)間沒(méi)人使用的話,服務(wù)器會(huì)把session刪除了!這個(gè)時(shí)長(zhǎng)在Tomcat中配置是30分鐘,可以在${CATALANA}/conf/web.xml找到這個(gè)配置,當(dāng)然你也可以在自己的web.xml中覆蓋這個(gè)配置!從客戶端請(qǐng)求中獲取Cookie。
<session-config><session-timeout>10</session-timeout></session-config>????????如果你打開網(wǎng)站的一個(gè)頁(yè)面開始長(zhǎng)時(shí)間不動(dòng),超出了10分鐘后,再去點(diǎn)擊鏈接或提交表單時(shí)你會(huì)發(fā)現(xiàn),你的session已經(jīng)丟失了!
? ? 6.Session其他常用API
????????String getId():獲取sessionId;
????????int getMaxInactiveInterval():獲取session可以的最大不活動(dòng)時(shí)間(秒),默認(rèn)為30分鐘。當(dāng)session在30分鐘內(nèi)沒(méi)有使用,那么Tomcat會(huì)在session池中移除這個(gè)session;
????????void setMaxInactiveInterval(int interval):設(shè)置session允許的最大不活動(dòng)時(shí)間(秒),如果設(shè)置為1秒,那么只要session在1秒內(nèi)不被使用,那么session就會(huì)被移除;
????????long getCreationTime():返回session的創(chuàng)建時(shí)間,返回值為當(dāng)前時(shí)間的毫秒值;
????????long getLastAccessedTime():返回session的最后活動(dòng)時(shí)間,返回值為當(dāng)前時(shí)間的毫秒值;
????????void invalidate():讓session失效!調(diào)用這個(gè)方法會(huì)被session失效,當(dāng)session失效后,客戶端再次請(qǐng)求,服務(wù)器會(huì)給客戶端創(chuàng)建一個(gè)新的session,并在響應(yīng)中給客戶端新session的sessionId;
????????boolean isNew():查看session是否為新。當(dāng)客戶端第一次請(qǐng)求時(shí),服務(wù)器為客戶端創(chuàng)建session,但這時(shí)服務(wù)器還沒(méi)有響應(yīng)客戶端,也就是還沒(méi)有把sessionId響應(yīng)給客戶端時(shí),這時(shí)session的狀態(tài)為新。
? ? 7.URL重寫
????????我們知道session依賴Cookie,那么session為什么依賴Cookie呢?因?yàn)榉?wù)器需要在每次請(qǐng)求中獲取sessionId,然后找到客戶端的session對(duì)象。那么如果客戶端瀏覽器關(guān)閉了Cookie呢?那么session是不是就會(huì)不存在了呢?
????????其實(shí)還有一種方法讓服務(wù)器收到的每個(gè)請(qǐng)求中都帶有sessioinId,那就是URL重寫!在每個(gè)頁(yè)面中的每個(gè)鏈接和表單中都添加名為jSessionId的參數(shù),值為當(dāng)前sessionid。當(dāng)用戶點(diǎn)擊鏈接或提交表單時(shí)也服務(wù)器可以通過(guò)獲取jSessionId這個(gè)參數(shù)來(lái)得到客戶端的sessionId,找到sessoin對(duì)象。
<body> <h1>URL重寫</h1> <a href='/day06_5/index.jsp;jsessionid=<%=session.getId() %>' <form action='/day06_5/index.jsp;jsessionid=<%=session.getId() %>' method="post"><input type="submit" value="提交"/> </form> </body>????????也可以使用response.encodeURL()對(duì)每個(gè)請(qǐng)求的URL處理,這個(gè)方法會(huì)自動(dòng)追加jsessionid參數(shù),與上面我們手動(dòng)添加是一樣的效果。
<a href='<%=response.encodeURL("/day06_5/index.jsp") %>' >主頁(yè)</a> <form action='<%=response.encodeURL("/day06_5/index.jsp") %>' method="post"><input type="submit" value="提交"/> </form>????????使用response.encodeURL()更加“智能”,它會(huì)判斷客戶端瀏覽器是否禁用了Cookie,如果禁用了,那么這個(gè)方法在URL后面追加jsessionid,否則不會(huì)追加。????????
總結(jié)
以上是生活随笔為你收集整理的Java-Web JSP、Cookie和Session域对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java-Web 编码和路径
- 下一篇: Java-Web JSTL标签库、