JavaWeb——Servlet原理、生命周期、IDEA中实现一个Servlet(全过程)

news2024/11/15 23:40:20

6、servlet

6.1、什么是servlet

在JavaWeb中,Servlet是基于Java编写的服务器端组件,用于处理客户端(通常是Web浏览器)发送的HTTP请求并生成相应的HTTP响应。Servlet运行在Web服务器上,与Web容器(如Tomcat)进行交互,通过Web容器将请求分发给适当的Servlet进行处理。

Servlet提供了一种动态生成和处理Web内容的方式,可以接收并解析HTTP请求,执行业务逻辑,生成HTML、XML或其他格式的响应结果,并将其返回给客户端。Servlet可以处理各种不同类型的请求,如GET请求、POST请求等,并可以访问请求的参数、请求头、会话信息等。

在Java中,编写一个Servlet需要继承自javax.servlet.http.HttpServlet类,并重写其中的一些方法,如doGet()、doPost()等。在这些方法中,开发人员可以编写处理请求和生成响应的逻辑。另外,Servlet也可以实现一些接口(如javax.servlet.Servlet、javax.servlet.Filter等),以实现更灵活的功能。

Servlet在JavaWeb开发中扮演着非常重要的角色,它可以与数据库进行交互、调用其他Java类库、生成动态内容等。通过Servlet,开发人员可以实现Web应用程序中的用户认证、数据查询、数据处理、页面跳转等功能。

需要注意的是,使用Servlet开发时,通常还会配合使用Web框架(如Spring MVC、Struts等)来简化开发流程和提供更强大的功能。

  • Sun公司在这些API中提供一个接口,叫做Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
    • 编写一个类,实现Servlet接口
    • 吧开发好的Java类部署到web服务器中

总而言之:把实现了Servlet接口的Java程序叫做:Servlet

