Servlet

一、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才会被销毁

4.我们自始至终都使用同一个Servlet对象去处理请求(单例模式),如果同时有10个请求过来访问Tomcat服务器,服务器会创建10个线程来处理请求,

所以避免使用全局变量, 多个线程操作全局变量存在线程安全的问题, service()方法中的局部变量不存在线程安全问题。

三、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"); 

//getParameterValues()方法可以获取多个参数名一样的数据,会得到一个数组(获取复选框的内容用这种方式)
String[] hobbies = req.getParameterValues("hobby");
System.out.println("爱好是:" + Arrays.toString(hobbies));

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方法前设置编码

注意:tomcat8.0之后,无论是get请求还是post请求只需要设置req.setCharacterEncoding("utf-8")即可

   tomcat8.0前,post请求乱码用req.setCharacterEncoding("utf-8")

         get请求用String s = new String(req.getParameter("name").getBytes("iso-8859-1"),"utf-8");

五、响应对象(HttpServletResponse)

1. 介绍

response响应对象用于响应浏览器发起的请求,其中封装了响应结果数据及客户端的一些信息等。

2. 使用

response对象是在服务器收到请求解析完后创建的,之后被传到了我们写的servlet中的service方法中,可以直接使用。

Tomcat底层会将response响应的内容自动转换为HTTP协议的格式,输出给浏览器。

​响应方法: response.getWriter().write(“响应内容”); 底层是本质就是网络编程的流输出。 注意:响应内容可以直接是数据,也可以是数据+HTML标签+CSS样式+JS脚本。

2.1  设置响应头

复制代码
//setHeader()方法作用:设置响应头,key相同的话,后面设置的值会覆盖前面设置的
resp.setHeader("key1", "value1");
resp.setHeader("key2", "value2");
resp.setHeader("key1", "value1_1");

//addHeader()方法作用:设置响应头,key相同的话,后面设置的值不会覆盖前面设置的
resp.addHeader("name1", "value1");
resp.addHeader("name2", "value2");
resp.addHeader("name1", "value1_1");

//下面两行代码是等价的
resp.setContentType("text/html;charset=utf-8");//设置响应的数据类型及解码方式
resp.setHeader("Content-Type", "text/html;charset=utf-8");//设置响应的数据类型及解码方式
复制代码

3. 注意

  1. 由Tomcat接收到请求后完成创建,并作为实参传递给对应的service方法使用,直接调用即可。

  2. 每次请求都会重新创建,请求结束后即销毁。

  3. HttpServletResponse是一个接口,service方法接收到的是实例化对象。

4. 乱码问题

目前我们在后端service方法中使用response对象响应浏览器时,如果响应结果中存在中文,会在浏览器中出现乱码。

因为Tomcat服务器默认使用utf-8的编码格式编码响应数据,而浏览器默认使用ISO-8859-1来解析响应数据。

解决:告诉浏览器使用utf-8的方式来解析数据。

resp.setContentType("text/html;charset=utf-8");

六、@WebServlet注解开发Servlet

在Servlet3.0以及之后的版本中支持注解式开发Servlet。对于Servlet的配置不再依赖于web.xml配置文件,而是使用@WebServlet注解完成Servlet的配置。

属性名类型作用
initParams WebInitParam[] Servlet的init参数
name String Servlet的名称
urlPatterns String[] Servlet的访问URL,支持多个
value String[] Servlet的访问URL,支持多个
loadOnStartup int 自启动Servlet
description String Servlet的描述
@WebServlet(name = "first", value = "/first", 
loadOnStartup = 1,
initParams = {@WebInitParam(name = "test", value = "aaa")},
description = "测试servlet")

注意:

  只指定一个value时,可以省略value

@WebServlet("/请求路径")

 

515-443-5015
posted @   ygdgg  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示