首页 > 编程语言 >Java-Servlet解析

Java-Servlet解析

时间:2023-05-22 21:32:15浏览次数:42  
标签:Java 请求 service Servlet 方法 HttpServlet 解析 servlet

前言

从事Javaweb项目开发有一段时间了,一直不理解它是怎么一回事,后来查询资料发现这里面涉及到几个东西,分别是tomcat、JavaEE中13个规范之一的servlet、以及springMVC。于是就去学习了一下,发现这里里面都是围绕这servlet进行的操作。于是就有了今天的这个总结。

Servlet

定义

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。 狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。 关于web服务器有很多种,其中常用的有tomcat、Netty,还有微软的IIS(Internet Information Services), 本文中用到的web服务器为tomcat

内部解析

既然说到这个servlet是一个规范,一般说到规范都是接口,就好比我们在项目开发过程中,前端开发工程师和后端的开发工程师都是根据接口文档去进行开发的,双方都遵守这个接口文档,那么开发过程就会减少很多不必要的麻烦。所以下图就是Servlet在Java中的结构展示。

image.png

package javax.servlet;
public interface Servlet {
    void init(javax.servlet.ServletConfig servletConfig) throws javax.servlet.ServletException;
    javax.servlet.ServletConfig getServletConfig();
    void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws javax.servlet.ServletException, java.io.IOException;
    java.lang.String getServletInfo();
    void destroy();
}

下面是servlet接口内部方法的展示一共是有5个方法

  • 第一个init(javax.servlet.ServletConfig servletConfig) 这个方法在servlet对象初始化的时候执行,只执行一次。
  • 第二个getServletConfig() 这个方法获取的是在web.xml中配置的参数比如: image.png
  • 第三个service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) 这个service方法就不得了了,这个方法就是我们具体要用到的请求接口方法了,通俗点讲就是,在web项目中将我们的业务代码可以放到这个service方法,当我们在项目中配置好了servlet的映射以后去调用请求,tomcat调用的就是这个方法。后面会具体演示,在实际开发中现在已经不是直接去实现了servlet接口了,而是重写HttpServlet这个类中的doGet和doPost方法。
  • 第四个getServletInfo() 当Servlet容器(如Tomcat)需要提供有关Servlet的信息时,它会调用getServletInfo()方法。通常情况下,这些信息用于管理和监视Servlet的部署和执行过程。例如,当管理员查看部署在Servlet容器中的应用程序时,可能会显示Servlet的名称、描述、版本号等信息。
  • 第五个destroy()、 当Servlet容器(如Tomcat)需要关闭或卸载Servlet时,它会调用Servlet的destroy()方法。这通常发生在以下情况下: 服务器关闭:当服务器关闭或重新启动时,Servlet容器会通知所有正在运行的Servlet执行销毁操作,以确保它们可以正确地释放资源。 Servlet被卸载:当应用程序的Servlet被从Servlet容器中卸载时,容器会先调用destroy()方法,然后才会将Servlet从容器中移除。 在destroy()方法中,Servlet可以执行一些清理任务,如释放打开的文件、关闭数据库连接、取消注册的监听器等。这是一个用于资源清理和释放的重要时机,以确保应用程序的正常关闭和资源的正确释放。

总结servlet接口

以上这些内容是JavaEE的servlet接口中定义的方法,这些方法中initdestroy都是只会执行一次,也就是说当tomcat程序启动,servlet中的这两个方法只会被调用一次,分别是创建servlet对象和销毁servlet时,那么大家肯定会问,既然只调用一次,哪是谁调用的呢?答案就是web容器去调用的,在web项目中我们写的代码最后都是由tomcat去执行的,但是tomcat怎么知道要调用你哪些类的哪些方法呢?为了解决这个问题,就有了这个servlet这个规范了,tomcat只去关注去实现了servlet接口的这些类,其它的类它不会去调用。

实际应用的servlet

上面的小总结说了,servlet是由tomcat去调用的,也就是说只要我们自己写的代码去实现了servlet的接口,并且在web.xml中配置了,那么当tomcat启动时它就会把我们自己写的servlet去给创建对象。 但是我们在实际应用的时候自己写的servlet类并没有去直接实现的servlet而是去继承的抽象类HttpServlet,这里大家就有疑问了,问什么不直接去实现servlet接口,却要去继承一个抽象类呢?这里就需要给大家说一下咱们一开始放出来的servlet的一个结构图(类图关系)了,image.png

