javaweb(2)之Servlet入門

Hello Servlet

  • 方式一

    一、新建 web 工程,編寫一個類,實現 javax.servlet.Servlet 接口:java

    package com.zze.servlet;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    public class HelloServlet1 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 Servlet1!!!");
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    
        @Override
        public void destroy() {
    
        }
    }
    Code

    二、在 WEB-INF/web.xml 的 web-app 節下加入以下配置:web

    <servlet>
        <!--給Servlet起名-->
        <servlet-name>HelloServlet1</servlet-name>
        <!--Servlet地址-->
        <servlet-class>com.zze.servlet.HelloServlet1</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <!--配置Servlet映射,該名稱對應上面已定義的Servlet名-->
        <servlet-name>HelloServlet1</servlet-name>
        <!--訪問時的路徑-->
        <url-pattern>/hello1</url-pattern>
    </servlet-mapping>

    三、接下來就能夠啓動服務,訪問 localhost:8080/hello1 :數組

  • 方式二

    一、同方式一相似,由於 tomcat 自己就爲咱們提供了 javax.servlet.Servlet 的實現類: javax.servlet.http.HttpServlet ,因此咱們直接繼承它,重寫咱們要使用的方法便可:瀏覽器

    package com.zze.servlet;
    
    import java.io.IOException;
    
    public class HelloServlet2 extends javax.servlet.http.HttpServlet {
        protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
            doGet(request, response);
        }
    
        protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
            response.getWriter().write("hello Servlet2!!!");
        }
    }
    Code

    二、同方式一,在 WEB-INF/web.xml 的 web-app 加入配置:tomcat

    <servlet>
        <servlet-name>HelloServlet2</servlet-name>
        <servlet-class>com.zze.servlet.HelloServlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet2</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>

    三、重啓 tomcat ,訪問 localhost:8080/hello2 :服務器

Servlet執行流程

建立 Servlet 以下,並加入配置:cookie

package com.zze.servlet;

import javax.servlet.*;
import java.io.IOException;

public class TestServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("from init");
    }

    @Override
    public ServletConfig getServletConfig() {
        System.out.println("from getServletConfig");
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("from service");
    }

    @Override
    public String getServletInfo() {
        System.out.println("from getServletInfo");
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("from destroy");
    }
}
Code

訪問,接着經過 shutdown.bat 關閉 tomcat, 查看輸出結果:session

from init
from service
from destroy
結論:
一、當 Servlet 被訪問時,會先執行它的 init 方法,接着纔是執行 service 方法,最後執行 destroy 方法。
二、init 方法只有在程序啓動後第一次訪問時纔會執行,service 方法會在每次訪問時執行。
三、destroy 執行有兩種狀況:第一種是經過 tomcat 的 shutdown.bat 腳本關閉 tomcat 時會執行,第二種狀況是將程序從 tomcat 中移除時會執行。

提早init方法的執行時機

能夠經過在 servlet 節下加入 load-on-startup 節讓指定 Servlet 實例的 init 方法在程序啓動時執行,以下:app

package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

public class TestServlet1 extends HttpServlet {
    @Override
    public void init() throws ServletException {
        System.out.println("form TestServlet1.init");
    }
}
com.zze.servlet.TestServlet1
package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

public class TestServlet2 extends HttpServlet {
    @Override
    public void init() throws ServletException {
        System.out.println("form TestServlet2.init");
    }
}
com.zze.servlet.TestServlet2
<?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_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>testServlet1</servlet-name>
        <servlet-class>com.zze.servlet.TestServlet1</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>testServlet2</servlet-name>
        <servlet-class>com.zze.servlet.TestServlet2</servlet-class>
        <load-on-startup>6</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>testServlet1</servlet-name>
        <url-pattern>/test1</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>testServlet2</servlet-name>
        <url-pattern>/test2</url-pattern>
    </servlet-mapping>
</web-app>
WEB-INF/web.xml

啓動程序,查看控制檯輸出:ide

form TestServlet1.init
form TestServlet2.init
結論:
一、只要 servlet 節下指定了 load-on-startup,那麼在程序啓動時這個節對應的 Servlet 就會被加載。
二、它的值必須是一個整數,表示 Servlet 的加載順序。
三、若是該元素的值爲負數或者沒有設置,則容器會當 Servlet 被請求時再加載。
四、若是值爲正整數或者 0 時,表示容器在應用啓動時就會加載並初始化該 Servlet,值越小,優先級越高,就越被先加載。值相同時,容器就會本身選擇順序來加載。

