JavaWeb(一)---servlet

C/S架构和B/S架构

C/S架构
  • C/S架构(Client/Server,客户端/服务器模式),是一种比较早的软件体系结构,也是生活中很常
    见的结构。这种结构将需要处理的业务合理地分配到客户端和服务器端,客户端通常负责完成与用户的交互任务,服务器通常负责数据的管理。C/S架构的主要优点如下:
    • 客户端的界面和功能可以很丰富。
    • 应用服务器的负荷较轻。
    • 响应速度较快。
  • C/S架构的主要缺点如下:
    • 适用面窄,用户群固定。
    • 维护和升级的成本高,所有的客户端都需要更新版本
B/S架构
  • B/S架构(Browser/Server,浏览器/服务器模式),是互联网兴起后的软件体系结构,该结构将
    系统功能实现的主要业务逻辑集中到服务器端,极少数业务逻辑在浏览器实现,浏览器通常负责完成与用户的交互任务,服务器通常负责数据的管理。B/S架构的主要优点如下:
    • 无需安装客户端,只要有浏览器即可。
    • 适用面广,用户群不固定。
    • 通过权限控制实现多客户访问的目的,交互性较强。
    • 维护和升级的成本低,无需更新所有客户端版本。
  • B/S架构的主要缺点如下:
    • 应用服务器的负荷较重。
    • 浏览器的界面和功能想要达到客户端的丰富程度需要花费大量的成本。
    • 在跨浏览器上不尽如人意,适配比较麻烦。
JavaWeb概念
  • Web本意为网页的含义,这里表示互联网上供外界访问的资源。
    互联网上供外界访问的资源主要分为以下两种:
    • 静态资源:主要指Web页面中供人们浏览的数据始终是不变。
    • 动态资源:主要指Web页面中供人们浏览的数据由程序产生,不同时间点访问页面看到的内
      容各不相同。
  • JavaWeb主要指使用Java语言进行动态Web资源开发技术的统称,是解决相关Web互联网领域的技术总和。
  • 早期的B/S架构
    在这里插入图片描述
  • 后来的B/S架构
    在这里插入图片描述
HTTP协议
概念
  • HTTP协议(HyperText Transfer Protocol,超文本传输协议)是由W3C(万维网联盟)组织制定
    的一种应用层协议,是用来规范浏览器与Web服务器之间如何通讯的数据格式,主要涉及浏览器
    的发请求格式和服务器的响应格式。
  • HTTP协议通常承载于TCP协议之上,而承载于TLS或SSL协议层之上的协议就是常说的HTTPS协
    议。
  • HTTP默认的端口号为80,HTTPS默认的端口号为443。
    在这里插入图片描述
HTTP请求格式
  • 客户端发送一个HTTP请求到服务器的请求消息主要包括:请求行、请求头、空白行和请求体。
请求行用来说明请求类型和要访问的资源以及所使用的HTTP版本,格式如下:
   请求类型 请求的路径 协议的版本(1.1)
请求头是紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息,格式
(key:value)如下:
   主机 请求长度 请求的浏览器相关信息
空白行就是请求头部的空行,即使后面的请求数据为空则必须有空行。
请求体也叫请求数据,可以添加任意的其他
  • 举例
POST /task01_demo01/demo1.html HTTP/1.1 
Host: localhost:8088 
Content-Length: 21 
Cache-Control: max-age=0 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64)
name=scott&pwd=1234
HTTP响应格式
  • 通常情况下服务器接收并处理客户端发过来的请求后会返回一个HTTP的响应消息,主要包括:响
    应行、响应头、空白行和响应体
响应行用来说明HTTP协议版本号和状态码以及状态消息,格式如下:
   协议的版本(1.0 1.1)  状态码 (200 成功  404 路径错误  500 服务错误) 状态信息
响应头用来说明客户端要使用的一些附加信息,格式(key:value)。 
空白行就是响应头部的空行,即使后面的请求数据为空则必须有空行。
    
响应体用来服务器返回给客户端的文本信息。
  • 举例
HTTP/1.1 200 OK   
Content-Type: text/html 
Content-Length: 588 
Date: Thu, 08 Sep 2021 12:59:54 GMT
<html><head><title>示例1</title></head>
<body><h1>这是一个HTML页面</h1></body>
</html>
Tomcat服务器
概念
  • Tomcat本意为公猫的含义,最初是由Sun公司的软件架构师詹姆斯·邓肯·戴维森开发的,后来他帮
    助将其变为开源项目并由Sun公司贡献给Apache软件基金会。
  • Tomcat 服务器是一个开源的轻量级Web应用服务器,在中小型系统和并发量小的场合下被普遍使
    用,是开发和调试Servlet、JSP 程序的首选。
安装方式
  • 下载解压即可:http://tomcat.apache.org/
目录结构
  • bin 主要存放二进制可执行文件和脚本。
  • conf 主要存放各种配置文件。
  • lib 主要用来存放Tomcat运行需要加载的jar包。
  • logs 主要存放Tomcat在运行过程中产生的日志文件。
  • temp 主要存放Tomcat在运行过程中产生的临时文件。
  • webapps 主要存放应用程序,当Tomcat启动时会去加载该目录下的应用程序。
  • work 主要存放tomcat在运行时的编译后文件,例如JSP编译后的文件。