GenericServlet类和HttpServlet类

GenericServlet类和HttpServlet类是Java Servlet API中的两个重要类,用于实现Servlet的基本功能。

  1. GenericServlet类:

    • GenericServlet是一个抽象类,实现了Servlet接口。
    • 它提供了Servlet的基本实现,可以被继承并用于创建自定义的Servlet。
    • GenericServlet适用于所有类型的协议,不仅限于HTTP协议。
    • 它简化了Servlet的编写,通过提供默认的空实现,使得开发者只需重写感兴趣的方法即可。
    • GenericServlet中最重要的方法是service(),用于处理客户端请求。默认情况下,它会委托给doGet(), doPost()等方法,可以在子类中进行重写以实现特定的请求处理逻辑。
    • 除了service()方法,GenericServlet还提供了其他有用的方法,如getServletConfig()getServletInfo(),用于获取Servlet的配置信息和描述信息。
  2. HttpServlet类:

    • HttpServletGenericServlet的子类,专门用于处理基于HTTP协议的请求。
    • 它扩展了GenericServlet,提供了更方便处理HTTP请求的方法和功能。
    • HttpServlet通过重写doGet()doPost()doPut()等方法,可以根据请求类型执行相应的处理逻辑。
    • 它还提供了一系列的钩子方法(如doHead()doDelete()doOptions()等),用于处理特定的HTTP请求方法。
    • HttpServlet还提供了一些用于处理HTTP请求的辅助方法,如获取请求参数、处理会话和Cookie等。

总结来说,GenericServlet类是一个通用的Servlet基类,适用于各种协议。而HttpServlet类是在GenericServlet基础上专门为HTTP协议提供了更方便的处理方法和功能。一般情况下,开发基于HTTP协议的Servlet时,应该使用HttpServlet类作为基类,以便更好地处理HTTP请求和提供相应的功能。 web项目中基本上都是使用的http协议,所以我们自己写的servlet类都是继承HttpServlet类的,因为这个类帮我们做了相应的http协议解析。

HttpServlet中的设计模式

既然使用http协议进行通信,那么http协议的请求是不同类型,比如post、get、put等,那这些类型请求servlet是如何区分呢?因为在servlet接口中只有一个service方法会被tomcat调用呀!所以这里就用到了设计模式中行为型的模板方法了。

首先看一下模板方法的定义

  • 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern), 指在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
  • 简单说, 模板方法模式定义一个操作中的算法的骨架,而将- -些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤。

image.png

逐步解析

在HttpServlet中定义好了相应不同类型请求的方法

  • doGet,如果 servlet 支持 HTTP GET 请求
  • doPost,对于 HTTP POST 请求
  • doPut,对于 HTTP PUT 请求
  • doDelete,对于 HTTP 删除请求 image.png 只要继承了HttpServlet重写以上不同的方法就可以在有相应类型的请求时调用对应的方法。那大家肯定会想,这么多方法它是怎么知道我请求这个servlet时发出的是什么请求呢?这里就要说一下了,这个HttpServlet中已经解析了http请求,也就是说它解析了这个请求是什么类型,当它解析到这个请求是post类型时就会调用doPost方法,它是怎么调用的呢?这里就说到了模板方法的核心了,定义算法骨架。在HttpServlet中有一个方法叫做service方法,这个方法并不是实现的servlet接口的那个service方法,这两个有区别。 image.png
  protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String method = req.getMethod();
        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }
        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);
        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);        
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);         
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);         
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);            
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);           
        } else {
            //
            // Note that this means NO servlet supports whatever
            // method was requested, anywhere on this server.
            //

            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
            
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }

image.png 所以当我们自己写的类继承了HttpServlet后去重新其中的doPost或者doGet等方法后会在HttpServlet中自定义的service方法中进行分发 image.png 可以看一下这个service方法中,有一个service方法调用,这是在调用HttpServlet中自定义的service方法进行后续的请求分发。 image.png

SpringMVC应用

