Java EE-04-Servlet

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. 方式1:將TOMCAT_HOME\lib\servlet-api.jar導(dǎo)入到模塊中的web\lib
  2. 方式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. 方式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. 方式2:Servlet3.0以上支持注解配置,可以不用web.xml了患雏;注解配置*:在Servlet實(shí)現(xiàn)類上使用@WebServlet("資源路徑")注解

    @WebServlet(urlPatterns = {"/uri1", "/uri2", "/uri3"})
    
  • 啟動(dòng)Tomcat后Tomcat引擎執(zhí)行的操作:
    1. 創(chuàng)建ServerSocket對(duì)象究珊,開啟指定端口
    2. Tomcat引擎掃描webapps目錄,根據(jù)瀏覽器的URL讀取指定項(xiàng)目中的web.xml
    3. Tomcat引擎掃描所有Servlet接口實(shí)現(xiàn)類纵苛,獲取類上的注解和注解的屬性值
    4. 當(dāng)Tomcat引擎接受到客戶端瀏覽器的請(qǐng)求后剿涮,會(huì)解析請(qǐng)求URL路徑,獲取訪問的Servlet的資源路徑
    5. 創(chuàng)建Request對(duì)象和Response對(duì)象
    6. 依次找servlet-mapping下的url-pattern攻人、servlet-name取试;servlet下的servlet-name、servlet-class
    7. 根據(jù)反射創(chuàng)建servlet-class指定的對(duì)象怀吻,調(diào)用service方法瞬浓,傳遞Request對(duì)象和Response對(duì)象
    8. 運(yùn)行service方法,將數(shù)據(jù)寫在Response對(duì)象的緩沖區(qū)中
    9. service方法結(jié)束后蓬坡,Tomcat引擎從Response對(duì)象的緩沖區(qū)中取出數(shù)據(jù)猿棉,組裝HTTP響應(yīng)信息回傳給瀏覽器

3. Servlet對(duì)象生命周期*

  1. void init(ServletConfig servletConfig)方法:Servlet對(duì)象初始化方法,在對(duì)象被創(chuàng)建后調(diào)用

    1. 只執(zhí)行一次(說明一個(gè)Servlet在內(nèi)存中只存在一個(gè)對(duì)象)

    2. 默認(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í)越高
      
    3. Servlet是單例的兆龙,多個(gè)用戶同時(shí)訪問時(shí)杖爽,可能存在線程安全問題;因此盡量避免在Servlet中使用共享變量

    4. ServletConfig對(duì)象可以獲取Servlet的初始化參數(shù)

  2. service(servletRequest, servletResponse):客戶端訪問一次就執(zhí)行一次

  3. void destroy():Servlet對(duì)象銷毀之前調(diào)用

    1. 只執(zhí)行一次
    2. 當(dāng)Servlet從服務(wù)器中移除或者服務(wù)器正常關(guān)閉的時(shí)候Servlet對(duì)象被銷毀,在銷毀前會(huì)執(zhí)行destroy方法
    3. 一個(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)用程序
    1. 每個(gè)Web應(yīng)用程序只有一個(gè)ServletContext對(duì)象化焕,在Tomcat啟動(dòng)時(shí)就已經(jīng)被創(chuàng)建好了
    2. Tomcat啟動(dòng)時(shí)會(huì)掃描webapps萄窜,找所有Web程序并為其創(chuàng)建ServletContext
    3. ServletContext是接口,實(shí)現(xiàn)類由Tomcat引擎提供
    4. 在ServletContext對(duì)象中存儲(chǔ)的任何數(shù)據(jù)撒桨,在整個(gè)Web應(yīng)用程序中全有效
  1. 獲取ServletContext實(shí)現(xiàn)類對(duì)象:

    1. GenericServlet抽象類的方法:getServletContext()
    2. ServletConfig接口方法:getServletContext()
  2. ServletContext對(duì)象作用:

    1. 作為域?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)
      
    2. 獲取web項(xiàng)目中文件的真實(shí)路徑查刻,以及將web項(xiàng)目中的文件轉(zhuǎn)成流*:

      // 根據(jù)資源名稱獲取資源的絕對(duì)路徑,傳遞相對(duì)于webapps下項(xiàng)目的路徑
      String getRealPath(String path)
      // 返回指定文件的流
      InputStream getResourceAsStream(String path)
      
    3. 獲取全局的初始化參數(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>
      
    4. 獲取文件的MIME類型:

      // 返回指定文件的MIME類型,如果MIME類型未知棋电,則返回null
      String getMimeType(String file)
      

5. HttpServlet

  • GenericServlet抽象類繼承了Servlet接口茎截;HttpServlet抽象類繼承了GenericServlet
  1. GenericServlet:將Servlet接口中其他的方法做了默認(rèn)空實(shí)現(xiàn),只將service()方法作為抽象

  2. HttpServlet:對(duì)http協(xié)議的一種封裝赶盔,簡(jiǎn)化操作

    1. 定義類繼承HttpServlet

    2. 重寫doGet/doPost方法

    3. 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)求行

  1. ServletRequest方法:

    // 獲取客戶端的IP地址*
    String getRemoteAddr()
    
    // 獲取服務(wù)端的端口號(hào)
    int getServerPort()
    
  2. 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)求頭*

  1. 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ù))*

  1. 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)
    
  2. 使用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ā)一起使用
  1. 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):
    1. 請(qǐng)求轉(zhuǎn)發(fā)的跳轉(zhuǎn)是由服務(wù)器發(fā)起的,因此跳轉(zhuǎn)操作不會(huì)發(fā)起新的請(qǐng)求西设,瀏覽器地址欄不會(huì)發(fā)生變化
    2. 請(qǐng)求轉(zhuǎn)發(fā)只能跳轉(zhuǎn)到本項(xiàng)目中的任意資源瓣铣,包括WEB-INF中的資源,不能跳轉(zhuǎn)到其他地方
    3. 請(qǐng)求轉(zhuǎn)發(fā)可以和ServletRequest域?qū)ο笠黄鹗褂?/li>
  1. 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)行

  1. HttpServletResponse方法:

    // 設(shè)置此響應(yīng)的狀態(tài)碼
    void setStatus(int sc)
    

