目 录CONTENT

文章目录

Servlet

在等晚風吹
2023-12-04 / 0 评论 / 0 点赞 / 12 阅读 / 0 字 / 正在检测是否收录...

Servlet

实现 Servlet 规范

​ 该类必须实现 Servlet 规范,即继承 HttpServlet 类(这个类需要jar包支持,这个jar包在哪里?在tomcatl-ib下的servlet-api.jar中),后续只需要进行业务的实现即可。

package com.study.testservlet;

public class Servlet01 extends HttpServlet {

}

重写 service 方法

​ 满足 Servlet 规范只是让我们的类能够满足接收请求的要求,接收到请求后需要对请求进行分析,以及进行业务逻辑处理,计算出结果,则需要添加代码,在规范中有一个叫做 service的方法,专门用来做请求处理的操作,我们要重写service方法,业务代码则可以写在该方法中。

package com.study.testservlet;

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;


public class Servlet01 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 控制台打印一句话
        System.out.println("hi servlet");
        // 响应一句话给浏览器
        resp.getWriter().write("hi servlet");
    }
}

设置注解

​ 在完成好了一切代码的编写后,还需要向服务器说明,特定请求对应特定资源。

​ 开发servlet项目,使用@WebServlet将一个继承于javax.servlet.http.HttpServlet 的类定义为Servlet组件。在Servlet3.0中 , 可以使用@WebServlet注解将一个继承于javax.servlet.http.HttpServlet的类标注为可以处理用户请求的 Servlet。

package com.study.testservlet;

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("/s01")
public class Servlet01 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 控制台打印一句话
        System.out.println("hi servlet");
        // 响应一句话给浏览器
        resp.getWriter().write("hi servlet");
    }
}

还可以用其它写法配置 Servlet:

@WebServlet(name="Servlet01",value="/ser01")
@WebServlet(name="Servlet01",urlPatterns = "/ser01")

也可以配置多个访问路径

@WebServlet(name="Servlet01",value={"/ser01",'/ser001'})
@WebServlet(name="Servlet01",urlPatterns={"/ser01",'/ser001'})

Servlet的其它实现方式

方式1:extends HttpServlet 类

方式2:extends GenericServlet抽象类

方式1代码:

package com.study.testservlet;

import javax.servlet.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;


@WebServlet("/s01")
public class Servlet01 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 控制台打印一句话
        System.out.println("hi servlet");
        // 响应一句话给浏览器
        resp.getWriter().write("hi servlet");
    }

}

方式2代码:

package com.study.testservlet;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;


@WebServlet("/s02")
public class Servlet02 extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet02...");
    }
}

方式3代码:

package com.study.testservlet;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;


@WebServlet("/s03")
public class Servlet03 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("servlet03...");
    }

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

    @Override
    public void destroy() {

    }
}

启动服务器,依次访问Servlet测试即可。

http://localhost:8888/s/s01

http://localhost:8888/s/s02

http://localhost:8888/s/s03

Servlet中方法的其它实现方式:

父类HttpServlet的service方法中会对请求做分发处理:

Servlet-45.png

所以子类 Servlet01中可以不用重写service方法,直接写doGet和doPost方法,被父类的service方法调用即可:(不推荐)

package com.study.testservlet;

import javax.servlet.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;

@WebServlet("/s01")
public class Servlet01 extends HttpServlet {
    //@Override
    /*protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 控制台打印一句话
        System.out.println("hi servlet");
        // 响应一句话给浏览器
        resp.getWriter().write("hi servlet");
    }*/

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("get...");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //System.out.println("post....");
        this.doGet(req,resp);//无论get请求和post请求都会走同一套业务逻辑。
    }
}

方式3:implements Servlet接口

用的最多:方式1

Servlet的生命周期

​ Servlet没有 main()方法,不能独立运行,它的运行完全由 Servlet 引擎来控制和调度。 所谓生命周期,指的是 servlet 容器何时创建 servlet 实例、何时调用其方法进行请求的处理、 何时并销毁其实例的整个过程。

  • 实例和初始化时机

    当请求到达容器时,容器查找该 servlet 对象是否存在,如果不存在,则会创建实例(通过反射)并进行初始化。

  • 就绪/调用/服务阶段

    有请求到达容器,容器调用 servlet 对象的 service()方法,处理请求的方法在整个生命周期中可以被多次调用; HttpServlet 的 service()方法,会依据请求方式来调用 doGet()或者 doPost()方法。但是, 这两个 do 方法默认情况下,会抛出异常,需要子类去 override。

  • 销毁时机

    当容器关闭时(应用程序停止时),会将程序中的 Servlet 实例进行销毁。

    上述的生命周期可以通过 Servlet 中的生命周期方法来观察。在 Servlet 中有三个生命周 期方法,不由用户手动调用,而是在特定的时机有容器自动调用,观察这三个生命周期方法 即可观察到 Servlet 的生命周期。

测试:定义一个Servlet,继承HttpServlet后重写如下三个方法:

init 初始化方法,在 Servlet 实例创建之后执行(证明该 Servlet 有实例创建了),系统方法服务器自动调用。

public void init(ServletConfig config) throws ServletException {
    System.out.println("实例创建了...");
}

service 就绪/调用/服务方法,每次有请求到达某个 Servlet 方法时执行,用来处理请求(证明该Servlet 进行服务了),系统方法服务器自动调用。

protected void service(HttpServletRequest req, HttpServletResponse resp) 
    throws ServletException, IOException {
    System.out.println("服务调用了...");
}

destroy 销毁方法,Servlet 实例销毁时执行(证明该 Servlet 的实例被销毁了),系统方法服务器自动调用。

public void destroy() {
	System.out.println("实例销毁了...");
}

除了上述三个方法外,再加入Servlet的构造方法,即可看到创建对象时机:

public Servlet04() {
  	System.out.println("构造方法调用...");
}

完整代码:

package com.study.testservlet;

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("/s05")
public class Servlet05 extends HttpServlet {
    public Servlet05(){
        System.out.println("构造器被调用了");
    }

    @Override
    public void init() throws ServletException {
        System.out.println("Servlet-init");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("处理业务 ");
    }

    @Override
    public void destroy() {
        System.out.println("Servlet对象被销毁");
    }
}

Servlet 的生命周期:

  1. Web Client 向 Servlet 容器(Tomcat)发出 Http 请求

  2. Servlet 容器接收 Web Client 的请求

  3. 根据反射构建Servlet对象(第一次请求会构建,之后不会重复创建对象,直到服务器关闭才会被销毁)

  4. 会构建HttpServletRequest 实现类对象、HttpServletResponse 实现类对象 ,处理请求和响应

  5. Servlet 容器调Servlet 对象的service 方法,把HttpServletRequest 实现类对象 与 HttpServletResponse 实现类对象 作为service的参数,供给方法内部使用

  6. Servlet 对象调用 HttpServletRequest 实现类对象的有关方法,获取 Http 请求信息

  7. Servlet 对象调用 HttpServletResponse实现类 对象的有关方法,生成响应数据

  8. Servlet 容器把 Servlet对象 的响应结果传给 Web Client

0

评论区