Servlet的初始化參數

package com.zze.servlet;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 獲取 ServletConfig 實例
        ServletConfig servletConfig = getServletConfig();
        // 獲取 Servlet 名稱,這個名稱指的是在 web.xml 中 servlet 節中配置的 servlet-name 節的值
        String servletName = servletConfig.getServletName();
        System.out.println(servletName);
        // 獲取當前 Servlet 對應 web.xml 中 servlet 節下全部 init-param 節 下的 param-name 節中的值
        Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
            String name = initParameterNames.nextElement();
            System.out.println(name);
            // 經過 init-param 下 param-name 的值獲取對應 param-value 的值
            String initParameterValue = servletConfig.getInitParameter(name);
            System.out.println(initParameterValue);
        }
       /*
       輸出結果:
       testServlet
       name
       bob
       age
       21
       */
    }
}
<?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_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>testServlet</servlet-name>
        <servlet-class>com.zze.servlet.TestServlet</servlet-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>bob</param-value>
        </init-param>
        <init-param>
            <param-name>age</param-name>
            <param-value>21</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>testServlet</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>
</web-app>
WEB-INF/web.xml

ServletContext使用

生命週期

建立:服務器啓動的時候,會爲託管的每個web應用程序,建立一個ServletContext對象

銷燬:從服務器移除託管,或者是關閉服務器。

獲取全局初始化參數

package com.zze.servlet;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;

public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        ServletContext servletContext = getServletContext();
        // 獲取 web.xml 中 web-app 節下全部 context-param 節 下的 param-name 節中的值
        Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
            String name = initParameterNames.nextElement();
            // 經過 context-param 下 param-name 的值獲取對應 param-value 的值
            String value = servletContext.getInitParameter(name);
            System.out.println(String.format("name:%s value:%s", name, value));
        }
        /*
        name:name value:rick
        name:age value:13
        */
    }
}
<?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_4_0.xsd"
         version="4.0">
    <context-param>
        <param-name>name</param-name>
        <param-value>rick</param-value>
    </context-param>
    <context-param>
        <param-name>age</param-name>
        <param-value>13</param-value>
    </context-param>
    <servlet>
        <servlet-name>testServlet</servlet-name>
        <servlet-class>com.zze.servlet.TestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>testServlet</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>
</web-app>
WEB-INF/web.xml
注:全局初始化參數的使用和 Servlet 的初始化參數類似,只是它的值在全部 Servlet 中均可以獲取到。

獲取web應用中的資源

現有以下結構:

若是想要在 Servlet 中讀取 test.properties ,能夠經過以下三種方式:

package com.zze.servlet;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class TestServletBak extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        func1();
        func2();
        func3();
    }

    private void func1() {
        try {
            ServletContext servletContext = getServletContext();
            // 參數傳入相對路徑:相對工程部署在 tomcat 下的工程根目錄
            InputStream inputStream = servletContext.getResourceAsStream("file/test.properties");
            Properties properties = new Properties();
            properties.load(inputStream);
            String name = properties.getProperty("name");
            System.out.println(String.format("from func1:%s", name));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void func2() {
        try {
            ServletContext servletContext = getServletContext();
            // 參數傳入相對路徑:相對工程部署在 tomcat 下的工程根目錄
            String realPath = servletContext.getRealPath("file/test.properties");
            FileInputStream inputStream = new FileInputStream(realPath);
            Properties properties = new Properties();
            properties.load(inputStream);
            String name = properties.getProperty("name");
            System.out.println(String.format("from func2:%s", name));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void func3() {
        try {
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("../../file/test.properties");
            Properties properties = new Properties();
            properties.load(inputStream);
            String name = properties.getProperty("name");
            System.out.println(String.format("from func3:%s", name));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

做用範圍

ServletContext 實例其實也是一個域對象,存儲在其中的數據能夠被全部 Servlet 共享。看以下示例:

package com.zze.servlet;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        ServletContext servletContext = getServletContext();
        servletContext.setAttribute("data", "this data is from SetServlet");
        System.out.println("set success");
    }
}
com.zze.servlet.SetServlet
package com.zze.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = getServletContext();
        String data = (String) servletContext.getAttribute("data");
        System.out.println(String.format("get success,data is '%s'",data));
    }
}
com.zze.servlet.GetServlet

依次訪問 SetServlet、GetServlet ,獲得輸出結果:

set success
get success,data is 'this data is from SetServlet'

請求對象-HttpServletRequest

獲取請求相關數據

package com.zze.servlet;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;

public class TestSerlvet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp){
        // 獲取請求頭
        Enumeration<String> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = req.getHeader(headerName);
            System.out.println(String.format("%s:%s", headerName, headerValue));
        }
        // cache-control:no-cache
        // postman-token:7b0b1d95-d1bd-4282-b516-40ea14910741
        // user-agent:PostmanRuntime/7.3.0
        // accept:*/*
        // host:localhost:8080
        // cookie:JSESSIONID=BB60472100AF2B9054BC9F61515203A8
        // accept-encoding:gzip, deflate
        // connection:keep-alive

        // 獲取請求參數
        Map<String, String[]> parameterMap = req.getParameterMap();
        Iterator<String> keys = parameterMap.keySet().iterator();
        while (keys.hasNext()) {
            String key = keys.next();
            String[] values = parameterMap.get(key);
            System.out.println(String.format("%s:%s", key, values[0]));
        }
        // name:zhangsan
    }
}

