springMVC 源码级别总结原理,DispatcherServlet核心方法

前言

springMVC自我总结

本次maven:

	<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.3.7.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.0.1</version><scope>provided</scope></dependency>

1.先上图

(这个是百度的,这个图好多网友都画了,都是一个意思,随便拿一个好看的,以便下面能写的通顺)
在这里插入图片描述

2.工作流程

以下每一步,对应上图的每一步,都是我自己的理解,如果有误,还请指出

1.用户发来请求,由于在web.xml中配置如下,请求进入了请求处理器:DispatcherServlet
在这里插入图片描述
2.在请求处理器中,第一步便是找到合适的控制器,即图中的第二步,对应源码解释:

 DispatcherServlet的doService方法的doDisPatch方法是核心逻辑所在,在doDispatch方法中,有一行是mappedHandler = this.getHandler(processedRequest);这个方法中有个HandlerMapping,我们一般叫这个为处理器,他有两个实现类第一个是:BeanNameUrlHandlerMapping,代表如果是XML配置方式的控制器,就用这个XML就是自定义Controller类实现org.springframework.web.servlet.mvc.Controller.Controller接口,然后在配置文件中配置bean标签的方式第二个是:RequestMapppingHandlerMaping,代表注解方式的控制器,就用这个注解方法就是在自定义Controller类上加注解@Controller,方法上加@RequestMapping的方式看源码包中,这两个实现类也是初始化的时候就定义好的,在源码包的DispatcherServlet.properties中这个便是找到合适的控制器,并返回返回的是HanderExecuteChain对象,这个对象包括Handler对象和拦截器数组,形成一个链返回

3.调用Handler,其实就是找到合适的处理器

同样在doDispatch方法中,有一行是:HandlerAdapter err1 = this.getHandlerAdapter(mappedHandler.getHandler());
这个就是选择到了合适的处理器,也用到了适配器模式HandlerAdapter 有三个实现:
第一个是:HttpRequestHanderAdapter
第二个是:SimpleControllerHanderAdapter
第三个是:AnnotationMethodHanderAdapter第一个和第二个对应的是XML的配置方式
第三个对应的是注解的配置方式

4.处理业务逻辑

同样在doDispatch方法中,有一行是:err = err1.handle(processedRequest, response, mappedHandler.getHandler());
这个就是处理业务逻辑了,这个方法会去执行我们自己写的Controller
前面两步,一个是找到合适的控制器,一个是找到合适的处理器,其实都是为了这一步做的,
之所以前面分成两步,我看就是为了解耦,让代码更加灵活,有扩展性

5.返回ModelAndView

上一步返回的即是ModelAndView对象

6,7,8.调用视图解析器,将model数据传给view

同样在doDispatch方法中,有一行是:this.processDispatchResult(processedRequest, response, mappedHandler, err, (Exception)dispatchException);这个方法下有个方法是:this.render(mv, request, response);这个方法下有个方法是: view = this.resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
这个方法下,才是真正的视图解析ViewResolver viewResolver = (ViewResolver)var5.next();view = viewResolver.resolveViewName(viewName, locale);
返回view这个要配合配置文件
一般我们都会在配置文件中配置视图解析器<!-- 配置视图解析器 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!-- 配置视图解析器的前缀和后缀 --><property name="prefix" value="/WEB-INF/jsp/"></property><property name="suffix" value=".jsp"></property></bean>在自定义Controller中,返回对应的jsp,也就是这里起的作用,前缀是全路径,后缀是视图类型
假如自定义Controller类中返回值为test,那么根据视图解析器可得将要跳转的页面路径为:/WEB-INF/jsp/test.jsp

3.springMVC的一些总结

1.先说与struts2的对比

如果你做过项目的重构,将struts2的架构转移到springMVC架构上,你就会深深的感受到这两个框架的区别了
感受最多的,就是struts2太多的成员变量了,struts2是多例的,所以struts2中的成员变量简直不能太多
而springMVC默认是单例的,这个时候所有controller的方法入参都要一个一个捋出来,真的不好玩
而springMVC保持单例,也是业界认可的,就是竟可能的就是使用单例
因为这样可以减少创建对象和回收对象的开销.也就是说,如果controller的类变量和实例变量最好以方法形参声明,不要以类变量和实例变量声明,这样也可以避免线程安全问题。当然,有了这个,struts2的值域的概念,也可以忘记了

2.spring和springMVC,都是容器的概念

spring是父容器,springMVC是子容器
父容器中拿不到子容器的bean
子容器可以拿到父容器的bean