6.2、HelloServlet

  1. 构建一个Maven项目,构建一个空的Maven项目,我们从头开始写

  2. 打开pom.xml即核心配置文件,先配置一些依赖(空的项目中,pom.xml文件中除非必要,并无其他东西,因此是没有任何一点依赖的)

        <dependencies>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>4.0.1</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>javax.servlet.jsp-api</artifactId>
                <version>2.2.1</version>
            </dependency>
        </dependencies>
    

    我们在此配置了servlet的一些相关依赖以及jsp的一些相关依赖

    依赖本质上是jar包,配置相关依赖,即在仓库中找到相应的jar包,如果报错,即仓库中没有该jar包,IDEA可能会提醒你安装,如果没有,则在网上找到相关资源下载并把jar包丢入仓库中

  3. 关于Maven父子工程的理解:我们一开始创建了一个空的Maven项目(Project),在这个项目中,我们还可以创建一些Maven模块(Module),当我们创建了一个名为servlet-01的Maven模块(以下我们称之为子项目)

    父项目的pom.xml中会有:

        <modules>
            <module>servlet-01</module>
        </modules>
    

    子项目的pom.xml中会有:

        <parent>
            <groupId>com.Xu</groupId>
            <artifactId>javaweb-02-servlet</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    

    (如果没有,可以手动添加)

    父项目中的jar包子项目可以直接使用,子项目的父项目无法直接使用,即类似于继承

  4. 将子Maven项目的结构搭建完整(创建java包,resource包等)忘记的同学可以回头看上面Maven配置的博客

  5. 编写一个Servlet程序

    1. 编写一个普通类

    2. 实现Servlet接口,这里我们直接继承HttpServlet(HttpServlet是Sun公司写好的,直接继承,不必实现)

      public class HelloServlet extends HttpServlet
      

      进入HttpServlet的源码发现:

      public abstract class HttpServlet extends GenericServlet 
      

      其同样继承了另一个类GenericServlet,再进入源码发现:

      public abstract class GenericServlet implements Servlet, ServletConfig, Serializable
      

      GenericServlet最终实现了 Servlet接口,所以,即使是继承HttpServlet,同样也是实现Servlet接口

      Servlet接口中,有几个方法:

          void init(ServletConfig var1) throws ServletException;
      
          ServletConfig getServletConfig();
      
          void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
      
          String getServletInfo();
      
          void destroy();
      

      其中,最为重要的是service方法,查看源码可以发现,GenericServlet没有实现该方法,而是将其定义为抽象方法:

      public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
      

      在HttpServlet才最终实现了它:

          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              String method = req.getMethod();
              long lastModified;
              if (method.equals("GET")) {
                  lastModified = this.getLastModified(req);
                  if (lastModified == -1L) {
                      this.doGet(req, resp);
                  } else {
                      long ifModifiedSince = req.getDateHeader("If-Modified-Since");
                      if (ifModifiedSince < lastModified) {
                          this.maybeSetLastModified(resp, lastModified);
                          this.doGet(req, resp);
                      } else {
                          resp.setStatus(304);
                      }
                  }
              } else if (method.equals("HEAD")) {
                  lastModified = this.getLastModified(req);
                  this.maybeSetLastModified(resp, lastModified);
                  this.doHead(req, resp);
              } else if (method.equals("POST")) {
                  this.doPost(req, resp);
              } else if (method.equals("PUT")) {
                  this.doPut(req, resp);
              } else if (method.equals("DELETE")) {
                  this.doDelete(req, resp);
              } else if (method.equals("OPTIONS")) {
                  this.doOptions(req, resp);
              } else if (method.equals("TRACE")) {
                  this.doTrace(req, resp);
              } else {
                  String errMsg = lStrings.getString("http.method_not_implemented");
                  Object[] errArgs = new Object[]{method};
                  errMsg = MessageFormat.format(errMsg, errArgs);
                  resp.sendError(501, errMsg);
              }
      
          }
      

      当然,这其中还有许多方法需要被重写才能完成我们想要的功能

    3. 重写doGet方法和doPost方法

      public class HelloServlet extends HttpServlet {
          // 由于get或者post只是请求实现的不同方式,可以相互调用,业务逻辑都一样
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              // ServletOutputStream outputStream = resp.getOutputStream();
              PrintWriter writer = resp.getWriter();
              writer.print("Hello, Servlet");
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              super.doPost(req, resp);
          }
      }
      
    4. 编写Servlet的映射

      为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径

      在web.xml文件中配置:

        <!--注册Servlet-->
        <servlet>
          <servlet-name>hello</servlet-name>
          <servlet-class>com.xu.servlet.HelloServlet</servlet-class>
        </servlet>
        <!--Servlet的注册(请求)路径-->
        <servlet-mapping>
          <servlet-name>hello</servlet-name>
          <url-pattern>/hello</url-pattern>
        </servlet-mapping>
      
    5. 配置Tomcat

    6. 启动测试

      1. 首先进入localhost时,是index.jsp页面,想要跳转到Servlet页面,则需要在域名后补上servlet-mapping的url-name,比如,在测试中,笔者所用的url-name为hello,则需要将域名改为:localhost:8080/s1/hello

    如果最终测试过程中,遇到:跳转到servlet页面时出现404的页面,则有可能是application context出现了问题,请进入smart tomcat中修改:

    在这里插入图片描述

    用项目名称,即project的名称,本示例中为javaweb-02-servlet

    如果遇到:跳转到servlet页面时出现500的情况,则是因为找不到相应的servlet的jar包,因此检查是否环境中配置了servlet的依赖,如果有,则查看Tomcat的版本:

    • Tomcat 9.x.x版本时,依赖中添加servlet的jar包名称为javax.servlet-api
    • Tomcat 10.x.x版本后,javax变更为javarta,因此查看是否依赖正确,如果不会修改,则卸载Tomcat 10 ,安装Tomcat 9(到目前为止,笔者使用的时Tomcat 10,但是在修改依赖时,将javax修改为javarta,会报错,还在查找原因当中,如果实在没有办法,笔者也只能将Tomcat 10 卸载,重新安装Tomcat 9)

6.3、Servlet原理

配置servlet:

想要Tomcat创建servlet实现类,就必须让Tomcat知道它在哪,因此我们在web.xml中配置servlet时,必须给出实现类的全限定类名

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!--注册Servlet-->
  <servlet>
    <servlet-name>hello</servlet-name>
    <!--全限定类名-->
    <servlet-class>com.xu.servlet.HelloServlet</servlet-class>
  </servlet>
  <!--Servlet的注册(请求)路径-->
  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
</web-app>

Tomcat会将被配置好的servlet放入HashMap中以待日后使用,当浏览器发送相应的请求时,Tomcat会在HashMap寻找相应的servlet,调用它并完成响应。

而且,Tomcat并不会一开始就创建servlet对象,而是当浏览器发送相应的请求时,才会调用无参构造函数(若只有有参构造函数而没有无参构造函数,服务器是无法调用的,请在写servlet应用类时注意添加无参构造函数)去创建servlet对象。

初始化:

