4另凌、實(shí)現(xiàn)重定向
一個(gè)web資源B收到客戶端A請(qǐng)求后蚁鳖,B他會(huì)通知A客戶端去訪問另外一個(gè)web資源C藻雌,這個(gè)過程叫重定向
常見場景:
- 用戶登錄
使用方法:
void sendRedirect(String var1) throws IOException;
測試:.
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 請(qǐng)求重定向
// 重定向的地址前要加上當(dāng)前當(dāng)前項(xiàng)目的路徑,否則會(huì)找不到重定向后的網(wǎng)頁
// 若不加會(huì)跳轉(zhuǎn)到: http://localhost:8080/img而不是http://localhost:8080/response/img
// 拆解: sendRedirect是封裝后的setHeader和setStatus
/*
// 修改響應(yīng)頭消息為重定位后的位置
resp.setHeader("Location","/response/img");
// 修改響應(yīng)的狀態(tài)碼
resp.setStatus(302);
*/
resp.sendRedirect("/response/img");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
面試題:請(qǐng)你聊聊重定向和轉(zhuǎn)發(fā)的區(qū)別栅贴?
相同點(diǎn)
- 頁面都會(huì)實(shí)現(xiàn)跳轉(zhuǎn)
不同點(diǎn)
- 請(qǐng)求轉(zhuǎn)發(fā)的時(shí)候著瓶,url地址欄不會(huì)產(chǎn)生變化
- 重定向時(shí)候瞳秽,url地址欄會(huì)發(fā)生變化瓣履;
5、簡單實(shí)現(xiàn)登錄重定向
表單提交后會(huì)進(jìn)入requestest里面 走doget方法 然后重定向到success
index.jsp
<html>
<body>
<h2>Hello World!</h2>
<%--這里提交的路徑,需要尋找到項(xiàng)目的路徑--%>
<%--${pageContext.request.contextPath}代表當(dāng)前的項(xiàng)目--%>
<form action="${pageContext.request.contextPath}/login" method="get">
用戶名: <input type="text" name="username"><br>
密碼: <input type="pwd" name="password"><br>
<%-- 提交表單--%>
<input type="submit">
</form>
<%--修改網(wǎng)頁編碼格式--%>
<%@ page contentType="text/html;charset=utf-8" %>
</body>
</html>
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 處理請(qǐng)求 從請(qǐng)求中獲取參數(shù)
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username + ":" + password);
// 將響應(yīng)重定向的時(shí)候一定要注意添加web項(xiàng)目路徑問題,否則會(huì)404(找不到網(wǎng)頁)
resp.sendRedirect("/response/success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
<servlet>
<servlet-name>request</servlet-name>
<servlet-class>com.tiga.servlet.RequestTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>request</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
請(qǐng)求轉(zhuǎn)發(fā)保留第一次請(qǐng)求時(shí)的數(shù)據(jù),重定向不保留
請(qǐng)求轉(zhuǎn)發(fā)是在服務(wù)端內(nèi)部跳轉(zhuǎn)(一次請(qǐng)求一次響應(yīng)),重定向的跳轉(zhuǎn)是把第一次請(qǐng)求的響應(yīng)返回給客戶端,讓客戶端重新發(fā)起一次跳轉(zhuǎn),(兩次請(qǐng)求兩次響應(yīng))
6.7练俐、HttpServletRequest
HttpServletRequest代表客戶端的請(qǐng)求袖迎,用戶通過Http協(xié)議訪問服務(wù)器,HTTP請(qǐng)求中的所有信息會(huì)被封裝到HttpServletRequest腺晾,通過這個(gè)HttpServletRequest的方法燕锥,獲得客戶端的所有信息;
獲取參數(shù)悯蝉,請(qǐng)求轉(zhuǎn)發(fā)
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 修改請(qǐng)求和響應(yīng)的編碼格式
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
// 通過請(qǐng)求獲取參數(shù)
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbys = req.getParameterValues("hobbys");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys));
// 通過請(qǐng)求轉(zhuǎn)發(fā)
System.out.println(req.getContextPath());
// getContextPath(): 獲取項(xiàng)目路徑
// 這里的 / : 代表當(dāng)前的webapp(web應(yīng)用), 請(qǐng)求轉(zhuǎn)發(fā)不用加項(xiàng)目名
req.getRequestDispatcher("/success.jsp").forward(req,resp);
// 修改響應(yīng)編碼格式
resp.setCharacterEncoding("utf-8");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
面試題:請(qǐng)你聊聊重定向和轉(zhuǎn)發(fā)的區(qū)別归形?
相同點(diǎn)
- 頁面都會(huì)實(shí)現(xiàn)跳轉(zhuǎn)
不同點(diǎn)
- 請(qǐng)求轉(zhuǎn)發(fā)的時(shí)候,url不會(huì)產(chǎn)生變化 307
- 重定向時(shí)候鼻由,url地址欄會(huì)發(fā)生變化暇榴; 302
重定向路徑需要寫項(xiàng)目名 請(qǐng)求轉(zhuǎn)發(fā)不需要寫
7、Cookie蕉世、Session
Cookie就是餅干蔼紧!很好理解的,就是你第一次訪問我我會(huì)攔截你狠轻,然后我給你分一塊餅干奸例,當(dāng)你有了這個(gè)餅干就相當(dāng)于有了一個(gè)令牌,以后訪問不會(huì)攔截你
客戶端:學(xué)生上學(xué)有發(fā)票(cookie) 服務(wù)器:學(xué)校有記錄(session)
7.1哈误、會(huì)話
會(huì)話:用戶打開一個(gè)瀏覽器哩至,點(diǎn)擊了很多超鏈接,訪問多個(gè)web資源蜜自,關(guān)閉瀏覽器菩貌,這個(gè)過程可以稱之為會(huì)話;
有狀態(tài)會(huì)話:一個(gè)同學(xué)來過教室重荠,下次再來教室箭阶,我們會(huì)知道這個(gè)同學(xué)纪铺,曾經(jīng)來過澜倦,稱之為有狀態(tài)會(huì)話;就是記錄了你的一些東西
客戶端 服務(wù)端
- 服務(wù)端給客戶端一個(gè) 信件嫩絮,客戶端下次訪問服務(wù)端帶上信件就可以了婆殿; cookie
- 服務(wù)器登記你來過了诈乒,下次你來的時(shí)候我來匹配你; seesion
7.2婆芦、保存會(huì)話的兩種技術(shù)
cookie
- 客戶端技術(shù) (響應(yīng)怕磨,請(qǐng)求)
session
- 服務(wù)器技術(shù),利用這個(gè)技術(shù)消约,可以保存用戶的會(huì)話信息肠鲫? 我們可以把信息或者數(shù)據(jù)放在Session中!
常見場景:網(wǎng)站登錄之后或粮,你下次不用再登錄了导饲,第二次訪問直接就上去了!
- 從請(qǐng)求中拿到cookie信息
- 服務(wù)器響應(yīng)給客戶端cookie
Cookie[] cookies = req.getCookies(); //獲得客戶端請(qǐng)求的Cookie
cookie.getName(); //獲得cookie中的key
cookie.getValue(); //獲得cookie中的value
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一個(gè)cookie對(duì)象
cookie.setMaxAge(24*60*60); //設(shè)置cookie的最長有效期
resp.addCookie(cookie); //服務(wù)端響應(yīng)給客戶端一個(gè)cookie
cookie:一般會(huì)保存在本地的 用戶目錄下 appdata氯材;
一個(gè)網(wǎng)站cookie是否存在上限渣锦!聊聊細(xì)節(jié)問題
- 一個(gè)Cookie只能保存一個(gè)信息;比如只能new一個(gè)String類型的字符串
- 一個(gè)web站點(diǎn)可以給瀏覽器發(fā)送多個(gè)cookie浓体,每個(gè)站點(diǎn)最多存放20個(gè)cookie泡挺;
- Cookie大小有限制: 4kb;
- 瀏覽器上限為300個(gè)cookie
刪除Cookie的方法命浴;
- 不設(shè)置有效期娄猫,關(guān)閉瀏覽器,自動(dòng)失效生闲;
- 設(shè)置最長有效期時(shí)間為 0 媳溺;
編碼,解碼:
Cookie cookie = new Cookie("name", URLEncoder.encode("超人", "UTF-8"));// 編碼
out.write(URLDecoder.decode(cookie.getValue(),"UTF-8"));// 解碼
a.服務(wù)端向客戶端增加cookie :response對(duì)象;服務(wù)端向客戶端獲取對(duì)象:request對(duì)象
b.不能直接獲取某一個(gè)單獨(dú)對(duì)象碍讯,只能一次性將 全部的cookie拿到
通過F12可以發(fā)現(xiàn) 除了自己設(shè)置的Cookie對(duì)象外悬蔽,還有一個(gè)name為 JSESSIONID的cookie
建議 cookie只保存 英文數(shù)字,否則需要進(jìn)行編碼捉兴、解碼
// 保存用戶上一次訪問的時(shí)間
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 服務(wù)器,告訴你,你來的時(shí)間,把這個(gè)時(shí)間封裝成為一個(gè)信件,你下次帶來,我就知道你來了
// 解決客戶端響應(yīng)時(shí)中文亂碼
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
// 響應(yīng)輸出信息到客戶端
// 伏筆: 變量名設(shè)置為out: out是jsp的內(nèi)置對(duì)象
PrintWriter out = resp.getWriter();
// Cookie: 服務(wù)器從客戶端以請(qǐng)求方式獲取
Cookie[] cookies = req.getCookies();// 返回?cái)?shù)組,說明Cookie可能存在多個(gè)
// 判斷Cookie是否存在
if (cookies != null) {
// 若Cookie存在
out.write("您上次訪問時(shí)間是: ");
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
// 比較Cookie的名字,并獲取Cookie的名字(key-value鍵值對(duì))
// 用字符串來比較防止空指針異常,因?yàn)間etName()可能是為null
if ("lastLoginTime".equals(cookie.getName())) {
// 把字符串類型變成時(shí)間戳,獲取Cookie中的value值
Long lastLoginTime = Long.parseLong(cookie.getValue());
// 把時(shí)間寫出到客戶端
Date date = new Date(lastLoginTime);
// toLocalString(): 本地時(shí)間格式化
out.write(date.toLocaleString());
}
}
} else {
// 向客戶端響應(yīng)信息,如果Cookie不為空,則不會(huì)執(zhí)行
// 不執(zhí)行原因: 因?yàn)闉g覽器自己攜帶了1個(gè)或多個(gè)Cookie去訪問你服務(wù)器了蝎困,你可以手動(dòng)刪除再嘗試訪問录语。
out.write("這是您第一次訪問本站");
}
// 服務(wù)器給客戶端響應(yīng)一個(gè)Cookie,第一次訪問后更新時(shí)間(Cookie的value值),因?yàn)橄旅娴拇a每運(yùn)行一次程序都會(huì)執(zhí)行
// 每次訪問都會(huì)給你一個(gè)小餅干,有了也會(huì)給你新的
// 創(chuàng)建一個(gè)Cookie對(duì)象
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+ "");
// 設(shè)置Cookie的最長有效期為 1天,把瀏覽器關(guān)了(結(jié)束會(huì)話),Cookie仍然保留著
cookie.setMaxAge(24*60*60);
// 響應(yīng)時(shí)傳入cookie
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
public class CookieDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 創(chuàng)建一個(gè)Cookie對(duì)象,key值(名字)必須要和要?jiǎng)h除的Cookie的名字相同
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
// 設(shè)置Cookie的最長有效期為0,
cookie.setMaxAge(0);
// 響應(yīng)給客戶端立馬過期
resp.addCookie(cookie);
// 配置一下Srvlet映射地址
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
// 在通信里傳輸中文最好用URLEncoder(編碼類)和URLDecoder(解碼類)
public class CookieDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 修改請(qǐng)求響應(yīng)的編碼格式
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
// 服務(wù)端通過客戶端的請(qǐng)求來獲得一個(gè)Cookie
Cookie[] cookies = req.getCookies();
// 通過響應(yīng)獲取一個(gè)輸出流
PrintWriter out = resp.getWriter();
// 判斷Cookie是否存在(為空)
if (cookies != null) {
out.write("你的名字是: ");
// 若Cookies存在,循環(huán)遍歷判斷Cookie的key值是否匹配
for (int i = 0; i < cookies.length; i++) {
// Cookie的編碼和解碼
Cookie cookie = cookies[i];
// 判斷cookie的key是否匹配
if ("name".equals(cookie.getName())) {
// Cookie執(zhí)行的也要修改轉(zhuǎn)碼格式
// 響應(yīng)到客戶端時(shí)解碼
// 響應(yīng)給客戶端cookie的value值
out.write(URLDecoder.decode(cookie.getValue(),"UTF-8"));
}
}
}else{
// 若Cookies數(shù)組不存在
out.write("這是您第一次訪問本站");
}
// 創(chuàng)建一個(gè)新的Cookie,添加到客戶端時(shí)編碼
Cookie cookie = new Cookie("name", URLEncoder.encode("超人", "UTF-8"));
// 通過服務(wù)端響應(yīng)給客戶端添加Cookie
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
7.4禾乘、Session(重點(diǎn))
session: 出生到死澎埠,就是你的唯一“會(huì)話”
session :會(huì)話
a.瀏覽網(wǎng)站:開始-關(guān)閉
b.購物: 瀏覽、付款始藕、退出
c.電子郵件:瀏覽蒲稳、寫郵件、退出
開始-結(jié)束
session執(zhí)行機(jī)制:
客戶端第一次請(qǐng)求服務(wù)端時(shí),(JSESSIONID和sessionId匹配失敗),服務(wù)端會(huì)生成一個(gè)session對(duì)象(用于保存該客戶的信息);
并且每個(gè)session對(duì)象都會(huì)自帶存有一個(gè)唯一的sessionId(用于區(qū)分其他不同客戶端請(qǐng)求同一服務(wù)端的session對(duì)象);并且會(huì)把sessionID的值復(fù)制一份成JSESSIONID,服務(wù)端會(huì)把JSESSIONID放到服務(wù)端生成的cookie里,然后服務(wù)端向客戶端做出響應(yīng),響應(yīng)時(shí)會(huì)把Cookie發(fā)送回給客戶端,因此客戶端的id和服務(wù)端的id就一一對(duì)應(yīng)起來了,就不會(huì)亂了;服務(wù)端的sessionID和客戶端的JSESSIONID一一對(duì)應(yīng)用來區(qū)分客戶
服務(wù)端又會(huì)生成一個(gè)cookie,并且該cookie的key(name)=JSESSIONID,value=服務(wù)端sessionId的值;
然后,服務(wù)端會(huì)在響應(yīng)客戶端的同時(shí),間該cookie發(fā)送給客戶端,至此,客戶端就有了一個(gè)cookie(JSESISONID);因此,客戶端的cookie就可以和服務(wù)端的session一一對(duì)應(yīng)(JSESSIONID - sessionID)
客戶端第二/n次請(qǐng)求服務(wù)端時(shí): 服務(wù)端會(huì)先用客戶端的cookie中的JSESSIONID,去服務(wù)端的session中匹配sessionId,若匹配成功(cookie中的JSESSIONID等于session中的sessionId),說明此用戶不是第一次訪問,無需登錄
- 一個(gè)瀏覽器(客戶端)對(duì)應(yīng)一個(gè)Session
什么是Session:
- 服務(wù)器會(huì)給每一個(gè)用戶(瀏覽器)創(chuàng)建一個(gè)Seesion對(duì)象伍派;
- 一個(gè)Seesion獨(dú)占一個(gè)瀏覽器江耀,只要瀏覽器沒有關(guān)閉,這個(gè)Session就存在诉植;
- 用戶登錄之后祥国,整個(gè)網(wǎng)站它都可以訪問!--> 保存用戶的信息倍踪;保存購物車的信息…..
Session和cookie的區(qū)別:
- Cookie是把用戶的數(shù)據(jù)寫給用戶的瀏覽器系宫,瀏覽器保存 (可以保存多個(gè))
- Session把用戶的數(shù)據(jù)寫到用戶獨(dú)占Session中,服務(wù)器端保存 (保存重要的信息建车,減少服務(wù)器資源的浪費(fèi))
- Session對(duì)象由服務(wù)創(chuàng)建扩借;
使用場景:
- 保存一個(gè)登錄用戶的信息;
- 購物車信息缤至;
- 在整個(gè)網(wǎng)站中經(jīng)常會(huì)使用的數(shù)據(jù)潮罪,我們將它保存在Session中;
作用域:ServletContext/ApplicationContext 全局(共享)(當(dāng)前web應(yīng)用)领斥,Session 會(huì)話,私有的,非共享的
使用Session:
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解決亂碼問題
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
resp.setCharacterEncoding("utf-8");
// 通過客戶端的請(qǐng)求獲取Session對(duì)象
HttpSession session = req.getSession();
// 給Session存東西,Session不僅可以存字符,還可以存對(duì)象
session.setAttribute("name", new Person("超人",20));
// 獲取Session的ID
String sessionId = session.getId();
// 判斷Session是否新創(chuàng)建
if (session.isNew()) {
// 若是新創(chuàng)建,則向客戶端響應(yīng)信息
resp.getWriter().write("session第一次創(chuàng)建成功" + sessionId);
}else{
// 若非新創(chuàng)建
resp.getWriter().write("session已在服務(wù)器存在了, ID為: " + sessionId);
}
// 注冊(cè)Servlet映射地址
// Session對(duì)象創(chuàng)建的時(shí)候做了什么
// 客戶端第一次訪問服務(wù)端時(shí),服務(wù)端創(chuàng)建了一個(gè)Session對(duì)象自帶存放了唯一一個(gè)sessionId,并且復(fù)制一份成JSESSIONID,
// 并且把JESSIONID放到服務(wù)端生成的cookie里,服務(wù)端響應(yīng)時(shí)發(fā)回cookie給客戶端,
// Cookie cookie = new Cookie("JSESSIONID", sessionId);
// resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
}
public class SessionDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解決亂碼問題
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
// 獲取session
HttpSession session = req.getSession();
Person person = (Person) session.getAttribute("name");
System.out.println(person.toString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
public class SessionDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 獲取Session對(duì)象
HttpSession session = req.getSession();
// 移除Session
// session.removeAttribute("name");
// 手動(dòng)注銷Session,客戶端(瀏覽器)的sessionId會(huì)被刪除,但瀏覽器再訪問服務(wù)端立馬會(huì)生成新的,效果同于關(guān)閉瀏覽器
session.invalidate();
// 注冊(cè)Servlet并映射地址
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
會(huì)話自動(dòng)過期:web.xml配置
<!-- 設(shè)置Session的默認(rèn)失效時(shí)間-->
<session-config>
<!-- x分鐘后Session自動(dòng)失效,以分鐘為單位-->
<session-timeout>1</session-timeout>
</session-config>
存在多個(gè)用戶訪問請(qǐng)求,Session是獲取針對(duì)個(gè)人的資源,而ServletContext/ApplicationContext可以獲取共享資源,是整個(gè)應(yīng)用級(jí)的,多個(gè)客戶端都可以訪問ServletContext/ApplicationContext
8嫉到、JSP
8.1、什么是JSP
Java Server Pages : Java服務(wù)器端頁面月洛,也和Servlet一樣何恶,用于動(dòng)態(tài)Web技術(shù)!
最大的特點(diǎn):
- 寫JSP就像在寫HTML
- 區(qū)別:
- HTML只給用戶提供靜態(tài)的數(shù)據(jù)
- JSP頁面中可以嵌入JAVA代碼嚼黔,為用戶提供動(dòng)態(tài)數(shù)據(jù)细层;
8.2、JSP原理
思路:JSP到底怎么執(zhí)行的唬涧!
代碼層面沒有任何問題
-
服務(wù)器內(nèi)部工作
tomcat中有一個(gè)work目錄疫赎;
IDEA中使用Tomcat的會(huì)在IDEA的tomcat中生產(chǎn)一個(gè)work目錄
發(fā)現(xiàn)頁面(jsp文件)轉(zhuǎn)變成了Java程序!
瀏覽器向服務(wù)器發(fā)送請(qǐng)求碎节,不管訪問什么資源捧搞,其實(shí)都是在訪問Servlet!
因?yàn)閖sp繼承了HttpServlet類
JSP最終也會(huì)被轉(zhuǎn)換成為一個(gè)Java類!
JSP 本質(zhì)上就是一個(gè)Servlet,只不過簡化了一些東西,他幫你做了很多事情,只需要寫頁面部分就可以了,相當(dāng)于jsp是封裝好的Servlet
**
//初始化
public void _jspInit() {
}
//銷毀
public void _jspDestroy() {
}
//JSPService
public void _jspService(.HttpServletRequest request,HttpServletResponse response)
判斷請(qǐng)求是get還是post類型
-
內(nèi)置一些對(duì)象: jsp中已經(jīng)創(chuàng)建好的對(duì)象,在寫jsp時(shí)嵌入java代碼可以直接使用這些對(duì)象
final javax.servlet.jsp.PageContext pageContext; //頁面上下文 javax.servlet.http.HttpSession session = null; //session final javax.servlet.ServletContext application; //applicationContext final javax.servlet.ServletConfig config; //config javax.servlet.jsp.JspWriter out = null; //out(輸出對(duì)象) final java.lang.Object page = this; //page:當(dāng)前 HttpServletRequest request //請(qǐng)求 HttpServletResponse response //響應(yīng)
這里的out就是前面resp.getWriter
-
jsp文件輸出頁面前加入的代碼
response.setContentType("text/html"); //設(shè)置響應(yīng)的頁面為html類型 pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out;
以上的這些個(gè)對(duì)象我們可以在JSP頁面中直接使用胎撇!
jsp頁面要訪問瀏覽器才會(huì)生成
通過瀏覽器上網(wǎng)本質(zhì)上就是訪問服務(wù)器,服務(wù)器里有web容器(Tomcat),Tomcat中可以放很多網(wǎng)站(web應(yīng)用),按對(duì)應(yīng)的地址一個(gè)訪問一個(gè),訪問到Tomcat之后會(huì)判斷對(duì)應(yīng)的請(qǐng)求,如果訪問的是jsp就去找對(duì)應(yīng)的jsp頁面,訪問到j(luò)sp之后不能直接使用,在web容器的作用下,將jsp頁面轉(zhuǎn)換成java文件,經(jīng)過轉(zhuǎn)換后得到一個(gè)新文件: xxx.jsp.java,得到之后要運(yùn)行,java文件就被編譯成xxx.jsp.class文件,編譯為class文件之后就被調(diào)到服務(wù)器里面,用戶真正訪問的是服務(wù)器,因此,服務(wù)器響應(yīng)得到處理完畢的class對(duì)象,這個(gè)對(duì)象就是Servlet
jsp只是別人幫忙做好了,做一個(gè)封裝,他幫我們?nèi)プ鍪虑?我們?nèi)ピL問jsp頁面最后還是訪問Servlet
在JSP頁面中介粘;
只要是 JAVA代碼就會(huì)原封不動(dòng)的輸出;
如果是HTML代碼晚树,就會(huì)被轉(zhuǎn)換為:
out.write("<html>\r\n");
這樣的格式碗短,輸出到前端!
配置Tomcat時(shí)把war包改為war explored,啟動(dòng)項(xiàng)目時(shí)選擇uddate classes and resources 實(shí)現(xiàn)熱更新,無需重啟服務(wù)器,啟動(dòng)速度快
8.3题涨、JSP基礎(chǔ)語法
任何語言都有自己的語法,JAVA中有,总滩。 JSP 作為java技術(shù)的一種應(yīng)用纲堵,它擁有一些自己擴(kuò)充的語法(了解,知道即可H蛴妗)席函,Java所有語法都支持!
JSP表達(dá)式
<%--
jsp表達(dá)式
作用: 用來將程序的輸出,輸出到客戶端
語法格式: <%= 變量或表達(dá)式%> 相當(dāng)于java語法中的: out.write()
--%>
<%= new java.util.Date()%>
jsp腳本片段
<%-- jsp腳本片段--%>
<%--jsp腳本表達(dá)式: <% %>--%>
<%
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
out.println("<h1>sum= " + sum + "</h1>");// jsp.java可以自動(dòng)把標(biāo)簽轉(zhuǎn)移成html格式,因?yàn)閖sp類里的response對(duì)象調(diào)用setContentType方法轉(zhuǎn)換響應(yīng)格式
%>
腳本片段的再實(shí)現(xiàn)
<%
// 因?yàn)樽兞勘欢x在了同一個(gè)方法_jspService方法里,所以變量不能重復(fù)定義聲明
int x = 10;
out.print(x);
%>
<hr>
<p>jsp文檔</p>
<%
int y = 2;
out.println(y);
%>
<%-- java代碼中嵌入HTML元素 --%>
<%
for (int i = 0; i < 5; i++) {
%>
<%--本質(zhì)是同一個(gè)Servlet(java)程序--%>
<%--因?yàn)槭菍懺谕粋€(gè)jsp類的jspService方法中才能被請(qǐng)求處理,可以在java代碼中夾入HTML標(biāo)簽--%>
<h1>hello world <%=i%></h1>
<%
}
%>
JSP聲明
<%--jsp中叫全局變量冈涧,JAVA里叫成員變量--%>
<%--之前寫的代碼沒用<%! %>都被放在jspService方法里面,這些寫法稱作jsp表達(dá)式輸出或一個(gè)jsp片段,都是為了這個(gè)方法里去做的--%>
<%--jspService方法是為了給客戶端響應(yīng),而這里面的代碼被寫到了jsp生成java的類里,作用域更高了,這叫jsp聲明--%>
<%!
static {
System.out.println("loading Servlet");
}
private int globalVar = 0;
public static void show(){
System.out.println("進(jìn)入了方法show");
}
%>
JSP聲明:<%!%>里的代碼會(huì)被編譯到JSP生成Java的類中茂附!其他的,就會(huì)被生成到_jspService方法中督弓!方法里面的可以調(diào)用方法外面的,而外面的作用于更高,這個(gè)方法隨著方法消失就沒了
在JSP营曼,嵌入Java代碼就可以用java了!
jsp語法:
<%%>
<%=%>
<%!%>
<%--注釋--%>
JSP的注釋愚隧,不會(huì)在客戶端顯示蒂阱,HTML的就會(huì)!
8.4狂塘、JSP指令
<%--這些代碼作用域都在jspService方法里面--%>
<%--
jsp表達(dá)式
作用: 用來將程序的輸出,輸出到客戶端
語法格式: <%= 變量或表達(dá)式%> 相當(dāng)于java語法中的: out.write()
--%>
<%--通過導(dǎo)入<%@ page import="java.util.*" %>可以不用寫全類名--%>
<%= new Date()%>
<%--分割線--%>
<hr>
<%-- jsp腳本片段--%>
<%--jsp腳本表達(dá)式: <% %>--%>
<%
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
out.println("<h1>sum= " + sum + "</h1>");// jsp.java可以自動(dòng)把標(biāo)簽轉(zhuǎn)移成html格式,因?yàn)閖sp類里的response對(duì)象調(diào)用setContentType方法轉(zhuǎn)換響應(yīng)格式
%>
<%
// 因?yàn)樽兞勘欢x在了同一個(gè)方法_jspService方法里,所以變量不能重復(fù)定義聲明
int x = 10;
out.print(x);
%>
<hr>
<p>jsp文檔</p>
<%
int y = 2;
out.println(y);
%>
<%-- java代碼中嵌入HTML元素 --%>
<%
for (int i = 0; i < 5; i++) {
%>
<%--本質(zhì)是同一個(gè)Servlet(java)程序--%>
<%--因?yàn)槭菍懺谕粋€(gè)jsp類的jspService方法中才能被請(qǐng)求處理,可以在java代碼中夾入HTML標(biāo)簽--%>
<h1>hello world <%=i%></h1>
<%
}
%>
<hr>
<%--jsp中叫全局變量录煤,JAVA里叫成員變量--%>
<%--之前寫的代碼沒用<%! %>都被放在jspService方法里面,這些寫法稱作jsp表達(dá)式輸出或一個(gè)jsp片段,都是為了這個(gè)方法里去做的--%>
<%--jspService方法是為了給客戶端響應(yīng),而這里面的代碼被寫到了jsp生成java的類里,作用域更高了,這叫jsp聲明--%>
<%!
static {
System.out.println("loading Servlet");
}
private int globalVar = 0;
public static void show(){
System.out.println("進(jìn)入了方法show");
}
%>
<hr>
<!-- 我是HTML注釋-->
- 自定義錯(cuò)誤頁面
<%--頁面的文本類型是HTML格式,并且編碼生成utf-8,頁面的編寫語言是java--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--這里的路徑都是以web開始的 如果按照之前module建項(xiàng)目的話,路徑是以webapp開始--%>
<%--定制錯(cuò)誤頁面方法一--%>
<%--<%@page errorPage="error/500.jsp" %>--%>
<%--方法二: 在web.xml中配置error-page--%>
<%--修改了web.xml就必須要重啟(服務(wù)器)Tomcat--%>
<%--顯式的聲明這是個(gè)錯(cuò)誤頁面--%>
<%@page isErrorPage="true" %>
<%--修改頁面編碼格式--%>
<%@page pageEncoding="utf-8" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int x = 1 / 0; // 算術(shù)異常,500錯(cuò)誤
%>
<%--定制錯(cuò)誤頁面--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<img src="../img/500.jpg" alt="500">
- 還可以在web.xml中配置錯(cuò)誤頁面
<!-- 配置錯(cuò)誤頁面-->
<error-page>
<error-code>404</error-code>
<!-- 位置開頭一定要先加斜杠表示當(dāng)前項(xiàng)目,否則會(huì)報(bào)錯(cuò)-->
<location>/error/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
- 包含(插入)頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--@include會(huì)將兩個(gè)頁面合二為一,就是會(huì)把兩個(gè)頁面的東西抽離出來放到一起,最后生成一個(gè)頁面--%>
<%--定義相同變量會(huì)重名--%>
<%--插入頁面--%>
<%--<%@include file="common/header.jsp"%>
<h1>網(wǎng)頁主體</h1>
<%
int i = 0; // 報(bào)錯(cuò)
%>
<%@include file="common/footer.jsp"%>--%>
<%--相當(dāng)于拿到了兩個(gè)頁面的文件,這些文件在jsp生成java的類里的static代碼塊中包含進(jìn)來了,相當(dāng)于拼接頁面,最后生成三個(gè)頁面--%>
<%--jsp標(biāo)簽導(dǎo)入頁面
jsp:include:拼接頁面,本質(zhì)還是三個(gè),三個(gè)頁面定義的變量互不影響
--%>
<jsp:include page="/common/header.jsp"/>
<h1>我是主體</h1>
<%
int i = 0;
%>
<jsp:include page="/common/footer.jsp"/>
</body>
</html>
8.5、9大內(nèi)置對(duì)象
客戶端第一次訪問jsp頁面的時(shí)候,會(huì)轉(zhuǎn)成java類,然后轉(zhuǎn)換成class對(duì)象,變成class對(duì)象后自動(dòng)生成9個(gè)對(duì)象
- PageContext 存東西
- Request 存東西
- Response
- Session 存東西
- Application 【SerlvetContext】 存東西
- config 【SerlvetConfig】
- out
- page 荞胡,不用了解
- exception
pageContext.setAttribute("name1","超人1號(hào)");// 保存的數(shù)據(jù)只在一個(gè)頁面中有效
request.setAttribute("name2","超人2號(hào)");// 保存的數(shù)據(jù)只在一次請(qǐng)求中有效,請(qǐng)求轉(zhuǎn)發(fā)會(huì)攜帶這個(gè)數(shù)據(jù)
session.setAttribute("name3","超人3號(hào)");// 保存的數(shù)據(jù)只在一次會(huì)話中有效,從打開瀏覽器到關(guān)閉瀏覽器
application.setAttribute("name4","超人4號(hào)");// 保存的數(shù)據(jù)只在服務(wù)器中有效,從打開服務(wù)器到關(guān)閉服務(wù)器
應(yīng)用場景:
request:客戶端向服務(wù)器發(fā)送請(qǐng)求妈踊,產(chǎn)生的數(shù)據(jù),用戶看完就沒用了泪漂,比如:新聞廊营,用戶看完沒用的!
session:客戶端向服務(wù)器發(fā)送請(qǐng)求窖梁,產(chǎn)生的數(shù)據(jù)赘风,用戶用完一會(huì)還有用,比如:購物車纵刘;
application:客戶端向服務(wù)器發(fā)送請(qǐng)求邀窃,產(chǎn)生的數(shù)據(jù),一個(gè)用戶用完了,其他用戶還可能使用瞬捕,比如:聊天數(shù)據(jù)鞍历;
8.6、JSP標(biāo)簽肪虎、JSTL標(biāo)簽劣砍、EL表達(dá)式
<!-- 導(dǎo)入jstl表達(dá)式依賴-->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--Jstl表達(dá)式依賴的standard標(biāo)簽庫的依賴-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
EL表達(dá)式: ${ }
作用:
- 獲取數(shù)據(jù)
- 執(zhí)行運(yùn)算
- 獲取web開發(fā)的常用對(duì)象
JSP標(biāo)簽
<%--標(biāo)簽夾層寫注釋會(huì)報(bào)500異常--%>
<%--插入頁面--%>
<%--<jsp:include page=""></jsp:include>--%>
<%--頁面轉(zhuǎn)發(fā)--%>
<%--
可以在請(qǐng)求轉(zhuǎn)發(fā)中攜帶參數(shù)
http://localhost:8080/jsptag.jsp?name=tiga&age=18
--%>
<jsp:forward page="jsptag2.jsp">
<jsp:param name="name" value="tiga"/>
<jsp:param name="age" value="18"/>
</jsp:forward>
<%--在請(qǐng)求轉(zhuǎn)發(fā)頁面中提取參數(shù)--%>
名字: <%=request.getParameter("name")%>
年齡: <%=request.getParameter("age")%>
JSTL表達(dá)式
JSTL標(biāo)簽庫的使用就是為了彌補(bǔ)HTML標(biāo)簽的不足;它自定義許多標(biāo)簽扇救,可以供我們使用刑枝,標(biāo)簽的功能和Java代碼一樣!
格式化標(biāo)簽
SQL標(biāo)簽
XML 標(biāo)簽
核心標(biāo)簽 (掌握部分)
JSTL標(biāo)簽庫使用步驟
- 引入對(duì)應(yīng)的 taglib
比如核心標(biāo)簽
<%--引入JSTL核心標(biāo)簽庫,才能用JSTL標(biāo)簽 c代表core--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- 使用其中的方法
- 在Tomcat9 也需要引入 jstl的包迅腔,否則會(huì)報(bào)錯(cuò):JSTL解析錯(cuò)誤
在tomcat的lib文件夾下導(dǎo)入上面兩個(gè)jar包
JSTL標(biāo)簽 - c: if
<body>
<h1>if測試</h1>
<hr>
<%--
EL表達(dá)式: 獲取表單中的數(shù)據(jù)
獲取屬性的參數(shù): ${param.參數(shù)名}
--%>
<%--和Java中的if條件判斷一樣--%>
<form action="coreif.jsp" method="get">
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登錄">
</form>
<%--判斷如果提交的用戶名如果是管理員,則登錄成功--%>
<%--test: 表示是必須要寫的條件--%>
<%--test值可以用來做是非判斷--%>
<%--var用來接收test比較出來的是非返回值--%>
<%--JSTL標(biāo)簽代碼只是看起來更整齊,彌補(bǔ)html標(biāo)簽的不足--%>
<c:if test="${param.username == 'admin'}" var = "isAdmin">
<c:out value="管理員歡迎您"></c:out>
</c:if>
<%--若不是管理員,則返回false--%>
<c:out value="${isAdmin}"></c:out>
</body>
JSTL標(biāo)簽 - c:choose c:when
<body>
<%--c:set用于存儲(chǔ)數(shù)據(jù),類似于if-else/switch,只要滿足就跳出循環(huán)--%>
<%--定義一個(gè)變量score,值為85--%>
<c:set var="score" value="85"/>
<c:choose>
<c:when test="${score >= 90}">
成績優(yōu)秀
</c:when>
<c:when test="${score >= 80}">
良好
</c:when>
<c:when test="${score >= 70}">
一般
</c:when>
</c:choose>
</body>
c:forEach
<body>
<%--先創(chuàng)建一個(gè)集合和往集合中存放對(duì)象--%>
<%
ArrayList<String> people = new ArrayList<>();
// 往集合里添加元素
people.add(0, "張三");
people.add(1, "李四");
people.add(2, "王五");
people.add(3, "趙六");
people.add(4, "孫七");
// 創(chuàng)建一個(gè)請(qǐng)求對(duì)象名叫l(wèi)ist,屬性名為people
request.setAttribute("list", people);
%>
<%--遍歷集合元素--%>
<%--
items: 表示要遍歷的對(duì)象
var: 表示遍歷對(duì)象中的每一個(gè)元素
begin: 表示開始遍歷下標(biāo)
end: 表示結(jié)束遍歷下標(biāo)
step: 表示增長步長
--%>
<c:forEach var="peoples" items="${list}">
<%-- 打印循環(huán)的值--%>
<c:out value="${peoples}"></c:out><br>
</c:forEach>
=============<br>
<c:forEach var="peoples" items="${list}" begin="1" end="4" step="2">
<c:out value="${peoples}"></c:out>
</c:forEach>
</body>
9装畅、JavaBean
實(shí)體類
JavaBean有特定的寫法:
- 必須要有一個(gè)無參構(gòu)造
- 屬性必須私有化
- 必須有對(duì)應(yīng)的get/set方法;
一般用來和數(shù)據(jù)庫的字段做映射 ORM沧烈;
ORM :對(duì)象關(guān)系映射
- 表--->類
- 字段-->屬性
- 行記錄---->對(duì)象
people表
id | name | age | address |
---|---|---|---|
1 | 超人1號(hào) | 3 | 廣州 |
2 | 超人2號(hào) | 18 | 廣州 |
3 | 超人3號(hào) | 100 | 廣州 |
- javabean實(shí)現(xiàn)類
class People{
private int id;
private String name;
private int id;
private String address;
}
class A{
new People(1,"超人1號(hào)",3掠兄,"西安");
new People(2,"超人2號(hào)",3,"廣州");
new People(3,"超人3號(hào)",3锌雀,"南京");
}
<body>
<%--通過jsp使用實(shí)體類,作用域?yàn)楫?dāng)前頁面--%>
<%--
id: 表示類實(shí)例化(對(duì)象)的變量名
class: 數(shù)據(jù)庫映射的類名
scope: jsp頁面的作用域
--%>
<%
// 等價(jià)于:
// People people = new People();
%>
<jsp:useBean id="people" class="com.tiga.pojo.People" scope="page"/>
<%
/*
等價(jià)于:
people.setId(1);
people.setName("超人");
people.setAge(10);
people.setAddress("廣州");
*/
%>
<%--通過jsp設(shè)置屬性--%>
<%--設(shè)置的對(duì)象名為name,對(duì)象屬性為property 設(shè)置值為value--%>
<jsp:setProperty name="people" property="id" value="1"/>
<jsp:setProperty name="people" property="name" value="超人"/>
<jsp:setProperty name="people" property="age" value="10"/>
<jsp:setProperty name="people" property="address" value="廣州"/>
<%--
等價(jià)于:
<%=people.getId()%>
--%>
<%--通過jsp獲取屬性--%>
id: <jsp:getProperty name="people" property="id"/>
姓名: <jsp:getProperty name="people" property="name"/>
年齡: <jsp:getProperty name="people" property="age"/>
地址: <jsp:getProperty name="people" property="address"/>
</body>
- 過濾器
- 文件上傳
- 郵件發(fā)送
- JDBC 復(fù)習(xí) : 如何使用JDBC , JDBC crud蚂夕, jdbc 事務(wù)
10、MVC三層架構(gòu)
什么是MVC: Model view Controller 模型(實(shí)體類,數(shù)據(jù)庫表中對(duì)應(yīng)的的字段)腋逆、視圖(jsp頁面)婿牍、控制器
10.1、早些年
用戶直接訪問控制層惩歉,控制層就可以直接操作數(shù)據(jù)庫牍汹;
10.2、MVC三層架構(gòu)
(View層)登錄-(Controller層)接受請(qǐng)求-(Modelr層)處理請(qǐng)求-交給業(yè)務(wù)層處理業(yè)務(wù)-dao層驗(yàn)證-數(shù)據(jù)庫
Model
業(yè)務(wù)處理 :業(yè)務(wù)邏輯(Service)
數(shù)據(jù)持久層:CRUD (Dao)
View
展示數(shù)據(jù)
提供鏈接發(fā)起Servlet請(qǐng)求 (a柬泽,form慎菲,img…)
Controller (Servlet)
接收用戶的請(qǐng)求 :(req:請(qǐng)求參數(shù)、Session信息….)
交給業(yè)務(wù)層處理對(duì)應(yīng)的代碼
控制視圖的跳轉(zhuǎn)
登錄--->接收用戶的登錄請(qǐng)求--->處理用戶的請(qǐng)求(獲取用戶登錄的參數(shù)锨并,username露该,password)---->交給業(yè)務(wù)層處理登錄業(yè)務(wù)(判斷用戶名密碼是否正確:事務(wù))--->Dao層查詢用戶名和密碼是否正確-->數(shù)據(jù)庫
11、Filter (重點(diǎn))
Filter:過濾器 第煮,
功能:
1.用來攔截傳入的請(qǐng)求和傳出的響應(yīng),過濾網(wǎng)站的數(shù)據(jù)解幼;
2.修改或以某種方式處理正在客戶端和服務(wù)端之間交換的數(shù)據(jù)流
實(shí)際開發(fā)中的使用場景:
- 處理中文亂碼
- 登錄驗(yàn)證….
客戶端訪問服務(wù)器時(shí),請(qǐng)求會(huì)先進(jìn)到過濾器再進(jìn)到Servlet,還可以同時(shí)加多個(gè)過濾器,這多個(gè)會(huì)形成一個(gè)鏈,有先后順序
如何使用過濾器?
與使用Servlet類似,Filter是java Web提供的一個(gè)接口,開發(fā)者只需要自定義一個(gè)類并實(shí)現(xiàn)該接口即可.
// 過濾器和web服務(wù)器同生共死
public class CharacterEncodingFilter implements Filter {
// 初始化
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("characterEncodingFilter已初始化");
}
// chain: 鏈 可以有很多個(gè)過濾器
/*
1.過濾方法中的所有代碼,在過濾特定請(qǐng)求(在web.xml中配置的filter請(qǐng)求)的時(shí)候都會(huì)執(zhí)行
2.必須讓過濾器繼續(xù)同行
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
System.out.println("CharacterEncodingFilter執(zhí)行前");
// 讓客戶端的請(qǐng)求繼續(xù)往下走,如果不寫,程序到過濾器就被攔截停止,而無法繼續(xù)訪問到Servlet
chain.doFilter(request,response);
System.out.println("CharacterEncodingFilter執(zhí)行后");
}
// 銷毀: web服務(wù)器關(guān)閉的時(shí)候,過濾會(huì)銷毀
public void destroy() {
System.out.println("characterEncodingFilter已銷毀");
}
}
與Servlet不同的是,實(shí)現(xiàn)Filter接口可以只實(shí)現(xiàn)doFilter一個(gè)方法,因?yàn)閖dk1.8的新特性,Filter接口中,只有doFilter是抽象方法,初始,銷毀方法都是默認(rèn)方法,default方法是已經(jīng)重寫過的方法,因此實(shí)現(xiàn)類不被再重寫,而實(shí)現(xiàn)Servlet接口也不用重寫所有方法是因?yàn)镚enericServlet實(shí)現(xiàn)了Servlet接口,在這個(gè)實(shí)現(xiàn)類中已經(jīng)屏蔽了一些抽象方法.
web.xml中配置Filter
<servlet>
<servlet-name>ShowServlet</servlet-name>
<servlet-class>com.tiga.servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/servlet/show</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/show</url-pattern>
</servlet-mapping>
<!-- 過濾特定的請(qǐng)求-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- 過濾器映射的類-->
<filter-class>com.tiga.filter.CharacterEncodingFilter</filter-class>
</filter>
<!-- 要過濾的請(qǐng)求-->
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!-- 只要是/servlet下的任何請(qǐng)求,都要經(jīng)過這個(gè)過濾器-->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
注意: doFilter方法中處理完業(yè)務(wù)邏輯之后,必須添加filterChain.doFilter(request,response);否則請(qǐng)求/響應(yīng)無法向后傳遞,一直停留在過濾器中.
12.監(jiān)聽器
如何使用監(jiān)聽器?
寫一個(gè)普通類實(shí)現(xiàn)監(jiān)聽器接口
// 統(tǒng)計(jì)在線人數(shù): 統(tǒng)計(jì)session
public class OnlineCountListener implements HttpSessionListener {
// 創(chuàng)建session監(jiān)聽
// 一旦創(chuàng)建session就會(huì)觸發(fā)一次這個(gè)事件
public void sessionCreated(HttpSessionEvent se) { // 形參代表session事件的一個(gè)對(duì)象
ServletContext sc = se.getSession().getServletContext();
// 獲取sessionId
System.out.println(se.getSession().getId());
/*
session銷毀:
1.手動(dòng)銷毀: se.getSession().invalidate();
2.自動(dòng)銷毀: 在web.xml中配置session過期時(shí)間
*/
// 假設(shè)session已經(jīng)創(chuàng)建了,就去獲取OnlineCount對(duì)象
Integer onlineCount = (Integer) sc.getAttribute("OnlineCount");
if (onlineCount == null) {
// 若為空,則給人數(shù)變量加一個(gè)
onlineCount = new Integer(1);
}else{
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
// 設(shè)置屬性
sc.setAttribute("OnlineCount", onlineCount);
}
// 銷毀session監(jiān)聽
// 一旦銷毀session就會(huì)觸發(fā)一次這個(gè)事件
public void sessionDestroyed(HttpSessionEvent se) {
// 獲取客戶端session的上下文
ServletContext sc = se.getSession().getServletContext();
// 假設(shè)session已經(jīng)創(chuàng)建了,就去獲取OnlineCount對(duì)象
Integer onlineCount = (Integer) sc.getAttribute("OnlineCount");
// 判斷onlineCount是否存在
if (onlineCount == null) {
onlineCount = new Integer(0);
} else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
// 把原來的值設(shè)置回去,減少新變量的產(chǎn)生
sc.setAttribute("OnlineCount",onlineCount);
}
}
- 在web.xml中配置Listener
<!-- 注冊(cè)監(jiān)聽器-->
<listener>
<listener-class>com.tiga.listener.OnlineCountListener</listener-class>
</listener>
<!-- session自動(dòng)銷毀-->
<!--<session-config>
<session-timeout>1</session-timeout>
</session-config>-->
過濾器過濾用戶登錄,注銷,權(quán)限案例
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 獲取前端請(qǐng)求參數(shù)
String username = req.getParameter("username");
// 判斷參數(shù)是否存在
if (username.equals("admin")) {
// 登錄成功, 設(shè)置用戶session的鍵和值
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
resp.sendRedirect("/sys/success.jsp");
} else {
// 登錄失敗
resp.sendRedirect("/error.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
// 用戶注銷類
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 獲取用戶的session
Object user_session = req.getSession().getAttribute("USER_SESSION");
// 判斷用戶是否注銷
if (user_session != null) {
// 若用戶session存在,則用戶可以通過注銷移除session
req.getSession().removeAttribute("USER_SESSION");
// 移除后用戶不能再進(jìn)入成功頁面,把用戶頁面重定向到登錄頁面
resp.sendRedirect("Login.jsp");
}else{
resp.sendRedirect("Login.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
<body>
<h1>登錄</h1>
<form action="/servlet/login" method="post">
<input type="text" name="username">
<input type="submit">
</form>
</body>
<body>
<%--
過濾用戶一般寫在過濾器里
<%
Object user_session = request.getSession().getAttribute("USER_SESSION");
if (user_session == null) {
response.sendRedirect("/Login.jsp");
}
%>--%>
<h1>主頁</h1>
<p><a href="/servlet/logout">注銷</a></p>
</body>
<body>
<h1>錯(cuò)誤</h1>
<h3>沒權(quán)限</h3>
<a href="/Login.jsp">返回登錄頁</a>
</body>