7.2 設(shè)置響應(yīng)頭

  1. 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)體

  1. 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");
    
  2. 瀏覽器下載文件思路:

    1. 獲取文件名

    2. 設(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)
      
    3. 使用ServletContext對(duì)象獲取文件的MIME類型,并設(shè)置為響應(yīng)報(bào)文的Content-Type

    4. 使用ServletContext對(duì)象獲取指定文件名的輸入流is

    5. 通過response獲取輸出流os

    6. 將is文件復(fù)制到os

    7. 關(guān)閉os和is

7.4 請(qǐng)求重定向

  • 請(qǐng)求重定向特點(diǎn):
    1. 重定向的跳轉(zhuǎn)是由瀏覽器發(fā)起的雄人,因此跳轉(zhuǎn)操作會(huì)發(fā)起新的請(qǐng)求从橘,瀏覽器地址欄會(huì)變成跳轉(zhuǎn)到的地址
    2. 重定向跳轉(zhuǎn)可以跳轉(zhuǎn)到任意地方(訪問另一個(gè)項(xiàng)目中的資源時(shí)要使用完整的URL),但不能跳轉(zhuǎn)到WEB-INF中的資源
    3. 重定向跳轉(zhuǎn)不能和ServletRequest域?qū)ο笠黄鹗褂?/li>
  1. HttpServletResponse方法:

    // 使用指定重定向URL將臨時(shí)重定向響應(yīng)發(fā)送到客戶端
    void sendRedirect(String location)
    

8. 會(huì)話

  1. 從打開瀏覽器訪問某個(gè)站點(diǎn)础钠,到關(guān)閉瀏覽器的整個(gè)過程恰力,稱為一次會(huì)話
  2. 會(huì)話技術(shù)就是記錄一次會(huì)話中客戶端的狀態(tài)與數(shù)據(jù);會(huì)話技術(shù)分為Cookie和Session:
    1. Cookie:將一次會(huì)話的數(shù)據(jù)存儲(chǔ)在瀏覽器端旗吁;大小和個(gè)數(shù)都有限制踩萎;只能存儲(chǔ)字符串且不支持中文;不是很安全
    2. Session:將一次會(huì)話的數(shù)據(jù)存儲(chǔ)在服務(wù)器端很钓;原則上大小是沒有限制香府;可以存儲(chǔ)基本數(shù)據(jù)類型和對(duì)象;相對(duì)較安全

