Servlet

  • server applet:运行在服务器端的小进程
  • 为了更好的理解servlet,我们先从B/S模式来示例
    • 用户输入账号密码,请求登录
      • 我们需要判断 用户A输入的账号和密码是否正确。
      • 此处需要运用 Java逻辑来判断。
      • 也就是,我们需要通过Java代码来确定。
      • 具体就是,通过Java类来实现。
    • 创建 Java类,判断账号密码
      • 但是,并非所有的Java类都可以在服务器端运行,想要在服务器端运行就必须依赖于服务器端。
      • 换句话说,想要在服务器端运行就要遵循服务器端的”规则“。
      • 而具体来说,在Java中的规则,即是接口。
  • Servlet就是一个接口
    • Servlet接口中定义了能被浏览器访问到的,且能被tomcat服务器识别到的Java类的规则。
    • 自定义一个类,实现Servlet接口,复写Servlet接口方法。

快速入门

  1. 创建JavaEE项目
  2. 定义一个实现了Servlet接口的类
  3. 实现Servlet接口中的抽象方法
  4. 重写抽象方法,输出文字
  5. 配置web.xml文档,设置虚拟路径
  6. 启动tomcat服务器
  7. 项目的访问路径 (虚拟目录):localhost:8080/web/demo
  8. 文字输出在服务器端
  9. 刷新一次页面,输出一次文字

java文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class  implements Servlet {


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() {}

}

在web/WEB-INF目录下,配置web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

<!-- name -->
<!-- 全类名 -->
<servlet>
<servlet-name>demo</servlet-name>
<servlet-class>Servlet.A_ServletDemo</servlet-class>
</servlet>

<!--配置Servlet映射-->
<!-- name -->
<!-- 虚拟路径 -->
<servlet-mapping>
<servlet-name>demo</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>

执行原理

客户端对服务器发出请求

  1. 用户通过浏览器对服务器发出请求( *http: //localhost:8080/web/demo *
  2. Tomcat服务器接受请求,并开始解析URL路径
    • web.xml文档
      • 首先,Tomcat服务器通过虚拟路径找到相对应的<url-pattern>标签。
      • 其次,Tomcat服务器通过<url-pattern>标签,获取<servlet-name>标签,以及<servlet-class>标签。
      • 最后,Tomcat服务器通过<servlet-class>标签,获取到Java文档的全类名。
  3. Tomcat服务器将java文档加载进内存(classObj = Class.forName(全类名);
  4. Tomcat服务器创建Servlet对象( classObj.instance();
  5. Tomcat服务器创建request对象和response对象。
    • request对象中封装 请求消息数据
    • response对象中封装 响应消息数据
  6. Tomcat服务器调用service方法,并传入request对象和response对象。
    • 我们通过request对象获取请求消息数据
    • 并通过response对象设置响应消息数据
  7. Tomcat服务器在给浏览器做出响应之前,会从response对象中拿出设置好的响应消息数据。

    不同的请求方式

    GET方式

  • 如果我们要通过GET方式来对Tomcat服务器发送请求,那么我们可以直接访问Tomcat服务器中的GET实现类。
    • 比如,我创建了一个HTTPServlet实现类,但是里面只重写了doGET方法。此时可打开Tomcat服务器,直接通过浏览器访问GET实现类,继而完成在Tomcat服务器中的操作。

      POST方式

  • 如果我们要通过POST方式来对Tomcat客户端发送请求,那么我们就不可以直接访问Tomcat客户端中的POST实现类。
    • 比如,创建一个HTTPServlet实现类,但是里面只重写了doPOST方法,此时打开Tomcat客户端,但是无法直接通过浏览器访问POST实现类。
    • 不过,可以通过使用POST方法传递的表单来实现。定义一个这样的POST表单,打开Tomcat客户端,访问POST表单,继而完成在Tomcat服务器中的操作。

抽象方法

  1. service 提供服务的方法
    • 只要servlet服务器被访问,service方法就会执行。
  2. *init 初始化的方法 *
    • 无论servlet服务器被访问多少次,init方法只会执行一次。
  3. *destroy 销毁的方法 *
    • 当servlet服务器被正常关闭时,destroy方法会执行一次。
  4. *getServletConfig 获取配置对象的方法 *
  5. *getServletInfo 获取servlet信息的方法 *
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    /* 初始化方法 */
    // 只会执行一次
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    System.out.println("===init()执行了");
    }

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

    /* 提供服务的方法 */
    // servlet被访问一次,就执行一次
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println("===service()执行了");
    }

    /* 获取servlet信息方法*/
    @Override
    public String getServletInfo() {
    return null;
    }

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

生命周期

被创建

  • servlet被创建时会执行init方法,且只执行一次。

修改配置

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

安全问题

  • Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的。
    • 所以多个用户同时访问时,可能存在线程安全问题。
    • 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对其修改值。

提供服务

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

被销毁

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

注解

  • 上述情况下,我们发现一个问题,即每次新建文档都需要在web.xml文档中添加虚拟路径。
  • 为了解决这个问题,官方在Servlet3.0版本支持了注解配置,从而代替web.xml文档了。
    • 在web.xml文档,除了需要指定虚拟目录以外,还需要指定文档目录。
    • 而对于注解来说,@WebServlet已经定义在文档中了,所以只需要指定虚拟目录即可。

步骤

  1. 创建JavaEE项目
  2. 定义一个实现了Servlet接口的类
  3. 实现Servlet接口中的抽象方法
  4. 重写抽象方法,输出文字
  5. 在类上使用@WebServlet注解,进行配置
    • @WebServlet(urlPatterns = “/demo3”)
    • *@WebServlet(“/demo3”) *
      • 此处填写的源代码应是”value=’’demo3” “,
      • 如果注解后只写一个属性的话,value可以不写。
  6. 启动tomcat服务器
  7. 项目的访问路径 (虚拟目录):localhost:8080/web/demo3
  8. 文字输出在服务器端
  9. 刷新一次页面,输出一次文字

体系结构

  • Servlet 接口
    • GenericServlet 抽象类 (继承)
      • HttpServlet 抽象类(继承)

GenericServlet 抽象类

  • GenericServlet抽象类 将Servlet接口中其他的抽象方法默认空实现,只将service()方法作为抽象方法。
  • 上述情况下,我们仍可以发现一个问题,即创建的实现了servlet接口的Java类中,有许多我们不需要重写的抽象方法。但是大部分情况下我只用需要实现service方法,那我们为什么不能不实现其他方法呢?
  • 为了解决这个问题,我们可以通过GenericServlet抽象类来完成。
    • Java类不再是 实现servlet接口
    • Java类如今是 继承GenericServelet抽象类

HttpServlet 抽象类

  • HttpServlet抽象类在其父类GenericServlet 抽象类的功能上更进一步。为了可以获取正确的数据,HttpServlet抽象类对请求的方法(get、post)自动进行了判断。
    • Java类继承 HttpServlet抽象类
    • 复写doGet/doPost方法

相关配置

  • urlpartten:Servlet访问路径
    • 一个Servlet可以定义多个访问路径 : @WebServlet({“/d4”,”/dd4”,”/ddd4”})
  • 路径定义规则:
    • 目录结构:/xxx
    • 多层目录结构:/xxx/xxx
    • 文档名:*.do