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. Seq2Seq ---学习笔记

    应用场景:机器翻译 与language model 不同 MT model 的a<0> 是由encoder 生成的. language model 的 a<0> 是 初始化的. ...

  2. 大兄dei,早点看清this吧

    说道this,可以说是前端中很重要的问题之一了,也是面试或者笔试常考的问题.所以还是早点看清this吧,大兄dei. this是什么?为什么要存在? this关键字是js中最最复杂的机制之一.他被自动 ...

  3. Python文件操作中的方法:.write()换行

    active =Truewhile active: message =input("\nPlease input your name:\n") if message =='q': ...

  4. WEB学习小笔记

    环境基于WIN10.IDEA最新版.JDK1.8.TOMCAT9 下面说的有错的地方希望指出,谢谢. STRUT2 1.在maven下的时候系统会系统创建一个叫做log4j的配置文件,但是到了这个版本 ...

  5. 【转】Anaconda下安装pyecharts步骤及常见错误

    本文转载自:https://blog.csdn.net/skj1995/article/details/81187954 (1)之前看了几篇博客,有人说用cmd命令在目录C:\Users\Admini ...

  6. es6转es5 在线转换工具

    es6转es5 在线转换工具 Babeljs es6console

  7. keras用法

    关于Keras的“层”(Layer) 所有的Keras层对象都有如下方法: layer.get_weights():返回层的权重(numpy array) layer.set_weights(weig ...

  8. mongo 修改器

    [$inc] 作用:修改器$inc可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作. Example: db.b.update({"uid" : "2 ...

  9. %zsy %lqs 随感

    今天是cj的大毒瘤zsy(对对,您说的都对,题目不难的啦,是我太菜啦)出题. 我校选手lqs仍然坚持高水平的发挥,wzy神犇却不在状态. 面对T1sb题(其实干了2h)和T3的原题(我&lqs ...

  10. 【模板】ST表

    给定一个长度为 \(N\) 的数列,和 \(M\) 次询问,求出每一次询问的区间\([l,r]\)内数字的最大值. 说明 对于30%的数据,满足: \(1 \leq N, M \leq 10 , 1≤ ...