说到这里就浅浅的说一下,SpringMVC的实现就是基于Servlet实现的,在配置mvc项目时用springMVC是需要在web.xml中进行配置的,大家可以看一下这个配置是什么。 image.png 再继续往下看,我们看一下SpringMVC中的核心类DispatcherServlet,可以看到,这个类其实也是实现了Servlet接口的。也就是说SpringMVC的实现是在基于Servlet开发的。 image.png

标签:Java,请求,service,Servlet,方法,HttpServlet,解析,servlet
From: https://blog.51cto.com/u_15918766/6327206

相关文章

  • 基于JAVA的springboot+vue“智慧食堂”设计与实现,食堂管理系统,附源码+数据库+lw文档+P
    1、项目介绍本系统的用户可分为用户模块和管理员模块两大界面组成。一个界面用于管理员登录,管理员可以管理系统内所有功能,主要有首页,个人中心,用户管理,菜品分类管理,菜品信息管理,留言板管理,系统管理,订单管理等功能;另一界面用于用户登录,用户进入系统可以实现首页,菜品信息,留言板,个人......
  • idea中jdk11用maven编译失败 Fatal error compiling: tools.jar not found: XX\Java
    ideamaven编译需要用到jdk的lib包里面的tools.jar文件,但是jdk1.8之后就没有tools.jar了。我这里用的是graalvm的jdk11,编译一直报错,网上也查不到。解决办法: 根据对应路径创建一个lib包,并把jdk1.8的lib下面的tools.jar复制一个放到这个包下面,让这个路径有这个包就行了。我......
  • java基于joda-date实现获取两个时间段对应类型的所有时间,比如说两年之间的所有日期,两
    /***获取两个时间段对应类型的所有时间**@paramtype日期类型,包含day、month、year*@parambeginTime开始时间*@paramendTime结束时间*@return*/publicstaticList<String>getBetweenTime(Stringtype,String......
  • JavaWeb
    htmlcssjavascriptjQueryxmldomjdomdom4jsaxpullServlet处理前端发送过来的请求Servlet容器,处理servlet的运行和管理它的生命周期以及共享数据jsp跳转servlet需要注意的一些问题jsp中的action和servlet中的注解@WebServlet("/firstServlet")应保持一致......
  • javax.validation.constraints 参数校验
    很痛苦遇到大量的参数进行校验,在业务中还要抛出异常或者不断的返回异常时的校验信息,在代码中相当冗长,充满了if-else这种校验代码,今天我们就来学习spring的javax.validation注解式参数校验. 为什么要用validatorjavax.validation的一系列注解可以帮我们完成参数校验......
  • 记录--九个超级好用的 Javascript 技巧
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助前言在实际的开发工作过程中,积累了一些常见又超级好用的Javascript技巧和代码片段,包括整理的其他大神的JS使用技巧,今天筛选了9个,以供大家参考。1、动态加载JS文件在一些特殊的场景下,特别是一些库和框架......
  • java前后端分离有详细内容吗?
    微服务架构java前后端分离都有哪些具体内容?目前,有不少客户朋友经常询问我们类似的问题。其实,在新的经济发展形势下,提质增效的低代码开发平台微服务架构早已成为不少新老客户的选择,它们不仅能提高办公协作效率,而且还能助力企业实现办公自动化快速发展。1、java前后端分离到底有啥......
  • javascript基础2
    script标签里一旦使用src加载外部js文件后,这个script标签就不能写js语句了警告框!通知用户出错了。alert("哈哈!")输入框-输入内容prompt得到输入内容永远都是字符串varn1=prompt("第一个数")varn2=prompt("第二个数")问询框-confirm("呵呵")使用弹出框来显示结果......
  • JavaScript中实现文件上传下载的三种解决方案(推荐)
    ​ 以ASP.NETCoreWebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API,包括文件的上传和下载。 准备文件上传的API #region 文件上传  可以带参数        [HttpPost("upload")]        publicJsonResultuploadProject(I......
  • java 基础
    1、hashMap原理是一个keyvalue的存储结构。把key经过hash算法行程一个索引,在理想的过程中,行程的key是惟一的,但是不理想的状况,就会出现相同的索引,也就是hash碰撞。解决hash冲突JDK1.7的时候,用链表+数组 JDK1.8引入了红黑树当链表的长度大于等于8,会先判断数组如果大于64会......