4.附上测试代码

web.xml

<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springconfig.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
</web-app>

springconfig.xml(这个应该是springmvc.xml,这样意思才算对,懒得改了,看懂就行)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"><!--扫描包--><context:component-scan base-package="com.zs"></context:component-scan><!--开启springMVC注解--><mvc:annotation-driven></mvc:annotation-driven><!-- 配置视图解析器 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!-- 配置视图解析器的前缀和后缀 --><property name="prefix" value="/WEB-INF/jsp/"></property><property name="suffix" value=".jsp"></property></bean><bean id="data" class="java.util.Date"></bean><bean name="/test1" class="com.zs.MyController"></bean></beans>

MyController.java(基于XML配置的)

package com.zs;import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyController implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {System.out.println("my controller run..............");return null;}
}

MyController2.java(基于注解配置的)

package com.zs;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Controller
public class MyController2 {@RequestMapping("/test2")public String handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {System.out.println("my controller2 run..............");return "index2";}
}

项目结构:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499948.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQLite3中的数据类型

一、概述 大多数的数据库引擎&#xff08;到现在据我们所知的除了sqlite的每个sql数据库引擎&#xff09;都使用静态的、刚性的类型&#xff0c;使用静态类型&#xff0c;数据的类型就由它的容器决定&#xff0c;这个容器是这个指被存放的特定列。 Sqlite使用一个更一般的动态类…

一个java工程师必知的安全意识(信息传输篇)

我们在遇到涉及用户密码&#xff0c;用户联系方式&#xff0c;身份证信息等敏感字段的时候&#xff0c;一般的处理方式是&#xff1a; 1.传输使用密文&#xff0c;拒绝明文传输用户密码&#xff0c;推荐明文加盐加密&#xff0c;后台再解密 比如要传输的明文是123456的明文密…

关于iOS7里的JavaScriptCore framework

在iOS7沸沸扬扬的扁平化论战之外&#xff0c;WWDC 2013还是公布了很多让开发者小兴奋的点&#xff0c;其中包括多任务加强支持background fetch和transfer&#xff0c;近场通信的AirDrop和p2p&#xff0c;以及游戏控制器和游戏中心的加强&#xff1b;当然还包括了让web开发同学…

[nginx报错]---unknown directive chunkin in /XXXXX/XXXXXX:XX的几种解决方式

问题&#xff1a; nginx报错:unknown directive “chunkin” in /XXXXX/XXXXXX:XX 解决&#xff1a; 当出现unknown directive&#xff0c;一般有个反应&#xff0c;就是nginx中&#xff0c;要么配置格式不对&#xff0c;要么多了什么东西&#xff0c;要么就是有不支持的语法…

[数据库] ------ mysql 执行计划

mysql 执行计划 简单来说&#xff0c;mysql整体架构分为三块&#xff1a;应用层&#xff0c;逻辑层&#xff0c;物理层 应用层&#xff1a;负责与客户端交互&#xff0c;建立连接&#xff0c;返回数据&#xff0c;响应请求。 逻辑层&#xff1a;负责查询处理&#xff0c;事务管…

[数据库] ------ mysql规范

mysql规范&#xff1a; mysql优化的第一步&#xff0c;就是规范&#xff0c;国有国法&#xff0c;家有家规&#xff0c;一个团队在一起开发&#xff0c;也一定要有一套明确的规范来相互制约&#xff0c;下面这些规范只是作为一个互联网行业的建议&#xff0c;我相信一个团队最…

深入浅出Fetch API

多年来&#xff0c;XMLHttpRequest一直是web开发者的亲密助手。无论是直接的&#xff0c;还是间接的&#xff0c; 当我们谈及Ajax技术的时候&#xff0c;通常意思就是基于XMLHttpRequest的Ajax&#xff0c;它是一种能够有效改进页面通信的技术。 Ajax的兴起是由于Google的Gmail…

[设计模式] ------ 策略模式

策略模式 它定义了算法家族&#xff0c;分别封装起来&#xff0c;让他们直接可以互相替换&#xff0c;此模式让算法的变化&#xff0c;不会影响到使用算法的客户 其实很简单&#xff0c;可能很多人都用到了&#xff0c;只不过还不知道这就是策略模式而已。 比如定义一个接口A…

OC语法简化