启动和关闭
  • 启动方式
    使用bin目录下的批处理文件startup.bat来启动Tomcat服务器,若出现一个毫秒数说明启动成
    功。
  • 关闭方式
    使用bin目录下的批处理文件shutdown.bat来关闭Tomcat服务器。
  • 注意事项
    启动之前首先安装JDK并配置环境变量JAVA_HOME,若希望Tomcat服务器可以在任意路径启动,则需要配置环境变量CATALINA_HOME。
    启动信息乱码的处理方式:logging.properties文件修改为
    java.util.logging.ConsoleHandler.encoding = GBK
配置文件(修改后要重启服务器)
  • server.xml文件是服务器的主配置文件,可以设置端口号、设置域名或IP、默认加载的项目、请求
    编码等。
    Connector port="8888" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />
    
  • tomcat-users.xml文件用来配置管理Tomcat服务器的用户与权限
    <role rolename="manager-gui"/>
    <user username="admin" password="123456" roles="manager-gui"/>
    
Tomcat的默认访问路径
  • Tomcat服务器会优先访问webapps下ROOT的index.jsp,如果有index.html会优先访问index.html
IDEA创建web项目
  • 创建空项目->创建模块->选择Java Enterprise->选择Application server->勾选Web Application
  • 配置Tomcat服务器,新增服务器,更改Deployment->Application context的名称
Servle的概念和使用
概念
  • Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,是Java语言编写的服务器端程序,换句话说,Servlet就是运行在服务器上的Java类。
  • Servlet用来完成B/S架构下客户端请求的响应处理,也就是交互式地浏览和生成数据,生成动态Web内容。
编程步骤
  • 建立一个Java Web Application项目并配置Tomcat服务器。
  • 自定义类实现Servlet接口或继承 HttpServlet类(推荐) 并重写service方法。
  • 将自定义类的信息配置到 web.xml文件并启动项目,配置方式如下:
<!-- 配置Servlet -->
<servlet>
<!-- HelloServlet是Servlet类的别名 -->
<servlet-name> HelloServlet </servlet-name>
<!-- com.nxy.task01.HelloServlet是包含路径的真实的Servlet类名 -->
<servlet-class> com.nxy.task01.HelloServlet </servlet-class>
</servlet>
<!-- 映射Servlet -->
<servlet-mapping>
<!-- HelloServlet是Servlet类的别名,与上述名称必须相同 -->
<servlet-name> HelloServlet </servlet-name>
<!-- /hello是供浏览器使用的地址 -->
<url-pattern> /hello </url-pattern>
</servlet-mapping>
Servlet接口
  • javax.servlet.Servlet接口用于定义所有servlet必须实现的方法。

  • 常用方法

    方法声明方法介绍
    void init(ServletConfig config)由servlet容器调用,以向servlet指示servlet正在被放入服务中
    void service(ServletRequest req,ServletResponse res)由servlet容器调用,以允许servlet响应请求
    ServletConfig getServletConfig()返回ServletConfig对象,该对象包含此servlet的初始化和启动参数
    String getServletInfo()返回有关servlet的信息,如作者、版本和版权
    void destroy()由servlet容器调用,以向servlet指示该servlet正在退出服务
    import javax.servlet.*;
    import java.io.IOException;
    
    public class HelloServlet 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 {
            System.out.println("接收到了浏览器的请求并做出了响应!");
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
GenericServlet类
  • 概念
    • javax.servlet.GenericServlet类主要用于定义一个通用的、与协议无关的servlet,该类实现了
      Servlet接口。
    • 若编写通用servlet,只需重写service抽象方法即可。
  • 常用方法
    方法声明方法介绍
    abstract void service(ServletRequest req,ServletResponse res)由servlet容器调用允许servlet响应请求
    import javax.servlet.GenericServlet;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import java.io.IOException;
    
    public class HelloServlet2 extends GenericServlet {
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            System.out.println("继承GenericServlet类的方式来创建Servlet");
        }
    }
    
HttpServlet类
  • 概念
    • javax.servlet.http.HttpServlet类是个抽象类并继承了GenericServlet类。
    • 用于创建适用于网站的HTTP Servlet,该类的子类必须至少重写一个方法。
  • 常用方法
    方法声明方法介绍
    void doGet(HttpServletRequestreq,HttpServletResponse resp)处理客户端的GET请求
    void doPost(HttpServletRequestreq,HttpServletResponse resp)处理客户端的POST请求
    void init()进行初始化操作
    void service(HttpServletRequest req,HttpServletResponse resp)根据请求决定调用doGet还是doPost方法
    void destroy()删除实例时释放资源
    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 HelloServlet3 extends HttpServlet {
    
        public HelloServlet3() {
            System.out.println("构造方法调用了");
        }
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("这是采用继承HttpServlet类的方式创建,以后的开发中推荐该方式!");
        }
    
        @Override
        public void destroy() {
            System.out.println("销毁操作开始喽...");
        }
    
        @Override
        public void init() throws ServletException {
            System.out.println("初始化操作开始喽...");
        }
    }
    
