本文最后更新于:4 个月前

Servlet: server applet

  • 概念:运行在服务器端的小程序
  • Servlet就是一个接口,定义了Java类被浏览器访问到(Tomcat识别)的规则(我是跳转内容)
  • 将来我们自定义一个类,实现Servlet接口,复写(重写Override)方法。

快速理解

快速理解

快速入门

  1. 创建JavaEE项目

  2. 定义一个类,实现Servlet接口

/* ServletDemo1.java */
package cn.itcast.web.servlet;

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

public class ServletDemo1 implements Servlet {
	//TODO
}

  1. 实现接口中的抽象方法
/* ServletDemo1.java */
package cn.itcast.web.servlet;

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

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("Hello Servlet");
    }

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

    @Override
    public void destroy() {

    }
    
}
  1. 配置Servlet,在web.xml的<web-app></web-app>中添加:
<!--配置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-mapping是做一个映射servlet-name对应servlet-classurl-pattern是资源路径(/开头

<servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>,中的cn.itcast.web.servlet.ServletDemo1全类名,这里涉及到反射。日后补充。

  1. 启动服务,看看结果

浏览器中是空白的,

但是IDEA控制台中显示“Hello Servlet”

每刷新一次页面,控制台就多一句“Hello Servlet”。

执行原理

  1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径

  2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容。

  3. 如果有,则在找到对应的<servlet-class>全类名涉及到反射

  4. tomcat会将字节码文件加载进内存,并且创建其对象

  5. 调用其方法

    • 为什么能调用方法?

    • 因为实现了【规则】(点击我跳转)。实现规则,实现Servlet接口,实现了接口中的方法。

ServletDemo

可以调试、运行,看看每个方法的执行次数。

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

/**
 * Servlet的方法
 */
public class ServletDemo1 implements Servlet {

    /**
     * 初始化的方法
     * 在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...");
    }

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

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

}

Servlet中的生命周期方法

1.被创建:执行init方法,只执行一次

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

1.第一次被访问时,创建

负整数

2.在服务器启动时,创建

0或正整数(一般0~10)

/**
 * 初始化的方法
 * 在Servlet被创建时,执行,且只执行一次。
 * @param servletConfig
 * @throws ServletException
 */
@Override
public void init(ServletConfig servletConfig) throws ServletException {
    System.out.println("init...");
    
    // 定义局部变量,这样不存在多线程的安全问题
    int number = 3;
}
  • Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的。
  • 多个用户同时访问时,可能存在线程安全问题。
  • 解决:尽量不要在Servlet中定义成员变量(定义局部变量就不存在安全问题了)。即使定义了成员变量,也不要对修改值。

2.提供服务:执行service方法,可执行多次

  • 每次访问Servlet时,Service方法都会被调用一次。
/**
 * 提供服务的方法
 * 每一次Servlet被访问时,执行。可执行多次。
 * @param servletRequest
 * @param servletResponse
 * @throws ServletException
 * @throws IOException
 */
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println("service...");
}

3.被销毁:执行destroy方法,只执行一次

  • Servlet被销毁时执行。服务器关闭时,Servlet被销毁
  • 只有服务器正常关闭时,才会执行destroy方法。
  • destroy方法在Servlet被销毁之前执行,一般用于释放资源
/**
 * 销毁的方法
 * 在服务器正常关闭时,执行。只执行一次。
 * 非正关闭时,destroy方法不会执行。
 */
@Override
public void destroy() {
    System.out.println("destroy...");
}

Servlet 3.0

  • 官方提供新的标准 Servlet 3.0
  • Java EE 6 开始支持 Servlet 3.0

好处

  • 支持注解配置。可以不需要web.xml了

步骤

  1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml

  2. 定义一个类,实现Servlet接口

  3. 复写方法

  4. 在类上使用@WebServlet注解,进行配置

    • @WebServlet("资源路径")
    • 比如:
      @WebServlet(urlPatterns = "/demo2")
      或
      @WebServlet(value = "/demo2")
      或
      @WebServlet("/demo2")
  1. 访问:http://localhost:8080/Servlet3/demo2

@WebServlet注解

  • @WebServlet中有个很特殊的属性value
  • 一般表示最重要的属性,就用value表示。
  • 特性:如果只有一个属性,value可以省略不写。
  • 除去value,最重要的属性是urlPatterns
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {

    String name() default "";	//相当于<Servlet-name>
    String[] value() default {};	//代表urlPatterns()属性配置
    String[] urlPatterns() default {};	//相当于<url-pattern>			
    int loadOnStartup() default -1;	//相当于<load-on-startup>			
    WebInitParam[] initParams() default {};			
    boolean asyncSupported() default false;			
    String smallIcon() default "";		
    String largeIcon() default "";			
    String description() default "";			
    String displayName() default "";
  
}

Servlet 体系结构

跳转到我得下一篇博文👉 [Servlet 体系结构](https://melodyjerry.gitee.io/blog/2020/02/20/Servlet 体系结构/)


 目录