Servlet

发布时间 2023-09-12 20:06:05作者: yanggdgg

一、Servlet继承结构

1. 概述

   tomcat服务器提供了Servlet规范的实现。我们写的代码要想被服务器调用,也必须遵守Servlet规范。
  自定义的Servlet类并没有去直接实现Servlet接口,是因为该接口中方法较多,Servlet接口有它的一系列实现类,我们继承实现类即间接的实现了Servlet接口。

 

2. 继承结构体系

 2.1 Servlet接口

package javax.servlet;

import java.io.IOException;

public interface Servlet {
//init(),创建Servlet对象后立即调用该方法完成一些初始化工作
    void init(ServletConfig var1) throws ServletException;
//getServletConfig(),ServletConfig是容器向servlet传递参数的载体
    ServletConfig getServletConfig();
//service(),处理客户端请求,执行业务操作,通过响应对象响应客户端请求
  void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; 
//getServletInfo(),获取servlet相关信息
  String getServletInfo(); 
//destroy(),在销毁前Servlet对象之前调用该方法
  void destroy(); 
}

2.2 ServletConfig接口

package javax.servlet;

import java.util.Enumeration;

public interface ServletConfig {
//返回Servlet的名字,即web.xml中<servlet-name>的值
    String getServletName();
//返回一个代表当前Web应用的ServletContext对象
    ServletContext getServletContext();
//根据初始化参数返回对应的初始化参数值
    String getInitParameter(String var1);
//返回一个Enumeration对象,包含了所有的初始化参数名
    Enumeration<String> getInitParameterNames();
}

2.3 GenericServlet抽象类

GenericServlet是实现了Servlet接口的抽象类;

在GenericServlet中进一步定义ileServlet接口的具体实现,设计目的是为了与应用层协议解耦;

在GenericServlet中包含一个Service抽象方法。

2.4 HttpServlet类

针对于处理HTTP协议的请求所定制;

HttpServlet继承了GenericServlet,实现了service方法,将ServletRequest对象和ServletResponse对象强转为HttpServletRequest对象和HttpServletResponse对象。

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request;
        HttpServletResponse response;
        try {
//将请求对象、响应对象强转
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)res;
        } catch (ClassCastException var6) {
            throw new ServletException(lStrings.getString("http.non_http"));
        }
//又调用了本类中的service方法(匹配请求方法作对应处理)
        this.service(request, response);
    }

2.5 注意事项

  tomcat服务器在接收到浏览器的请求后,会调用Servlet的service方法处理器请求,如果当前自定义的Servlet类没有service方法会调用父类的service方法进行处理。

二、Servlet的生命周期

1. 执行过程

Servlet的生命周期是由容器管理的,分别经历三个阶段:

  初始化:创建Servlet实例化对象,执行init()方法

  服务:调用service()方法处理接收到的请求数据并响应

  销毁:当退出服务器前,会调用destroy()方法进行servlet的销毁

 2. 注意

1.Servlet对象只会被创建及初始化一次,然后驻留在内存中而不是使用完就销毁;

2.创建及初始化Servlet对象时机

  ① 默认情况下在服务器第一次收到对应请求,经过解析创建Servlet实例对象

  ② 如果配置了 load-on-starup(优先级) 就在启动服务器时创建和初始化。

3.当服务器关闭时,Servlet才会被销毁

三、Servlet在Tomcat中运行的原理

启动Tomcat服务器后,

  1. 解析web项目的web.xml文件 

    ①默认情况:

      解析出url-partten和servlet-class

    ②配置了load-on-startup:

      解析出的url-partten作为key,根据servlet-class通过反射创建Servlet的对象作为value,存储到map集合中。

  2.Tomcat服务器接收请求

  3.Tomcat服务器解析请求,查找请求的资源

    ①默认情况:根据url解析的结果,找到web.xml中匹配的url-partten,获取包名和类名,利用反射完成方法的调用。

    ②配置了load-on-startup:根据url解析的结果,在map集合中根据key(url-partten)获取对应的实例化对象,调用service方法。

注意:以上流程是Tomcat自动执行,是不可见的。

四、请求对象(HttpServletRequest)

  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。

  • GET请求只能进行url编码,而POST支持多种编码方式。

  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

  • GET请求在URL中传送的参数是有长度限制的,而POST则没有。对参数的数据类型GET只接受ASCII字符,

  • POST既可是字符也可是字节。

  • GET相比POST来说不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

  • GET参数通过URL传递,POST放在Request body中。

1. request对象来源

浏览器发送请求后,由tomcat服务器接收到,然后对请求的信息进行解析,将解析结果封装到HttpServletRequest和HttpServletResponse两个对象中。

然后tomcat通过反射调用service方法的时候,又将这两个对象传递给了service方法。

2. request对象的特点

  1. 在tomcat服务器接收请求后,对请求进行解析后创建的。

  2. 每次请求,tomcat服务器都会重新创建。

  3. request对象存储了此次请求的所有数据(http协议中的请求行、头、体)。

3. request对象的使用

 

1.request对象获取请求行数据

        //获取请求行信息
        //获取请求方式
        String method = req.getMethod();
        System.out.println("请求方式是:" + method);

        //获取请求的URI
        String uri = req.getRequestURI();
        System.out.println("请求的URI是:" + uri);

        //获取请求协议
        String scheme = req.getScheme();
        System.out.println("请求的协议是:" + scheme);

 

 

2.request对象获取请求头数据

  //获取请求头信息,根据键名去获取
        //获取请求的主机信息
        String host = req.getHeader("host");
        System.out.println("请求的主机信息是:" + host);
-------------------------------------------------------------------
//获取所有的请求头信息
//拿到所有请求头的名字
Enumeration<String> headerNames = req.getHeaderNames();
while(headerNames.hasMoreElements()){
String key = headerNames.nextElement();
String value = req.getHeader(key);
System.out.println(key + ":" + value);
}

 

 

3.request对象获取请求体数据

String name = req.getParameter("name");

 

 

4.request对象获取其他数据

 

//获取其他数据
        //获取项目路径, 格式是 /项目名
        String contextPath = req.getContextPath();
        System.out.println("项目路径是:" + contextPath);

        //获取请求的url地址
        String url = req.getRequestURL().toString();
        System.out.println("请求的url地址是:" + url);

        //获取服务器的ip
        String serverName = req.getServerName();
        System.out.println("服务器的ip地址是:" + serverName);

        //获取服务器的端口
        int serverPort = req.getServerPort();
        System.out.println("服务器的端口是:" + serverPort);
    }
}

4. 乱码问题

目前我们在请求体中如果携带的请求数据存在中文,在后台使用req.getParameter方法获取的时候会出现乱码,出现乱码的本质原因是因为编码与解码方式不一致导致的。

Tomcat服务器接收到请求后,会解析请求,并将请求中的数据给封装到HttpServletRequest对象中。所以,我们对request对象中的数据进行重新编码即可。

在service方法中设置

req.setCharacterEncoding("utf-8");

注意:要在调用getParameter方法前设置编码