使用注解
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "HelloServlet4", urlPatterns = "/hello4")
public class HelloServlet4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Post请求方式...");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Get请求方式...");
        this.doPost(request, response);
    }

   /* @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("使用注解...");
        String method = req.getMethod();
        System.out.println("获取到的请求方式为:" + method);
        if ("get".equalsIgnoreCase(method)) {
            doGet(req, resp);
        }
        if ("post".equalsIgnoreCase(method)) {
            doPost(req, resp);
        }
    }*/
}

Servlet 生命周期

在这里插入图片描述

  • 构造方法只被调用一次,当第一次请求Servlet时调用构造方法来创建Servlet的实例。
  • init方法只被调用一次,当创建好Servlet实例后立即调用该方法实现Servlet的初始化。
  • service方法被多次调用,每当有请求时都会调用service方法来用于请求的响应。
  • destroy方法只被调用一次,当该Servlet实例所在的Web应用被卸载前调用该方法来释放当前占用
    的资源。
POST和GET请求
GET请求
发出GET请求的主要方式:
(1)在浏览器输入URL按回车
(2)点击<a>超链接
(3)点击submit按钮,提交 <form method=“get”>表单
GET请求特点:
会将请求数据添加到请求URL地址的后面,只能提交少量的数据、不安全
POST请求
发出POST请求的方法如下:
点击submit按钮,提交 <form method=“post”>表单
POST请求的特点:
请求数据添加到HTTP协议体中,可提交大量数据、安全性好
ServletRequest接口
概念
 - javax.servlet.ServletRequest接口主要用于向servlet提供客户端请求信息,可以从中获取到任何请求信息。
- Servlet容器创建一个ServletRequest对象,并将其作为参数传递给Servlet的service方法。
常用方法
方法声明方法介绍
String getParameter(String name)以字符串形式返回请求参数的值,如果该参数不存在,则返回空值
String[] getParameterValues(String name)返回一个字符串对象数组,其中包含给定请求参数所具有的所有值,如果该参数不存在,则返回空值
Enumeration getParameterNames()返回包含此请求中包含的参数名称的字符串对象的枚举。如果请求没有参数,则方法返回空枚举
Map<String, String[]> getParameterMap()返回请求参数的键值对,一个键可以对应多个值
String getRemoteAddr()返回发送请求的客户端或最后一个代理的IP地址
int getRemotePort()返回发送请求的客户端或最后一个代理的端口号
HttpServletRequest接口
概念
  • javax.servlet.http.HttpServletRequest接口是ServletRequest接口的子接口,主要用于提供HTTP请求信息的功能。
  • 不同于表单数据,在发送HTTP请求时,HTTP请求头直接由浏览器设置。
  • 可直接通过HttpServletRequest对象提供的一系列get方法获取请求头数据。
常用方法
方法声明方法介绍
String getRequestURI()返回此请求的资源路径信息
StringBuffer getRequestURL()返回此请求的完整路径信息
String getMethod()返回发出此请求的HTTP方法的名称,例如GET、POST
String getQueryString()返回路径后面请求中附带的参数
String getServletPath()返回此请求中调用servlet的路径部分
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>请求参数的获取和测试</title>
</head>
<body>
<form action="parameter" method="post">
    姓名:<input type="text" name="name"/><br/>
    年龄:<input type="text" name="age"/><br/>
    爱好:<input type="checkbox" name="hobby" value="Java"/>Java
          <input type="checkbox" name="hobby" value="C"/>C
          <input type="checkbox" name="hobby" value="C++"/>C++<br/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>
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.PrintWriter;
import java.util.Enumeration;
import java.util.Map;
import java.util.Random;
import java.util.Set;

public class ParameterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 6.设置请求信息中的编码方式为utf-8来解决乱码问题
        request.setCharacterEncoding("utf-8");

        // 1.获取指定参数名称对应的参数值并打印
        String name = request.getParameter("name");
        System.out.println("获取到的姓名为:" + name);
        String[] hobbies = request.getParameterValues("hobby");
        System.out.print("获取到的爱好有:");
        for (String ts : hobbies) {
            System.out.print(ts + " ");
        }
        System.out.println();

        System.out.println("-------------------------------------------------------");
        // 2.获取所有参数的名称
        Enumeration<String> parameterNames = request.getParameterNames();
        System.out.print("获取到的所有参数名称为:");
        while (parameterNames.hasMoreElements()) {
            System.out.print(parameterNames.nextElement() + " ");
        }
        System.out.println();

        System.out.println("-------------------------------------------------------");
        // 3.获取请求参数名和对应值的第二种方式
        Map<String, String[]> parameterMap = request.getParameterMap();
        // 使用Map集合中所有的键值对组成Set集合
        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
        // 遍历Set集合
        for (Map.Entry<String, String[]> me : entries) {
            System.out.print(me.getKey() + "对应的数值有:");
            for (String ts : me.getValue()) {
                System.out.print(ts + " ");
            }
            System.out.println();
        }

        System.out.println("-------------------------------------------------------");
        // 4.获取客户端请求的其它信息
        System.out.println("发送请求的客户端IP地址为:" + request.getRemoteAddr());
        System.out.println("发送请求的客户端端口号为:" + request.getRemotePort());
        System.out.println("请求资源的路径为:" + request.getRequestURI());
        System.out.println("请求资源的完整路径为:" + request.getRequestURL());
        System.out.println("请求方式为:" + request.getMethod());
        System.out.println("请求的附带参数为:" + request.getQueryString());
        System.out.println("请求的Servlet路径为:" + request.getServletPath());

        System.out.println("-------------------------------------------------------");
        // 5.向浏览器发出响应数据
        // 获取响应数据的默认编码方式
        String characterEncoding = response.getCharacterEncoding();
        System.out.println("服务器响应数据的默认编码方式为:" + characterEncoding); // ISO-8859-1
        // 设置服务器和浏览器的编码方式以及文本类型
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = response.getWriter();
        //writer.write("I Received!");
        //writer.write("我接收到了!");
        Random ra = new Random();
        int num = ra.nextInt(100) + 1;
        writer.write("<h1>" + num + "</h1>");
        System.out.println("服务器发送数据成功!");
        writer.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
