JavaWeb Servlet详解

本文介绍了Servlet的基本概念,包括如何在Web项目中添加依赖,创建和配置Servlet,重写关键方法如service和init,以及处理中文乱码。还涵盖了Servlet的生命周期、不同创建时机和常用的映射规则,以及3.0版本以后的注解配置和XML配置的区别。
摘要由CSDN通过智能技术生成

Servlet(Server Applet)服务器小程序,主要功能用于生成动态Web内容,Servlet就是一个接口,定义了Java类被浏览器访问到(Tomcat识别)的规则。

在这里插入图片描述

快速入门

  1. 创建Web项目,导入Servlet依赖坐标。
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <!-- provided指的是在编译和测试过程中有效,最后生成的war包时不会加入
        因为Tomcat的lib目录中已经有servlet-api这个jar包,
        如果在生成war包的时候生效就会和Tomcat中的jar包冲突,导致报错-->
    <scope>provided</scope>
</dependency>
  1. 定义一个类,实现Servlet接口,并重写接口中所有方法,并在service方法中输入一句话
import javax.servlet.*;
import java.io.IOException;

public class ServletDemo1 implements Servlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) 
            throws ServletException, IOException {
        System.out.println("你好,Servlet");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {}

    @Override
    public ServletConfig getServletConfig() { return null; }

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

    @Override
    public void destroy() {}

}
  1. 在类上使用@WebServlet注解,配置该Servlet的访问路径
@WebServlet("/hello001")
public class ServletDemo1 implements Servlet {...}
  1. 启动Tomcat,浏览器中输入URL地址访问该Servlet,然后控制台就会打印刚刚写的"你好,servlet"

在这里插入图片描述

控制台中文乱码

Servlet在打印中文时,出现乱码,可以进行如下配置:

在这里插入图片描述

-Dfile.encoding=UTF-8

在这里插入图片描述

执行流程

浏览器发出http://localhost:8080/hello/hello001请求,从请求中可以解析出三部分内容,分别是localhost:8080hellohello001

  1. 根据localhost:8080可以找到要访问的Tomcat Web服务器
  2. 根据hello可以找到部署在Tomcat服务器上的web项目
  3. 根据hello001可以找到要访问的是项目中的哪个Servlet类,根据@WebServlet后面的值进行匹配
  4. 找到ServletDemo1这个类后,Tomcat Web服务器就会为ServletDemo1这个类创建一个对象,然后调用对象中的service方法

ServletDemo1实现了Servlet接口,所以类中必然会重写service方法供Tomcat Web服务器进行调用。
service方法中有ServletRequest和ServletResponse两个参数,ServletRequest封装的是请求数据,ServletResponse封装的是响应数据

生命周期

Servlet运行在Servlet容器(web服务器)中,其生命周期由容器来管理,分为4个阶段:

  1. 加载和实例化: 默认情况下,当Servlet第一次被访问时,由容器创建Servlet对象。

默认情况,Servlet会在第一次访问被容器创建,但是如果创建Servlet比较耗时的话,那么第一个访问的人等待的时间就比较长,用户的体验就比较差,这时,可以设置将Servlet放到服务器启动的时候来创建:

@WebServlet(urlPatterns = "/demo1", loadOnStartup = 1)
// loadOnstartup的取值有两类情况
// (1)负整数:第一次访问时创建Servlet对象,默认为-1
// (2)0或正整数:服务器启动时创建Servlet对象,数字越小优先级越高
  1. 初始化: 在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象,完成一些如加载配置文件、创建连接等初始化的工作。该方法只调用一次。
  2. 请求处理: 每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理。
  3. 服务终止: 当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法完成资源的释放。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收。

常用方法

  • void init(ServletConfig config):初始化方法,在Servlet被创建时执行,只执行一次。
  • void service(ServletRequest req, ServletResponse res):提供服务方法, 每次Servlet被访问,都会调用该方法。
  • void destroy():销毁方法,当Servlet被销毁时,调用该方法。在内存释放或服务器关闭时销毁Servlet。
  • String getServletInfo():获取Servlet信息,该方法用来返回Servlet的相关信息,没有什么太大的用处,一般返回一个空字符串即可。
  • ServletConfig getServletConfig():获取ServletConfig对象。创建Servlet对象的时候会调用init方法,必定会传入一个ServletConfig对象,只需要将服务器传过来的ServletConfig进行返回即可。
@WebServlet(urlPatterns = "/hello003", loadOnStartup = 1)
public class ServletDemo3 implements Servlet {

    private ServletConfig servletConfig;

    public void init(ServletConfig config) throws ServletException {
        this.servletConfig = config;
        System.out.println("init...");
    }
    public ServletConfig getServletConfig() {
        return servletConfig;
    }

    // ...
}

体系结构

在这里插入图片描述

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

