Hello Servlet

  • 方式一

    1、新建 web 工程,编写一个类,实现 javax.servlet.Servlet 接口:

    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

    2、在 WEB-INF/web.xml 的 web-app 节下加入如下配置:

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

    3、接下来就可以启动服务,访问 localhost:8080/hello1 :

  • 方式二

    1、同方式一类似,因为 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

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

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

    3、重启 tomcat ,访问 localhost:8080/hello2 :

Servlet执行流程

创建 Servlet 如下,并加入配置:

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, 查看输出结果:

from init
from service
from destroy
结论:
1、当 Servlet 被访问时,会先执行它的 init 方法,接着才是执行 service 方法,最后执行 destroy 方法。
2、init 方法只有在程序启动后第一次访问时才会执行,service 方法会在每次访问时执行。
3、destroy 执行有两种情况:第一种是通过 tomcat 的 shutdown.bat 脚本关闭 tomcat 时会执行,第二种情况是将程序从 tomcat 中移除时会执行。

提前init方法的执行时机

可以通过在 servlet 节下加入 load-on-startup 节让指定 Servlet 实例的 init 方法在程序启动时执行,如下:

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

启动程序,查看控制台输出:

form TestServlet1.init
form TestServlet2.init
结论:
1、只要 servlet 节下指定了 load-on-startup,那么在程序启动时这个节对应的 Servlet 就会被加载。
2、它的值必须是一个整数,表示 Servlet 的加载顺序。
3、如果该元素的值为负数或者没有设置,则容器会当 Servlet 被请求时再加载。
4、如果值为正整数或者 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

总结:
1、地址栏:重定向显示的是最后显示的资源地址;而请求转发显示的是最初请求的那个地址。
2、请求次数:重定向最少有两次请求,服务器在接收到请求后,会通过返回状态码 302 告知浏览器需要重定向,通过响应头中的 Location 告知浏览器重定向位置;而请求转发只有一次,因为服务器内部帮客户端执行了后续的工作。
3、跳转路径:重定向可以跳转到任意路径,不是自己的工程路径也可以跳转;请求转发只能在当前项目路径中跳转。
4、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 值帮助客户端在服务端维护一块对应的独立的内存空间。

javaweb(2)之Servlet入门的更多相关文章

  1. 浅谈JavaWEB入门必备知识之Servlet入门案例详解

    工欲善其事.必先利其器,想要成为JavaWEB高手那么你不知道servlet是一个什么玩意的话,那就肯定没法玩下去,那么servlet究竟是个什么玩意?下面,仅此个人观点并通过一个小小的案例来为大家详 ...

  2. JavaWeb之Servlet入门(二)

    1. 准备 在JavaWeb之Servlet入门(一)中,我们完成了第一个Servlet程序,完成了从URL到后台控制器的中转过程,接下来我们延续JavaWeb之Servlet入门(一)学习下如何传参 ...

  3. Servlet视频学习笔记 57-58 (servlet入门和调用过程)

    网易云课堂<30天轻松掌握JavaWeb视频>servlet部分 课时57 servlet开发入门 servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术.S ...

  4. JavaWeb学习之Servlet(二)----Servlet的生命周期、继承结构、修改Servlet模板

    [声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4140466.html 一.http协议回顾: 在上一篇文章中:JavaW ...

  5. HTTP协议 Servlet入门 Servlet工作原理和生命周期 Servlet细节 ServletConfig对象

    1 HTTP协议特点   1)客户端->服务端(请求request)有三部份     a)请求行--请求行用于描述客户端的请求方式.请求的资源名称,以及使用的HTTP协议版本号 请求行中的GET ...

  6. JavaWeb三大组件(Servlet,Filter,Listener 自己整理,初学者可以借鉴一下)

    JavaWeb三大组件(Servlet,Filter,Listener 自己整理,初学者可以借鉴一下) Reference

  7. java之servlet入门操作教程一续

    本节主要是在java之servlet入门操作教程一  的基础上使用myeclipse实现自动部署的功能 准备: java之servlet入门操作教程一 中完成myFirstServlet项目的创建: ...

  8. (转)JavaWeb学习之Servlet(二)----Servlet的生命周期、继承结构、修改Servlet模板

    [声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4140466.html 一.http协议回顾: 在上一篇文章中:JavaW ...

  9. servlet入门与进阶

    servlet入门与进阶 1.servlet基础认知 Servlet(Server Applet):全称Java Servlet,是用Java编写的服务器端程序,其主要功能在于交互式地浏览和修改数据, ...

随机推荐

  1. 【转】RPC简单介绍

    RPC简单介绍 RPC 1. RPC是什么 RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络 ...

  2. C++ 如何决定字面常量类型

    C++ 是如何决定字面常量的类型的? #include <iostream> #include <cmath> int main() { using namespace std ...

  3. (笔记)一场由SD卡引发的灾难

    一场由SD卡引发的灾难   注:此文章转自“https://user.qzone.qq.com/63915185/blog/1512562541”.   Flash里面的数据在使用过程中莫名改变或不翼 ...

  4. GoLang之反射

    反射 反射(reflect) 所谓反射(reflect)就是能检查程序在运行时的状态. 使用反射的三条定律: 反射可以将“接口类型变量”转换为“反射类型对象”: 反射可以将“反射类型对象”转换为“接口 ...

  5. Ubuntu 10.04下架设流媒体服务器

    Ubuntu 10.04下架设流媒体服务器 个人建议:使用DarwinStreamingSrvr5.5.5,因为DarwinStreamingSrvr6.0.3安装过程中有很多问题需要解决! 目前主流 ...

  6. JavaScript系统对象

    1. 本地对象(非静态对象) 常用对象有: Object.Function.Array.String.Boolean.Number.Date.RegExp.Error 注:本地对象需要new之后再使用 ...

  7. GPRS模块在Linux平台上ppp拨号上网总结与心得

    linux平台的ppp拨号上网,(注明:这里只谈命令行拨号,用linux就要习惯和熟练使用命令行) 在网上常见的有三种方式:1.使用智能的ppp拨号软件wvdial:参考案例:本博客的<使用wv ...

  8. Redis防止重複請求鎖功能

    class Lock { const PREFIX_KEY = "MY_LOCK:"; static private $LOCKED = []; static public fun ...

  9. LeetCode - 768. Max Chunks To Make Sorted II

    This question is the same as "Max Chunks to Make Sorted" except the integers of the given ...

  10. PXC 57 二进制安装

    1.准备阶段 1.1 在三个节点上分别创建:用户组 用户组 目录 --用户组 用户组 #/usr/sbin/groupadd mysql #/usr/sbin/useradd -g mysql mys ...