ServletResponse接口
概念
  • javax.servlet.ServletResponse接口用于定义一个对象来帮助Servlet向客户端发送响应。
  • Servlet容器创建ServletResponse对象,并将其作为参数传递给servlet的service方法。
常用方法
方法声明方法介绍
PrintWriter getWriter()返回可向客户端发送字符文本的PrintWriter对象
String getCharacterEncoding()获取响应内容的编码方式
void setContentType(String type)如果尚未提交响应,则设置发送到客户端响应的内容类型。内容类型可以包括字符编码规范,例如text/html;charset=UTF-8
HttpServletReponse 接口
概念
  • javax.servlet.http.HttpServletResponse接口继承ServletResponse接口,以便在发送响应时提供特定于HTTP的功能。
常用方法
方法声明方法介绍
void sendRedirect(String location)使用指定的重定向位置URL向客户端发送临时重定向响应
示例
// 继承HttpServlet
public class HelloWorld extends HttpServlet {
	// 重写HttpServlet中的doGet方法
	protected void doGet(HttpServletRequest request, HttpServletResponse
	response)
	throws IOException, ServletException {
	// 设置响应输出编码,避免中文乱码
	response.setContentType(“text/html;charset=utf-8);
	// 获取响应输出流
	PrintWriter out= response.getWriter();
	// 利用输出流输出信息
	out.println(<html><body> Hello world!</body></html>);
	//关闭流
	out.close();
	}
}
Servlet接受中文乱码
原因
  • 浏览器在提交表单时,会对中文参数值进行自动编码。当Tomcat服务器接收到浏览器请求后自动解码,当编码与解码方式不一致时,就会导致乱码。
解决POST接受乱码
接收之前设置编码方式:
request.setCharacterEncoding(“utf-8”)
提示:
必须在调用request.getParameter(“name”)之前设置
解决GET接受乱码
将接收到的中文乱码重新编码:
// 接收到get请求的中文字符串
String name = request.getParameter("name");
// 将中文字符重新编码,默认编码为ISO-8859-1
String userName = new String(name.getBytes(“ISO-8859-1”),“utf-8");
ServletConfig接口
概念
  • javax.servlet.ServletConfig接口用于描述Servlet本身的相关配置信息,在初始化期间用于将信息传递给Servlet配置对象。
配置方式
 <servlet>
        <servlet-name>ConfigServlet</servlet-name>
        <servlet-class>com.nxy.demo02.ConfigServlet</servlet-class>
        <!-- 实现初始化参数的配置 -->
        <init-param>
            <!-- 初始化参数的名称 -->
            <param-name>userName</param-name>
            <!-- 初始化参数的数值 -->
            <param-value>admin</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>123456</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>ConfigServlet</servlet-name>
        <url-pattern>/config</url-pattern>
    </servlet-mapping>
常用方法
方法声明方法介绍
String getServletName()返回Servlet的别名
String getInitParameter(String name)返回包含初始化参数值的字符串,如果该参数不存在,则返回null
Enumeration getInitParameterNames()将servlet的初始化参数的名称作为字符串对象的枚举返回,如果servlet没有初始化参数,则返回空枚举
ServletContext getServletContext()返回对调用方正在其中执行的ServletContext的引用
示例
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;

public class ConfigServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("初始化操作执行了...");
        System.out.println("Servlet的别名是:" + servletConfig.getServletName()); // ConfigServlet

        System.out.println("-----------------------------------------------");
        // 获取配置文件中的初始化参数信息
        String userName = servletConfig.getInitParameter("userName");
        System.out.println("获取到的初始化用户名为:" + userName);
        // 获取所有配置参数的名称
        Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
            System.out.println("初始化参数名为:" + initParameterNames.nextElement());
        }

        System.out.println("-----------------------------------------------");
        // 获取ServletContext接口的引用
        ServletContext servletContext = servletConfig.getServletContext();
        System.out.println("获取到的ServletContext引用为:" + servletContext);
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}
ServletContext接口
概念
  • javax.servlet.ServletContext接口主要用于定义一组方法,Servlet使用这些方法与它的Servlet容器通信。
  • 服务器容器在启动时会为每个项目创建唯一的一个ServletContext对象,用于实现多个Servlet之间的信息共享和通信。
  • 在Servlet中通过this.getServletContext()方法可以获得ServletContext对象。