8.1 Cookie

  1. Cookie是一種客戶端的會(huì)話技術(shù)码倦,它是服務(wù)器存放在瀏覽器的一小份數(shù)據(jù)回还,瀏覽器以后每次訪問該服務(wù)器的時(shí)候都會(huì)將這小份數(shù)據(jù)攜帶到服務(wù)器去

  2. Cookie本質(zhì)是響應(yīng)頭的Set-Cookie和請(qǐng)求頭的Cookie

  3. 服務(wù)器往瀏覽器存儲(chǔ)Cookie:

    1. 創(chuàng)建一個(gè)Cookie對(duì)象:new Cookie(String name, String value)
    2. 設(shè)置Cookie對(duì)象的有效期:void setMaxAge(int expiry)
      1. -1:代表將Cookie數(shù)據(jù)保存到瀏覽器文件中直到瀏覽器關(guān)閉;默認(rèn)
      2. 正整數(shù):代表將數(shù)據(jù)以秒為單位保存到保存到磁盤中直到有效期到期
      3. 0:代表刪除瀏覽器端同name叹洲、同path的Cookie
    3. 設(shè)置Cookie對(duì)象的有效路徑:void setPath(String uri)
    4. 將Cookie添加到HttpServletResponse中
  4. 服務(wù)器從瀏覽器的請(qǐng)求中獲取Cookie:

    1. 從HttpServletRequest中獲取瀏覽器帶過來的所有Cookie
    2. 遍歷出每一個(gè)Cookie對(duì)象
    3. 根據(jù)getName()獲取key柠硕;根據(jù)getValue()獲取值
  5. name和path相同的Cookie會(huì)被覆蓋

  6. 當(dāng)Cookie被瀏覽器禁用時(shí),可以將Cookie的信息設(shè)置在URL中響應(yīng)給瀏覽器

  7. 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)
    
  8. 將Cookie添加到HttpServletResponse中的方法:

    void addCookie(Cookie cookie)
    
  9. 從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

  1. 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ì)象厢钧。

  2. 由于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)

  3. Session對(duì)象銷毀時(shí)機(jī)

    1. 默認(rèn)閑置30分鐘后銷毀霞扬,也可以調(diào)用HttpSession的setMaxInactiveInterval(int interval)方法修改
    2. 調(diào)用HttpSession的invalidate()方法銷毀
    3. 服務(wù)器異常關(guān)閉銷毀
  4. Session的執(zhí)行過程:

    1. 當(dāng)HttpServletRequest調(diào)用getSession()時(shí),會(huì)判斷本次請(qǐng)求中是否有一個(gè)名為JSESSIONID的Cookie
    2. 如果沒有枫振,則創(chuàng)建Session對(duì)象喻圃,并將該Session對(duì)象的JSESSIONID以Cookie形式響應(yīng)給瀏覽器
    3. 如果有,則根據(jù)JSESSIONID尋找指定的Session對(duì)象
    4. 如果指定的Session對(duì)象存在粪滤,則直接使用
    5. 如果指定的Session對(duì)象銷毀了斧拍,則執(zhí)行第2步
  5. HttpServletRequest獲取Session的方法:第一次調(diào)用時(shí)創(chuàng)建session,之后調(diào)用通過sessionId找到Session進(jìn)行使用

    HttpSession getSession()
    
  6. HttpSession在一次會(huì)話作為域?qū)ο蟠嫒?shù)據(jù)的方法:

    Object getAttribute(String name)
    void setAttribute(String name, Object value)
    void removeAttribute(String name)
    
  • 防止表單重復(fù)提交思路:

    1. 方式1:點(diǎn)擊表單頁面時(shí)杖小,給session中存儲(chǔ)一個(gè)標(biāo)志如subToken肆汹,并設(shè)置給表單頁面,表單提交時(shí)攜帶subToken窍侧,服務(wù)器判斷session中的subToken是否與表單攜帶來的一致县踢,若一致則提交成功并清除session中的subToken转绷,這樣重復(fù)提交時(shí)session中的subToken與表單攜帶來就不一致了
    2. 方式2:給數(shù)據(jù)庫增加唯一鍵約束伟件,確保數(shù)據(jù)庫只可以添加一條數(shù)據(jù)
    3. 方式3:提交成功后重定向
    4. 方式4:使用JavaScript設(shè)置標(biāo)志位,提交后屏蔽提交按鈕
    5. 方式5:使用AOP自定義切入
  • 使用Session校驗(yàn)驗(yàn)證碼思路:

    1. 創(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的路徑
      }
      
    2. 創(chuàng)建html頁面斧账,在img的src屬性中寫訪問步驟1中Servlet的路徑

    3. 在校驗(yàn)Servlet中,獲取html頁面輸入的驗(yàn)證碼內(nèi)容并和Session中的驗(yàn)證碼內(nèi)容進(jìn)行忽略大小寫的比較

    4. 切換圖片即重新設(shè)置img的src屬性煞肾,可以使用js的點(diǎn)擊事件完成咧织;為了防止緩存,可以在src的url后面加上請(qǐng)求參數(shù)籍救,讓每次的url不同