**HttpServlet:**对http协议的一种封装,简化操作,定义类继承HttpServlet,复写doGet/doPost方法

因为将来开发的都是B/S架构的web项目,都是HTTP协议,所以一般会通过继承HttpServlet来写代码:

@WebServlet("/hello004")
public class ServletDemo4 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        //TODO GET 请求方式处理逻辑
        System.out.println("get...");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        //TODO Post 请求方式处理逻辑
        System.out.println("post...");
    }
}

要想发送一个GET请求,请求该Servlet,只需要通过浏览器发送http://localhost:8080/hello/hello004,就能看到doGet方法被执行了。

要想发送一个POST请求,请求该Servlet,单单通过浏览器是无法实现的,这个时候就需要编写一个form表单来发送请求,在webapp下创建一个a.html页面,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/hello/hello004" method="post">
        <input name="username"/><input type="submit"/>
    </form>
</body>
</html>

在HttpServlet的service方法中,先获取请求方式,再根据不同的请求方式调取对应的doXxx方法。

在这里插入图片描述

如果不继承使用HttpServlet,而是直接实现Servlet接口,这个操作则需要自己来完成,以用作不同的处理逻辑。

@WebServlet

Servlet 3.x之后引入了“注解Annotation”特性。@WebServlet()是Servlet的核心注解。

常用参数

  • loadOnStartup:创建时机,负数为第一次被访问时创建,0或正整数为在服务器启动的时候创建,默认为-1,数字越小优先级越高。

  • value:同下

  • urlPatterns:映射地址。

配置规则

  • 精确匹配: 一个Servlet可以定义多个访问路径: @WebServlet({"/d4","/dd4","/ddd4"})
@WebServlet(urlPatterns = {"/demo7", "/demo8"})
public class ServletDemo7 extends HttpServlet {
    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {
        System.out.println("demo7 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}

此时在浏览器上输入http://localhost:8080/hello/demo7,http://localhost:8080/hello/demo8这两个地址都能访问到ServletDemo7的doGet方法。

  • 目录匹配: 可以进入该目录下的所有路径都可以匹配,如果有精度更高的路径,则优先精度更高的。@WebServlet({"/d4/*"})
@WebServlet(urlPatterns = "/user/*")
public class ServletDemo9 extends HttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {
        System.out.println("demo9 get...");
    }

    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}

此时如果访问http://localhost:8080/hello/userhttp://localhost:8080/hello/user/ahttp://localhost:8080/hello/user/a/b ,都可以访问到该doGet 方法。

但是如果同时有一个路径为@WebServlet(urlPatterns = "/user/a") 的路径,则会优先进入该路径下的方法,因为这个的精确度最高,所以优先级最高。

  • 扩展名匹配: 匹配指定的扩展名,使用扩展名时,不可以加\,不能写成"/*.xx"@WebServlet(urlPatterns = "*.do")
@WebServlet(urlPatterns = "*.do")
public class ServletDemo10 extends HttpServlet {

    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {
        System.out.println("demo10 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}

此时,访问路径http://localhost:8080/hello/[任意].do ,都可以被匹配到。

  • 任意匹配: 匹配任何路径,可以写\\* ,后者的优先级高于前者。
@WebServlet(urlPatterns = "/*")
public class ServletDemo12 extends HttpServlet {
    @Override
    protected void doGet(ServletRequest req, ServletResponse res) {
        System.out.println("demo12 get...");
    }
    @Override
    protected void doPost(ServletRequest req, ServletResponse res) {
    }
}

//*的区别:

  1. 当项目中的Servlet配置了/,会覆盖掉tomcat中的DefaultServlet,当其他的url-pattern都匹配不上时都会走这个Servlet。
  2. 当项目中配置了/*,意味着匹配任意访问路径。
  3. DefaultServlet是用来处理静态资源,如果配置了/会把默认的覆盖掉,就会引发请求静态资源的时候没有走默认的而是走了自定义的Servlet类,最终导致静态资源不能被访问。

XML配置

@WebServlet是Servlet从3.0版本后开始支持注解配置,3.0版本前只支持XML配置文件的配置方法。

在web.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_4_0.xsd"
         version="4.0">
    
    <!-- 声明servlet -->
    <servlet>
        <!-- servlet的别名 -->
        <servlet-name>demo13</servlet-name>
        <!--servlet对应的类-->
        <servlet-class>run.arbor.web.ServletDemo13</servlet-class>
        <!-- servlet的创建时机,可写可不写 -->
        <load-on-startup>0</load-on-startup>
    </servlet>

    <!-- 映射,将servlet与url绑定 -->
    <servlet-mapping>
        <!-- servlet的名称,要和上面的名称一致-->
        <servlet-name>demo13</servlet-name>
        <!-- servlet的访问路径-->
        <url-pattern>/demo13</url-pattern>
    </servlet-mapping>

</web-app>
  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VincentHu_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值