web服务器

web服务器从字面上理解:是用于存储web网站程序的服务器

WebServer做了哪些事儿?

当客户端(可以是浏览器、也可以是postman等工具)发送请求给服务器后,服务器会调用并执行对应的逻辑代码进行请求处理。逻辑代码是由程序员自己编写然后放进服务器进行运行,然后讲运行后的结果返回给客户端。那么服务器需要处理两件事情:

  • 1、处理网络连接
  • 2、找到我要寻找的资源(无论是程序还是其他网页资源)
  • 3、将找到的东西返回给用户

处理网络连接这里就不重点阐述,默认他能够接受并处理http协议栈的请求。

这里的资源在网上一般叫web资源:

web资源按照实现的技术和呈现的效果的不同,又分为静态资源和动态资源两种
静态资源:
html,css,js,txt,mp4视频,jpg图片…
动态资源:
JSP页面,Servlet程序

对于静态资源比较好办,直接返回就好了。但是对于动态资源比如代码如java代码,我必须找到这个代码的class文件,还需要根据请求找到代码从哪里开始运行。在本地我们直接运行main方法即可启动程序执行java代码,但是在web应用中我们不可能每次来个请求,我都去点一下main方法去执行相应的代码。

所以聪明的程序员们写了一个根据用户请求来调用相应逻辑代码的容器(对象),执行完相应逻辑后,java主线程并没有结束,而是在那里等待用户请求。这个容器就叫做服务器,每个请求的过程就是把程序员自己些的代码放入这个服务器执行并相应的过程。可是这个容器要能跑java代码的话,那也就必须要按照jvm规范去实现。那么服务器又如何知道去应该调用那个类和哪个方法来处呢?也就是服务器怎么才能认识程序员执行的代码。由于java的多态的性质,程序员写的代码只要和服务器共同实现一个接口。只要将程序员写的这个对象传入服务器,就可以直接执行这个代码。而这个技术就叫Servlet,只要程序员的请求都去实现servlet接口,请求的时候传给服务器容器,就去找这个实例对象中的一个service方法,再由service方法根据请求信息去找到对应的业务逻辑执行。而如tomcat服务器就是一种这样的服务器实现。

用户访问页面过程:

  1. 用户通过点击链接或者直接输入URL访问Servlet。
  2. Web服务器接收到请求后,交给Servlet容器。
  3. Servlet容器通过反射实例化Servlet。
  4. 调用Servlet特定方法对请求进行处理,并且产生一个响应。
  5. 响应由Servlet容器返回给Web容器。
  6. Web容器包装这个响应,以HTTP响应的形式发送给浏览器。

下面看个具体实现

Spring MVC (DispatcherServlet)请求处理流程

从servlet的doService开始:

DispatcherServlet中的 doService();

/*** Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}* for the actual dispatching.*//*翻译:暴露(个人理解是讲参数取出,或者传入新的参数)请求参数并指派(传递)给 doDispatch() 方法目的: 为了实际调度(处理请求)个人理解: 即对request进行预加工,设置默认属性,然后将 request,response 传入 doDispatch() 方法,对请求进行处理*/@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {if (logger.isDebugEnabled()) {String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +" processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");}// Keep a snapshot of the request attributes in case of an include,// to be able to restore the original attributes after the include.Map<String, Object> attributesSnapshot = null;if (WebUtils.isIncludeRequest(request)) {attributesSnapshot = new HashMap<String, Object>();Enumeration<?> attrNames = request.getAttributeNames();while (attrNames.hasMoreElements()) {String attrName = (String) attrNames.nextElement();if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {attributesSnapshot.put(attrName, request.getAttribute(attrName));}}}// Make framework objects available to handlers and view objects.request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());//mark ...  FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);if (inputFlashMap != null) {request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));}request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);try {//springMVC处理请求的核心doDispatch(request, response);}finally {if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Restore the original attribute snapshot, in case of an include.if (attributesSnapshot != null) {restoreAttributesAfterInclude(request, attributesSnapshot);}}}}

doDispatch(request, response) 方法:

