SpringBoot核心技术篇-web开发

目录

一、SpringMVC自动配置概览

二、简单功能分析

2.1静态资源访问

1、静态资源路径

2、webjar

 2.2、欢迎页支持

2.3、自定义 Favicon

2.4、静态资源配置原理

1、配置类中只有一个构造器

2、资源处理的默认规则 

 3、欢迎页的处理规则

三、请求参数处理

3.1 请求映射原理

3.2 参数处理原理

1、 HandlerAdapter

2、执行目标方法

3、参数解析器-HandlerMethodArgumentResolver

 4、结果处理器

5、如何确定目标方法每一个参数的值

6、 挨个判断所有参数解析器那个支持解析这个参数

7、 解析这个参数的值​编辑

 3.3、Servlet API:

3.4、复杂参数:

1、原理: 

2、目标方法执行完毕后

3.处理派发结果




一、SpringMVC自动配置概览

Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(大多场景我们都无需自定义配置)

SprongBoot通过xxxAutoConfiguration的类,对我们一些我们常常用到的场景进行了默认设置。

例如在SpringMvc XML版我们要设置的:视图解析器、全局异常解析器、静态资源访问、前端控制器等等都无序我们进行配置。只需要将我们想要设置的在配置文件中设置即可

当然我们想要自定义,也是可以的自己定义这些类,SpringBoot就会使用自定义的类

二、简单功能分析

2.1静态资源访问

1、静态资源路径

只要静态资源放在类路径下(resources下的):

/static  、 /public、 /resources 、 /META-INF/resources 

访问: 当前项目的根路径 /静态资源名称

