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...");
    }
}
相关推荐
跃ZHD3 分钟前
前后端分离,Jackson,Long精度丢失
java
blammmp24 分钟前
Java:数据结构-枚举
java·开发语言·数据结构
暗黑起源喵42 分钟前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong1 小时前
Java反射
java·开发语言·反射
九圣残炎1 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
wclass-zhengge1 小时前
Netty篇(入门编程)
java·linux·服务器
Re.不晚2 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
雷神乐乐2 小时前
Maven学习——创建Maven的Java和Web工程,并运行在Tomcat上
java·maven
码农派大星。2 小时前
Spring Boot 配置文件
java·spring boot·后端
顾北川_野2 小时前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java