Servlet的基本认识

本内容主要来源于《看透Spring MVC源码分析与实践——韩路彪》一书

Servlet是server+Applet的缩写,表示一个服务器的应用。Servlet其实就是一套规范。

一、servlet接口

  Servlet3.1中servlet接口定义如下:

public interface Servlet {

   //init方法在容器启动时被容器调用(当load-on-startup设置为负数或者不设置时会在Servlet第一次用到时才被调用),只会调用一次。
   public void init(ServletConfig config) throws ServletException;    //getServletConfig方法用于获取ServletConfig。
   public ServletConfig geServletConfig();    //service方法用于处理一个请求。
   public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;    //getServletInfo方法可以获取一些Servlet相关的信息,这个方法需要自己去实现,默认返回空字符串。
   public String getServletInfo();    //destroy方法用于在Servlet销毁(一般指关闭服务器)时释放一些资源,也只会调用一次。
   public void destroy();
}

  1.1init方法:

    init方法被调用时会接受到一个ServletConfig(Servlet的配置)类型的参数,是容器传进去的。我们在web.xml中定义Servlet时通过init-param标签配置的参数就是通过ServletConfig来保存的。

  1.2 getServletConfig 方法:

  1.3 service方法:

  1.4 getServletInfo方法:

  1.5 destroy方法:

二、ServletConfig接口:

  ServletConfig接口的定义如下:

public interface ServletConfig {

    //获取Servlet的名字,也就是在web.xml中定义的servlet-name
public String getServletName(); //返回的ServletContext代表着我们这个应用本身。其实就是Tomcat中Context的门面类ApplicationContextFacade。
public ServletContext getServletContext(); //用于获取init-param配置的参数
public String getInitParameter(String name); //用于获取配置的所有init-param的名字的集合
public Enumeration<String> getInitParameterNames();
}

  其中方法getServletContext返回值ServletContext代表了应用本身,所以ServletContext里边设置的参数就可以被当前应用的所有的Servlet所共享。

  我们做项目的时候都知道参数可以保存在session中,也可以保存在application中,而servlet的参数就是保存在servletContext中。

  可以这么理解,ServletConfig是Servlet级的,ServletContext是Context级的。当然ServletContext的功能非常强大,不只是保存配置参数。

  在ServletContext的接口中有一个方法:public Servlet getContext(String uripath),它可以根据路径获取到同一个站点下的别的应用的ServletContext,由于安全的原因,一般返回的是null。

三、GenericServlet抽象类:

public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {
}

  GenericServlet是Servlet的默认实现,主要做了三件事:

    1.实现了ServletConfig的接口。

      我们可以直接调用ServletConfig里面的方法。因此当我们需要获取ServletContext时就可以直接调用getServletConfig(),而不用调用getServletConfig().getServletContext()了。

    2.提供了无参的init方法。

      GenreicServlet实现了Servlet的init(ServletConfig config)方法,将里面的config赋值给了自身的内部变量config,然后调用了无参的init方法,这个无参的init()方法是个模板方法,可以在子类中通过覆盖它来完成自己的初始化工作。

    @Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
// NOOP by default
}

    3.提供了两个log方法。

      一个是记录日志,一个是记录异常。

//记录日志
public void log(String msg) {
getServletContext().log(getServletName() + ": " + msg);
}
//记录异常
public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
}

  一般我们都是有自己的日志处理方式,所以用的不多。而且GenreicServlet是与具体协议无关的。

四、HttpServlet抽象类:

  HttpServlet使用HTTP协议实现的Servlet的基类,因此在我们写Servlet的时候直接继承HttpServlet就可以了。Spring MVC中的DispatcherServlet就是继承的HttpServlet。

  因为是和协议相关的,所以这里就比较关心请求的事情了。在HttpServlet中主要重写了service方法,将父类中(Servlet接口)service方法的参数ServletRequest和ServletResponse转换为HttpServletRequest和HttpServletResponse。

//重写父类的方法
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException { HttpServletRequest request;
HttpServletResponse response; try {
//强转参数
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
//如果请求类型不相符,则抛出异常
throw new ServletException("non-HTTP request or response");
}
//调用本类中http的处理方法
service(request, response);
} //本类中方法
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;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
// Invalid date header - proceed as if none was set
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// 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);
}
}

  这里只是将Servlet中的一些源码做些分析。