配置方式
<!--在web.xml中配置ServletContext初始化参数 -->
<context-param>
	<param-name>username</param-name>
	<param-value>scott</param-value>
<context-param>
<context-param>
	<param-name>password</param-name>
	<param-value>tiger</param-value>
<context-param>
常用方法
方法声明方法介绍
String getInitParameter(String name)返回包含初始化参数值的字符串,如果该参数不存在,则返回null
Enumeration getInitParameterNames()将servlet的初始化参数的名称作为字符串对象的枚举返回,如果servlet没有初始化参数,则返回空枚举
String getRealPath(String path)返回包含给定虚拟路径的实际路径的字符串
String getContextPath()返回与此上下文关联的主路径
InputStream getResourceAsStream(String path将位于指定路径的资源作为InputStream对象返回
void setAttribute(String name, Object object)将指定的属性名和属性值绑定到当前对象
Object getAttribute(String name)根据执行的属性名获取属性值
void removeAttribute(String name)删除指定的属性名信息
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;
import java.util.Enumeration;

public class ContextServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.配置参数的获取
        ServletContext servletContext = getServletConfig().getServletContext();
        Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
            String s = initParameterNames.nextElement();
            System.out.println( s + "对应的值为:" + servletContext.getInitParameter(s));
        }

        System.out.println("----------------------------------------------------------");
        // 2.相关路径的获取
        // 本质上就是获取工程路径    /工程名
        String contextPath = servletContext.getContextPath();
        System.out.println("获取上下文关联的路径信息为:" + contextPath); // /task01_demo02

        // / 在服务器被解析为: http://ip地址:端口号/工程名  获取实际路径信息
        // 获取到的是部署工程路径信息   对应  当前工程中的web目录
        String realPath = servletContext.getRealPath("/");
        // C:\Users\Marz\IdeaProjects\javaweb\out\artifacts\task01_demo02_war_exploded\
        System.out.println("获取到的实际路径信息为:" + realPath);

        System.out.println("----------------------------------------------------------");
        // 3.设置和获取属性信息
        servletContext.setAttribute("key", "value");
        Object key = servletContext.getAttribute("key");
        System.out.println("根据参数指定的属性名获取到的属性值为:" + key); // value
        servletContext.removeAttribute("key");
        key = servletContext.getAttribute("key");
        System.out.println("根据参数指定的属性名获取到的属性值为:" + key); // null
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
Servlet+JDBC应用
  • 在Servlet中可以使用JDBC技术访问数据库,常见功能如下:
    • 查询DB数据,然后生成显示页面,例如:列表显示功能。
    • 接收请求参数,然后对DB操作,例如:注册、登录、修改密码等功能。
  • 为了方便重用和便于维护等目的,经常会采用DAO(Data Access Object)模式对数据库操作进行独立封装
    在这里插入图片描述
  • DAO工厂(工厂模式)
    工厂类:封装了对象的创建细节,为调用者提供
    符合要求的对象。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>实现简单的注册功能</title>
</head>
<body>
<form action="register" method="post">
    用户名:<input type="text" name="userName"/><br/>&nbsp;&nbsp;&nbsp;&nbsp;码:<input type="text" name="password"/><br/>
    <input type="submit" value="注册"/>
</form>
</body>
</html>
<?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>RegisterServlet</servlet-name>
        <servlet-class>com.nxy.demo01.servlet.RegisterServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RegisterServlet</servlet-name>
        <url-pattern>/register</url-pattern>
    </servlet-mapping>
</web-app>
package com.nxy.demo01.model;

public class User {
    private int id;
    private String userName;
    private String password;

    public User() {
    }