解決中文參數亂碼

方法一:手動編碼再解碼。

package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;

public class TestSerlvet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException {
        String value = req.getParameter("name");
        // 由於咱們提交參數時編碼是"UTF-8" 而req.getParameter 默認使用 "ISO-8859-1" 進行解碼,
        // 因此咱們能夠先用 "ISO-8859-1" 將其編碼回字節數組,而後使用"UTF-8"解碼就可正確顯示內容
        String valueStr = new String(value.getBytes("ISO-8859-1"), "UTF-8");
        System.out.println(String.format("%s:%s", "name", valueStr));
        // name:張三
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 設置以什麼編碼解析請求體,對 GET 方式無用
        req.setCharacterEncoding("UTF-8");
        String name = req.getParameter("name");
        System.out.println(name);
        // 張三
    }
}

方法二:配置 tomcat 的解碼方式:

在 tomcat 目錄下的 conf/server.xml 中 Connector 節下加上 URIEncoding 屬性:

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />

以後 req.getParameter 就會使用 UTF-8 進行解碼了。

響應對象-HttpServletResponse

響應內容

package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 設置輸出 ContentType
        response.setContentType("text/plain;charset=utf-8");
        // 設置響應狀態碼
        response.setStatus(200);
        // 以字符流方式響應數據
        response.getWriter().write("hello");
        // 以字節流方式響應數據
        response.getOutputStream().write("world".getBytes());
    }
}

解決中文響應亂碼

package com.zze.servlet;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 設置輸出 ContentType,讓瀏覽器以 utf-8 解析響應內容
        response.setContentType("text/plain;charset=utf-8");
        // 以 utf-8 編碼響應內容
        response.setCharacterEncoding("utf-8");
        // 以字符流方式響應數據
        response.getWriter().write("哈哈哈哈哈");
        // java.lang.String.getBytes() 默認使用 utf-8 編碼
        response.getOutputStream().write("啦啦啦啦啦".getBytes("utf-8"));
    }
}

下載文件

package com.zze.servlet;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class TestServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 文件名
        String fileName = "testdownload.cs";
        // 文件路徑
        String filePath = "files/" + fileName;
        // 設置響應頭通知瀏覽器下載文件而不是直接打開
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        // 獲取該文件輸入流
        // String realPath = getServletContext().getRealPath(filePath);
        // InputStream inputStream = new FileInputStream(realPath);
        InputStream inputStream = getServletContext().getResourceAsStream(filePath);
        // 轉化爲輸出流響應
        ServletOutputStream outputStream = response.getOutputStream();
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, len);
        }
        outputStream.close();
        inputStream.close();
    }
} 

解決下載文件時中文文件名亂碼

public static String EncodeFileName(HttpServletRequest request, String fileName) {
    try {
        String downloadFileName = null;
        String agent = (String) request.getHeader("USER-AGENT");
        if (agent != null && agent.toLowerCase().indexOf("firefox") > 0) {
            downloadFileName = "=?UTF-8?B?" + (new String(Base64.getEncoder().encode(fileName.getBytes("UTF-8")))) + "?=";
        } else {
            downloadFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
        }
        return downloadFileName;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

請求轉發和重定向

請求轉發

package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("from TestServlet1");
        request.getRequestDispatcher("/test2").forward(request,response);
    }
}
path:/test1
package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("from TestServlet2");
        response.getWriter().write("from TestServlet2");
    }
}
path:/test2

