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. mac 上安装 openJDK11

    紧接上篇,mac现在基本上作为开发者的主力机,当然也要安装jdk的 首先需要卸载原来的jdk8,如下: ls /Library/Java/JavaVirtualMachines/ sudo rm -r ...

  2. Python中的string模块的学习

    代码为主,相信有python基础的都能看懂: ? [python] view plain copy >>> import string   >>> string.a ...

  3. 理解、学习与使用 JAVA 中的 OPTIONAL<转>

    从 Java 8 引入的一个很有趣的特性是 Optional  类.Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都 ...

  4. Smart Link

    Smart Link通过两个接口相互配合工作来实现功能.这样的一对接口组成了一个Smart Link组.为了区别一个Smart Link组中的两个接口,我们将其中的一个叫做主接口,另一个叫做从接口.同 ...

  5. SpringBoot 全配置(推荐收藏)

    # =================================================================== # COMMON SPRING BOOT PROPERTIE ...

  6. C_C++变量命名规则

    变量命名规则是为了增强代码的可读性和容易维护性.以下为C++必须遵守的变量命名规则: 变量名只能是字母(A-Z,a-z)和数字(0-9)或者下划线(_)组成. 第一个字母必须是字母或者下划线开头. 不 ...

  7. 【Linux常用工具】

    tmux - 终端分屏工具 man - Help cat/more/less - 文件阅读 less还具有字符串搜索功能

  8. nginx的日志配置

    本文转自:https://www.cnblogs.com/biglittleant/p/8979856.html 版权归属原作者!!!!!! nginx access日志配置 access_log日志 ...

  9. linux Ubuntu系统安装百度aip

    1.下载百度api pip install baidu-aip 2.配置视频转码工具ffmpeg Ubuntu16.04下安装FFmpeg(超简单版) 第一步:添加源. sudo add-apt-re ...

  10. [Manthan, Codefest 18][Codeforces 1037F. Maximum Reduction]

    题目链接:1037F - Maximum Reduction 题目大意:给出一段代码,给你一个长度为n的数组和数字k,求程序运行结果,mod 1e9+7输出 简单翻译下代码的意思,初始定义一个空数组b ...