/*** Process the actual dispatching to the handler.* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters* to find the first that supports the handler class.* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers* themselves to decide which methods are acceptable.* @param request current HTTP request* @param response current HTTP response* @throws Exception in case of any kind of processing failure*//*大致翻译: 所有http请求都是由这个方法处理,取决于 HandlerAdapters 或 handlers 决定哪个方法处理HandlerAdapter 将会通过查找 servlect 初始化后(安装后)的 HandlerAdapters 列表,找到第一个满足的 HandlerAdapter所有请求处理 handler 将会通过 HandlerMappings 查找到*/protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;//mark WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {// 视图类ModelAndView mv = null;// 异常类Exception dispatchException = null;try {//检查request类型 判断 http请求是否 multipart/form-data 类型processedRequest = checkMultipart(request);multipartRequestParsed = (processedRequest != request);// Determine handler for the current request.  // 获取 匹配当前请求的 HandlerExecutionChain类 的 handlermappedHandler = getHandler(processedRequest);// mappedHandler.getHandler() 返回值是个Object 类型  通过打断点证实是个 HandlerMethod 类 /*public class HandlerMethod {/** Logger that is available to subclasses */protected final Log logger = LogFactory.getLog(HandlerMethod.class);// controller 的类private final Object bean;// spring 的beanFactoryprivate final BeanFactory beanFactory;//匹配url(@RequestMapping) 处理的method 方法private final Method method;//mark.... private final Method bridgedMethod;//参数private final MethodParameter[] parameters;}*/if (mappedHandler == null || mappedHandler.getHandler() == null) {//未获取到请求即返回noHandlerFound(processedRequest, response);return;}// Determine handler adapter for the current request./*(适配器模式)通过遍历 handlerAdapters 来查找 supports 这个handler 的 handlerAdapter 类, 返回第一个匹配,查找不到即抛异常HandlerAdapter 的 supports 方法源码在 AbstractHandlerMethodAdapter(模板方法模式)控制子类的 supportsInternal 方法在 RequestMappingHandlerAdapter 中 supportsInternal 方法中 写死了return true 此处 supportsInternal 方法可以用来 自己创建 HandlerAdapter 与 自己定义 HandlerMethod 处理对象的格式 判断 handler 是否是 HandlerMethod 类型 AbstractHandlerMethodAdapter 类中的 supports() 方法:@Overridepublic final boolean supports(Object handler) {return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));}此处也可以知道 handler 的类型 是 HandlerMethod*/HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.String method = request.getMethod();boolean isGet = "GET".equals(method);if (isGet || "HEAD".equals(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if (logger.isDebugEnabled()) {logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);}if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {return;}}/*applyPreHandle 方法中调用了 HandlerExecutionChain 类中的 HandlerInterceptor 拦截器对请求进行拦截处理(preHandle方法)HandlerInterceptor 可以通过配置    <mvc:interceptors> 拦截器 </mvc:interceptors>  对请求进行拦截HandlerInterceptor 的 preHandle() 方法*/if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// Actually invoke the handler.// 翻译: 真正调用请求方法主体 即controller 中处理请求的那个 method 也是 HandlerMethod 中的method 属性// handler 方法中还有很多逻辑// 返回视图 @ResponseBody 情况下 mv 为null, 但是返回值已经存到response中mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(request, mv);// 调用 HandlerInterceptor 拦截器的 postHandle 方法mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}//返回视图,浏览器上展示效果processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {/*调用拦截器的 afterCompletion() 方法*/triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Error err) {triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);}finally {if (asyncManager.isConcurrentHandlingStarted()) {// Instead of postHandle and afterCompletionif (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}}

