Javaweb-2

4另凌、實(shí)現(xiàn)重定向

一個(gè)web資源B收到客戶端A請(qǐng)求后蚁鳖,B他會(huì)通知A客戶端去訪問另外一個(gè)web資源C藻雌,這個(gè)過程叫重定向

image.png

常見場景:

  • 用戶登錄

使用方法:

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ā)生變化瓣履;
image.png

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ā)

image.png
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ù)端

  1. 服務(wù)端給客戶端一個(gè) 信件嫩絮,客戶端下次訪問服務(wù)端帶上信件就可以了婆殿; cookie
  2. 服務(wù)器登記你來過了诈乒,下次你來的時(shí)候我來匹配你; seesion

7.2婆芦、保存會(huì)話的兩種技術(shù)

cookie

  • 客戶端技術(shù) (響應(yīng)怕磨,請(qǐng)求)

session

  • 服務(wù)器技術(shù),利用這個(gè)技術(shù)消约,可以保存用戶的會(huì)話信息肠鲫? 我們可以把信息或者數(shù)據(jù)放在Session中!

常見場景:網(wǎng)站登錄之后或粮,你下次不用再登錄了导饲,第二次訪問直接就上去了!

image.png
  1. 從請(qǐng)求中拿到cookie信息
  2. 服務(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ì)話”

1568344560794.png

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)站它都可以訪問!--> 保存用戶的信息倍踪;保存購物車的信息…..
image.png

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>
image.png

存在多個(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目錄

image.png

發(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)
      
  1. 判斷請(qǐng)求是get還是post類型

  2. 內(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

  1. 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;
    
  2. 以上的這些個(gè)對(duì)象我們可以在JSP頁面中直接使用胎撇!

jsp頁面要訪問瀏覽器才會(huì)生成

image.png

通過瀏覽器上網(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)簽 (掌握部分)

image.png

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ò)誤
image.png

在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、早些年

image.png

用戶直接訪問控制層惩歉,控制層就可以直接操作數(shù)據(jù)庫牍汹;

10.2、MVC三層架構(gòu)

image.png

(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>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市包警,隨后出現(xiàn)的幾起案子撵摆,更是在濱河造成了極大的恐慌,老刑警劉巖害晦,帶你破解...
    沈念sama閱讀 212,332評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件特铝,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鲫剿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,508評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門鳄逾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人灵莲,你說我怎么就攤上這事雕凹。” “怎么了政冻?”我有些...
    開封第一講書人閱讀 157,812評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵枚抵,是天一觀的道長。 經(jīng)常有香客問我明场,道長俄精,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,607評(píng)論 1 284
  • 正文 為了忘掉前任榕堰,我火速辦了婚禮,結(jié)果婚禮上嫌套,老公的妹妹穿的比我還像新娘逆屡。我一直安慰自己,他們只是感情好踱讨,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,728評(píng)論 6 386
  • 文/花漫 我一把揭開白布魏蔗。 她就那樣靜靜地躺著,像睡著了一般痹筛。 火紅的嫁衣襯著肌膚如雪莺治。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,919評(píng)論 1 290
  • 那天帚稠,我揣著相機(jī)與錄音谣旁,去河邊找鬼。 笑死滋早,一個(gè)胖子當(dāng)著我的面吹牛榄审,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播杆麸,決...
    沈念sama閱讀 39,071評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼搁进,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了昔头?” 一聲冷哼從身側(cè)響起饼问,我...
    開封第一講書人閱讀 37,802評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎揭斧,沒想到半個(gè)月后莱革,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,256評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,576評(píng)論 2 327
  • 正文 我和宋清朗相戀三年驮吱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了茧妒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,712評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡左冬,死狀恐怖桐筏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拇砰,我是刑警寧澤梅忌,帶...
    沈念sama閱讀 34,389評(píng)論 4 332
  • 正文 年R本政府宣布,位于F島的核電站除破,受9級(jí)特大地震影響牧氮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瑰枫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,032評(píng)論 3 316
  • 文/蒙蒙 一踱葛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧光坝,春花似錦尸诽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鸳惯,卻和暖如春商蕴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芝发。 一陣腳步聲響...
    開封第一講書人閱讀 32,026評(píng)論 1 266
  • 我被黑心中介騙來泰國打工绪商, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人辅鲸。 一個(gè)月前我還...
    沈念sama閱讀 46,473評(píng)論 2 360
  • 正文 我出身青樓部宿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瓢湃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子理张,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,606評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • Java web筆記 一、HTTP協(xié)議 HTTP(超文本傳輸協(xié)議)绵患,它是一種主流B/S架構(gòu)中應(yīng)用的通信協(xié)議雾叭。具有以...
    默羊的筆記本閱讀 548評(píng)論 0 0
  • 1. HTML HTML指的超文本標(biāo)記語言(Hyper Text Markup Language), 是一種用來描...
    天際神游閱讀 2,736評(píng)論 0 0
  • 0. 引言 學(xué)習(xí)Jsp的目的是為了解技術(shù)從前后端強(qiáng)耦合到前后端分離的過程,增加自己的技術(shù)積淀落蝙。了解并且體會(huì)這個(gè)過程...
    付凱強(qiáng)閱讀 1,209評(píng)論 0 5
  • 目錄 1 Socket 2 軟件結(jié)構(gòu) 3 Servlet 4 HTTP5 單點(diǎn)登錄SSO 6 常見問題...
    小小千千閱讀 527評(píng)論 0 0
  • 1.1 Servlet 1.1.1 什么是Servlet Servlet是JavaWeb三大組件之一(Servle...
    海若Hero閱讀 2,055評(píng)論 0 5