JavaWeb會話總結(jié)!![附帶案例]
閱讀本文大概需要 14?分鐘。
1.1會話的概念
一次會話中包含多次請求和響應(yīng)。 一次會話:瀏覽器第一次給服務(wù)器資源發(fā)送請求,會話建立,直到有一方斷開為止,一次會話結(jié)束。
1.2會話的功能
在一次會話的范圍內(nèi)的多次請求間,共享數(shù)據(jù)。
1.3會話實(shí)現(xiàn)的方式
客戶端會話技術(shù):Cookie 服務(wù)端會話技術(shù):Session
1.4Cookie
概念:客戶端會話技術(shù),將數(shù)據(jù)保存到客戶端
快速入門
使用步驟
創(chuàng)建Cookie對象,綁定數(shù)據(jù)
new?Cookie(String?name,?String?value);
服務(wù)端發(fā)送Cookie到客戶端
response.addCookie(Cookie?cookie);
客戶端訪問新資源,攜帶Cookie數(shù)據(jù)
Cookie[]?cookies?=?request.getCookie();
項(xiàng)目實(shí)戰(zhàn)
案例編碼
寫Cookie數(shù)據(jù)到客戶端的Servlet
package?org.taoguoguo.cookie;
import?javax.servlet.ServletException;
import?javax.servlet.annotation.WebServlet;
import?javax.servlet.http.Cookie;
import?javax.servlet.http.HttpServlet;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
import?java.io.IOException;
/**
?*?@author?taoguoguo
?*?@description?Cookie快速入門-寫Cookie數(shù)據(jù)到客戶端的Servlet
?*?@website?https://www.cnblogs.com/doondo
?*?@create?2020-11-17?21:44
?*/
@WebServlet("/CookieDemo1")
public?class?CookieDemo1?extends?HttpServlet?{
????protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
????????//1.創(chuàng)建Cookie對象
????????Cookie?c?=?new?Cookie("msg","hello");
????????//2.發(fā)送Cookie
????????response.addCookie(c);
????}
????protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
????????this.doPost(request,?response);
????}
}
獲取客戶端Cookie數(shù)據(jù)的Servlet
package?org.taoguoguo.cookie;
import?javax.servlet.ServletException;
import?javax.servlet.annotation.WebServlet;
import?javax.servlet.http.Cookie;
import?javax.servlet.http.HttpServlet;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
import?java.io.IOException;
/**
?*?@author?taoguoguo
?*?@description?cookie快速入門-獲取客戶端Cookie數(shù)據(jù)
?*?@website?https://www.cnblogs.com/doondo
?*?@create?2020-11-17?21:46
?*/
@WebServlet("/CookieDemo2")
public?class?CookieDemo2?extends?HttpServlet?{
????protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
????????//3.獲取Cookie
????????Cookie[]?cookies?=?request.getCookies();
????????//獲取數(shù)據(jù),遍歷Cookie
????????if(cookies!=null){
????????????for(Cookie?cookie:cookies){
????????????????System.out.println(cookie.getName()?+?"->"?+?cookie.getValue());
????????????}
????????}
????}
????protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
????????this.doPost(request,?response);
????}
}
輸出結(jié)果:
msg->hello
Cookie實(shí)現(xiàn)原理
基于響應(yīng)頭?set-cookie和請求頭cookie實(shí)現(xiàn)
客戶端請求訪問服務(wù)器,服務(wù)器將需要存儲到cookie里面的內(nèi)容,通過鍵值對形式寫到set-cookie頭中,然后將數(shù)據(jù)響應(yīng)給客戶端;
客戶端再次發(fā)送請求時,會將存儲在客戶端的Cookie數(shù)據(jù),放在請求頭cookie中,提交給服務(wù)端,服務(wù)器可獲取請求頭中Cookie的數(shù)據(jù),進(jìn)行數(shù)據(jù),從而做到交互。
Cookie的細(xì)節(jié)
一次是否可以發(fā)送多個Cookie?
可以,服務(wù)端可以創(chuàng)建多個Cookie對象,使用response調(diào)用多次addCookie方法發(fā)送Cookie即可。 Cookie在瀏覽器中的有效時間?
默認(rèn)情況下,當(dāng)瀏覽器關(guān)閉,Cookie數(shù)據(jù)被銷毀 持久化存儲
/*int?取值分類
?正數(shù):將Cookie數(shù)據(jù)寫到硬盤文件中,持久化存儲,Cookie 存活時間(單位為:秒)
?負(fù)數(shù):默認(rèn)值
?零:刪除Cookie信息
*/
setMaxAge(int?seconds)
package?org.taoguoguo.cookie;
import?javax.servlet.ServletException;
import?javax.servlet.annotation.WebServlet;
import?javax.servlet.http.Cookie;
import?javax.servlet.http.HttpServlet;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
import?java.io.IOException;
/**
?*?@author?taoguoguo
?*?@description?Cookie存活時間舉例
?*?@website?https://www.cnblogs.com/doondo
?*?@create?2020-11-17?21:46
?*/
@WebServlet("/CookieDemo3")
public?class?CookieDemo3?extends?HttpServlet?{
????protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
????????//1.創(chuàng)建Cookie對象
????????Cookie?cookie?=?new?Cookie("msg","setMaxAge");
????????//2.設(shè)置Cookie的存活時間
????????cookie.setMaxAge(30);???//將Cookie持久化硬盤,30后會自動刪除Cookie文件
????????//3.發(fā)送Cookie
????????response.addCookie(cookie);
????}
????protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
????????this.doPost(request,?response);
????}
}
Cookie是否可以存儲中文
Tomcat 8 之前,Cookie中不能直接存儲中文數(shù)據(jù) 解決方案:將中文轉(zhuǎn)碼,一般采用URL編碼
//存中文到Cookie編碼
Cookie?cookie?=?new?Cookie("uname",URLEncoder.encode(uname,"utf-8"));
//獲取Cookie解碼
String?value?=?URLDecoder.decode(cookie.getValue(),"utf-8");
Tomcat 8 之后,Cookie支持中文數(shù)據(jù),但不支持特殊字符,依然可以通過URL編碼解決
Cookie的獲取范圍多大?
默認(rèn)情況下,Cookie不能共享 假設(shè)在一個Tomcat服務(wù)器中,部署了多個web項(xiàng)目,那么這些web項(xiàng)目的Cookie能否共享?
//設(shè)置cookie的取值范圍?默認(rèn)情況下,設(shè)置未當(dāng)前的虛擬目錄,也就是?request.getContext的值
//如果需要共享,需要將path?設(shè)置為父級別目錄
//比如?/project1;?/project2?兩個項(xiàng)目需要共享,則?setPath("/")
c.setPath(String?path)
不同的Tomcat服務(wù)器間Cookie共享問題? 設(shè)置一級域名相同,那么多個服務(wù)器之間的Cookie可以共享
?/**
?比如,貼吧的域名為:tieba.baidu.com ?而新聞的域名為 news.baidu.com
?其中?baidu.com?為一級域名?tieba、news?等為二級域名
?c.setDomain(".baidu.com")?那么tieba.baidu.com?和?news.baidu.com中的Cookie可以共享
?*/
?c.setDomain(String?path);
Cookie的特點(diǎn)和作用
Cookie存儲數(shù)據(jù)在客戶端瀏覽器 瀏覽器對于單個Cookie的大小限制,以及對同一個域名下的總Cookie數(shù)量也有限制(20個)
「作用:」
cookie一般用于存儲少量的不太敏感的數(shù)據(jù) 在不登陸的情況下,服務(wù)器對客戶端的身份的識別 比如在百度瀏覽器未登錄情況下做一些偏好設(shè)置,服務(wù)端發(fā)一個Cookie給瀏覽器,瀏覽器訪問時帶上這個Cookie,服務(wù)端就可以渲染對應(yīng)的偏好設(shè)置
Cookie案例
需求:1。訪問一個Servlet,如果第一次訪問,則提示:您好,歡迎首次訪問;如果不是第一次訪問,則提示歡迎回來,您上次訪問時間為:顯示時間字符串。
分析:
可以采用Cookie來完成
在服務(wù)器中的Servlet來判斷是否有一個名為 lastTime的Cookie 有:不是第一次訪問
沒有:第一次訪問
響應(yīng)數(shù)據(jù),您好,歡迎你首次訪問 寫回Cookie: lastTime:當(dāng)前時間 響應(yīng)數(shù)據(jù):歡迎回來,你上次訪問的時間為:獲取lastTime中Cookie數(shù)據(jù) 寫回Cookie, 更新Cookie時間的值
案例代碼:
package?org.taoguoguo.cookie;
import?javax.servlet.ServletException;
import?javax.servlet.annotation.WebServlet;
import?javax.servlet.http.Cookie;
import?javax.servlet.http.HttpServlet;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;
import?java.io.IOException;
import?java.net.URLDecoder;
import?java.net.URLEncoder;
import?java.text.SimpleDateFormat;
import?java.util.Date;
/**
?*?@author?taoguoguo
?*?@description?Cookie案例
?*?@website?https://www.cnblogs.com/doondo
?*?@create?2020-11-17?21:46
?*/
@WebServlet("/cookieTest")
public?class?CookieTest?extends?HttpServlet?{
????protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
????????//設(shè)置響應(yīng)消息體的數(shù)據(jù)格式和編碼
????????response.setContentType("text/html;charset=utf-8");
????????//1.獲取所有Cookie
????????Cookie[]?cookies?=?request.getCookies();
????????boolean?flag?=?false;???//默認(rèn)沒有Cookie
????????//2.遍歷Cookie數(shù)組
????????if(cookies!=null?&&?cookies.length>0){
????????????for?(Cookie?cookie?:?cookies)?{
????????????????//3.獲取cookie的名稱
????????????????String?name?=?cookie.getName();
????????????????//4.判斷名稱是否為?lastTime
????????????????if("lastTime".equals(name)){
????????????????????flag?=?true;
????????????????????//Cookie存在,不是第一次訪問
????????????????????String?value?=?cookie.getValue();
????????????????????value?=?URLDecoder.decode(value,"utf-8");
????????????????????//獲取當(dāng)前時間的字符串,重新設(shè)置Cookie的值,重新發(fā)送Cookie
????????????????????String?str_date?=?new?SimpleDateFormat("yyyy年MM月dd日?HH:mm:ss").format(new?Date());
????????????????????str_date?=?URLEncoder.encode(str_date,?"utf-8");
????????????????????cookie.setValue(str_date);
????????????????????//設(shè)置Cookie的存活時間
????????????????????cookie.setMaxAge(60*60);????//一小時
????????????????????response.addCookie(cookie);
????????????????????//cookie
????????????????????response.getWriter().write("歡迎回來,您上次的訪問時間為:?"
+value+"");
????????????????}
????????????}
????????}
????????if(cookies?==?null?||?cookies.length==0?||?flag?==?false){
????????????//沒有?第一次訪問
????????????String?str_date?=?new?SimpleDateFormat("yyyy年MM月dd日?HH:mm:ss").format(new?Date());
????????????//時間輸出格式中空格特殊字符處理
????????????str_date?=?URLEncoder.encode(str_date,?"utf-8");
????????????Cookie?cookie?=?new?Cookie("lastTime",str_date);
????????????//設(shè)置Cookie的存活時間
????????????cookie.setMaxAge(60*60);????//一小時
????????????response.addCookie(cookie);
????????????response.getWriter().write("您好,歡迎你首次訪問
");
????????}
????}
????protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
????????this.doPost(request,?response);
????}
}
1.5 JSP總結(jié)
JSP 概念
Java Server Page: Java服務(wù)端頁面,可以理解為一個特殊的頁面,既可以定義html標(biāo)簽,又可以定義Java代碼,用于簡化書寫。
JSP 原理
JSP 本質(zhì)就是一個Servlet ,在啟動項(xiàng)目訪問 JSP 頁面時,我們的Tomcat容器空間中,會將JSP 文件 編譯為一個 .java 文件 然后Javac編譯為一個.class文件 提供訪問。我們可以打開 index.jsp 經(jīng)過編譯 后的 index_jsp.java , 發(fā)現(xiàn)其繼承 自?org.apache.jasper.runtime.HttpJspBase,而 HttpJspBase 繼承自 HttpServlet, 所以說 JSP 本質(zhì) 就是 Servlet
而這個Servlet 的 service 方法 做的事情 就是將我們的返回數(shù)據(jù),通過輸出流 拼接html 標(biāo)簽 ,從而實(shí)現(xiàn)頁面展示效果。
JSP 腳本
<% Java代碼 %> 定義的 Java代碼在Jsp 轉(zhuǎn)換成 java后,位于Service方法中,Service 方法中可以怎么寫,該腳本語法就可以怎么寫。 <%! Java代碼 %> 定義的 Java代碼 在Jsp 轉(zhuǎn)換成 java后,位于類的成員變量中,但這種一般用得比較少。因?yàn)閟ervlet是單例的,多個線程同時訪問,如果值有修改,其他線程獲取時會存在線程安全問題,Servlet中一般推薦定義局部變量。 <%= Java代碼 %> 定義的Java代碼,會輸出到頁面上。 out.print()可以輸出什么,該腳本就可以定義什么
JSP內(nèi)置對象
在 JSP 頁面不需要獲取和創(chuàng)建,可以直接使用的對象
JSP一共有9個內(nèi)置對象:
request response out:字符輸出流對象,可以將數(shù)據(jù)輸出到頁面上。和response.getWriter()類似 response.getWriter() 和 out.write 的區(qū)別:tomcat 服務(wù)器真正給客戶端做出響應(yīng)之前,會先找 response 緩沖區(qū)數(shù)據(jù),再找 out 緩沖區(qū)數(shù)據(jù)。response.getWriter() 數(shù)據(jù)輸出永遠(yuǎn)再 out.write() 之前
1.6 Session
概念
服務(wù)器端的會話技術(shù),在一次會話的多次請求間共享數(shù)據(jù),將數(shù)據(jù)保存在服務(wù)器端的對象中,HttpSession
快速入門
獲取 HttpSession 對象: HttpSession session = request.getSession(); 使用 HttpSession 對象: Object getAttribute(String name); void setAttribute(String name, Object value); void removeAttribute(String name); 案例編碼 SessionDemo1設(shè)置Session數(shù)據(jù)
package?org.taoguoguo.session;
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?javax.servlet.http.HttpSession;
import?java.io.IOException;
/**
@author?taoguoguo
@description?${NAME}
@website?https://www.cnblogs.com/doondo
@create?2020-11-23?23:00
*/
@WebServlet("/sessionDemo1")
public?class?SessionDemo1?extends?HttpServlet?{
?protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
?????//使用Session共享數(shù)據(jù)
?????//1.獲取Session
?????HttpSession?session?=?request.getSession();
?????//2.存儲數(shù)據(jù)
?????session.setAttribute("msg","hello?session");
?}
?protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
?????this.doPost(request,?response);
?}
}
SessionDemo2獲取Session數(shù)據(jù)
package?org.taoguoguo.session;
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?javax.servlet.http.HttpSession;
import?java.io.IOException;
/**
*?@author?taoguoguo
*?@description?${NAME}
*?@website?https://www.cnblogs.com/doondo
*?@create?2020-11-23?23:00
*/
@WebServlet("/sessionDemo2")
public?class?SessionDemo2?extends?HttpServlet?{
???protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
???????//使用Session獲取數(shù)據(jù)
???????//1.獲取Session
???????HttpSession?session?=?request.getSession();
???????//2.存儲數(shù)據(jù)
???????Object?msg?=?session.getAttribute("msg");
???????System.out.println(msg);
???}
???protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
???????this.doPost(request,?response);
???}
}
Session實(shí)現(xiàn)原理
思考SessionDemo1 和 SessionDemo2 是不是同一個Session呢? 答案是肯定的同一個。不然怎么從Session中獲取到數(shù)據(jù)呢?
Session的實(shí)現(xiàn)是依賴于Cookie的,當(dāng)服務(wù)器創(chuàng)建一個Session時,會在內(nèi)部記錄一個SessionId,而服務(wù)器響應(yīng)數(shù)據(jù)給客戶端時,會在響應(yīng)頭中設(shè)置Cookie: JseesionId:sessionid值的方式,將創(chuàng)建的SessionId 發(fā)放到客戶端。而客戶端再次請求服務(wù)器時,會將客戶端的Cookie:JessionId 發(fā)送到服務(wù)端,服務(wù)端根據(jù)這個SessionId,就能獲取到對應(yīng)ID的Session對象,拿到會話中的數(shù)據(jù)。
Session的細(xì)節(jié)
當(dāng)客戶端關(guān)閉后,服務(wù)器不關(guān)閉,兩次獲取的Session是否為同一個?
默認(rèn)情況下,不是。因?yàn)橐淮涡碌臅挘瑥膔equest中獲取的Session對象的SessionId是不一樣的。 如果需要相同,可以通過創(chuàng)建Cookie,鍵為 JESSIONID,設(shè)置最大存活時間,讓Cookie持久化的方法來實(shí)現(xiàn)。因?yàn)镾ession是基于Cookie來是實(shí)現(xiàn)的,只要Cookie每次攜帶的JessionId相同,就是同一個Session。實(shí)例代碼:
package?org.taoguoguo.session;
import?javax.servlet.ServletException;
import?javax.servlet.annotation.WebServlet;
import?javax.servlet.http.*;
import?java.io.IOException;
/**
*?@author?taoguoguo
*?@description?${NAME}
*?@create?2020-11-23?23:00
*/
@WebServlet("/sessionDemo3")
public?class?SessionDemo3?extends?HttpServlet?{
???protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
???????//使用Session獲取數(shù)據(jù)
???????//1.獲取Session
???????HttpSession?session?=?request.getSession();
???????System.out.println(session);
???????//期望客戶端關(guān)閉后,session也能相同
???????Cookie?cookie?=?new?Cookie("JESSIONID",session.getId());
???????cookie.setMaxAge(60*60);
???????response.addCookie(cookie);
???}
???protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
???????this.doPost(request,?response);
???}
}
客戶端不關(guān)閉,服務(wù)器關(guān)閉,兩次獲取的Session是同一個嗎?不是同一個,因?yàn)镾ession對象是由服務(wù)器創(chuàng)建的,服務(wù)器關(guān)閉,Session對象就內(nèi)存就清空了。重啟后新創(chuàng)建的Session的地址值是隨機(jī)分配的。但現(xiàn)在有個場景,假設(shè)用戶在基于Session實(shí)現(xiàn)的購物車中,添加了N件商品,但準(zhǔn)備下單時接到電話。接電話過程中,服務(wù)器重啟。待電話結(jié)束后,點(diǎn)擊下單,Session由于不是同一個對象數(shù)據(jù)丟失了該如何處理?
服務(wù)器Tomcat已經(jīng)實(shí)現(xiàn)了Session的鈍化和活化。將項(xiàng)目打成 war 包部署到Tomcat的 webapp 目錄下,正常啟動Tomcat,訪問存儲Session的Servlet, 當(dāng)Tomcat正常關(guān)閉時,Tomcat 的 work 目錄會產(chǎn)生一個?
SESSIONS.ser?的文件,持久化Session的數(shù)據(jù),當(dāng)Tomcat再次啟動時,會將SESSION.ser?文件數(shù)據(jù)加載到Tomcat內(nèi)存中序列化為Session對象,從而拿到Session存儲的數(shù)據(jù)。但I(xiàn)DEA 編輯器只實(shí)現(xiàn)的Session的鈍化,沒有實(shí)現(xiàn)Session的活化。IDEA在啟動Tomcat時,會先刪除 work 目錄,然后新建work 目錄,獲取不到Session.ser?文件,及其存儲的數(shù)據(jù)。在服務(wù)器啟動后,將Session文件轉(zhuǎn)換為內(nèi)存中的Session對象即可 在服務(wù)器正常關(guān)閉之前,將Session對象序列化到硬盤上 Session的鈍化: Session的活化: Session什么時候被銷毀?
服務(wù)器關(guān)閉 session 對象調(diào)用 invalidate() 方法 session的默認(rèn)失效時間為30分鐘 Tomcat 的 web.xml 選擇性配置 設(shè)置Session時長:
???30
Session的特點(diǎn)
Session用于存儲一次會話的多次請求的數(shù)據(jù),存在服務(wù)器端。 Session可以存儲任意類型,任意大小的數(shù)據(jù)。
Session與Cookie的區(qū)別
Session 存儲數(shù)據(jù)在服務(wù)端,Cookie在客戶端 Session沒有數(shù)據(jù)大小限制,Cookie有大小限制 Session數(shù)據(jù)存在服務(wù)端較為安全,Cookie相對不安全
1.7 Session案例
案例需求
訪問帶有驗(yàn)證碼的登錄頁面,用戶輸入用戶名,密碼,及驗(yàn)證碼
如果用戶名和密碼輸入有誤,則跳轉(zhuǎn)至登錄頁面,提示:用戶名或密碼錯誤 如果驗(yàn)證碼錯誤,跳轉(zhuǎn)登錄頁面,提示:驗(yàn)證碼錯誤 如果全部輸入正確,則跳轉(zhuǎn)至主頁 success.jsp 顯示:用戶名,歡迎您
案例編碼:
驗(yàn)證碼Servlet
package?org.taoguoguo.servlet;
import?javax.imageio.ImageIO;
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.awt.*;
import?java.awt.image.BufferedImage;
import?java.io.IOException;
import?java.util.Random;
/**
*?@author?taoguoguo
*?@description?${NAME}
*?@website?https://www.cnblogs.com/doondo
*?@create?2020-11-24?23:33
*/
@WebServlet("/checkCodeServlet")
public?class?CheckCodeServlet?extends?HttpServlet?{
?protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
?????//1.創(chuàng)建一個圖像緩沖區(qū)對象
?????int?width?=?100;
?????int?height?=?50;
?????BufferedImage?image?=?new?BufferedImage(width,?height,?BufferedImage.TYPE_3BYTE_BGR);
?????//2.美化圖片
?????//2.1填充背景色
?????Graphics?graphics?=?image.getGraphics();????//畫筆對象
?????graphics.setColor(Color.pink);??//設(shè)置畫筆顏色
?????graphics.fillRect(0,0,width,height);
?????//2.2畫邊框
?????graphics.setColor(Color.blue);
?????graphics.drawRect(??0,0,width-1,height-1);
?????//2.3寫驗(yàn)證碼
?????String?code?=?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456789";
?????//生成隨機(jī)角標(biāo)
?????Random?random?=?new?Random();
?????StringBuilder?builder?=?new?StringBuilder();
?????for?(int?i=1;?i<=4;?i++){
?????????int?index?=?random.nextInt(code.length());
?????????//獲取字符
?????????char?c?=?code.charAt(index);
?????????builder.append(c);
?????????graphics.drawString(String.valueOf(c),width/5*i,height/2);
?????}
?????//將驗(yàn)證碼存入到Session
?????String?checkCode_session?=?builder.toString();
?????request.getSession().setAttribute("checkCode_session",checkCode_session);
?????//2.4畫干擾線
?????graphics.setColor(Color.green);
?????for(int?i=0;?i<10;?i++){
?????????int?x1?=?random.nextInt(width);
?????????int?y1?=?random.nextInt(height);
?????????int?x2?=?random.nextInt(width);
?????????int?y2?=?random.nextInt(height);
?????????graphics.drawLine(x1,y1,x2,y2);
?????}
?????//3.將圖片輸出到頁面展示
?????ImageIO.write(image,"jpg",response.getOutputStream());
?}
?protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
?????this.doPost(request,?response);
?}
}
login.jsp
<%--
?User:?taoGuoGuo
?Date:?2020/11/24
?Time:?23:36
?WebSite:?https://www.cnblogs.com/doondo/
--%>
<%@?page?contentType="text/html;charset=UTF-8"?language="java"?%>
???login
???
???
???
