java:Servlet

文章目录

背景

我们访问浏览器访问一个地址,最终是访问到了这个 java 类,而 java 是运行在 Tomcat 上的,所以 Tomcat 作为一个服务器会把这个访问地址指向这个类中,这个类就是 Servlet,Servlet 就是一个具有一定规范的类,具体规范后面会说。

步骤

  1. 创建JavaEE项目
  2. 定义一个类,实现Servlet接口
    • public class ServletDemo1 implements Servlet
  3. 实现接口中的抽象方法
  4. 配置Servlet
    在web.xml中配置:
xml 复制代码
<!--配置Servlet -->
<servlet>
    <servlet-name>demo1</servlet-name>
    <servlet-class>cn.xxx.web.servlet.ServletDemo1</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>demo1</servlet-name>
    <url-pattern>/demo1</url-pattern>
</servlet-mapping>

原理

  1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
  2. 查找web.xml文件,是否有对应的 <url-pattern> 标签体内容。
  3. 如果有,则在找到对应的 <servlet-class> 全类名
  4. tomcat会将字节码文件加载进内存,并且创建其对象
  5. 调用其方法

示例

一般 java web 项目根目录会有 web/WEB-INF/web.xml 文件,如果你新建的项目没有的话,可以按照下面的操作新增

servlet 就是在这个文件里配置的,如下:

xml 复制代码
<?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_3_1.xsd"
         version="3.1">


    <!--配置Servlet -->
    <servlet>
        <servlet-name>demo1</servlet-name>
        <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>demo1</servlet-name>
        <url-pattern>/demo1</url-pattern>
    </servlet-mapping>

    <!--配置Servlet -->
    <servlet>
        <servlet-name>demo2</servlet-name>
        <servlet-class>cn.itcast.web.servlet.ServletDemo2</servlet-class>
        <!--指定Servlet的创建时机
            1.第一次被访问时,创建
                * <load-on-startup>的值为负数
            2.在服务器启动时,创建
                * <load-on-startup>的值为0或正整数
        -->

        <load-on-startup>-5</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>demo2</servlet-name>
        <url-pattern>/demo2</url-pattern>
    </servlet-mapping>

</web-app>

当你浏览器访问 127.0.0.1:8080/demo2,指向的类就是上面的配置文件中的 cn.itcast.web.servlet.ServletDemo2,如下:

java 复制代码
package cn.itcast.web.servlet;

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

/**
 * Servlet的方法
 */
public class ServletDemo2 implements Servlet {
    private int age = 3;

    /**
     * 初始化方法
     * 在Servlet被创建时,执行。只会执行一次
     * @param servletConfig
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init.....");
    }

    /**
     * 获取ServletConfig对象
     * ServletConfig:Servlet的配置对象
     * @return
     */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 提供服务方法
     * 每一次Servlet被访问时,执行。执行多次
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service.....");
        int number = 3;
    }

    /**
     * 获取Servlet的一些信息,版本,作者等等。。
     * @return
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * 销毁方法
     * 在服务器正常关闭时,执行,执行一次。
     */
    @Override
    public void destroy() {
        System.out.println("destroy.....");
    }
}

生命周期

被创建

执行init方法,只执行一次

  • Servlet什么时候被创建?默认情况下,第一次被访问时,Servlet被创建
  • 可以配置执行Servlet的创建时机,在<servlet>标签下配置。
    1. 第一次被访问时创建
      • <load-on-startup> 的值为负数,默认就是 -1
    2. 在服务器启动时创建
      • <load-on-startup> 的值为0或正整数

注意:

Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的,多个用户同时访问时,可能存在线程安全问题。

解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值

提供服务

执行service方法,执行多次

  • 每次访问Servlet时,Service方法都会被调用一次。

被销毁

执行destroy方法,只执行一次

  • Servlet被销毁时执行。服务器关闭时,Servlet被销毁
  • 只有服务器正常关闭时,才会执行destroy方法。
  • destroy方法在Servlet被销毁之前执行,一般用于释放资源

Servlet3.0

之前我们如果 servlet 多的话,那么需要在 web.xml 配置很多,所以在 Servlet 3.0 之后,可以不用创建 web.xml 文件。

java 复制代码
package cn.xxx.web.servlet;

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

// 当注解value只有一个的时候可以不写键值对
//@WebServlet({"/d4","/dd4","/ddd4"})
//@WebServlet("/user/demo4")
//@WebServlet("/user/*")
//@WebServlet("/*")
//@WebServlet("*.do")
@WebServlet("/demo2")
public class ServletDemo 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("Servlet3.0来了.....");
    }

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

    @Override
    public void destroy() {

    }
}

IDEA与tomcat的相关配置

  1. IDEA会为每一个tomcat部署的项目单独建立一份配置文件

    • 启动项目的时候查看控制台的log:Using CATALINA_BASE: "C:\Users\fqy\.IntelliJIdea2018.1\system\tomcat\xxx"
  2. 工作空间项目和 tomcat部署的web项目 是两回事

    • tomcat真正访问的是"tomcat部署的web项目","tomcat部署的web项目"对应着"工作空间项目" 的web目录下的所有资源
    • WEB-INF目录下的资源不能被浏览器直接访问。

Servlet的继承体系结构

复制代码
Servlet -- 接口
		|
GenericServlet -- 抽象类
	    |
HttpServlet  -- 抽象类

GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象,将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可

HttpServlet:对http协议的一种封装,简化操作

  1. 定义类继承HttpServlet
  2. 复写doGet/doPost方法

一般来说,我们写一个简单的 Servlet 如下:

java 复制代码
package cn.xxx.web.servlet;

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


@WebServlet("/demo1")
public class ServletDemo1 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("demo1....");
    }

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

    @Override
    public void destroy() {

    }
}

可以看到,我们只用了 service 函数,但是却得把其他生命周期也写上,所以就有了 GenericServlet,将Servlet接口中其他的方法做了默认空实现,我们直接继承 GenericServlet 如下:

java 复制代码
package cn.xxx.web.servlet;

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("/demo2")
public class ServletDemo2 extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("demo2.....");
    }
}

那么以上并不支持 http 的其他请求例如 post 请求,所以有了 HttpServlet

java 复制代码
package cn.xxx.web.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("/demo3")
public class ServletDemo3 extends HttpServlet {

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

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost...");
    }
}
相关推荐
掘金-我是哪吒10 分钟前
分布式微服务系统架构第156集:JavaPlus技术文档平台日更-Java线程池使用指南
java·分布式·微服务·云原生·架构
亲爱的非洲野猪36 分钟前
Kafka消息积压的多维度解决方案:超越简单扩容的完整策略
java·分布式·中间件·kafka
wfsm38 分钟前
spring事件使用
java·后端·spring
微风粼粼1 小时前
程序员在线接单
java·jvm·后端·python·eclipse·tomcat·dubbo
缘来是庄1 小时前
设计模式之中介者模式
java·设计模式·中介者模式
rebel1 小时前
若依框架整合 CXF 实现 WebService 改造流程(后端)
java·后端
代码的余温3 小时前
5种高效解决Maven依赖冲突的方法
java·maven
慕y2743 小时前
Java学习第十六部分——JUnit框架
java·开发语言·学习
paishishaba3 小时前
Maven
java·maven
张人玉3 小时前
C# 常量与变量
java·算法·c#