很多刚从其他编程语言转到Objective-C的同学看到长长的函数名会感到崩溃&#xff0c;这种语法让消息的传递像一个英语句子&#xff0c;大大增强了可读性。比如你想初始化一个浮点数&#xff0c;需要这么写&#xff1a; NSNumber value [NSNumber numberWithFloat:123.45f];从这…

[设计模式] ------ 简单工厂模式

简单工厂模式 不同类型下创建对应的不同的对象&#xff0c;得到不同的结果&#xff0c;就叫简单生产模式 比如 定义一个接口&#xff0c;叫A&#xff0c;里面有方法a&#xff0c;返回int类型 类B1实现A接口&#xff0c;也实现a方法&#xff0c;里面做的是加法运算 类B2实现…

Podfile语法

一、Podfile Podfile文件详细描述了一个或多个工程中targets的依赖关系。Podfile会默认创建一个隐式的目标链接到工程中用户的第一个target&#xff0c;名称为“default”。 一个Podfile可以非常简单: pod AFNetworking, ~> 1.0 也可以配置的复杂一点,如下: source https:/…

[设计模式] ------ 模板模式

模板模式 模板模式&#xff0c;定义一个操作中的算法的骨架&#xff0c;而将一些步骤延迟到子类中&#xff0c;模板方法使得子类可以不改变一个算法的结构&#xff0c;就可以重定义该算法的某些特定步骤 一般是定义一个抽象类&#xff0c;有抽象方法&#xff0c;有骨架方法&a…

获取本地沙盒文件的MIMEType

通过发送一个基于本地文件的URL请求&#xff0c;从响应对象中获取MIMEType值。代码如下&#xff1a;NSString *path [[NSBundle mainBundle] pathForResource:"测试文件"ofType:"pdf"]; //创建本地文件URL NSURL *url [NSURL fileURLWithPath:path]; //创…

第19章总结

一.Java绘图类 1.Graphics类 Graphics类是所有图形上下文的抽象基类&#xff0c;它允许应用程序在组件以及闭屏图像上进行绘制。Graphics类封装了Java支持的基本绘图操作所需的状态信息&#xff0c;主要包括颜色、字体、画笔、文本、图像等。 2.Graphics2D类 Graphics2…

如何写一个数据库中间件以及需要准备的知识储备

什么是数据库中间件 1.透明化使用方无感知&#xff0c;或者尽量少感知。通过现有的接入端接入已有服务 2.增量服务不改变数据库本身功能的前提下&#xff0c;提供额外的功能与服务一个原则不破坏原有逻辑&#xff0c;并且让用户基于之前的经验可以快速上手接入端协议的选择 1.…

HTTP断点续传

一、概述所谓断点续传&#xff0c;其实只是指下载&#xff0c;也就是要从文件已经下载的地方开始继续下载。在以前版本的HTTP协议是不支持断点的&#xff0c;HTTP/1.1开始就支持了。一般断点下载时才用到Range和Content-Range实体头。HTTP协议本身不支持断点上传&#xff0c;需…

RSA公钥文件(PEM)解析

公钥语法为&#xff1a; RSAPublicKey :: SEQUENCE { modulus INTEGER, //RSA合数模n publicExponent INTEGER //RSA公开幂e } 说明&#xff1a; 1.此语法中的modulus和publicExponent&#xff0c;提取自对应私钥中的同名域值。 2.PKCS1和PKCS8的公钥文件是一样的&#xff…

[spring boot] ------ 总结1

spring boot 设计目的&#xff1a;简化spring应用的初始搭建以及开发过程 spring环境的微服务&#xff1a;对原有技术的封装&#xff08;spring springMVC&#xff09; 简化开发&#xff0c;提高开发效率&#xff08;原ssm--->spring boot mybatis&#xff09; 自动配置&…

RSA私钥文件(PEM-PKCS#1)解析

在PKCS#1 RSA算法标准中定义RSA私钥语法 RSAPrivateKey :: SEQUENCE { version Version, //版本 modulus INTEGER, // RSA合数模 n publicExponent INTEGER, //RSA公开幂 e privateExponent INTEGER, //RSA私有幂 d prime1 INTEGER, //n的素数因子p prime2 INTEGER, //n的…

Spring的@Configuration使用cglib代理的效果和我自己写的简单实现

下面的代码&#xff0c;照着复制就能跑起来 今天看了下Spring的Configuration&#xff0c;即java类配置bean,&#xff08;这个spring3的新功能&#xff0c;虽然现在已经spring5了&#xff0c;但是这种配置bean的方式也是比较火的&#xff09; 做了如下测试&#xff0c;发现一个…