9. Servlet抽取思想

Servlet抽取思想:在一個(gè)Servlet實(shí)現(xiàn)類中自定義不同方法來處理不同請(qǐng)求

  1. 在每個(gè)請(qǐng)求中添加參數(shù)來標(biāo)識(shí)要調(diào)用的方法
  2. 獲取客戶端要調(diào)用的方法名
  3. 使用反射习绢,根據(jù)方法名獲取方法
  4. 執(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();
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末闪萄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子奇颠,更是在濱河造成了極大的恐慌败去,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烈拒,死亡現(xiàn)場(chǎng)離奇詭異圆裕,居然都是意外死亡广鳍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門吓妆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赊时,“玉大人,你說我怎么就攤上這事耿战〉暗穑” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵剂陡,是天一觀的道長(zhǎng)狈涮。 經(jīng)常有香客問我,道長(zhǎng)鸭栖,這世上最難降的妖魔是什么歌馍? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮晕鹊,結(jié)果婚禮上松却,老公的妹妹穿的比我還像新娘。我一直安慰自己溅话,他們只是感情好晓锻,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著飞几,像睡著了一般砚哆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上屑墨,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天躁锁,我揣著相機(jī)與錄音,去河邊找鬼卵史。 笑死战转,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的以躯。 我是一名探鬼主播槐秧,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼忧设!你這毒婦竟也來了刁标?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤见转,失蹤者是張志新(化名)和其女友劉穎命雀,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體斩箫,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吏砂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年撵儿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狐血。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淀歇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出匈织,到底是詐尸還是另有隱情浪默,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布缀匕,位于F島的核電站纳决,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏乡小。R本人自食惡果不足惜阔加,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望满钟。 院中可真熱鬧胜榔,春花似錦、人聲如沸湃番。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吠撮。三九已至尊惰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纬向,已是汗流浹背择浊。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工戴卜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留逾条,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓投剥,卻偏偏與公主長(zhǎng)得像师脂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子江锨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

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

  • 寫后記:2017/11/22最近因?yàn)榧ろ?xiàng)目需要做校園網(wǎng)的課表吃警、成績(jī)查詢功能,不得不使用模擬請(qǐng)求啄育,去請(qǐng)求uims教...
    大海畫家閱讀 1,247評(píng)論 0 2
  • Java Servlet 是運(yùn)行在服務(wù)器的程序酌心,是客戶端的請(qǐng)求和服務(wù)器的數(shù)據(jù)庫之間的中間層,它的主要任務(wù)為: 讀取...
    風(fēng)逍遙閱讀 477評(píng)論 0 0
  • 簡(jiǎn)介 java servlet:作為一個(gè)程序挑豌,其運(yùn)行在web服務(wù)器或其他應(yīng)用服務(wù)器上安券。其充當(dāng)客戶端請(qǐng)求和服務(wù)器上數(shù)...
    月明星稀_8184閱讀 402評(píng)論 0 0
  • Servlet: server applet 運(yùn)行在服務(wù)器端的小程序 Servlet就是一個(gè)接口墩崩,定義了Java類...
    聽你講故事啊閱讀 234評(píng)論 0 0
  • } // 設(shè)置響應(yīng)內(nèi)容類型response.setContentType("text/html;charset=U...
    卡斯特梅的雨傘閱讀 251評(píng)論 0 1