Servlet中有一个方法:init(ServletConfig var),它将会完成本Servlet的初始化功能,Tomcat在创建完成Servlet的实例化对象后,将会立即执行初始化操作

service:

service是servlet中十分重要的方法,当我们发送多次请求时,并不会重复创建servlet对象servlet实例化对象只会创建一个,也就是说,当一个servlet类的实例化对象被创造出来,后续发送的请求,都是由这个实例化对象进行回应),而是会不断调用service方法进行响应,比如,我们在service方法中加入以下代码:

    @Override
    public void init() throws ServletException {
        System.out.println("servlet---->init");
    }    

	@Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("servlet -----> service");
    }

在发送多次请求时,我们可以发现:

在这里插入图片描述

servlet初始化操作只执行了一次,而service方法则每请求一次,便调用一次。

销毁:

通过调用destroy方法来销毁一个servlet对象,一般而言,关闭浏览器并不会销毁该servlet实例化对象,而是当服务器关闭时才会销毁,即:一个servlet对象的销毁是tomcat服务器调用其destroy方法来完成的。

servlet生命周期:

第一次发送请求 → Tomcat创建servlet对象→调用初始化方法init→执行service方法

非首次发送请求→执行service方法

关闭服务器→调用destroy方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1131247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

警惕!又2本期刊被“On Hold”!

【SciencePub学术】 此前&#xff0c;继一本SSCI期刊被取消“On hold”标识后&#xff0c;仍处于“On Hold”状态的期刊有6本&#xff0c;其中包括4本SCI期刊和2本ESCI期刊。近日&#xff0c;经小编查询&#xff0c;又新增2本“On Hold”期刊&#xff0c;详情如下&#xff1a;…

实例演示:拉格朗日乘子法(Lagrange multiplier method)

拉格朗日乘子法&#xff08;Lagrange multiplier method&#xff09;是一种寻找多元函数在一组约束下的极值的方法。通过引入拉格朗日乘子&#xff0c;可将有d个变量与k个约束条件的最优化问题转化为具有dk个变量的无约束优化问题求解。这种方法将一个有n个变量与k个约束条件的…

以数据赋能,星辰天合推进智慧化校园建设

近日&#xff0c;上海市高等教育学会校园网络专业委员会 2023 年度学术年会在上海举办&#xff0c;本次会议以“数智赋能教育 生成美好未来”为主题&#xff0c;围绕 AI 与教育融合、高校数字化转型创新发展等内容进行了专业研讨。 XSKY星辰天合解决方案总监李瑞宇作了《应用融…

ETHERNET/IP从站转CANOPEN主站连接AB系统的配置方法

你还在为配置网关的ETHERNET/IP从站和CANOPEN主站发愁吗&#xff1f;今天来教你解决办法&#xff01; 一&#xff0c;首先&#xff0c;配置网关的ETHERNET/IP从站&#xff0c;需要使用AB系统的配置方法&#xff0c;具体步骤如下 1&#xff0c;使用 AB 系统配置网关的 ETHERNET/…

Leetcode—547.省份数量【中等】

2023每日刷题&#xff08;八&#xff09; Leetcode—547.省份数量 实现代码 static int father[210] {0};int Find(int x) {if(x ! father[x]) {father[x] Find(father[x]);}return father[x]; }void Union(int x, int y) {int a Find(x);int b Find(y);if(a ! b) {fathe…

【java学习—八】单例设计模式(5)

文章目录 1. 相关概念2. 单例设计模式-饿汉式3. 单例设计模式-懒汉式4. 总结 1. 相关概念 单例&#xff1a;只有一个实例&#xff08;实例化对象&#xff09; 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就像是经典的…

MTC怎么办理?什么产品需要做MTC?

什么是MTC认证&#xff1f; 欧盟MTC认证也叫EN 10204认证&#xff0c;也叫承压材质认证。主要是对金属&#xff0c;钢材的一个追溯来源。 对于所有风险等级压力设备的承压部件材料及直接焊接到承压部件上的附件&#xff0c; 压力设备制造商必须通过向材料制造商索要保证其可追溯…

Android 应用流量监控实践

背景 得物Apm系统本身包含网络接口性能监控的能力&#xff0c;但接口监控主要关注的是接口的耗时、异常率等信息&#xff0c;没有流量消耗相关维度的统计信息&#xff0c;并且一部分流量消耗可能来自于音视频等其他特殊场景&#xff0c;在接口监控的盲区外。 为了了解用户目前…

EPB功能开发与测试(基于ModelBase实现)