static-path-pattern 默认是/**  

(当前项目 + static-path-pattern + 静态资源名 = 静态资源文件夹下找 )

SpringBoot核心技术篇-web开发_第1张图片

SpringBoot核心技术篇-web开发_第2张图片

原理 静态映射/**

请求进来,先去找Controller看能不能处理。不能处理的所以请求又都交给静态资源处理器、静态资源也找不到则响应404页面

改变默认的静态资源前缀和路径

spring:
  mvc:
    #设置静态资源的模式  默认是/**
    static-path-pattern: /res/**
  web:
    resources:
      static-locations: [classpath:/haha/]

2、webjar

自动映射 /webjars/**

WebJars - Web Libraries in Jars

        
            org.webjars
            jquery
            3.5.1
        

访问地址:http://localhost:8080/webjars/jquery/3.5.1/jquery.js 后面地址要按照依赖里面的包路径

 2.2、欢迎页支持

静态资源路径下  index.html

   可以配置静态资源路径

   但是不可以配置静态资源的访问前缀。否则回导致index.html不能被默认访问(后面源码中可以看见)

2.3、自定义 Favicon

favicon.ico 放在静态资源目录下即可。

是小图标的设置

2.4、静态资源配置原理

SpringBoot启动默认加载XXXAutoConfiguration类(自动配置类)

而静态资源配置的原理是因为自动加载了WebMVCAutoConfiguration自动配置类,才生效

@AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class })
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class WebMvcAutoConfiguration {

 主要配置了什么

SpringBoot核心技术篇-web开发_第3张图片

SpringBoot核心技术篇-web开发_第4张图片

 SpringBoot核心技术篇-web开发_第5张图片

配置文件的相关属性  WebMvcPorperties  ===>  spring.mvc

                                  WebProperties  ===>    spring.web

1、配置类中只有一个构造器

主要就是进行一些初始化工作

webProperties、mvcProperties  是获取配置文件中的相关信息
beanFactory  bean工厂  等

SpringBoot核心技术篇-web开发_第6张图片

2、资源处理的默认规则 

SpringBoot核心技术篇-web开发_第7张图片

spring:

  web:
   addMappings: false   禁用所有静态资源规则

 默认的四种静态资源的位置

 3、欢迎页的处理规则

SpringBoot核心技术篇-web开发_第8张图片

WelcomePageHandlerMapping这个类是欢迎页的规则

SpringBoot核心技术篇-web开发_第9张图片

这个源码也体现了静态资源的前缀必须要是/**才行 

三、请求参数处理

3.1 请求映射原理

主要是通过DispatcherServlet这个前端控制器来实现的

SpringBoot核心技术篇-web开发_第10张图片

而DispatcherServlet其实它的父类是HttpServerlet,HttpServlet是通过doGet()、doPost()、等等请求方法进行实现映射的

然后我们发现是FrameworkServlet中有doGet()、doPost()的方法,并且每个方法调用了

processRequest(request, response);

SpringBoot核心技术篇-web开发_第11张图片

 processRequest(request, response);方法中的核心方法是doService(request,response)

SpringBoot核心技术篇-web开发_第12张图片

doService()方法是一个抽象类,它的实现是在DispatcherServlet中 

 每一个doService中都调用doDispatch(request,response)

SpringBoot核心技术篇-web开发_第13张图片

 SpringBoot核心技术篇-web开发_第14张图片

 SpringBoot核心技术篇-web开发_第15张图片

RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则。 

SpringBoot核心技术篇-web开发_第16张图片

SpringBoot核心技术篇-web开发_第17张图片

所有的请求映射都在HandlerMapping中。

  • SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;
  • SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
  • 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。
    • 如果有就找到这个请求对应的handler
    • 如果没有就是下一个 HandlerMapping
  • 我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。自定义 HandlerMapping

3.2 参数处理原理

 HandlerMapping中能找到处理请求的Handler(即能找到请求到底是访问的那个方法)

然后通过为当前的Handler找一个适配器HandlerAdapter 进行参数的处理,适配器的主要作用执行目标方法并确定方法参数的每个值

SpringBoot核心技术篇-web开发_第18张图片

1、 HandlerAdapter

SpringBoot核心技术篇-web开发_第19张图片

进入到方法中我们可以看到 handlerAdpaters一共有四种 

第一种支持方法书上标注@RequestMapping的     第二种是支持函数式变成的 。这两种是我们经常要使用的

 这里我们是通过@RequestMapping注解标注的方法,因此第一次就成功得到了对应的处理器适配器

2、执行目标方法

SpringBoot核心技术篇-web开发_第20张图片

进入这个方法,我们方法最终是执行的这个方法

SpringBoot核心技术篇-web开发_第21张图片 

SpringBoot核心技术篇-web开发_第22张图片

 

 进入这个方法后我们发现了两个关键的参数

this.argumentResolvers   参数解析器      this.returnValueHandlers 结果处理器

这里是将这些方法先设置到  invocableMethod

3、参数解析器-HandlerMethodArgumentResolver

确定将要执行的目标方法的每一个参数的值是什么;

SpringMvc目标方法能写多少种参数类型,取决于参数解析器

一共有27种   我们常见的如@RequestParam  @PathVariable等 

SpringBoot核心技术篇-web开发_第23张图片

通过这个结果我们看到了有两个方法

supportsParameter() 这个是先判断这个参数是否有参数解析器能解析   

如果能解析就执行下面的方法

resolveArgument()

SpringBoot核心技术篇-web开发_第24张图片

 4、结果处理器

这个显示的SpringMvc目标方法能有多少中返回结果 

SpringBoot核心技术篇-web开发_第25张图片

介绍完上面两个参数,继续执行找到要执行目标方法的代码

SpringBoot核心技术篇-web开发_第26张图片 

SpringBoot核心技术篇-web开发_第27张图片 

 进入后  我们在117和118个打一个端点  然后在Controller代码中打一个端点

我们发现117执行完毕后执行执行的是 Controller的代码 也就是15行的

 这说明了117这个代码执行完毕后就将方法的参数已经解析完毕了。

下面我们进入到117行代码中,看一下到底是如何解析的

SpringBoot核心技术篇-web开发_第28张图片

 我们发现这个args执行完毕后就是参数的值,然后通过doInvoke(args)反射进行执行

SpringBoot核心技术篇-web开发_第29张图片

SpringBoot核心技术篇-web开发_第30张图片 

 args得到的值和我输入参数的值一样

 因此解析方法就是在146行代码中,我们进入一探究竟

5、如何确定目标方法每一个参数的值

进入后这句是获取方法参数的类型、参数使用说明注解的

SpringBoot核心技术篇-web开发_第31张图片

 SpringBoot核心技术篇-web开发_第32张图片

 SpringBoot核心技术篇-web开发_第33张图片

6、 挨个判断所有参数解析器那个支持解析这个参数

SpringBoot核心技术篇-web开发_第34张图片

@RequestParam是直接判断是否通过这个注解检查

SpringBoot核心技术篇-web开发_第35张图片 

通过检查后进行参数的获取

 

7、 解析这个参数的值SpringBoot核心技术篇-web开发_第36张图片

 通过名称获取值

SpringBoot核心技术篇-web开发_第37张图片 得到zhangsan的值

SpringBoot核心技术篇-web开发_第38张图片

这样第一个参数的值就获取到了

 3.3、Servlet API:

WebRequest、ServletRequest、MultipartRequest、 HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId

SpringBoot核心技术篇-web开发_第39张图片

 

ServletRequestMethodArgumentResolver 以上的部分参数

 

3.4、复杂参数:

MapModel(map、model里面的数据会被放在request的请求域 request.setAttribute)、Errors/BindingResult、RedirectAttributes( 重定向携带数据)ServletResponse(response)、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder

Map map, Model model, HttpServletRequest request

这三个都是可以给request域中放数据    

1、原理: 

进入看看参数解析器是如何解析的

SpringBoot核心技术篇-web开发_第40张图片

 看第一个参数map

 进入解析方法,最终得到

SpringBoot核心技术篇-web开发_第41张图片

然后调用的是getModel  给我们返回的ModelMap  

SpringBoot核心技术篇-web开发_第42张图片 

map类型的参数,会返回 

mavContainer的 getModel() ;

getModel() 最终返回的是  private final ModelMap defaultModel = new BindingAwareModelMap();

这个继承的是

SpringBoot核心技术篇-web开发_第43张图片

 这样第一个参数args[0]就是

第二个参数同理,model我们得到的是

SpringBoot核心技术篇-web开发_第44张图片 

 最终完毕后转发到success

SpringBoot核心技术篇-web开发_第45张图片

这个时候,我们看一下mavContainer   发现model和map是在同一个BindingAwareModelMap

SpringBoot核心技术篇-web开发_第46张图片 

接着往下执行,看一下处理返回结果的方法中 这个mvaContainer执行了什么操作

SpringBoot核心技术篇-web开发_第47张图片 主要就是处理一下结果

继续

2、目标方法执行完毕后

 执行完毕后,我们会将所有的数据都放在ModelAndViewContainer,包含有页面地址号view ,还包含有model数据SpringBoot核心技术篇-web开发_第48张图片

 SpringBoot核心技术篇-web开发_第49张图片

 SpringBoot核心技术篇-web开发_第50张图片

SpringBoot核心技术篇-web开发_第51张图片 

 最终执行完毕后

SpringBoot核心技术篇-web开发_第52张图片

3.处理派发结果

 

mv就是modelAndVie   render是渲染  进入这方法

SpringBoot核心技术篇-web开发_第53张图片 

 视图渲染

 

 

	@Override
	protected void renderMergedOutputModel(
			Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		// Expose the model object as request attributes.
		exposeModelAsRequestAttributes(model, request);

		// Expose helpers as request attributes, if any.
		exposeHelpers(request);

		// Determine the path for the request dispatcher.
		String dispatcherPath = prepareForRendering(request, response);

		// Obtain a RequestDispatcher for the target resource (typically a JSP).
		RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
		if (rd == null) {
			throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
					"]: Check that the corresponding file exists within your web application archive!");
		}

		// If already included or response already committed, perform include, else forward.
		if (useInclude(request, response)) {
			response.setContentType(getContentType());
			if (logger.isDebugEnabled()) {
				logger.debug("Including [" + getUrl() + "]");
			}
			rd.include(request, response);
		}

		else {
			// Note: The forwarded resource is supposed to determine the content type itself.
			if (logger.isDebugEnabled()) {
				logger.debug("Forwarding to [" + getUrl() + "]");
			}
			rd.forward(request, response);
		}
	}

 关键:暴露模型作为请求属性

exposeModelAsRequestAttributes(model, request);

SpringBoot核心技术篇-web开发_第54张图片

 所以这把就解释了,为什么是Map 和Model是在请求域中

这个代码就解释了为什么

你可能感兴趣的:(SpringBoot的二次学习,spring,boot,java,后端,spring,servlet)