1. Servlet簡(jiǎn)介
Servlet(Server Applet)是Java Servlet的簡(jiǎn)稱诵次,稱為小服務(wù)程序或服務(wù)連接器愈魏,用Java編寫的服務(wù)器端程序煤傍,具有獨(dú)立于平臺(tái)和協(xié)議的特性区丑,主要功能在于交互式地瀏覽和生成數(shù)據(jù)牵现,生成動(dòng)態(tài)Web內(nèi)容持痰。
2. Servlet基本使用*
2.1 添加依賴
- 方式1:將TOMCAT_HOME\lib\servlet-api.jar導(dǎo)入到模塊中的web\lib
- 方式2:在項(xiàng)目結(jié)構(gòu)中給該模塊的Dependencies添加Library灶搜,然后選擇相應(yīng)Tomcat配置
2.2 創(chuàng)建javax.servlet.Servlet實(shí)現(xiàn)類
- 一般可以繼承HttpServlet
package com.liu2m.servlet;
import javax.servlet.*;
import java.io.IOException;
public class ServletImpl implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
servletResponse.getWriter().write("hello, servlet" + System.currentTimeMillis());
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
2.3 配置Servlet實(shí)現(xiàn)類的映射路徑
-
方式1:在web.xml的web-app標(biāo)簽里配置Servlet實(shí)現(xiàn)類的映射路徑
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!--配置Servlet實(shí)現(xiàn)類的信息--> <servlet> <!--配置Servlet名稱,可以任意工窍,但建議與類名相同--> <servlet-name>ServletImpl</servlet-name> <!--配置Servlet類的全路徑--> <servlet-class>com.liu2m.servlet.ServletImpl</servlet-class> </servlet> <!--配置Servlet映射關(guān)系--> <servlet-mapping> <!--配置關(guān)聯(lián)的Servlet名稱割卖,要和上面配置的實(shí)現(xiàn)類信息相對(duì)應(yīng)--> <servlet-name>ServletImpl</servlet-name> <!--配置訪問路徑: 絕對(duì)匹配*:/path 目錄匹配:/a/b/* 擴(kuò)展名匹配:*.后綴 目錄匹配和擴(kuò)展名匹配不能同時(shí)使用 --> <url-pattern>/impl</url-pattern> </servlet-mapping> </web-app>
-
方式2:Servlet3.0以上支持注解配置,可以不用web.xml了患雏;注解配置*:在Servlet實(shí)現(xiàn)類上使用@WebServlet("資源路徑")注解
@WebServlet(urlPatterns = {"/uri1", "/uri2", "/uri3"})
- 啟動(dòng)Tomcat后Tomcat引擎執(zhí)行的操作:
- 創(chuàng)建ServerSocket對(duì)象究珊,開啟指定端口
- Tomcat引擎掃描webapps目錄,根據(jù)瀏覽器的URL讀取指定項(xiàng)目中的web.xml
- Tomcat引擎掃描所有Servlet接口實(shí)現(xiàn)類纵苛,獲取類上的注解和注解的屬性值
- 當(dāng)Tomcat引擎接受到客戶端瀏覽器的請(qǐng)求后剿涮,會(huì)解析請(qǐng)求URL路徑,獲取訪問的Servlet的資源路徑
- 創(chuàng)建Request對(duì)象和Response對(duì)象
- 依次找servlet-mapping下的url-pattern攻人、servlet-name取试;servlet下的servlet-name、servlet-class
- 根據(jù)反射創(chuàng)建servlet-class指定的對(duì)象怀吻,調(diào)用service方法瞬浓,傳遞Request對(duì)象和Response對(duì)象
- 運(yùn)行service方法,將數(shù)據(jù)寫在Response對(duì)象的緩沖區(qū)中
- service方法結(jié)束后蓬坡,Tomcat引擎從Response對(duì)象的緩沖區(qū)中取出數(shù)據(jù)猿棉,組裝HTTP響應(yīng)信息回傳給瀏覽器
3. Servlet對(duì)象生命周期*
-
void init(ServletConfig servletConfig)方法:Servlet對(duì)象初始化方法,在對(duì)象被創(chuàng)建后調(diào)用
只執(zhí)行一次(說明一個(gè)Servlet在內(nèi)存中只存在一個(gè)對(duì)象)
-
默認(rèn)情況下屑咳,第一次被訪問時(shí)Servlet被創(chuàng)建萨赁,但也可以在web.xml的<servlet>標(biāo)簽下配置Servlet的創(chuàng)建時(shí)機(jī)
<load-on-startup>負(fù)數(shù)</load-on-startup>:第一次被訪問時(shí)創(chuàng)建 <load-on-startup>0或正整數(shù)</load-on-startup>:在服務(wù)器啟動(dòng)時(shí)創(chuàng)建 整數(shù)越小,啟動(dòng)優(yōu)先級(jí)越高
Servlet是單例的兆龙,多個(gè)用戶同時(shí)訪問時(shí)杖爽,可能存在線程安全問題;因此盡量避免在Servlet中使用共享變量
ServletConfig對(duì)象可以獲取Servlet的初始化參數(shù)
service(servletRequest, servletResponse):客戶端訪問一次就執(zhí)行一次
-
void destroy():Servlet對(duì)象銷毀之前調(diào)用
- 只執(zhí)行一次
- 當(dāng)Servlet從服務(wù)器中移除或者服務(wù)器正常關(guān)閉的時(shí)候Servlet對(duì)象被銷毀,在銷毀前會(huì)執(zhí)行destroy方法
- 一個(gè)Servlet在運(yùn)行service()方法時(shí)可能會(huì)產(chǎn)生其他的線程慰安,因此需要確認(rèn)在調(diào)用destroy()方法時(shí)腋寨,這些線程已經(jīng)終止或完成
4. ServletContext*
- 在Tomcat中的Web項(xiàng)目也叫Web應(yīng)用程序;Web應(yīng)用程序?qū)ο骃ervletContext可以描述整個(gè)Web應(yīng)用程序
- 每個(gè)Web應(yīng)用程序只有一個(gè)ServletContext對(duì)象化焕,在Tomcat啟動(dòng)時(shí)就已經(jīng)被創(chuàng)建好了
- Tomcat啟動(dòng)時(shí)會(huì)掃描webapps萄窜,找所有Web程序并為其創(chuàng)建ServletContext
- ServletContext是接口,實(shí)現(xiàn)類由Tomcat引擎提供
- 在ServletContext對(duì)象中存儲(chǔ)的任何數(shù)據(jù)撒桨,在整個(gè)Web應(yīng)用程序中全有效
-
獲取ServletContext實(shí)現(xiàn)類對(duì)象:
- GenericServlet抽象類的方法:getServletContext()
- ServletConfig接口方法:getServletContext()
-
ServletContext對(duì)象作用:
-
作為域?qū)ο笫苟鄠€(gè)Servlet可以共享數(shù)據(jù)*:
// 給ServletContext對(duì)象的Map中添加鍵值對(duì) void setAttribute(String name, Object object) // 從ServletContext對(duì)象的Map中根據(jù)鍵取值 Object getAttribute(String name) // 從ServletContext對(duì)象的Map中根據(jù)鍵移除鍵值對(duì) void removeAttribute(String name)
-
獲取web項(xiàng)目中文件的真實(shí)路徑查刻,以及將web項(xiàng)目中的文件轉(zhuǎn)成流*:
// 根據(jù)資源名稱獲取資源的絕對(duì)路徑,傳遞相對(duì)于webapps下項(xiàng)目的路徑 String getRealPath(String path) // 返回指定文件的流 InputStream getResourceAsStream(String path)
-
獲取全局的初始化參數(shù):
// 獲取初始化參數(shù)值元莫,傳遞參數(shù)名;如果參數(shù)不存在蝶押,則返回null String getInitParameter(String name) 初始化參數(shù)配置在web.xml踱蠢,如: <context-param> <!--參數(shù)的鍵--> <param-name>key</param-name> <!--參數(shù)的值--> <param-value>value</param-value> </context-param>
-
獲取文件的MIME類型:
// 返回指定文件的MIME類型,如果MIME類型未知棋电,則返回null String getMimeType(String file)
-
5. HttpServlet
- GenericServlet抽象類繼承了Servlet接口茎截;HttpServlet抽象類繼承了GenericServlet
GenericServlet:將Servlet接口中其他的方法做了默認(rèn)空實(shí)現(xiàn),只將service()方法作為抽象
-
HttpServlet:對(duì)http協(xié)議的一種封裝赶盔,簡(jiǎn)化操作
定義類繼承HttpServlet
重寫doGet/doPost方法
-
HttpServlet有兩個(gè)service方法企锌,先調(diào)用重寫的父類方法,將其參數(shù)向下轉(zhuǎn)型為自己的方法參數(shù)類型于未,然后傳遞給自己的方法
父類方法:void service(ServletRequest req, ServletResponse res) 自己方法:void service(HttpServletRequest req, HttpServletResponse resp)
- 通乘涸埽可以使用同一段代碼來處理同一個(gè)請(qǐng)求的不同請(qǐng)求方式,如在doGet中調(diào)用doPost或在doPost中調(diào)用doGet
6. ServletRequest
6.1 獲取請(qǐng)求行
-
ServletRequest方法:
// 獲取客戶端的IP地址* String getRemoteAddr() // 獲取服務(wù)端的端口號(hào) int getServerPort()
-
HttpServletRequest方法:
// 獲取請(qǐng)求方式* String getMethod() // 獲取站點(diǎn)的根路徑(Application context)* String getContextPath() // 獲取請(qǐng)求的URI* // 如:/servlet/request String getRequestURI() // 獲取請(qǐng)求的URL // 如:http://localhost:8080/servlet/request StringBuffer getRequestURL() // 獲取全部請(qǐng)求參數(shù)(get請(qǐng)求的URL中烘浦,?后面的內(nèi)容) String getQueryString()
6.2 獲取請(qǐng)求頭*
-
HttpServletRequest方法:
// User-Agent:瀏覽器的信息 // Referer:該請(qǐng)求來自哪里抖坪;可以防盜鏈、防止惡意請(qǐng)求 // Content-Type:指示資源的MIME類型 // Authorization:HTTP授權(quán)的授權(quán)證書 String getHeader(String name)
6.3 獲取請(qǐng)求體(獲取請(qǐng)求參數(shù))*
-
ServletRequest方法:
// 獲得指定參數(shù)名對(duì)應(yīng)的值闷叉;如果沒有則返回null擦俐,如果有多個(gè)則獲得第一個(gè) String getParameter(String name) // 獲得指定參數(shù)名對(duì)應(yīng)的所有的值;此方法專門為復(fù)選框提供 String[] getParameterValues(String name) // 獲得所有的請(qǐng)求參數(shù)握侧;key為參數(shù)名蚯瞧;value為key對(duì)應(yīng)的所有值 Map<String, String[]> getParameterMap() // 設(shè)置請(qǐng)求體的編碼 // Tomcat8之前,get和post請(qǐng)求都會(huì)發(fā)生中文亂碼 // Tomcat8+品擎,get不會(huì)發(fā)生中文亂碼埋合,post還會(huì)發(fā)生中文亂碼 // 解決中文亂碼:在獲取請(qǐng)求參數(shù)之前,設(shè)置請(qǐng)求體的編碼為"UTF-8" void setCharacterEncoding(String env)
-
使用BeanUtils將請(qǐng)求參數(shù)封裝到一個(gè)JavaBean中:
創(chuàng)建一個(gè)POJO類萄传,類中的屬性名和請(qǐng)求參數(shù)名相對(duì)應(yīng) 使用BeanUtils需要導(dǎo)入jar包饥悴,如: commons-beanutils-1.8.3.jar commons-beanutils-bean-collections-1.8.3.jar commons-logging-1.2.jar BeanUtils類靜態(tài)方法: // 參數(shù)1為一個(gè)JavaBean對(duì)象 // 參數(shù)2為getParameterMap獲取的Map<String, String[]> static void populate(Object bean, Map<String,? extends Object> properties)
6.4 作為域?qū)ο蠊蚕頂?shù)據(jù)*
- ServletRequest只能在同一次請(qǐng)求中作為域?qū)ο蠊蚕頂?shù)據(jù),可以配合請(qǐng)求轉(zhuǎn)發(fā)一起使用
-
ServletRequest方法:
Object getAttribute(String name) void setAttribute(String name, Object o) void removeAttribute(String name)
6.5 請(qǐng)求轉(zhuǎn)發(fā)*
- 請(qǐng)求轉(zhuǎn)發(fā)特點(diǎn):
- 請(qǐng)求轉(zhuǎn)發(fā)的跳轉(zhuǎn)是由服務(wù)器發(fā)起的,因此跳轉(zhuǎn)操作不會(huì)發(fā)起新的請(qǐng)求西设,瀏覽器地址欄不會(huì)發(fā)生變化
- 請(qǐng)求轉(zhuǎn)發(fā)只能跳轉(zhuǎn)到本項(xiàng)目中的任意資源瓣铣,包括WEB-INF中的資源,不能跳轉(zhuǎn)到其他地方
- 請(qǐng)求轉(zhuǎn)發(fā)可以和ServletRequest域?qū)ο笠黄鹗褂?/li>
-
ServletRequest方法:
// 獲取一個(gè)指定路徑資源的RequestDispatcher對(duì)象 RequestDispatcher getRequestDispatcher(String path) RequestDispatcher的方法: // 將請(qǐng)求從一個(gè)servlet轉(zhuǎn)發(fā)到服務(wù)器上的另一個(gè)資源 void forward(ServletRequest request, ServletResponse response) 請(qǐng)求轉(zhuǎn)發(fā)使用示例: request.getRequestDispatcher("/本項(xiàng)目資源路徑").forward(request, response);
7. ServletResponse
7.1 設(shè)置狀態(tài)行
-
HttpServletResponse方法:
// 設(shè)置此響應(yīng)的狀態(tài)碼 void setStatus(int sc)
7.2 設(shè)置響應(yīng)頭
-
HttpServletResponse方法:
// 用給定名稱和值設(shè)置響應(yīng)頭贷揽。如果已經(jīng)設(shè)置了頭棠笑,則新值將重寫以前的值 // Refresh:指定秒之后重定向,格式:秒數(shù); url=網(wǎng)址 // Location:服務(wù)器告訴瀏覽器重定向到Location指定的URL // Content-Disposition:指示客戶端下載文件禽绪,格式:attachment;filename=文件名 // Content-Type:設(shè)置響應(yīng)內(nèi)容的MIME類型 void setHeader(String name, String value) // 設(shè)置將要發(fā)送到客戶端的響應(yīng)的內(nèi)容類型 void setContentType(String type)
7.3 設(shè)置響應(yīng)體
-
ServletResponse方法:
// 返回適用于在響應(yīng)中編寫二進(jìn)制數(shù)據(jù)的輸出流 ServletOutputStream getOutputStream() // 返回可將字符文本發(fā)送到客戶端的PrintWriter對(duì)象 PrintWriter getWriter() 以上兩個(gè)流是互斥的蓖救,頁面輸出只能使用其中的一個(gè)流 解決字符流輸出的中文亂碼: 在響應(yīng)之前設(shè)置: response.setContentType("text/html;charset=UTF-8");
-
瀏覽器下載文件思路:
獲取文件名
-
設(shè)置響應(yīng)報(bào)文的Content-Disposition,并將文件名編碼印屁;不同瀏覽器請(qǐng)求頭內(nèi)容的編碼循捺、解碼方式不同
java.net.URLEncoder類靜態(tài)方法: // 使用特定的編碼方案將字符串轉(zhuǎn)換為application/x-www-form-urlencoded格式 static String encode(String s, String enc)
使用ServletContext對(duì)象獲取文件的MIME類型,并設(shè)置為響應(yīng)報(bào)文的Content-Type
使用ServletContext對(duì)象獲取指定文件名的輸入流is
通過response獲取輸出流os
將is文件復(fù)制到os
關(guān)閉os和is
7.4 請(qǐng)求重定向
- 請(qǐng)求重定向特點(diǎn):
- 重定向的跳轉(zhuǎn)是由瀏覽器發(fā)起的雄人,因此跳轉(zhuǎn)操作會(huì)發(fā)起新的請(qǐng)求从橘,瀏覽器地址欄會(huì)變成跳轉(zhuǎn)到的地址
- 重定向跳轉(zhuǎn)可以跳轉(zhuǎn)到任意地方(訪問另一個(gè)項(xiàng)目中的資源時(shí)要使用完整的URL),但不能跳轉(zhuǎn)到WEB-INF中的資源
- 重定向跳轉(zhuǎn)不能和ServletRequest域?qū)ο笠黄鹗褂?/li>
-
HttpServletResponse方法:
// 使用指定重定向URL將臨時(shí)重定向響應(yīng)發(fā)送到客戶端 void sendRedirect(String location)
8. 會(huì)話
- 從打開瀏覽器訪問某個(gè)站點(diǎn)础钠,到關(guān)閉瀏覽器的整個(gè)過程恰力,稱為一次會(huì)話
- 會(huì)話技術(shù)就是記錄一次會(huì)話中客戶端的狀態(tài)與數(shù)據(jù);會(huì)話技術(shù)分為Cookie和Session:
- Cookie:將一次會(huì)話的數(shù)據(jù)存儲(chǔ)在瀏覽器端旗吁;大小和個(gè)數(shù)都有限制踩萎;只能存儲(chǔ)字符串且不支持中文;不是很安全
- Session:將一次會(huì)話的數(shù)據(jù)存儲(chǔ)在服務(wù)器端很钓;原則上大小是沒有限制香府;可以存儲(chǔ)基本數(shù)據(jù)類型和對(duì)象;相對(duì)較安全
8.1 Cookie
Cookie是一種客戶端的會(huì)話技術(shù)码倦,它是服務(wù)器存放在瀏覽器的一小份數(shù)據(jù)回还,瀏覽器以后每次訪問該服務(wù)器的時(shí)候都會(huì)將這小份數(shù)據(jù)攜帶到服務(wù)器去
Cookie本質(zhì)是響應(yīng)頭的Set-Cookie和請(qǐng)求頭的Cookie
-
服務(wù)器往瀏覽器存儲(chǔ)Cookie:
- 創(chuàng)建一個(gè)Cookie對(duì)象:new Cookie(String name, String value)
- 設(shè)置Cookie對(duì)象的有效期:void setMaxAge(int expiry)
- -1:代表將Cookie數(shù)據(jù)保存到瀏覽器文件中直到瀏覽器關(guān)閉;默認(rèn)
- 正整數(shù):代表將數(shù)據(jù)以秒為單位保存到保存到磁盤中直到有效期到期
- 0:代表刪除瀏覽器端同name叹洲、同path的Cookie
- 設(shè)置Cookie對(duì)象的有效路徑:void setPath(String uri)
- 將Cookie添加到HttpServletResponse中
-
服務(wù)器從瀏覽器的請(qǐng)求中獲取Cookie:
- 從HttpServletRequest中獲取瀏覽器帶過來的所有Cookie
- 遍歷出每一個(gè)Cookie對(duì)象
- 根據(jù)getName()獲取key柠硕;根據(jù)getValue()獲取值
name和path相同的Cookie會(huì)被覆蓋
當(dāng)Cookie被瀏覽器禁用時(shí),可以將Cookie的信息設(shè)置在URL中響應(yīng)給瀏覽器
-
Cookie類:
常用構(gòu)造: // 創(chuàng)建一個(gè)Cookie對(duì)象(Cookie只能保存字符串运提,且不能保存中文) Cookie(String name, String value) 常用方法: // 獲取Cookie中設(shè)置的key String getName() // 獲取Cookie中設(shè)置的value String getValue() // 設(shè)置Cookie對(duì)象的有效期:expiry是秒 void setMaxAge(int expiry) // 設(shè)置Cookie對(duì)象的有效路徑:uri使用絕對(duì)路徑 // 一般可以設(shè)置為當(dāng)前項(xiàng)目路徑:cookie.setPath(request.getContextPath()) void setPath(String uri)
-
將Cookie添加到HttpServletResponse中的方法:
void addCookie(Cookie cookie)
-
從HttpServletRequest中獲取瀏覽器帶過來的所有Cookie的方法:
Cookie[] getCookies()
-
自定義Cookie工具類:
import javax.servlet.http.Cookie; /** * 自定義Cookie工具類 */ public class CookieUtils { public static Cookie createAndSetCookie(String name, String value, int expiry, String uri) { // 1. 創(chuàng)建一個(gè)Cookie對(duì)象 Cookie cookie = new Cookie(name, value); // 2. 設(shè)置Cookie對(duì)象的有效期 cookie.setMaxAge(expiry); // 3. 設(shè)置Cookie對(duì)象的有效路徑 cookie.setPath(uri); return cookie; } public static String getCookieValue(Cookie[] cookies, String name) { String value = null; if (cookies != null) { for (Cookie cookie : cookies) { if (cookie.getName().equals(name)) { value = cookie.getValue(); break; } } } return value; } }
-
示例:使用Cookie記錄上一次訪問時(shí)間
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 解決響應(yīng)的中文亂碼 response.setContentType("text/html;charset=UTF-8"); // 使用自定義Cookie工具類獲取name對(duì)應(yīng)的值 String name = "lastTime"; Cookie[] cookies = request.getCookies(); String value = CookieUtils.getCookieValue(cookies, name); // 判斷是否為第一次訪問 if (value != null) { response.getWriter().println("上次訪問時(shí)間:" + value); } else { response.getWriter().println("第一次訪問"); } // 設(shè)置Cookie的新值為當(dāng)前時(shí)間 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd/HH:mm:ss"); String currentTime = sdf.format(new Date()); Cookie timeCookie = CookieUtils.createAndSetCookie(name, currentTime, 60 * 60, request.getContextPath()); // 將新創(chuàng)建的Cookie添加到response中 response.addCookie(timeCookie); }
8.2 Session
Session是一種服務(wù)器端的技術(shù)蝗柔。服務(wù)器為每一個(gè)瀏覽器開辟一塊內(nèi)存空間,即Session對(duì)象民泵,每一個(gè)Session對(duì)象都對(duì)應(yīng)一個(gè)JSESSIONID癣丧,服務(wù)器把JSESSIONID存儲(chǔ)到Cookie中,再次訪問的時(shí)候栈妆,瀏覽器把JSESSIONID帶過來胁编,找到對(duì)應(yīng)的Session對(duì)象厢钧。
由于Session就是一個(gè)基于Cookie的域?qū)ο?/strong>,因此其作用范圍默認(rèn)為一次會(huì)話嬉橙;當(dāng)本次會(huì)話結(jié)束后早直,瀏覽器端的Cookie沒有了,但Session對(duì)象還在服務(wù)器中市框;可以手動(dòng)設(shè)置JSESSIONID這個(gè)Cookie的有效時(shí)長(zhǎng)
-
Session對(duì)象銷毀時(shí)機(jī):
- 默認(rèn)閑置30分鐘后銷毀霞扬,也可以調(diào)用HttpSession的setMaxInactiveInterval(int interval)方法修改
- 調(diào)用HttpSession的invalidate()方法銷毀
- 服務(wù)器異常關(guān)閉銷毀
-
Session的執(zhí)行過程:
- 當(dāng)HttpServletRequest調(diào)用getSession()時(shí),會(huì)判斷本次請(qǐng)求中是否有一個(gè)名為JSESSIONID的Cookie
- 如果沒有枫振,則創(chuàng)建Session對(duì)象喻圃,并將該Session對(duì)象的JSESSIONID以Cookie形式響應(yīng)給瀏覽器
- 如果有,則根據(jù)JSESSIONID尋找指定的Session對(duì)象
- 如果指定的Session對(duì)象存在粪滤,則直接使用
- 如果指定的Session對(duì)象銷毀了斧拍,則執(zhí)行第2步
-
HttpServletRequest獲取Session的方法:第一次調(diào)用時(shí)創(chuàng)建session,之后調(diào)用通過sessionId找到Session進(jìn)行使用
HttpSession getSession()
-
HttpSession在一次會(huì)話作為域?qū)ο蟠嫒?shù)據(jù)的方法:
Object getAttribute(String name) void setAttribute(String name, Object value) void removeAttribute(String name)
-
防止表單重復(fù)提交思路:
- 方式1:點(diǎn)擊表單頁面時(shí)杖小,給session中存儲(chǔ)一個(gè)標(biāo)志如subToken肆汹,并設(shè)置給表單頁面,表單提交時(shí)攜帶subToken窍侧,服務(wù)器判斷session中的subToken是否與表單攜帶來的一致县踢,若一致則提交成功并清除session中的subToken转绷,這樣重復(fù)提交時(shí)session中的subToken與表單攜帶來就不一致了
- 方式2:給數(shù)據(jù)庫增加唯一鍵約束伟件,確保數(shù)據(jù)庫只可以添加一條數(shù)據(jù)
- 方式3:提交成功后重定向
- 方式4:使用JavaScript設(shè)置標(biāo)志位,提交后屏蔽提交按鈕
- 方式5:使用AOP自定義切入
-
使用Session校驗(yàn)驗(yàn)證碼思路:
-
創(chuàng)建一個(gè)獲取驗(yàn)證碼并將驗(yàn)證碼的內(nèi)容存儲(chǔ)到session域?qū)ο笾械腟ervlet
1. 導(dǎo)入驗(yàn)證碼jar包议经,如:ValidateCode.jar 2. 在Servlet中創(chuàng)建驗(yàn)證碼并返回給瀏覽器 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 創(chuàng)建驗(yàn)證碼圖片 ValidateCode validateCode = new ValidateCode(200, 50, 4, 10); // 2. 將驗(yàn)證碼的內(nèi)容存儲(chǔ)到session域?qū)ο笾? String code = validateCode.getCode(); request.getSession().setAttribute("code", code); // 3. 將驗(yàn)證碼圖片通過response的字節(jié)流輸出到瀏覽器 validateCode.write(response.getOutputStream()); // 4. 在img的src屬性中寫訪問這個(gè)Servlet的路徑 }
創(chuàng)建html頁面斧账,在img的src屬性中寫訪問步驟1中Servlet的路徑
在校驗(yàn)Servlet中,獲取html頁面輸入的驗(yàn)證碼內(nèi)容并和Session中的驗(yàn)證碼內(nèi)容進(jìn)行忽略大小寫的比較
切換圖片即重新設(shè)置img的src屬性煞肾,可以使用js的點(diǎn)擊事件完成咧织;為了防止緩存,可以在src的url后面加上請(qǐng)求參數(shù)籍救,讓每次的url不同
-
9. Servlet抽取思想
Servlet抽取思想:在一個(gè)Servlet實(shí)現(xiàn)類中自定義不同方法來處理不同請(qǐng)求
- 在每個(gè)請(qǐng)求中添加參數(shù)來標(biāo)識(shí)要調(diào)用的方法
- 獲取客戶端要調(diào)用的方法名
- 使用反射习绢,根據(jù)方法名獲取方法
- 執(zhí)行獲取到的方法
try {
// 獲取客戶端要調(diào)用的方法名
String methodName = request.getParameter("method");
// 使用反射,根據(jù)方法名獲取方法
Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
// 執(zhí)行獲取到的方法蝙昙;執(zhí)行的是this的方法
method.invoke(this, request, response);
} catch (Exception e) {
e.printStackTrace();
}