    public User(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
package com.nxy.demo01.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class DbUtil {
    private static String jdbcName;   // 用于描述驱动信息
    private static String dbUrl;      // 用于描述URL信息
    private static String dbUserName; // 用户描述用户名信息
    private static String dbPassword; // 用户描述密码信息

    // 进行静态成员的初始化操作
    static {
        jdbcName = "com.mysql.jdbc.Driver";
        dbUrl = "jdbc:mysql://localhost:3306/db_web";
        dbUserName = "root";
        dbPassword = "123456";
        try {
            Class.forName(jdbcName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        Connection con = DriverManager.getConnection(dbUrl, dbUserName, dbPassword);
        return con;
    }

    /**
     * 关闭连接
     * @param con
     * @throws SQLException
     */
    public static void closeConnection(Connection con, PreparedStatement psts) throws SQLException {
        if (null != con) {
            con.close();
        }
        if (null != psts) {
            psts.close();
        }
    }
}

package com.nxy.demo01.dao;

import com.nxy.demo01.model.User;
import com.nxy.demo01.util.DbUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class UserDao {

    public int createUser(User user) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try {
            // 1.获取连接
            connection = DbUtil.getConnection();
            // 2.准备sql语句
            String sql = "insert into t_user values(null, ?, ?)";
            // 3.获取PrepareStatement类型的引用
            preparedStatement = connection.prepareStatement(sql);
            // 4.向问号所占的位置设置数据
            preparedStatement.setString(1, user.getUserName());
            preparedStatement.setString(2, user.getPassword());
            // 5.执行sql语句
            int row = preparedStatement.executeUpdate();
            return row; // 执行成功
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 6.关闭资源
            try {
                DbUtil.closeConnection(connection, preparedStatement);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return 0; // 执行失败
    }
}

import com.nxy.demo01.dao.UserDao;
import com.nxy.demo01.model.User;

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.PrintWriter;

public class RegisterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.获取请求对象中保存的用户名和密码信息
        String userName = request.getParameter("userName");
        System.out.println("获取到的用户名为:" + userName);
        String password = request.getParameter("password");
        System.out.println("获取到的密码为:" + password);
        // 2.将接受到的用户名和密码信息打包成用户对象交给DAO层进行处理
        User user = new User(userName, password);
        UserDao userDao = new UserDao();
        int res = userDao.createUser(user);
        // 3.将处理结果响应到浏览器
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        if (1 == res) {
            System.out.println("注册成功!");
            writer.write("<h1>注册成功!</h1>");
        } else {
            writer.write("<h1>注册失败!</h1>");
        }
        writer.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
重定向和转发
重定向的概述

(1)重定向的概念
首先客户浏览器发送http请求,当web服务器接受后发送302状态码响应及对应新的location给客户浏览器,客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址,服务器根据此请求寻找资源并发送给客户。
(2)重定向的实现
实现重定向需要借助javax.servlet.http.HttpServletResponse接口中的以下方法:

方法声明方法介绍
void sendRedirect(String location)使用指定的重定向位置URL向客户端发送临时重定向响应

(3)重定向的原理

在这里插入图片描述
(4)重定向的特点

  • 重定向之后,浏览器地址栏的URL会发生改变。
  • 重定向过程中会将前面Request对象销毁,然后创建一个新的Request对象。
  • 重定向的URL可以是其它项目工程。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>重定向的测试</title>
</head>
<body>
<form action="redirectServlet" method="post">
    <input type="submit" value="重定向"/>
</form>
</body>
</html>
package com.nxy.demo02.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 RedirectServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("接收到了浏览器的请求...");
        // 重定向,也就是给浏览器发送一个新的位置
        //response.sendRedirect("target.html");
        response.sendRedirect("https://www.baidu.com/index.php?tn=monline_3_dg");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
转发的概述
概念
  • 一个Web组件(Servlet/JSP)将未完成的处理通过容器转交给另外一个Web组件继续处理,转发的各个组件会共享Request和Response对象。
实现
  • 绑定数据到Request对象
方法声明方法介绍
Object getAttribute(String name)将指定属性值作为对象返回,若给定名称属性不存在,则返回空值
void setAttribute(String name,Object o)在此请求中存储属性值
  • 获取转发器对象
方法声明方法介绍
RequestDispatcher getRequestDispatcher(String path)返回一个RequestDispatcher对象,该对象充当位于给定路径上的资源的包装器
  • 转发操作
方法声明方法介绍
void forward(ServletRequest request, ServletResponse response)将请求从一个servlet转发到服务器上的另一个资源(Servlet、JSP文件或HTML文件
package com.nxy.demo02.servlet;

import javax.servlet.RequestDispatcher;
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 ForwardServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("接收到了浏览器的请求...");
        // 向request对象中设置属性信息
        request.setAttribute("key1", "value1");
        // 转发,也就是让Web组件将任务转交给另外一个Web组件
        //RequestDispatcher requestDispatcher = request.getRequestDispatcher("/targetServlet");
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("https://www.baidu.com/index.php?tn=monline_3_dg");
        requestDispatcher.forward(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
package com.nxy.demo02.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 TargetServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("转发过来了...");
        // 获取request对象中的属性值判断是否共享
        Object key1 = request.getAttribute("key1");
        System.out.println("获取到的属性值为:" + key1); // value1
        // 通过打印流向页面写入转发成功的信息
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("<h1>转发成功!</h1>");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

转发的特点
  • 转发之后浏览器地址栏的URL不会发生改变。
  • 转发过程中共享Request对象。
  • 转发的URL不可以是其它项目工程。
重定向和转发的比较

在这里插入图片描述

Servlet线程安全
  • 服务器在收到请求之后,会启动一个线程来进行相应的请求处理。
  • 默认情况下,服务器为每个Servlet只创建一个对象实例。当多个请求访问同一个Servlet时,会有多个线程访问同一个Servlet对象,此时就可能发生线程安全问题。
  • 多线程并发逻辑,需要使用synchronized对代码加锁处理,但尽量避免使用。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Servlet线程安全的测试</title>
</head>
<body>
<iframe width="600px" height="100px" src="thread?name=zhangfei"></iframe><br/>
<iframe width="600px" height="100px" src="thread?name=guanyu"></iframe><br/>
<iframe width="600px" height="100px" src="thread?name=liubei"></iframe><br/>
</body>
</html>
package com.nxy.demo02.servlet;

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

@WebServlet(name = "ThreadServlet", urlPatterns = "/thread")
public class ThreadServlet extends HttpServlet {

    //private String name; // 准备一个成员变量,作为共享资源

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //synchronized (this) {
            // 1.获取request对象中名字为name的参数数值并赋值给成员变量name
            String name = request.getParameter("name");
            System.out.println("获取到的name数值为:" + name);
            // 2.睡眠5秒钟
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 3.使用打印流将成员变量name的数值发送给浏览器
            PrintWriter writer = response.getWriter();
            writer.write("<h1>" + name + "</h1>");
            writer.close();
        //}
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}
状态管理
  • Web程序基于HTTP协议通信,而HTTP协议是”无状态”的协议,一旦服务器响应完客户的请求之后,就断开连接,而同一个客户的下一次请求又会重新建立网络连接。
  • 服务器程序有时是需要判断是否为同一个客户发出的请求,比如客户的多次选购商品。因此,有必要跟踪同一个客户发出的一系列请求。
  • 把浏览器与服务器之间多次交互作为一个整体,将多次交互所涉及的数据保存下来,即状态管理。
  • 多次交互的数据状态可以在客户端保存,也可以在服务器端保存。状态管理主要分为以下两类:
    客户端管理:将状态保存在客户端。基于Cookie技术实现。
    服务器管理:将状态保存在服务器端。基于Session技术实现。
Cookie技术(浏览器)
  • 基本概念
    • Cookie本意为”饼干“的含义,在这里表示客户端以“名-值”形式进行保存的一种技术。
    • 浏览器向服务器发送请求时,服务器将数据以Set-Cookie消息头的方式响应给浏览器,然后浏览器
      会将这些数据以文本文件的方式保存起来。
    • 当浏览器再次访问服务器时,会将这些数据以Cookie消息头的方式发送给服务器
相关的方法
  • 使用javax.servlet.http.Cookie类的构造方法实现Cookie的创建

    方法声明方法介绍
    Cookie(String name, String value)根据参数指定数值构造对象
  • 使用javax.servlet.http.HttpServletResponse接口的成员方法实现Cookie的添加

    方法声明方法介绍
    void addCookie(Cookie cookie)添加参数指定的对象到响应
    package com.nxy.demo03.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet(name = "CookieServlet", urlPatterns = "/cookie")
    public class CookieServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.测试一下浏览器的请求是否到达
            System.out.println("看看有没有执行到这里哦!");
            // 2.创建Cookie对象并添加到响应信息中
            Cookie cookie = new Cookie("name", "zhangfei");
            response.addCookie(cookie);
            System.out.println("创建Cookie成功!");
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    
  • 使用javax.servlet.http.HttpServletRequest接口的成员方法实现Cookie对象的获取

    方法声明方法介绍
    Cookie[] getCookies()返回此请求中包含的所有Cookie对象
    package com.nxy.demo03.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet(name = "CookieServlet2", urlPatterns = "/cookie2")
    public class CookieServlet2 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.获取客户端发来的Cookie信息并打印出来
            Cookie[] cookies = request.getCookies();
            System.out.println("获取到的Cookie信息有:");
            for (Cookie tc : cookies) {
                System.out.println(tc.getName() + "对应的值为:" + tc.getValue());
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    
  • 使用javax.servlet.http.Cookie类的构造方法实现Cookie对象中属性的获取和修改

    方法声明方法介绍
    String getName()返回此Cookie对象中的名字
    String getValue()返回此Cookie对象的数值
    void setValue(String newValue)设置Cookie的数值
    package com.nxy.demo03.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet(name = "CookieServlet3", urlPatterns = "/cookie3")
    public class CookieServlet3 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.获取客户端发来的Cookie信息并打印出来
            Cookie[] cookies = request.getCookies();
            for (Cookie tc : cookies) {
                // 2.当获取到的Cookie对象的名字为name时,将对应的数值修改为guanyu并添加到响应信息中
                if ("name".equalsIgnoreCase(tc.getName())) {
                    tc.setValue("guanyu");
                    response.addCookie(tc);
                    break;
                }
            }
            System.out.println("修改Cookie信息成功!");
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    
  • Cookie的生命周期

    • 默认情况下,浏览器会将Cookie信息保存在内存中,只要浏览器关闭,Cookie信息就会消失。
    • 如果希望关闭浏览器后Cookie信息仍有效,可以通过Cookie类的成员方法实现。
    方法声明功能介绍
    int getMaxAge()返回cookie的最长使用期限(以秒为单位)
    void setMaxAge(int expiry)设置cookie的最长保留时间(秒)
    package com.nxy.demo03.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @WebServlet(name = "CookieServlet4", urlPatterns = "/cookie4")
    public class CookieServlet4 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.创建Cookie信息
            Cookie cookie = new Cookie("name", "liubei");
            // 2.获取Cookie信息的默认使用期限
            int maxAge = cookie.getMaxAge();
            System.out.println("该Cookie的默认使用期限是:" + maxAge);
            // 3.修改Cookie信息的使用期限
            // 正数表示在指定的秒数后失效   负数表示浏览器关闭后失效   0表示马上失效
            //cookie.setMaxAge(0);
            cookie.setMaxAge(60*10);
            // 4.添加到响应信息中
            response.addCookie(cookie);
            System.out.println("设置Cookie的生命周期成功!");
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
  • Cookie的路径问题

    • 浏览器在访问服务器时,会比较Cookie的路径与请求路径是否匹配,只有匹配的Cookie才会发送给服务器
    • Cookie的默认路径等于添加这个Cookie信息时的组件路径,例如:/项目名/目录/add.do请求添加了一个Cookie信息,则该Cookie的路径是 /项目名/目录。
    方法声明功能介绍
    void setPath(String uri)设置cookie的路径信息访问的请求地址必须符合Cookie的路径或者其子路径时,浏览器才会发送Cookie信息
Cookie的特点
  • Cookie技术不适合存储所有数据,程序员只用于存储少量、非敏感信息,原因如下:
    • 将状态数据保存在浏览器端,不安全。
    • 保存数据量有限制,大约4KB左右。
    • 只能保存字符串信息。
    • 可以通过浏览器设置为禁止使用。
Session技术
概念
  • Session本意为"会话"的含义,是用来维护一个客户端和服务器关联的一种技术。
  • 浏览器访问服务器时,服务器会为每一个浏览器都在服务器端的内存中分配一个空间,用于创建一个Session对象,该对象有一个id属性且该值唯一,我们称为SessionId,并且服务器会将这个SessionId以Cookie方式发送给浏览器存储。
  • 浏览器再次访问服务器时会将SessionId发送给服务器,服务器可以依据SessionId查找相对应的Session对象。
相关的方法
  • 使用javax.servlet.http.HttpServletRequest接口的成员方法实现Session的获取。

    方法声明方法介绍
    HttpSession getSession()返回此请求关联的当前Session,若此请求没有则创建一个
    package com.nxy.demo03.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    @WebServlet(name = "SessionServlet", urlPatterns = "/session")
    public class SessionServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.调用getSession方法获取或者创建Session对象
            HttpSession session = request.getSession();
            // 2.判断该Session对象是否为新建的对象
            System.out.println(session.isNew()? "新创建的Session对象": "已有的Session对象");
            // 3.获取编号并打印
            String id = session.getId();
            System.out.println("获取到的Session编号为:" + id);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    
    • 使用javax.servlet.http.HttpSession接口的成员方法实现判断和获取。
    方法声明方法介绍
    boolean isNew()判断是否为新创建的Session
    String getId()获取Session的编号
  • 使用javax.servlet.http.HttpSession接口的成员方法实现属性的管理。

    方法声明方法价绍
    Object getAttribute(String name)返回在此会话中用指定名称绑定的对象,如果没有对象在该名称下绑定,则返回空值
    void setAttribute(String name, Object value)使用指定的名称将对象绑定到此会话
    void removeAttribute(String name)从此会话中删除与指定名称绑定的对象
    package com.nxy.demo03.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    @WebServlet(name = "SessionServlet2", urlPatterns = "/session2")
    public class SessionServlet2 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            HttpSession session = request.getSession();
            // 1.设置属性名和属性值
            session.setAttribute("name", "machao");
            // 2.获取指定属性名对应的属性值
            System.out.println("获取到的属性值为:" + session.getAttribute("name")); // machao
            // 3.删除指定的属性名
            session.removeAttribute("name");
            // 4.获取指定属性名对应的属性值
            System.out.println("获取到的属性值为:" + session.getAttribute("name")); // null
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    
Session的生命周期
  • 为了节省服务器内存空间资源,服务器会将空闲时间过长的Session对象自动清除掉,服务器默认的超时限制一般是30分钟。

  • 使用javax.servlet.http.HttpSession接口的成员方法实现失效实现的获取和设置

    方法声明方法介绍
    int getMaxInactiveInterval()获取失效时间
    void setMaxInactiveInterval(int interval)设置失效时间
    package com.nxy.demo03.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.io.IOException;
    
    @WebServlet(name = "SessionServlet3", urlPatterns = "/session3")
    public class SessionServlet3 extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.获取Session对象
            HttpSession session = request.getSession();
            // 2.获取对象的默认失效时间并打印
            int maxInactiveInterval = session.getMaxInactiveInterval();
            System.out.println("获取到的失效时间为:" + maxInactiveInterval); // 1800
            // 3.修改实现时间后重新获取并打印
            session.setMaxInactiveInterval(1200);
            maxInactiveInterval = session.getMaxInactiveInterval();
            System.out.println("获取到的失效时间为:" + maxInactiveInterval); // 1200
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doPost(request, response);
        }
    }
    
    
  • 可以配置web.xml文件修改失效时间。

    <session-config>
    	<session-timeout>30</session-timeout>
    </session-config>
    
Session的特点
  • 数据比较安全。
  • 能够保存的数据类型丰富,而Cookie只能保存字符串。
  • 能够保存更多的数据,而Cookie大约保存4KB。
  • 数据保存在服务器端会占用服务器的内存空间,如果存储信息过多、用户量过大,会严重影响服务器的性能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值