getHandler(processedRequest) 方法 返回 HandlerExecutionChain 对象,            getHandlerInternal 通过获取request 的url 请求 ,从urlMap 找到RequestMapping的Method 封装成 handlder( HandlerMethod 类 ),这就找到了我们要执行的类的方法了

    /*** Look up a handler for the given request, falling back to the default* handler if no specific one is found.* @param request current HTTP request* @return the corresponding handler instance, or the default handler* @see #getHandlerInternal*/@Overridepublic final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {// 通过 request 获取 handler (HandlerMethod 类型 )/*getHandlerInternal 通过获取request 的url 请求 ,从urlMap 找到RequestMapping的Method 封装成 handlder( HandlerMethod 类 )*/Object handler = getHandlerInternal(request);if (handler == null) {handler = getDefaultHandler();}if (handler == null) {return null;}// Bean name or resolved handler?if (handler instanceof String) {String handlerName = (String) handler;handler = getApplicationContext().getBean(handlerName);}/*将 handlder( HandlerMethod 类 ) 与 request 方法 并添加拦截器数组封装成 HandlerExecutionChain 的对象返回代码块:protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));chain.addInterceptors(getAdaptedInterceptors());
// url请求String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);//找到匹配该请求的 MappedInterceptor 拦截器for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {chain.addInterceptor(mappedInterceptor.getInterceptor());}}return chain;}*/return getHandlerExecutionChain(handler, request);}

getHandlerAdapter(mappedHandler.getHandler()) 方法,返回 HandlerAdapter 对象

    /*** Return the HandlerAdapter for this handler object.* @param handler the handler object to find an adapter for* @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.*/protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {for (HandlerAdapter ha : this.handlerAdapters) {if (logger.isTraceEnabled()) {logger.trace("Testing handler adapter [" + ha + "]");}/*此处判断 spring MVC加载的 HandlerAdapter 列表,是否符合处理这个 handler 能力 (是否支持)*/if (ha.supports(handler)) {return ha;}}throw new ServletException("No adapter for handler [" + handler +"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");}

processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException) 方法处理视图并跳转到页面 (处理异常HandlerExceptionResolvers 出现的地方)

/*** Handle the result of handler selection and handler invocation, which is* either a ModelAndView or an Exception to be resolved to a ModelAndView.*/private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {boolean errorView = false;if (exception != null) {if (exception instanceof ModelAndViewDefiningException) {logger.debug("ModelAndViewDefiningException encountered", exception);mv = ((ModelAndViewDefiningException) exception).getModelAndView();}else {Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);/*处理异常,异常HandlerExceptionResolvers处理器*/mv = processHandlerException(request, response, handler, exception);errorView = (mv != null);}}// Did the handler return a view to render?if (mv != null && !mv.wasCleared()) {/*跳转页面 ViewResolver 用来解析页面*/render(mv, request, response);if (errorView) {WebUtils.clearErrorRequestAttributes(request);}}else {if (logger.isDebugEnabled()) {logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +"': assuming HandlerAdapter completed request handling");}}if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Concurrent handling started during a forwardreturn;}if (mappedHandler != null) {// 调用了 拦截器 HandlerInterceptor 的afterCompletion() 方法mappedHandler.triggerAfterCompletion(request, response, null);}}

Controller

 @Controller //告诉编译器当前类为一个控制器@RequestMapping("/hello"),实现url和控制器之间的映射。

severlet通过url找到控制器,从而实现执行我们类里面的某个方法

代码解析参考:

Spring MVC (DispatcherServlet)请求处理流程_zjs40的博客-CSDN博客

