mvc源码分析
A. 有一点java基础,如何成为一名java架构师
在Java程序员行业中,有不少Java开发人员的理想是成为一名优秀的Java架构师,Java架构师的主要任务不是从事具体的软件程序的编写,而是从事更高层次的开发构架工作。他必须对开发技术非常了解,并且需要有良好的组织管理能力。可以这样说,一物雹个Java架构师工作的好坏决定了整个软件开发项目的成败。那么Java架构师需要掌握哪些知识点呢?
1、框架源码分析
设计模式:Singleton单例模式,Factory工厂模式,Proxy代理模式,Template模板模式,Prototype原型模式等
Spring5:Spring提醒结构,IOC注入原理,AOP设计原理,Spring事务处理机制,SpringMVC,Spring源码分析。
Mybatis:Mybatis体系结构,Mybatis核心应用与配置,Mybatis关联查询,与Spring集成,Mybatis源码分析。
2、性能优化
JVM性能优化:剖析JVM整体结构,详解垃圾回收机制GC,JVM性能调优与工具排查
Nginx调优:Nginx项目架构,Nginx核心配置,Nginx负载算法配置
Tomcat调优:Tomcat运行机制及框架,Tomcat线程模型,Tomcat性能调优
Mysql性能优化:SQL执行计划,AQL优化,索引优化。
3、掌握池技术
对象池,连接池,线程池,Java反射技术,写框架必备的技术,但是有严重的性能问题,替代方案Java字节码技术。
4、掌握nio,值得注意的是“直接内存”的特点,使用场景。
5、掌握Java多线程同步异步。
6、掌握Java各种集合对象的实现原理,了解这些可以让你在解决问题时选择罩兄帆合适的数据结构,高效的解决问题。
7、熟练使用各种数据结构和算法,数组、哈希、链表、排序树就是一句话要么是时间换空间要么是空间换时间。
8、熟悉tcp协议,创建连接三次握手和断开连接四次握手的尘旁整个过程,不了解的话,无法对高并发网络应用做优化。
9、熟悉http协议,尤其是http头,我发现好多工作五年以上的都弄不清session和cookie的生命周期以及它们之间的关联。
10、熟悉系统集群、负载均衡、反向代理、动静分离,网站静态化。
11、掌握分布式。
Java并发编程和网络编程:Java线程状态,线程池,线程通信,线程安全,Netty高性能原理
分布式开发框架:分布式系统口调用技术:RPC,Apache分布式系统Zookeeper原理与应用,阿里Dubbo设计思想与应用
分布式中间件:分布式服务器治理,分布式消息通信,分布式数据缓存,MongoDB企业集群解决方案
12、掌握数据库的设计能力,对它基本的参数优化,慢查询日志分析,主从复制的配置,至少要成为半个mysqldba。
B. Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC
最近我整理了一下一线架构师的Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC,分享给大家一起学习一下~ 文末免费获取哦
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
1.1 Spring面试必备题+解析
1.2 Spring学习笔记
(1)Spring源码深入解析
(2)Spring实战
1.3 Spring学习思维脑图
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
2.1 Spring Boot面试必备题+解析
2.2 Spring Boot学习笔记
(1)Spring Boot实践
(2)SpringBoot揭秘 快速构建微服务体系
2.3 SpringBoot学习思维脑图
springcloud是微服务架构的集大成者,将一系列优秀的组件进行了整合。基于springboot构建,对我们熟悉spring的程序员来说,上手比较容易。通过一些简单的注解,我们就可以快速的在应用中配置一下常用模块并构建庞大的分布式系统。
3.1 Spring Cloud面试必备题+解析
3.2 Spring Cloud学习笔记
(1)Spring Cloud参考指南
SpringMVC是一种基于Java的实现MVC设计模式的请求驱动类型的轻量级Web框架,使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发
4.1 Spring MVC面试必备题+解析
4.2 Spring MVC学习笔记
(1)看透Spring MVC源代码分析与实践
(2)精通Spring MVC
最后分享一下一份JAVA核心知识点整理(PDF)
C. spring mvc 常用注解详解
前言
现在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了。不过要想灵活运用Spring MVC来应对大多数的Web开发,就必须要掌握它的配置及原理。
Spring mvc 介绍
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发
image.png
spring mvc 常用注解详解
@Controller
在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在SpringMVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 等一些注解用以定义请求URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。其标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。此外我们还需要将controller注册到spring里
@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径,作用于方法上,表明该处理器的请求地址=父路径+方法上url+method,其拥有6个属性
1、 value, method;定义处理器访问的具体体质
value: 指定请求的实际地址,指定的地址可以是URI Template 模式;
method: 指定请求的method类型, GET、POST、PUT、DELETE等;
2、consumes,proces 定义处理器内容类型
consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
proces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
3、params,headers 定义处理器处理类型
params: 指定request中必须包含某些参数值,才让该方法处理!
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。
@PathVariable
用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。如:
@requestParam
@requestParam主要用于在SpringMVC后台控制层获取参数,类似一种是request.getParameter("name"),它有三个常用参数:defaultValue = "0", required = false, value = "isApp";defaultValue 表示设置默认值,required 铜过boolean设置是否是必须要传入的参数,value 值表示接受的传入的参数类型。
@ResponseBody
作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。使用时机:返回的数据不是html标签的页面,而是其他某种格式的数据时(如json等)使用;
@RequestBody
该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。
spring mvc 拦截器配置
preHandle:预处理回调方法,返回值:true表示继续流程,false表示流程中断(如登录检查失败),不会继续续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。
spring mvc 静态资源放问配置
image.png
spring mvc 文件上传
前端
后端
spring mvc 工作流程详解
image.png
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
如果你也对Java架构比如分布式、微服务、源码分析、性能优化、高并发高可用等技术感兴趣可以在手机上面私信我,回复“架构”二字即可免费领取一套价值3880的架构资料哦。
D. 浅谈SpringMvc HttpMessageConverter
1.HttpMessageConverter是SpringMvc框架中一个重要的组件,其主要职责是对@RequestBody的解析(该注解作用就是告诉mvc,这个参数由Http的请求头,经过HttpMessageConverter解析得到)
看一下该接口
该接口的canRead方法表指亏示其支持的Class类型,MediaType是其支持的http的ContentType类型,假如一个Http请求是Application/json,Mvc框架会去寻找支持该MediaType的Converter,然后再判断@RequestBody注解对应的class类型是否支持,如果支持,那么就交由对应的MessageConverter去解析。
另一个问题就是,这个类是解析什么呢,实际上,HttpInputMessage是指HttpServletRequest的Body的流汪槐,可以看接口。
那么Mvc框架的部分核心我们就能猜到了,一个Http请求过来,包括Header和Body,对于其中的困逗友Body的流将会被DispatcherServlet包装成SpringMvc的HttpRequest,然后委托RequestChainExecutor,经过一系列处理,最终Body的流到了HttpMessageConverter(这里不是那么准确),重点需要理解的就是一个Http请求,头部会被HttpMessageConverter获取并解析,如果找不到对应的HttpMessageConverter,Spring框架会报异常。
一般情况下,我们常见的有StringHttpMessageConverter(text/plain+String),ByteArrayHttpMessageConverter(application/octet-stream+byte[]),FormHttpMessageConverter(好几个),FastJsonHttpMessageConverter(application/json+Object)等。
如果要自定义一个HttpMessageConverter,只要继承AbstractHttpMessageConverter就可以,其中运用了模板方法,具体的逻辑组织在AbstractHttpMessageConverter中已经实现,只需要实现以下方法和构造方法就可以使用了。
该部分就是,将HttpMessage(通过容器的HttpRequest获得相关属性),首先read请求时,直接转readInternal(子类实现),如果是write响应,则先判断返回的结果类型是不是流,是流就直接构建Message响应(返回流,如果直接读取就会被消费了,流只能读一次,对应的就是Controller(MethodHandler)的返回结果),如果是其他类型,则交由实现类将JavaObject变成流。
综上所述,HttpMessageConverter就是负责将Http请求的Body与JavaObject之间进行转换,那么在哪里可以配置呢?在WebMvcConfigurationSupport的configureMessageConverters中可以配置,默认情况boot会在存在对应classPath时自动注入mvc相关配置,而关于HttpMessageConverter在不重写configureMessageConverters时默认配置一堆,一旦自定义配置了,就只支持自己定义的几个了。
关于模板方法,在中也有使用到,同样的套路,父类定义方法模板(骨架),子类实现逻辑原语。
对于一个Http请求,Tomcat(一定猜测)首先监听端口,收到请求就委托一个Thread去初始化Servlet或者执行Servlet,并通过ThreadLocal来保存HttpServletContext和HttpRequest与HttpResponse,如果去测试的话,你会发现Tomcat基于装饰器模式用RequestFacade,ResponseFacade封装了Request和Response,请求到DispatcherServlet,SpringMvc则解析请求头(可以重复解析)和请求Body,通过请求头方法类型交给doDispatch进行解析,最终交给RequestChainExecutor去执行,通过请求头得到路径交给不同的MethodHandler(Controller接口与@Controller)去处理。根据MethodHandler对应方法的注解(@RequestBody,@ResponseBody,@PathVariable等)来交给HttpMessageConverter(Body的解析)、Converter(默认的非Body的解析)、HandlerMethodArgumentResolver(报文头解析及前置处理)、(方法返回参数处理)等进行Http报文和JavaObject的转换。
我实在懒得写清除细节了,截图头疼,没必要深究源码(太细节了),先搞清楚Mvc的各个组件再说。
Mvc 数据流
Http(Header+Body)->HttpMessage(Body)->HttpMessageConverter->JavaObject
(Header)->Converter+Format SPI
Mvc Controller拓展
MethodHandler+MethodHandlerInterceptor+HandlerMethodArgumentResolver+
+Aspect(有些拓展基于代理)
E. vertx获取所有的handler
Vert.x - 学习记录 - 只有一二三的博客 - CSDN博客
2020年12月22日真正调用处理逻辑的入口往往是处理器(Handler),Vert.x保证同一个普通Verticle(也就是EventLoop Vert...
CSDN编程社区
Vert.x - SpringBoot 整合 vertx - 小毕超的博客 - CSDN博客 - vertx
1. vertx 前面的文章讲解了 vertx 的简介及 vertx-web 的路由,看过的小伙伴应该对 vertx 有了一定的了解,从前面的演示来看,都
2. SpringBoot 整合 vertx 首先新建一个 SpringBoot 项目,注意不要引入其他 web 框架。在 pom 中引入依赖,注意这里我使用的是 vertx 4.1.
CSDN编程社区
二. Vert.x - Web开发之路由 - 知乎
第一种就是get请求直接拼接在URL后的参数,比如:http://localhost:8080/method?param=hello router.route(HttpMethod.GET, "/method").handler(request
第二种是获取路径的参数,比铅核如:http://localhost:8080/method/xiaoming/xm123 // 获取参数 router.route(HttpMethod.GET, "/method/:user/:
第三种是获取到请求体中的数据,也就是post提交的数据。这个稍微有一些繁琐,首先要指定一个BodyHandler,然后才能通过requestContext对象来获取body体中的数据。获取body
知乎
Vert.x学习笔记(一) Vert.x 核心包 - 蒲公英云
6月11日创建Vertx对象 要使用Vertx的第一步就是创建Vertx对象,所有API都要通过这个对象来调用。一般情况下,一个程序只需要一个Vertx对象即可,不过有...
蒲公英云
vert.x学习(七),使用表单获取用户提交的数据 | 表单
router.post("/user")的作用是当用户在表单页面点击保存按钮后,触发post请求,vert.x会将这个请求路由到router.post("/user").handler里面,在...
www.lmlphp.com
深入槐仔掘浅出Vert.x 第一季 第6集 Vert.x获取请求参数戚旅——body参数
231次播放
07:25
合集
深入浅出Vert.x 第一季 vertx快速入门 java高性能异步非阻塞框架
听歌不循环
2020年10月21日
Vertx-web第三课 bodyhandler
38:49
合集
Vertx4.*
哔哩哔哩
2021年07月10日
...框架的使用体验(一) - 程小明的coding的博客 - CSDN博客 - vertx 并发
6月21日Vert.x的Handler内部是atomic/原子操作,Verticle内部是thread safe/线程安全的,Verticle之间传递的数据是immutable/不可改变的。
CSDN编程社区
源码分析 - Vertx入门和源码浅析 - 个人文章 - SegmentFault 思否
1. Vertx 实现类VertxImpl,它的重要线程 eventLoopGroup acceptorEventLoopGroup
2. Verticle 1) Verticle起作用的方式,主要是通过Vertx进行部署,也就是deployVerticle 2) Verticle部署,主要是Vertx框架把vertx 和context 传给Verticle
3. Context上下文 1) 子类:ContextInternal EventLoopContext 2) 上下文是通过Vertx创建,如ContextInternal callingContext = vertx.getOrCreateContext(); 3
思否开发者社区
vertx web记录route 每个handler的执行时长 - 蒲公英云
1. 配置route,将route模块加载到vertx中,vertx通过调用listen方法绑定监听
2. 请求到来之后,调用 listenContext.runOnContext将请求交给route模块处理
3. 模块handler会创建VertxThread,并开启一个由vertx管理的线程进行处理
蒲公英云
06-架构师-SpringMVC如何获取handler源码分析
22:16
合集
架构师专场——springmvc
F. springbootmavenplugin必须要有吗
-Version: 1.0
Created-By: Maven Archiver 3.4.0
Build-Jdk-Spec: 11
Implementation-Title: springbootfirst
Implementation-Version: 0.0.1-SNAPSHOT
SpringBoot插件生成的jar包行困结构为
BOOT-INF/classes 中包含项目所有的class文件,BOOT-INF/lib 下包含项目依赖的第三方jar包,MANIFEST.MF文件内容为
Manifest-Version: 1.0
Created-By: Maven Archiver 3.4.0
Build-Jdk-Spec: 11
Implementation-Title: springbootfirst
Implementation-Version: 0.0.1-SNAPSHOT
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.imooc.springbootfirst.SpringbootfirstApplication
Spring-Boot-Version: 2.1.6.RELEASE
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
插件是如何找到启动类的
描述文件中纳芹的Start-Class就是我们项目的启动类,我们可以查看插件源码来分析
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-loader</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
先引入插件的maven依赖
RepackageMojo就是repackage打包要执行的逻辑,核洞带毕心类为Repackager
在插件创建MANIFEST.MF文件过程中,如果我们没有配置MainClass属性,就会通过MainClassFinder类来查找MainClass
private static final String SPRING_BOOT_APPLICATION_CLASS_NAME = "org.springframework.boot.autoconfigure.SpringBootApplication";
protected String findMainMethod(JarFile source) throws IOException {
return MainClassFinder.findSingleMainClass(source, this.layout.getClassesLocation(),
SPRING_BOOT_APPLICATION_CLASS_NAME);
}
在所有类中查找包含SpringBootApplication注解且包含main方法的类,并当做启动类,内部通过ASM字节码库来解析class文件得到类信息。
启动流程
java -jar springbootfirst-0.0.1-SNAPSHOT.jar
java启动jar包会找META-INF/MANIFEST.MF文件中的Main-Class来启动,SpringBoot插件最终生成的Main-Class为 org.springframework.boot.loader.JarLauncher类。
/**
* jar包类型的启动器
*
* @author Phillip Webb
* @author Andy Wilkinson
* @since 1.0.0
*/
public class JarLauncher extends ExecutableArchiveLauncher {
static final String BOOT_INF_CLASSES = "BOOT-INF/classes/";
static final String BOOT_INF_LIB = "BOOT-INF/lib/";
public JarLauncher() {
}
protected JarLauncher(Archive archive) {
super(archive);
}
@Override
protected boolean isNestedArchive(Archive.Entry entry) {
if (entry.isDirectory()) {
return entry.getName().equals(BOOT_INF_CLASSES);
}
return entry.getName().startsWith(BOOT_INF_LIB);
}
public static void main(String[] args) throws Exception {
new JarLauncher().launch(args);
}
}
最终运行的是MANIFEST.MF文件中Start-Class,值为com.imooc.springbootfirst.SpringbootfirstApplication,其实就是我们项目中配置的启动类。
/**
* 启动器
*
* @author Phillip Webb
* @author Dave Syer
* @since 1.0.0
*/
public abstract class Launcher {
/**
* 启动流程
*/
protected void launch(String[] args) throws Exception {
JarFile.registerUrlProtocolHandler();
//根据BOOT-INF/classes下的class文件和BOOT-INF/lib下的第三方jar包创建Archive
//创建的ClassLoader为LaunchedURLClassLoader类型
ClassLoader classLoader = createClassLoader(getClassPathArchives());
launch(args, getMainClass(), classLoader);
}
/**
* 创建新的LaunchedURLClassLoader,从多个URL中加载class
*/
protected ClassLoader createClassLoader(URL[] urls) throws Exception {
return new LaunchedURLClassLoader(urls, getClass().getClassLoader());
}
/**
* 将新的类加载器设置到线程上下文中,并启动应用程序
*/
protected void launch(String[] args, String mainClass, ClassLoader classLoader) throws Exception {
Thread.currentThread().setContextClassLoader(classLoader);
createMainMethodRunner(mainClass, args, classLoader).run();
}
/**
* 创建一个Main方法运行器来启动应用程序
*/
protected MainMethodRunner createMainMethodRunner(String mainClass, String[] args, ClassLoader classLoader) {
return new MainMethodRunner(mainClass, args);
}
}
创建新的ClassLoader类型LaunchedURLClassLoader,从BOOT-INF/classes下和BOOT-INF/lib下的所有jar包中加载class。加载我们整个项目的都是LaunchedURLClassLoader类加载器。
/**
* 一个执行Main方法的工具类
*
* @author Phillip Webb
* @author Andy Wilkinson
* @since 1.0.0
*/
public class MainMethodRunner {
private final String mainClassName;
private final String[] args;
/**
* Create a new {@link MainMethodRunner} instance.
* @param mainClass the main class
* @param args incoming arguments
*/
public MainMethodRunner(String mainClass, String[] args) {
this.mainClassName = mainClass;
this.args = (args != null) ? args.clone() : null;
}
public void run() throws Exception {
//使用线程上下文类加载器加载MainClass,就是我们项目中的SpringbootfirstApplication
Class<?> mainClass = Thread.currentThread().getContextClassLoader().loadClass(this.mainClassName);
//执行Main方法
Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
mainMethod.invoke(null, new Object[] { this.args });
}
}
参考
springboot 打包插件spring-boot-maven-plugin打包机制及内部结构分析
分类: spring
标签: spring, maven, java
好文要顶 关注我 收藏该文
strongmore
粉丝 - 9 关注 - 5
+加关注
00
« 上一篇: IDEA中对非Maven项目导出jar包
» 下一篇: java实现对图片打马赛克
posted @ 2021-11-04 18:50 strongmore 阅读(6395) 评论(0) 编辑 收藏 举报
刷新评论刷新页面返回顶部
登录后才能查看或发表评论,立即 登录 或者 逛逛 博客园首页
【推荐】阿里云新人特惠,爆款云服务器2核4G低至0.46元/天
编辑推荐:
· 一次 SQL 调优,聊一聊 SQLSERVER 数据页
· 终于弄明白了 RocketMQ 的存储模型
· 应届毕业生程序员在面试时如何做好自我介绍?
· Redis 网络模型究竟有多强
· 不规则图形背景排版高阶技巧 -- 酷炫的六边形网格背景图
阅读排行:
· 来自一位十年.net研发老人的吐血整理:.Net技术栈-网址导航
· 做算法的这一年——2022年个人年终总结
· .Net 7 团队把国内的龙芯确实当做一等公民和弃用的项目
· 我希望来年,更多是靠关系和模式挣钱——2022年我的总结与思考
· 平淡详和的一年——2022年个人总结与思考
昵称: strongmore
园龄: 3年7个月
粉丝: 9
关注: 5
+加关注
< 2023年1月 >
日 一 二 三 四 五 六
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 1 2 3 4
5 6 7 8 9 10 11
搜索
找找看
谷歌搜索
常用链接
我的随笔
我的评论
我的参与
最新评论
我的标签
最新随笔
1.单元测试框架之Junit使用及原理分析
2.Kotlin学习之反射
3.Kotlin学习之Kotlin和Java之间相互调用
4.Kotlin学习之函数
5.Kotlin学习之委托
6.Kotlin学习之面向对象
7.Kotlin学习之基本语法
8.SpringMVC整合Swagger简单使用及原理分析
9.SpringMVC源码分析之一个请求的处理
10.Spring整合Mqtt原理分析
我的标签
java(220)
算法(40)
数据结构(39)
spring(30)
设计模式(28)
python(11)
多线程(8)
踩坑(8)
linux(8)
kotlin(8)
更多
积分与排名
积分 - 174759
排名 - 6340
随笔分类
c语言(2)
html(2)
java(136)
js(4)
kotlin(7)
leetcode(11)
linux(8)
python学习之旅(8)
spring(28)
机器学习(1)
数据结构与算法(34)
网络(2)
随笔档案
2022年6月(6)
2022年5月(28)
2022年4月(12)
2022年3月(5)
2022年2月(1)
2021年11月(3)
2021年10月(6)
2021年9月(13)
2021年8月(21)
2021年7月(13)
2021年6月(9)
2021年5月(6)
2021年4月(11)
2021年3月(21)
2021年2月(5)
更多
阅读排行榜
1. java中文转拼音(12794)
2. java操作yaml文件(9029)
3. java实现图片压缩(7791)
4. jdk8升级jdk11踩坑记录(lombok版本不兼容)(7465)
5. IDEA版本和Maven版本不兼容的问题(6840)
评论排行榜
1. Lombok原理分析及简单实现(4)
2. java中BloomFilter(布隆过滤器)简单使用(3)
3. java中如何通过程序检测线程死锁(1)
4. Spring中表达式语言spring-expression简单使用(1)
5. 关于100个人随机给钱的模拟实验(1)
推荐排行榜
1. MurmurHash算法简单介绍(2)
2. java操作yaml文件(2)
3. java进行PDF和图片之间的相互转换(2)
4. JMX简单入门(2)
5. 浏览器的DNS解析过程分析(1)
最新评论
1. Re:Spring中表达式语言spring-expression简单使用
支持
--我叫城北徐公
2. Re:java中BloomFilter(布隆过滤器)简单使用
@strongmore 好的好的,感谢回复~~...
--言小蹊
3. Re:java中BloomFilter(布隆过滤器)简单使用
@言小蹊 在IDEA上...
--strongmore
4. Re:java中BloomFilter(布隆过滤器)简单使用
您好,请问您这是是如何查看内存使用情况的?您是在eclipse上运行的代码吗?
--言小蹊
5. Re:java实现一个短URL生成器
博主介绍的短链接生成核心代码的确挺实用的,短链接就是将长的网页址通过技术方法进行缩短为短串。其实短链接只有生成和跳转还不能满足实际业务需求,还需要考虑其使用场景,目前短链接使用场景主要是短信内带短链接...
--缩链
Copyright © 2023 strongmore
Powered by .NET 7.0 on Kubernetes
1. 前言
2. 打包原理
3. 插件是如何找到启动类的
4. 启动流程
5. 参考
G. SpringMVC
一、SpringMVC应用
1.springmvc是一个表现层的框架
经典三层架构:表现层, service层, 层。
Spring MVC和Struts2一样,都是 为了解决表现层问题 的web框架,它们都是基于 MVC 设计模
式的。而这些表现层框架的主要职责就是处理前端HTTP请求。
Spring MVC 本质可以认为是对servlet的封装,简化了我们serlvet的开发
2.工作流程:
开发过程:
请求处理流程:
九大组件:
3.请求参数绑定,说白了SpringMVC是如何接受参数的:
原生servlet接收一个整型参数:
SpringMVC框架对Servlet的封装,简化了servlet的很多操作,SpringMVC框架对Servlet的封装,简化了servlet的很多操作
参数绑定:取出参数值绑定到handler⽅法的形参上
默认支持 Servlet API 作为方法参数:
绑定简单类型参数:
绑定Pojo类型参数:
绑定Pojo包装对象参数:
绑定日期类型参数(需要配置自定义类型转换器):
4.Restful风格
什么是Restful:
什么是rest:
Restful的优点:
Restful的特性:
Restful的示例:
SpringMVC如何支持Restful风格的请求:
5.Ajax Json交互
交互:两个方向
什么是Json:
@ResponseBody注解:
分析SpringMVC使用Json交互:
二、SpringMVC高级技术
1.拦截器(Inteceptor)使用
监听器、过滤器、拦截器的对比:
拦截器的执行流程:
多个拦截器的执行流程:
自定义SpringMVC拦截器:
2.处理multipart形式的数据
文件上传:
3.在控制器中处理异常:
4.基于Flash属性的跨重定向请求数据传递:
三、手写SpringMVC框架:
四、SpringMVC源码剖析
1.前端控制器 DispatcherServlet 继承结构:
2.重要时机点分析
SpringMVC处理请求的流程即为:
3.核心步骤getHandler方法剖析:
4.核心步骤getHandlerAdapter方法剖析:
5.核心步骤ha.handle方法剖析:
6.核心步骤processDispatchResult方法剖析:
7.SpringMVC九大组件初始化:
五、SSM整合
1.整合策略:先整合Spring + Mybatis,然后再整合SpringMVC
2.Mybatis整合Spring
3.整合SpringMVC
未完待补充完整。。。
H. 从源码理解总结web容器、spring容器、spring mvc容器三者关系
本篇,我打算从springMVC项目的web.xml的配置文件入手,通过部分源码逐步去理解解释三个容器的关系以及调用顺序,因为是基于我个人的理解,可能有所不足。
一般web.xml文件里会有如下两段配置信息:
我们先了解下web.xml,以下引用自 《web.xml文件是什么?有什么用?--详解》 :
然后结合我们上面的web.xml中关于spring和spring mvc的配置信息来进入话题:
首先,启动web容器的时,会先生成对应项目的ServelContent对象,这个是每个项目的上下文,这个ServelContent可以管理所有的servlet,并将我们web.xml中设置的<context-param>内容作为键值对交给这个对象。
然后加载<listener>标签内容,这个时候就会产生org.springframework.web.context.ContextLoaderListener。
spring的这个 ContextLoaderListener 在接下来的过程中很重要,我们来看一下源码
首先,可以看出它继承了ContextLoader类,并实现了ServletContextListener接口。
这里再直接引用他人的结论 《Spring中ContextLoaderListener作用》
好了,人家说法中回到我们的起点了,我们基本都被人告知“ContextLoaderListener的作用是创建并初始化spring容器”
那我们就可以深入进去看看,到底哪里做了这一步:
首先,我们知道了ServletContextListene是ServletContext的监听者,监听器的响应动作就是在服务器启动时contextInitialized会被调用,关闭的时候contextDestroyed被调用,这个好理解,那我们就来看一下ContextLoaderListener重写的contextInitialized方法到底做了什么。
我们再进入观察initWebApplicationContext方法细看
我因为自己消化过一遍,直接给出关键位置的方法说明——
1、首先是278行:创建了WebApplicationContext,我们可以理解为spring容器的壳子有了
2、其次是288和289行:对ApplicationContext加载了配置文件,并设置servletContext为WebApplicationContext的parent,到这一步,可以理解为我们的spring容器也就差不多成型了
3、接下来是294行:把ApplicationContext对象以键值对的形式存到servletContext中,这一步很关键,就是因为servletContext中存在这个键值对,所以其他内部成员可以通过servletContext访问到ApplicationContext,当然也能使用其管理的bean,而spring mvc则没有这样存在servletContext,所以我觉得正是这一步决定了子容器springmvc可以取用父容器内的bean,反着则不然。
接下来直到轮到我们的springmvc容器<servlet>标签内容
会生成控制org.springframework.web.servlet.DispatcherServlet,这是一个前端控制器,主要的内容我之前也有一篇文章做过自我记录
《Spring MVC的工作机制简单理解》
我们可以看到设置的
<load-on-startup>1</load-on-startup>
这个标签大概意思就是:
1、load-on-startup 元素标记容器是否应该在web应用程序启动的时候就加载这个servlet,(实例化并调用其init()方法)。
2、它的值必须是一个整数,表示servlet被加载的先后顺序。
3、如果该元素的值为负数或者没有设置,则容器会当Servlet被请求时再加载。
4、如果值为正整数或者0时,表示容器在应用启动时就加载并初始化这个servlet,值越小,servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
在DispatcherServlet的时候就根据springMVC容器容器的配置文件生成。
比如我这边就是
那顺序确定了,我们再看一下spring和spring mvc的父子关系哪里确定:
我们可以从下面3个截图看到dispatcherServlet的继承关系,同时,init方法用的是dispatcherServlet父类的父类的方法。
重点在于initServletBean()方法,经过追踪,我们找到该方法的最终实现又是在dispatcherServlet的父类FrameworkServlet中
其中涉及父子关系的实际是在219行的initWebApplicationContext()方法
initWebApplicationContext()方法主要用于创建或刷新WebApplicationContext实例,并对Servlet功能所使用的变量进行初始化。
从238行源码就可以看到,它获得ContextLoaderListener中初始化的rootContext,
在246行设置了父子关系的引用,也就是从这一点我们看到了spring和springMVC的父子关系!
并且,可以看到这只是一条单向的引用,spring中没有引用直接指向springMVC,也就是子类能找到父类,然而父类都不知道这个子类,父子容器之间内部对象调用关系更明了。
再通过构造函数和Servlet的contextAttribute属性查找ServletContext来进行webApplicationContext实例的初始化,最终。
这个方法内263行源码onRefresh(wac)方法是FrameworkServlet提供的模板方法,在子类,也就是我们的DispatcherServlet的onRefresh()方法中进行了重写。而在onRefresh()方法中调用了initStrategies()方法来完成初始化工作,初始化Spring MVC的9个组件。
1、Tomcat在启动时给每个Web应用创建一个全局的上下文环境,这个上下文就是ServletContext,其为后面的Spring容器提供环境。
2、Tomcat在启动过程中触发容器初始化事件,Spring的ContextLoaderListener会监听到这个事件,它的contextInitialized方法会被调用,在这个方法中,Spring会初始化全局的Spring根容器,这个就是Spring的IoC容器,IoC容器初始化完毕后,Spring将其存储到ServletContext中,便于以后来获取。
3、Tomcat在启动过程中还会扫描Servlet,一个Web应用中的Servlet可以有多个,以SpringMVC中的DispatcherServlet为例,这个Servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个Servlet请求。
4、Servlet会在容器启动时加载或延迟加载(根据启动级别设置数字)。延迟加载时,当第一个请求达到时,serlet容器发现对应Servlet还没有被实例化,就调用Servlet的init方法。
在spring MVC里
DispatcherServlet在初始化的时候会建立自己的容器,叫做SpringMVC 容器,用来持有Spring MVC相关的Bean。同时,Spring MVC还会通过ServletContext拿到Spring根容器,并将Spring根容器设为SpringMVC容器的父容器,请注意,Spring MVC容器可以访问父容器中的Bean,但是父容器不能访问子容器的Bean, 也就是说Spring根容器不能访问SpringMVC容器里的Bean。
说的通俗点就是,在Controller里可以访问Service对象,但是在Service里不可以访问Controller对象。
I. 详解Spring mvc工作原理及源码分析
Model 模型层 (javaBean组件 = 领域模型(javaBean) + 业务层 + 持久层)
View 视图层( html、jsp…)
Controller 控制层(委托模型层进行数据处理)
springmvc是一个web层mvc框架,类似struts2。
springmvc是spring的部分,其实就是spring在原有基础上,又提供了web应用的mvc模块。
实现机制:
struts2是基于过滤器实现的。
springmvc是基于servlet实现的。
运行速度:
因为过滤器底层是servlet,所以springmvc的运行速度会稍微比structs2快。
struts2是多例的
springmvc单例的
参数封装:
struts2参数封装是基于属性进行封装。
springmvc是基于方法封装。颗粒度更细。
⑴ 用户发送请求至DispatcherServlet。
⑵ DispatcherServlet收到请求调用HandlerMapping查询具体的Handler。
⑶ HandlerMapping找到具体的处理器(具体配置的是哪个处理器的实现类),生成处理器对象及处理器拦截器(HandlerExcutorChain包含了Handler以及拦截器集合)返回给DispatcherServlet。
⑷ DispatcherServlet接收到HandlerMapping返回的HandlerExcutorChain后,调用HandlerAdapter请求执行具体的Handler(Controller)。
⑸ HandlerAdapter经过适配调用具体的Handler(Controller即后端控制器)。
⑹ Controller执行完成返回ModelAndView(其中包含逻辑视图和数据)给HandlerAdaptor。
⑺ HandlerAdaptor再将ModelAndView返回给DispatcherServlet。
⑻ DispatcherServlet请求视图解析器ViewReslover解析ModelAndView。
⑼ ViewReslover解析后返回具体View(物理视图)到DispatcherServlet。
⑽ DispatcherServlet请求渲染视图(即将模型数据填充至视图中) 根据View进行渲染视图。
⑾ 将渲染后的视图返回给DispatcherServlet。
⑿ DispatcherServlet将响应结果返回给用户。
(1)前端控制器DispatcherServlet(配置即可)
功能:中央处理器,接收请求,自己不做任何处理,而是将请求发送给其他组件进行处理。DispatcherServlet 是整个流程的控制中心。
(2)处理器映射器HandlerMapping(配置即可)
功能:根据DispatcherServlet发送的url请求路径查找Handler
常见的处理器映射器:BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping,
,(不建议使用)
(3)处理器适配器HandlerAdapter(配置即可)
功能:按照特定规则(HandlerAdapter要求的规则)去执行Handler。
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展多个适配器对更多类型的处理器进行执行。
常见的处理器适配器:HttpRequestHandlerAdapter,,
(4)处理器Handler即Controller(程序猿编写)
功能:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler。
(5)视图解析器ViewReslover(配置即可)
功能:进行视图解析,根据逻辑视图名解析成真正的视图。
ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
springmvc框架提供了多种View视图类型,如:jstlView、freemarkerView、pdfView...
(6)视图View(程序猿编写)
View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf...)
引入相关依赖:spring的基本包、springmvc需要的spring-webmvc,日志相关的slf4j-log4j12,jsp相关的jstl、servlet-api、jsp-api。
因为DispatcherServlet本身就是一个Servlet,所以需要在web.xml配置。
一、使用默认加载springmvc配置文件的方式,必须按照以下规范:
①命名规则:-servlet.xml ====> springmvc-servlet.xml
②路径规则:-servlet.xml必须放在WEB-INF下边
二、如果要不按照默认加载位置,则需要在web.xml中通过标签来指定springmvc配置文件的加载路径,如上图所示。
将自定义的 Controller 处理器配置到 spring 容器中交由 spring 容器来管理,因为这里的 springmvc.xml 配置文件中处理器映射器配置的是 BeanNameUrlHandlerMapping ,根据名字可知这个处理器映射器是根据 bean (自定义Controller) 的 name 属性值url去寻找执行类 Handler(Controller) , 所以bean的name属性值即是要和用户发送的请求路径匹配的 url 。
根据视图解析路径:WEB-INF/jsps/index.jsp
功能:根据bean(自定义Controller)的name属性的url去寻找执行类Controller。
功能:自定义的处理器(Controller)实现了Controller接口时,适配器就会执行Controller的具体方法。
会自动判断自定义的处理器(Controller)是否实现了Controller接口,如果是,它将会自动调用处理器的handleRequest方法。
Controller接口中有一个方法叫handleRequest,也就是处理器方法。
因此,自定义的Controller要想被调用就必须实现Controller接口,重写Controller接口中的处理器方法。