1. Servlet 结构图

2. servlet接口

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

Init方法被调用时会接收到一个 ServletConfig类型的参数,是容器传进去的。 ServletConfig顾名思义指的是 Servlet的配置,我们在 web.xml中定义 Servlet时通过 init-param标签 配置的参数就是通过ServletConfig来保存的,比如,定义Spring MVC的Servlet时指定配置 文件位置的contextConfigLocation参数就保存在ServletConfig中,例如下面的配置:

<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml,classpath:webmvc-config.xml
</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

 Tomcat 中 Servlet 的 init 方法是在 org.apache.catalina.core.StandardWrapper 的 initServlet 方法中调用的。

2.1 ServletConfig 接口

public interface ServletConfig {
   //获取Servlet的名字,也就是我们在web.xml中定义的servlet-name
String getServletName();
   //ServletContext代表 的是我们这个应用本身
ServletContext getServletContext();
   //用于获取init-param配置的参数
String getInitParameter(String var1);
   //用于获取配置 的所有init-param的名字集合
Enumeration<String> getInitParameterNames();
}

2.2 GenericServlet

GenericServlet是Servlet的默认实现,主要做了三件事:①实现了 SbrvletConfig接口,我 们可以直接调用ServletConfig里面的方法;②提供了无参的ink方法;③提供了 log方法。

2.3 HttpServlet

  HttpServlet是 用 HTTP 协议实现的 Servlet的基类,写 Servlet时直接继承它就可以了, 不需要时从头实现 Servlet接口,我们要分析的 Spring MVC中 的 DispatcherServlet就是继承 的 HttpServlet。既然 HttpServlet是跟协议相关的,当然主要关心的是如何处理请求 ,所 以 HttpServlet主要重写了 service方法。在 service方法中首先将 ServletRequest和 ServletResponse 转换为 HttpServletRequest 和 HttpServletResponse, 然后根据 Http 请求的类型不同 将请求路由到不同的处理方法。

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
//如果请求不符合规范直接抛出异常
if(req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
//转换类型
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
this.service(request, response);
} else {
throw new ServletException("non-HTTP request or 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 = 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);
}
}
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}

  

  

 

[springMvc] 源码分析笔记(一)的更多相关文章

  1. [springMvc] 源码分析笔记(二)

    1.SpringMvc 中核心Servlet的继承结构图 2.HttpServletBean public abstract class HttpServletBean extends HttpSer ...

  2. [心得体会]SpringMVC源码分析

    1. SpringMVC (1) springmvc 是什么? 前端控制器, 主要控制前端请求分配请求任务到service层获取数据后反馈到springmvc的view层进行包装返回给tomcat, ...

  3. 8、SpringMVC源码分析(3):分析ModelAndView的形成过程

    首先,我们还是从DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) throw ...

  4. 7、SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解

    从上一篇 SpringMVC源码分析(1) 中我们了解到在DispatcherServlet.doDispatch方法中会通过 mv = ha.handle(processedRequest, res ...

  5. zeromq源码分析笔记之线程间收发命令(2)

    在zeromq源码分析笔记之架构说到了zmq的整体架构,可以看到线程间通信包括两类,一类是用于收发命令,告知对象该调用什么方法去做什么事情,命令的结构由command_t结构体确定:另一类是socke ...

  6. springMVC源码分析--ViewNameMethodReturnValueHandler返回值处理器(三)

    之前两篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)和springMVC源码分析--HandlerMethodReturnValu ...

  7. springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)

    在上一篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)我们介绍了返回值解析器HandlerMethodReturnValueHand ...

  8. springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)

    之前两篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)和springMVC源码解析--HandlerMethodArgumentResol ...

  9. springMVC源码分析--访问请求执行ServletInvocableHandlerMethod和InvocableHandlerMethod

    在之前一篇博客中springMVC源码分析--RequestMappingHandlerAdapter(五)我们已经简单的介绍到具体请求访问的执行某个Controller中的方法是在RequestMa ...

随机推荐

  1. 18.12.09-C语言练习:黑洞数 / Kaprekar问题

    题目: 程序: #include <stdio.h> int main(void) { int n, a, b, c, t, A, B; printf("输入一个三位数整数:&q ...

  2. REST framework---基于类的视图

    一.程序设计 1.路由设计 from django.conf.urls import url from django.contrib import admin from app import view ...

  3. Dapper 批量插入

    环境 Mssql 自带的Dapper.Net 批量插入 是一条条循环插入 这里改成了单条 Ps:主要此方法要控制字符串长度哦,每个数据库对单条sql字符长度的限制是不一样的. /// <summ ...

  4. 利用airbase-ng建立Soft AP

    利用airbase-ng建立Soft AP,再利用一些常见工具进行嗅探,或对抓包进行分析是出现比较早的一种MITM攻击方法.网上有很多关于手动实现的文章,也有一些自动实现脚本.这些脚本通常分两类,一类 ...

  5. CAN双机通讯调试小结(SJA1000与MCP2515通讯)

    2011-12-07 21:36:02. 效果图: 1,51的SJA1000自收自发测试完成,见上一篇小结. 2,SJA1000自测完成后,再自测MCP2515就非常容易.主要是设置工作模式为回环模式 ...

  6. 虚拟蜜罐honeyd安装使用

    转https://blog.csdn.net/jack237/article/details/6828771

  7. Ruby学习笔记之升级ruby的版本

    升级ruby版本,有时候安装ruby的版本过低,需要进行升级,例如安装在centos6.7安装fpm需要ruby版本在1.9以上. 0x00 主机环境如下 [root@test ~]# cat /et ...

  8. ApiDoc官方文档

    链接地址:https://blog.csdn.net/whatday/article/details/84590795

  9. 2.裴波那契(Fibonacci)数列

    裴波那契(Fibonacci)数列 f(n)= ⎧⎩⎨0,1,f(n−1)+f(n−2),n =0n =1n>1 求裴波那契数列的第n项.(题目来自剑指offer) 1.递归解法,效率很低的解法 ...

  10. Protocol Buffer序列化/反序列化---初体验(java版)

    今天闲遐时学习了 Protocol Buffer 在网上看到了许多资料,其中不泛精品,想要详细了解的请看文章结尾的友情链接,我这里就做加深印象,快速入门的一个完整的demo,仅此而已. 学完你可以得到 ...