Servlet详解(从xml到注解)

发布于:2024-05-05 ⋅ 阅读:(30) ⋅ 点赞:(0)


概述

介绍

  1. servlet是一个接口,即规范
  2. 定义的实现类必须实现接口中的所有的抽象方法
  3. Servlet全称Server Applet,服务器端的程序。是sun公司提供的一套规范,用来处理客户端请求,响应给浏览器的动态web资源。其实servlet的实质就是java代码,通过java的API动态的向客户端输出内容,并且从客户端接受数据
  4. 一个类要想通过浏览器被访问到,那么这个类就必须直接或间接的实现Servlet接口

作用

  1. 接受客户端的请求
  2. 处理业务逻辑
  3. 响应给浏览器端

Snipaste_2024-04-30_19-20-04.png

快速入门

  1. 创建web项目
  2. 导入servlet依赖
 <dependencies>
        <!--导入servlet依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
        </dependency>
    </dependencies>
  1. 在创建的web项目中自定义类实现Servlet接口
  2. 在自定义类中实现Servlet接口中的抽象方法
  3. 在实现Servlet接口的service方法中书写处理业务逻辑(可以先输出一句话)
  4. 在web项目的核心配置文件web.xml中配置访问servlet的路径
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		  http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
           version="3.1">
    <!--
       5.在web项目的核心配置文件web.xml中配置访问servlet的路径。
	    说明:这样配置是告知tomcat有具体的Servlet类需要被访问。
    -->
    <!--
        1.<servlet> 表示将当前Servlet类注册到tomcat中,告知tomcat有一个类要被访问
    -->
    <servlet>
        <!--
            表示当前要被访问类的标识,在当前web.xml中要唯一,helloWorldServlet属于标识符
        -->
        <servlet-name>helloWorldServlet</servlet-name>
        <!--
            配置要访问 的servlet类,必须是类的全路径:包名.类名。
            说明:tomcat底层通过获取这里的类全路径使用反射技术调用当前类的无参构造方法创建对象
        -->
        <servlet-class>com.itheima.sh.a_demo_01.HelloWorldServlet</servlet-class>
    </servlet>
    <!--
        配置要访问的servlet类的映射路径
    -->
    <servlet-mapping>
        <!--这里要和上面的servlet-name文本值一致,这里找到上面的servlet-name-->
        <servlet-name>helloWorldServlet</servlet-name>
        <!--浏览器上地址栏上输入的映射路径及访问路径,这里必须加/-->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>
  1. 启动tomact
  2. 在浏览器中访问servlet类

Snipaste_2024-04-30_19-38-54.png

Servelt的执行原理

执行流程:

Snipaste_2024-04-30_20-03-03.png

执行原理

  1. 当我们点击run时,tomact之所以会启动,是因为程序入口(main方法)在tomact中
  2. tomact开始运行,会加载web项目里面的配置文件web.xml(xml解析,读取数据)
    1. 主要是根据url-pattern找到对应的servlet-class
  3. 然后tomact进入等待状态(永不停止,除非手动关闭)
  4. 当用户在浏览器中输入地址:http://localhost:8080/hello就会定位到tomact的访问的项目下面的某个servlet中
  5. tomact会根据 /hello的servlet的虚拟路径找到HelloServlet的全限定名
  6. tomcat底层通过反射创建HelloServlet的对象,并调用HelloServlet的service方法
Class clazz = Class.forName("全限定名");
Servlet servlet = clazz.newInstance();//实际上HelloServlet对象,向上转型
servlet.service();

生命周期

概述

指的是一个对象从生(创建)到死(销毁)的一个过程

API

  1. 谁创建servlet对象:tomact调用反射技术创建对象
  2. 何时创建对象:第一次访问Servlet类的时候创建Servlet对象,调用无参构造方法创建对象,使用对象立刻调用init方法进行初始化(init)

init方法只会执行一次,然后调用service方法处理业务逻辑

  1. 创建对象之后每次访问servlet类的时候只会执行service方法
  2. 关闭tomact服务器时,关闭之前使用servlet类的对象调用destory方法销毁资源

Snipaste_2024-04-30_20-30-02.png

服务器启动,立刻加载Servlet对象(理解)

项目中的web.xml

<!--配置Servlet-->
    <servlet>
        <servlet-name>LifeDemo01Servlet</servlet-name>
        <servlet-class>com.itheima.sh.b_servlet_02.LifeDemo01Servlet</servlet-class>
        <!-- 服务器启动创建Servlet类的对象,默认值是-1表示第一次访问创建对象,如果文本值大于等于0,表示tomcat启动创建对象
             如果多个servlet都配置了该标签,那么文本值越小创建Servlet的优先级越高
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>LifeDemo01Servlet</servlet-name>
        <url-pattern>/life01</url-pattern>
    </servlet-mapping>

实现Servlet方式(三种)

Snipaste_2024-04-30_19-28-22.png

实现Servlet接口

就是快速入门那个案例

实现GenericServlet抽象类,只重写service方法

