SpringBoot相关原理
静态资源配置原理
SpringBoot启动默认加载 很多xxxAutoConfiguration 类(自动配置类)。以SpringMVC功能的自动配置类 WebMvcAutoConfiguration为例。其使用注解@EnableConfigurationProperties({ WebMvcProperties.class, WebProperties.class })
将属性与配置类中的值进行绑定。处理资源的默认规则由addResourceHandlers()
规定。若resources.addMappings=false会直接返回(禁用所有静态资源的访问)。之后会在Spring设置的默认的路径(\"classpath:/META-INF/resources/\",\"classpath:/resources/\", \"classpath:/static/\", \"classpath:/public/\")下寻找静态资源。
Rest原理(表单提交)
在我们没有自定义HiddenHttpMethodFilter的时候会使用默认值进行处理。表单提交时再请求方式是POST的前提下使用_method=PUT/DELETE时。请求会被HiddenHttpMethodFilter拦截。判断是POST请求之后获取_method的值。原生的request会被包装为requestWrapper,requestWrapper重写了getMethod方法,返回的是_method对应的值。
请求映射原理
主要起作用的是DispatcherServlet中的doDispatch()方法。在获取到请求之后getHandler()会根据请求找到合适的Handler(即Controller的方法)。Spring在启动时扫描所有的Controller并解析注解,并把这些信息保存到HandlerMappings中,其中RequestMappingHandlerMapping保存了所有的@RequestMapping 和handler的映射规则。根据这些映射规则以及传入的request最终确定使用哪个Controller方法
参数处理原理
首先在HandlerMapping中找到可以处理请求的Handler(即Controller的方法)。然后为当前的Handler寻找一个适配器(HandlerAdapter)。之后会执行适配器的handle()方法(mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
)。在这个方法中会获得参数解析器argumentResolvers。参数解析器会根据注解的类型来解析其对应的参数。SpringMVC能解析多少种方法参数,取决于有多少种参数解析器。在获得参数解析器后,也会获得返回值处理器returnValueHandlers,返回值处理器决定了能返回哪些参数。真正执行目标方法的函数是ServletInvocableHandlerMethod类中的Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
。确定目标方法每一个参数的值使用到了如下函数:Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
,首先获取到方法参数的详细信息,通过增强for循环挨个判断使用哪个参数解析器,如果匹配成功,就将解析器放入缓存,以提高后续程序的执行效率。然后使用解析器进行解析得到参数对应的值。然后遍历所有的方法参数获得所有参数对应的值。
处理自定义参数的情况,例如自己封装的类:
会在参数解析的过程中使用WebDataBinder将请求参数的值绑定到指定的JavaBean里。因为使用HTTP协议传输的数据,传输的都是文本,而我们需要具体的包装类,例如Integer,Date等等,WebDataBinder会利用里面的Converters将请求数据转化成指定的数据类型。再次封装到JavaBean中。
如果传输的数据和自己封装的类的属性不是一一对应匹配的。可以通过重写 WebMvcConfigurer中的addFormatters方法,再重写addFormatters中的convert方法,自己按需将请求域中的数据封装到自己的自定义类中。
内容协商原理
内容协商:根据客户端接收能力不同,返回不同类型的数据。内容协商是在获取了请求参数之后的事情。其需要将返回值进行处理,转化为客户端能够接收的数据类型。
在拿到对应注解的处理器之后,在核心方法writeWithMessageConverters()中,首先获取客户端支持接收的内容类型(默认获取Accept请求头字段的内容)。然后拿到能够接收的类型和能够提供的类型。使用双重for循环进行匹配得到最佳匹配类型。然后再是一个for循环,在messageConverters中寻找支持最佳匹配类型的Convert,之后再使用这个Convert进行数据类型的转换。
视图解析原理
在处理的过程中,所有传入的数据和视图地址都会被放在ModelAndViewContainer中。在调用处理器方法执行完之后会返回一个ModelAndView对象。之后由processDispatchResult()方法决定页面如何响应。在processDispatchResult()中由render()方法进行页面渲染。render()方法通过视图解析器解析视图名称得到View对象。View对象再调用自己的render()方法进行页面渲染。
拦截器原理
根据当前请求,找到可以处理请求的handler以及handler的所有拦截器,并把拦截器放在HandlerExecutionChain中。然后为当前handler找一个适配器(HandlerAdapter),在适配器解析前执行applyPreHandle()。在该方法先顺序执行所有拦截器的preHandle()方法,如果返回为True,执行下一个拦截器的preHandle(),如果返回为False,则倒序执行所有已经执行了的拦截器的afterCompletion()方法,并直接跳出,不执行目标方法。
所有的拦截器返回都为True,之后会执行目标方法。之后会倒序执行所有拦截器的postHandle()方法。在前面的步骤中有任何的异常,都会直接倒序执行afterCompletion()方法。
在页面成功渲染完成之后,也会倒序执行afterCompletion()方法。
文件上传原理
文件上传解析器先使用isMultipart()先判断是否为文件上传请求,之后使用resolveMultipart()对请求进行解析,并封装为MultipartHttpServletRequest对象。之后寻找一个是适配器(HandlerAdapter),再执行适配器的handle()方法,在handle()方法中会使用参数解析器argumentResolvers中的RequestPartMethodArgumentResolver对属于文件类型的参数进行解析,将request中的文件信息封装为一个Map,key是自己定义的名字,value是封装好的MultipartFile。之后返回ModelAndView,之后再进行页面渲染。
感觉自己总结的不太好,后续有时间会继续完善,如有错误请指出
来源:https://www.cnblogs.com/xuzhuo123/p/16085532.html
本站部分图文来源于网络,如有侵权请联系删除。