訪問 localhost:8080/test1 ,輸出結果:

from TestServlet1
from TestServlet2

重定向

package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("from TestServlet1");
        response.sendRedirect("/test2");
        /*
        至關於:
        response.setStatus(302);
        response.setHeader("Location","/test2");
        */
    }
}
path:/test1
package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("from TestServlet2");
        response.getWriter().write("from TestServlet2");
    }
}
path:/test2

訪問 localhost:8080/test1 ,輸出結果:

from TestServlet1
from TestServlet2

總結:
一、地址欄:重定向顯示的是最後顯示的資源地址;而請求轉發顯示的是最初請求的那個地址。
二、請求次數:重定向最少有兩次請求,服務器在接收到請求後,會經過返回狀態碼 302 告知瀏覽器須要重定向,經過響應頭中的 Location 告知瀏覽器重定向位置;而請求轉發只有一次,由於服務器內部幫客戶端執行了後續的工做。
三、跳轉路徑:重定向能夠跳轉到任意路徑,不是本身的工程路徑也能夠跳轉;請求轉發只能在當前項目路徑中跳轉。
四、request對象:由於重定向就是發起一個新的請求,因此 request 就是一個新的 request 對象,沒法使用上一次的 request 對象;而請求轉發本質上仍是同一次請求,因此能夠正常使用初始請求對象。

Cookie和Session

Cookie

package com.zze.servlet;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class SetCookieServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        Cookie cookie1 = new Cookie("name", "zhangsan");
        cookie1.setDomain("localhost"); // 設置請求指定域時才攜帶 cookie
        cookie1.setPath("/cookie"); // 設置請求指定路徑時才攜帶 cookie
        cookie1.setMaxAge(60); // 設置有效時間,單位爲「秒」
        Cookie cookie2 = new Cookie("age","20");
        response.addCookie(cookie1);
        response.addCookie(cookie2);
        System.out.println("請求成功");
    }
}
path:/cookie/set
package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class GetCookieServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            String name = cookie.getName();
            String value = cookie.getValue();
            System.out.println(String.format("name:%s,value:%s",name,value));
        }
    }
}
path:/cookie/get

先訪問 localhost:8080/cookie/set :

再訪問 localhost:8080/cookie/get ,控制檯輸出:

name:age,value:20
name:name,value:zhangsan
name:_gcl_au,value:1.1.931601231.1544668650
name:_ga,value:GA1.1.337106894.1544668656
name:_pk_id.5.1fff,value:2b0610186745f3b2.1545900897.3.1545987031.1545986337.
name:_gid,value:GA1.1.1827212045.1546481630

Cookie 實際上就是存儲在瀏覽器端的一個小數據。由於 http 請求是無狀態的,即客戶端和服務器通信的時候是無狀態的。Cookie 的做用就是能夠幫咱們在每次請求的時候攜帶數據到服務端,而服務端能夠根據接收到的攜帶的數據間接實現狀態持久。

Session

package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class SetSessionServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        session.setAttribute("name", "zhangsan");
        session.setAttribute("age",21);
        System.out.println("設置 Session 成功");
    }
}
path:/session/set
package com.zze.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Enumeration;

public class GetSessionServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        Enumeration<String> attributeNames = session.getAttributeNames();
        while (attributeNames.hasMoreElements()){
            String name = attributeNames.nextElement();
            Object value = session.getAttribute(name);
            System.out.println(String.format("name:%s value:%s",name,value.toString()));
        }
    }
}
path:/session/get

先訪問 localhost:8080/session/set ,再訪問 localhost:8080/session/get ,控制檯輸出:

設置 Session 成功
SessionId:A2582CD80E2AFCE986D15C9C4C5FCF68
name:name value:zhangsan
name:age value:21

能夠看到,請求 localhost:8080/session/get 時攜帶的名爲 JSESSIONID 的 Cookie 值就是輸出的 SessionId。

Session 是基於 Cookie 實現的,它實際上就是經過 Cookie 攜帶惟一 SessionId 值幫助客戶端在服務端維護一塊對應的獨立的內存空間。
相關文章
相關標籤/搜索