间接实现Servlet接口

实现HttpServlet实现类

重写doGet()方法和doPost()方法 ctrl+O

实现HttpServlet实现类的原理

image-20221207165520172.png
注意:查看某个类的成员结构快捷键:alt+7
结构图:ctrl+alt+U

编写servlet常见问题

遇到500

表示服务器内部异常

遇到404

浏览器客户端访问服务器的资源不存在,基本都是路径有问题
:报404的根本原因就是用户操作不当导致的,比如:url路径输入错误
解决

  • 修改访问地址
  • 在服务器创建资源
  • maven点击clean清除target,然后重新部署

遇到405

服务器servlet没有重写doGet或者doPost方法

启动服务器错误

:只要启动服务器报错基本就是你的路径有问题,路径没有书写/

Servlet基本的映射路径

一个Servlet类映射多个路径
Snipaste_2024-04-30_21-42-54.png

Servlet映射路径配置规范

完全路径匹配

就是访问什么在web.xml中配置什么路径
/hello

目录匹配

/user/*
只要访问以/user开始的路径都可以访问

后缀名匹配

.do,.action 注意这里不能书写/
访问以.do或者.action结尾的资源路径,后缀名都属于标识符

缺省路径

/
如果上述三种路径都不满足就访问缺省路径
上述访问路径的优先级
完全路径匹配>目录匹配>后缀名匹配>缺省路径

绝对路径

写法

  1. 带网络的三要素
    1. http://ip地址:端口号/资源路径
  2. 不带网络的三要素
    1. /资源路径 这个的/不能省略,要求访问的资源必须在同一哥服务器上

代码实现

html:

<a href="http://127.0.0.1:8080/pathAbso">带网络三要素的绝对路径</a><br>
<a href="/pathAbso">不带网络三要素的绝对路径</a><br>

web.xml:

<servlet>
        <servlet-name>pathAbso01Servlet</servlet-name>
        <servlet-class>com.itheima.sh.a_servlet_01.PathAbso01Servlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>pathAbso01Servlet</servlet-name>
        <url-pattern>/pathAbso</url-pattern>
    </servlet-mapping>

相对路径

不是相对当前项目,而是针对当前浏览器地址栏上的url而言的
案例一:
Snipaste_2024-05-02_10-52-26.png

 #假设我们在浏览器地址栏访问的页面路径: http://localhost:8080/demo01.html
 #而在demo01.html页面想使用相对路径访问servlet: http://localhost:8080/pathAbso
 	 说明:
        如果在http://localhost:8080/demo01.html 页面中访问 http://localhost:8080/pathAbso 该servlet,我们通过url		  
        观察发现只有最后一级目录不一样,所以在demo01.html页面中相对的路径的写法是:./pathAbso  这里的./表示当前路径
        可以省略不写即直接写 pathAbso

demo01.html:
	<a href="./pathAbso">相对路径</a><br>
    <a href="pathAbso">相对路径</a><br>

案例二:
Snipaste_2024-05-02_10-53-10.png

 # 如果在http://localhost:8080/aaa/demo02.html 页面中访问 http://localhost:8080/pathAbso 该servlet
    我们通过url观察发现在demo02.html也面中书写访问的servlet即pathAbso和当前页面的父目录aaa是同等目录,
    所以我这里先找该页面的父目录,然后在找该servlet即pathAbso ../pathAbso    
    ../表示上一级目录或者父目录,找到父目录之后再找servlet即pathAbso
demo02.html:
    <a href="../pathAbso">相对路径</a><br>

Servlet3.0注解开发

问题

之前我们都是使用web.xml进行servlet映射路径的配置。这样配置的弊端:web.xml中具有非常多个配置信息,显得非常臃肿并且容易出错,冗余

解决问题

使用web.xml配置映射路径的方式属于servlet2.5的技术,从serclet3.0开始引入注解配置访问servlet取代了web.xml配置

   <!--  TODO:想使用注解开发导入的Servlet依赖必须是3.0以上的      -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

配置步骤

  1. 在包右键–new–servlet
  2. 输入类名
  3. 在方法体内输入逻辑代码
  4. 在浏览器地址栏中输入访问路径

实现

  1. 创建

Snipaste_2024-05-02_11-29-16.png

  1. 输入类名

Snipaste_2024-05-02_11-29-35.png

  1. 类中逻辑代码
package com.itheima.sh.c_servlet_anno_03;

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("/annoDemo01Servlet")
public class AnnoDemo01Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("注解开发");
    }
}

  1. 在浏览器地址栏输入访问的路径:

Snipaste_2024-05-02_11-30-51.png

修改idea创建注解的servlet模板

  1. File–settings
  2. 找到servlet的模板,按照下面修改

Snipaste_2024-05-02_11-32-58.png

#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
@javax.servlet.annotation.WebServlet("/${Entity_Name}")
public class ${Class_Name} extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
            doGet(request,response);
}

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {

}
}

关于web3.0注解开发的属性

Snipaste_2024-05-02_11-34-13.png