ModelBase是经纬恒润开发的车辆仿真软件&#xff0c;包含两个大版本&#xff1a;动力学版本、智能驾驶版本。动力学版包含高精度动力学模型&#xff0c;能很好地复现车辆在实际道路中运行的各种状态变化&#xff0c;可用于乘用车、商用车动力底盘系统算法开发、控制器仿真测试&…

嵌入式Linux_学习路线+基础知识

嵌入式Linux_学习路线基础知识 一、学习路线 说明&#xff1a;u-boot是一大块学起来需要三到六个月比较耗时&#xff0c;也属于比较落后的知识点&#xff0c;所以暂时不学习&#xff0c;内核也是如此暂时不学习&#xff0c;从应用层入手&#xff0c;先入门再深入 二、Shell指令…

企业CRM系统选型时的一些建议

随着市场环境的变化&#xff0c;越来越多的企业有了使用CRM客户管理系统的需求。市面上那么多的CRM品牌&#xff0c;我们该如何选择呢&#xff1f;下面我们就来说说企业CRM系统选型时的一些建议。 1、明确自身需求 企业要厘清使用CRM的目的&#xff1a;是遇到了只有CRM才能解…

友宝赴港上市能否成为无人零售业领头羊?

北京友宝在线科技股份有限公司&#xff08;以下简称“友宝”&#xff09;近日宣布赴港上市&#xff0c;拟募集资金2.35亿港元&#xff0c;这引起了业界和投资者的广泛关注。据了解这已经是友宝第三次冲击港股IPO了&#xff0c;但是至今仍在门外徘徊。 据招股说明书显示&#x…

zfile环境搭建(存储引擎为minio)

zfile项目地址 minio环境搭建参考 本地运行 修改zfile项目配置文件&#xff0c;更改数据库为MySQL&#xff08;注释掉灰色高亮部分&#xff0c;启用下面的 MySQL 信息并修改为你的数据库信息&#xff09; ## sqlite #spring.datasource.driver-class-nameorg.sqlite.JDBC #s…

【C++面向对象】3. 友元

文章目录 【 1. 友元函数 】【 2. 友元类 】 友元可以是一个函数&#xff0c;该函数被称为 友元函数&#xff1b;友元也可以是一个类&#xff0c;该类被称为 友元类。友元可以理解为 原类 的 朋友&#xff0c;友元&#xff08;友元函数和友元类&#xff09;不是原类的成员&…

【vue3】状态过渡-GSAP插件实现

效果图&#xff1a; 实现代码 安装库&#xff1a;npm install --save-dev gsap 引入&#xff1a;import gsap from gsap <template><div><el-input v-model"num.currNum" type"number" step"20" style"width: 120px;"…

基于多尺度分形残差注意力网络的超分辨率重建算法

1.引言 深度神经网络可以显著提高超分辨率的质量&#xff0c;但现有方法难以充分利用低分辨率尺度特征和通道信息&#xff0c;从而阻碍了卷积神经网络的表达能力。针对此类问题&#xff0c;本章提出了一种多尺度分形残差注意力网络&#xff08;Multi-scale Fractal Residual A…

js快速回顾

组成 书写位置 声明 ![在这里插入图片描述](https://img-blog.csdnimg.cn/83e92ae533714d5bb45d0cbb00d19e20.png)数据类型

【HyperQuest】调参

1 前言 平台网址链接 平台介绍&#xff1a;这是一个网络应用程序&#xff0c;专门为机器学习的初学者设计&#xff0c;可以轻松地通过直觉来选择正确的超参数。 以此篇文章记录我的调参结果和个人总结&#xff0c;如果大家有更好的效果&#xff0c;欢迎留言交流~ 2 调参思路 …

C语言行列式转置

#include<stdio.h> void main() {int a[3][4] { {1,2,3},{4,5,6},{7,8,9} };int b[4][3] {0};int zf sizeof(a) / sizeof(a[0][0]);//总长int row_len sizeof(a) / sizeof(a[0]);//行数int col_len zf / row_len;//列数int i, j, k0,count0;for (i 0; i <row_le…

福建三明大型工程机械3D扫描测量工程零件开模加工逆向抄数-CASAIM中科广电

高精度3D扫描测量技术已经在大型工件制造领域发挥着重要作用&#xff0c;可以高精度高效率实现全尺寸三维测量&#xff0c;本期&#xff0c;CASAIM要分享的应用是大型工程机械3D扫描测量案例。 铣轮是深基础施工领域内工法先进、技术复杂程度高、高附加值的地连墙设备&#xff…