整天都说Servlet,那什么是Servlet呢?
答:Servlet就是运行在服务器端的一段代码,可以帮我们处理网络请求,说白了就是我们平时Main方法里面执行的那一段逻辑,不过我们的程序跑在Servlet容器中,并没有Main方法可以执行,那我们写的这段代码怎么办呢?
Tomcat,也就是我们常说的Servlet容器,其实就是一个大的Main方法,像是一个永动机一样,时时刻刻的监听着来自网络的请求,所以我们才说Tomat是Web服务器+Servlet容器,如果Tomcat是个大的main方法,我们想让他帮忙执行我们的逻辑,总要告诉他我们要执行的代码长什么样子吧,这就要求我们的Servlet要遵循一定的规范,要不然随便一段代码都能被用来处理网络请求,岂不是乱套了,所以Tomcat就实现了著名的Servlet规范,现在我们来看看Servlet规范是个什么东东?
servlet规范就是JDK提供的Servlet接口,我们来看看这个接口的内容
只要实现了这个接口,就代表了我们遵循了Servlet规范,下面我们就看看怎么实现这个接口,首先我们看一看有哪些Servlet的实现类,我们参考一下
首先映入眼帘的就是跟我们servlet同根同源的GenericServlet,我们看一下结构,有个大概印象
道理我都懂,可是这个ServletConfig是个什么东西,这个我们暂且按住不表,这个是跟我们著名的ServletContext有着千丝万缕关系的大人物,后面会详细展开,我们先看一下GenericServlet帮我们实现了哪些关于Servlet的东西,我们从上往下,首先是Init方法
其实也没干啥,就是把ServletConfig,我们就先认为这就是我们项目的Servlet配置,把它由参数变量的位置提拔到了全局变量的位置,然后调用另外一个Init方法去进行Servlet初始化,往下看会发现这是一个空方法,如果子类有什么特殊的初始化要求,可以去实现这个方法
然后就是我们的getServletConfig方法
很简单,就是把上面Init方法中的参数给返回回去,这也是为什么上一步要把这个变量提升到全局变量的高度,接下来就是重头戏,我们的Service方法,看一看他都为什么实现了什么
???WTF,最重要的方法居然是个抽象方法,不说了。。。抬走,下一位
下一位。。
看到最后我们的结论就是GenericServlet是个不是规范胜似规范的东西,干的唯一一件事情就是把ServletConfig提升到了全局高度,可以在子类中获取到这个配置信息,所以从这边找经验是没戏了,大佬就是大佬,jdk里面的可能都是规范吧,我们把目光转向我们的tomcat,都说他是实现了Servlet规范的Servlet容器,里面应该有些干货,上来就是重头戏,HttpServlet
光听这个名字就不简单,又是Http又是Servlet,仔细想一想这两方面不就是tomcat全部的工作么,这个狂妄的名字都敢叫,我们看看里面有些什么门道,结果上来就发现,他实现了上面介绍的那位大佬,GenericServlet,还是一步一步看,首先是init方法
首先我们发现并没有init方法。。那不用说了继承了上面大佬的init方法,然后是getServletConfig,也是直接继承的GenericServlet,这也是GenericServlet给我们提供的唯二的贡献,直接看service方法
首先HttpServlet默认请求为HttpSetrvletRequest,就好像你去饭店,服务员就默认你是吃饭的人,而不是逛街的人一样,最重要的一步就是Service方法被重载了,看一下
首先就是根据请求信息,拿到请求方式,然后一堆的if-else去判断,如果是GET方法就调用doGet,是PSOT就调用doPost,HEAD,PUT等类推,如果都不是就返回一个501,现在看来httpServlet起码帮我们分析了根据请求是什么,去调用不同的方法,现在重点就来到了doGet和doPost这些方法上
其实doGet什么也没干,毕竟现在已经到了逻辑处理的部分了,巧妇难为无米之炊,纵然HttpServlet再强大,他也不会了解你具体的业务需求,所以他就返回了405和400的错误码,如果你继承了HttpServlet,但什么都不写,Get请求过来会得到一个405
其他方法也是一样,其实重头戏到这里已经差不多了,到这里我们发现了,其实想要实现Servlet规范,并不需要我们从头开始每个方法都去实现一遍,如果我们需要的是处理Http请求,我们只需要继承HttpServlet,去实现不同的请求逻辑就可以了,看完了这些规范,我们看一个真正的Servlet,DefaultServlet,听这个名字就是会经常被忽略的那一种,但是这个是非常重要的,他是专门处理静态文件的一个Servlet,是默认在tomcat的wex.xml中配置的,当你的项目出现静态资源加载不出来的时候就要考虑是不是项目的web.xml配置的servlet拦截了这个DefaultServlet的工作,下面我们来看看这个servlet,首先是init
首先需要明白的一点就是Init方法是用来初始化一些内容的,如上图所示,首先通过getServletConfig来获得我们的全局servletConfig,这里面定义了很多内容,值得注意的有fileEncoding,定义了字符编码,input,output定义了输入和输出的缓冲区大小,下面具体看一下service方法,因为DefaultServlet是继承自httpServlet所以我们直接关注doGet和doPost的实现方式即可
可以看到,又调用了ServResource方法,通过名字可以看的出来,就是根据请求信息中的资源路径,去项目下具体的位置获取静态资源,代码过长就不贴出来了,有兴趣的朋友可以去源码里看一下
doPost其实还是调用的doGet方法
总结一下:
要想实现一个能在servlet容器中运行的服务端程序,需要Tomcat去识别并调用,所以应该遵循servlet规范
实现servlet规范只需要实现jdk提供的servlet接口即可
servlet接口中方法很多,我们如果直接实现的话比较繁琐
jdk提供了GenericServlet,实现了servlet接口,把servletConfig从局部变量提升为全局变量,方便在其他方法中读取到Servlet配置信息中的值,但是没有实现最核心的service方法
Tomact提供的httpServlet,继承自GenericServlet,对service方法进行了处理,根据请求方式封装了doGet,doPost,doPut等方法
实现servlet规范就只需要继承自HttpServlet,重写doGet等方法即可
以tomcat默认的静态资源处理DefaultServlet为例看一下servlet实现的具体步骤,谢谢大家~
文章转载自微信公众号:左右逢猿