【计算机是如何通信 四】Web服务器/Severlet/DispatcherServlet/Controller相关推荐

  1. 计算机网路实验二 多线程Web服务器的设计与实现

    计算机网路实验二 多线程Web服务器的设计与实现 一. 实验目的及任务 1.实验目的 熟悉简单网络的搭建与基本配置: 熟悉socket.多线程编程: 熟悉JDK编程工具的基本使用: 熟悉HTTP协议: ...

  2. dns服务器v6解析 windows_04:缓存DNS、Split分离解析、电子邮件通信、Web服务器项目实战...

    一. 环境的准备 关闭两台虚拟机的SELinux [root@svr7 ~]# setenforce 0 #修改当前运行模式[root@svr7 ~]# getenforce #查看当前运行模式Per ...

  3. 计算机存储器相关演讲,四、服务器和存储系统系列专题主题演讲

    四.服务器和存储系统系列专题主题演讲 四.服务器和存储系统系列专题主题演讲 星期二,下午12:15-1:00 多功能厅B 1)发展为高效的数据中心 企业正致力于构建更加可靠和经济有效的简易数据中心.他 ...

  4. LINUX从零开始——SERVICES(系统服务管理进阶)——Day4 [缓存DNS、Split分离解析、电子邮件通信、Web服务器项目实战]

    一.环境准备 1.还原快照,开启虚拟机A与虚拟机B,以root用户登录 二 .环境设置 1.防火墙设置: 虚拟机A [root@A ~]# firewall-cmd --set-default-zon ...

  5. HTTP的WEB服务器做了些什么?

    Web服务器的实现 Web 服务器实现了 HTTP 和相关的 TCP 连接处理. 负责管理 Web 服务器提供的资源, 以及对 Web 服务器的配置. 控制及扩展方面的管理. Web 服务器逻辑实现了 ...

  6. HTTP权威指南记录 ---- Web服务器

    Web服务器 Web服务器的实现 Web服务器会对HTTP请求进行处理并提供响应.术语"Web服务器"可以用来表示Web服务器的软件,也可以用来表示提供Web页面的特定设备或计算机 ...

  7. 彻底吃透Web服务器、容器、应用程序服务器与反向代理

    出处:cnblogs.com/vipyoumay/p/7455431.html 我们知道,不同肤色的人外貌差别很大,而双胞胎的辨识很难.有意思的是 Web 服务器/Web 容器/Web 应用程序服务器 ...

  8. Servlet的本质以及与Web服务器的关系

    简单介绍了Java Web的概念以及Web应用的发展. 文章目录 1 Java Web概述 2 Web请求 3 Web服务器与Servlet的关系 3.1 web服务器 3.2 Servlet规范 3 ...

  9. weblogic多次连接后tcp服务堵塞_一文看懂 Web服务器、应用服务器、Web容器、反......

    导读:我们知道,不同肤色的人外貌差别很大,而双胞胎的辨识很难.有意思的是Web服务器/Web容器/Web应用程序服务器/反向代理有点像四胞胎,在网络上经常一起出现.本文将带读者对这四个相似概念如何区分 ...

最新文章

  1. C# linq创建嵌套组
  2. jvm系列(八):jvm知识点总览
  3. lombok和maven_Lombok,AutoValue和Immutables,或如何编写更少,更好的代码返回
  4. 智慧交通day01-算法库01:numba
  5. 测试开发——flask视图函数与路由 实战重点
  6. vim编辑器学习记录
  7. python蒙特卡洛模拟_用Python实现蒙特卡洛模拟
  8. 全球及中国SxS(遥控潜水器)行业商业模式分析及投资风险预测2022年版
  9. 品牌出海:如何做好本土化运营?
  10. Authorization loop detected on Conduit with realm “WSMAN“
  11. 4246. 【五校联考6day2】san
  12. Poco库使用:任务管理器TaskManager
  13. 再次推荐台湾电影《国士无双》_原水_新浪博客
  14. 5G要来了,实际测试告诉你它的速度到底有多快!
  15. unity2019安装完后打不开直接闪退_VS2019打不开或没反应该怎么解决?
  16. ChatGPT4高分通过数据库系统工程师(DBA)认证
  17. sql server 里面的主要数据文件和次要数据文件有什么区别呢
  18. 后厂村码农的真实生活,颠覆你的想象
  19. mysql批量插入没有返回主键id
  20. 网站速度优化的一些方法

热门文章

  1. php 和mysql实现抢购功能_php处理抢购类功能的高并发请求
  2. linux lpte_linux常用命令
  3. python判断点在直线的哪一侧_判断点在直线的哪一侧
  4. python socket发送数组_利用pyprocessing初步探索数组排序算法可视化
  5. ef1a启动子_常见的真核和原核表达系统的启动子(promoters)
  6. 读写分离怎么实现_项目中如何实现读写分离?怎么配置?
  7. exfat文件系统_u盘文件系统exfat格式优缺点有哪些【详细介绍】
  8. ios html5缩小,IOS H5页面图片点击捏合放大缩小
  9. php attr,PHP DOMAttr isId()用法及代码示例
  10. 深度学习和目标检测系列教程 2-300:小试牛刀,使用 ImageAI 进行对象检测