servlet-servlet的简单认识——源码解析的更多相关文章

  1. KBEngine简单RPG-Demo源码解析(1)

    一:环境搭建1. 确保已经下载过KBEngine服务端引擎,如果没有下载请先下载          下载服务端源码(KBEngine):              https://github.com ...

  2. SpringMVC一点简单地源码解析

    . 1.1 init(初始化) 在第一次发出请求时,会调用HttpServletBean 的init()方法 org.springframework.web.servlet.HttpServletBe ...

  3. KBEngine简单RPG-Demo源码解析(2)

    七:服务端资产库文件夹结构http://kbengine.org/cn/docs/concepts/directorys.html看assets, 注意:demo使用的不是默认的assets资产目录, ...

  4. KBEngine简单RPG-Demo源码解析(3)

    十四:在世界中投放NPC/MonsterSpace的cell创建完毕之后, 引擎会调用base上的Space实体, 告知已经获得了cell(onGetCell),那么我们确认cell部分创建好了之后就 ...

  5. 设计模式-简单工厂Coding+jdk源码解析

    感谢慕课geely老师的设计模式课程,本套设计模式的所有内容均以课程为参考. 前面的软件设计七大原则,目前只有理论这块,因为最近参与项目重构,暂时没有时间把Coding的代码按照设计思路一点点写出来. ...

  6. 简单理解 OAuth 2.0 及资料收集,IdentityServer4 部分源码解析

    简单理解 OAuth 2.0 及资料收集,IdentityServer4 部分源码解析 虽然经常用 OAuth 2.0,但是原理却不曾了解,印象里觉得很简单,请求跳来跳去,今天看完相关介绍,就来捋一捋 ...

  7. springMVC源码解析--ViewResolver视图解析器执行(三)

    之前两篇博客springMVC源码分析--ViewResolver视图解析器(一)和springMVC源码解析--ViewResolverComposite视图解析器集合(二)中我们已经简单介绍了一些 ...

  8. Spring-Session实现Session共享实现原理以及源码解析

    知其然,还要知其所以然 ! 本篇介绍Spring-Session的整个实现的原理.以及对核心的源码进行简单的介绍! 实现原理介绍 实现原理这里简单说明描述: 就是当Web服务器接收到http请求后,当 ...

  9. Spring5源码解析-论Spring DispatcherServlet的生命周期

    Spring Web框架架构的主要部分是DispatcherServlet.也就是本文中重点介绍的对象. 在本文的第一部分中,我们将看到基于Spring的DispatcherServlet的主要概念: ...

随机推荐

  1. 修改Egret引擎代码的方法

    某些情况下,我们需要修改Egret引擎的源码,我们可以在源码目录(一般如下:xxx\Egret\engine\x.x.x\src\egret)下直接修改ts代码. 在对应的项目下打开CMD命令行,输入 ...

  2. redhat杂记

    1.设置sudo权限:修改/etc/sudoers文件,找到root    ALL=(ALL)       ALL,在后面添加nginx ALL=(ALL) NOPASSWD: ALL 2.用sed命 ...

  3. com.android.jack.CommandLine: Internal compiler error

    Android studio编译的时候出现错误: SEVERE: com.android.jack.CommandLine: Internal compiler error Error:Executi ...

  4. JDK中Unsafe类详解

    Java中Unsafe类详解 在openjdk8下看Unsafe源码 浅析Java中的原子操作 Java并发编程之LockSupport http://hg.openjdk.java.net/jdk7 ...

  5. yii2的数据库读写分离配置

    简介 数据库读写分离是在网站遇到性能瓶颈的时候最先考虑优化的步骤,那么yii2是如何做数据库读写分离的呢?本节教程来给大家普及一下yii2的数据库读写分离配置. 两个服务器的数据同步是读写分离的前提条 ...

  6. Java泛型知识点全方位总结

    前言 我一直认为泛型是编程语言设计中一个非常基本和重要的概念.Java中的泛型是什么?他们为什么在那里?他们是如何发展的?在学习基础知识时,对仿制药的透彻理解是非常重要的.因此,我阅读了<Jav ...

  7. 转:The Difference Between a LayoutTransform and a RenderTransform

    来自:http://www.tuicool.com/articles/fIfm22 #770 – The Difference Between a LayoutTransform and a Rend ...

  8. OSG相关扩展工程

    https://blog.csdn.net/wang15061955806/article/details/51003803 OSG的相关扩展,OSG针对每个特定应用,也有很多的开发者进行开发和完善, ...

  9. go关键字之type用法

    1.定义结构体 type Student struct {     name string code int }       2.类型别名 type i int64 var age i = 30   ...

  10. python @staticmethod和@classmethod的作用

    一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法. 而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用. 这有利于组织代码,把某些应 ...