SpringBoot:Web 开发相关原理

阅读: 评论:0

SpringBoot:Web 开发相关原理

SpringBoot:Web 开发相关原理

      • 静态资源配置原理
        • 静态资源处理规则
      • 请求参数处理
        • 请求映射
        • 请求映射原理

静态资源配置原理

静态资源处理规则

sssSpringBoot启动自动加载 xxxAutoConfiguration 自动配置类

sssSpringMVC功能的自动配置类大都集中在 ==》 WebMvcAutoConfiguration ,生效

@Configuration(proxyBeanMethods = false
)
@ConditionalOnWebApplication(type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})   // 没有 WebMvcConfigurationSupport 类生效💦
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {...	...	....	....	...	...
}

sssWebMvcAutoConfiguration 生效给容器中配置了什么?

 // WebMvcAutoConfiguration 内部类@Configuration(	proxyBeanMethods = false )	@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})	//配置文件的相关属性和xxx进行了绑定@Order(0)public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {...	...	...}

sss配置文件的相关属性和xxx进行了绑定:

ssdssWebMvcProperties ==》 spring.mvc ResourceProperties ==》 sources

ssdssWebProperties ==》 spring.web

ssdssWebMvcAutoConfigurationAdapter 只有一个有参构造器,有参构造器所有参数值都会从容器中确定。如下:

/**
@ ResourceProperties :获取和spring.web绑定的所有的值的对象
@ WebMvcProperties :获取和spring.mvc绑定的所有的值的对象
@ ListableBeanFactory :Spring的beanFactory
@ HttpMessageConverters :找到所有的HttpMessageConverters
@ ResourceHandlerRegistrationCustomizer :找到资源处理器的自定义器
@ DispatcherServletPath
@ ServletRegistrationBean 给应用注册Servlet、
*/public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {sourceProperties = resourceProperties;this.mvcProperties = mvcProperties;this.beanFactory = ssageConvertersProvider = sourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.IfAvailable();this.dispatcherServletPath = dispatcherServletPath;this.servletRegistrations = servletRegistrations;}

sss资源处理的默认规则:

 public void addResourceHandlers(ResourceHandlerRegistry registry) {// addMappings默认为true,即允许静态资源💦//并且因为调用resourceProperties属性,点进去发现是属于ResourceProperties类,相对应于容器的组件,看注1💦if (!sourceProperties.isAddMappings()) {logger.debug("Default resource handling disabled");} else {//设置缓存的时间Duration cachePeriod = Cache().getPeriod();CacheControl cacheControl = Cache().getCachecontrol().toHttpCacheControl();// 设置 webjars 中静态资源访问规则💦if (!registry.hasMappingForPattern("/webjars/**")) {this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).Seconds(cachePeriod)).setCacheControl(cacheControl));}// 设置静态资源的路径 StaticLocations() 获得,默认为 "/**",可以修改💦String staticPathPattern = StaticPathPattern();if (!registry.hasMappingForPattern(staticPathPattern)) {this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).StaticLocations())).Seconds(cachePeriod)).setCacheControl(cacheControl));}}}

sss【注1】:

public class ResourceProperties {private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};private String[] staticLocations;public ResourceProperties() {this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;this.addMappings = true;this.chain = new ResourceProperties.Chain();this.cache = new ResourceProperties.Cache();}public String[] getStaticLocations() { return this.staticLocations;}
spring: resources: # 禁用所有静态资源 add-mappings: false # 设置缓存 cache: period: 11000 # 修改静态资源路径 static-locations: classpath:/stat_resources/

sss欢迎页处理规则:

 //HandlerMapping:处理器映射。保存了每一个Handler能处理那些请求。@Beanpublic WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {// 跳转欢迎页,看注【注2】💦WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, WelcomePage(), StaticPathPattern());welcomePageHandlerMapping.Interceptors(mvcConversionService, mvcResourceUrlProvider));welcomePageHandlerMapping.CorsConfigurations());return welcomePageHandlerMapping;}

sss【注2】:

 WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Optional<Resource> welcomePage, String staticPathPattern) {// 要使用欢迎页必须是 “ /** ”💦if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {logger.info("Adding welcome page: " + ());this.setRootViewName("forward:index.html");} else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {// 静态资源路径不是默认配置,就调用 Controller 处理 /index 请求💦logger.info("Adding welcome page template: index");this.setRootViewName("index");}}

sss【注3】:•favicon :浏览器默认会发请求访问 /favicon.ico当静态资源请求规则是 /** 时,可以访问。如果自己指定了静态资源请求路径则不能访问。

请求参数处理

请求映射

sssrest使用:

ssdssRest风格支持(使用HTTP请求方式动词表示对资源的操作)

ssdss以前: ○ 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户

sdssdsdsd s ○ 现在: /user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户

sdssdsdsd s ○ 核心Filter :HiddenHttpMethodFilter

ssdsdsddsdsdss ■ 用法: 表单method=post,隐藏域 _method=put

ssdsdsddsdsdss ■ SpringBoot中手动开启

spring:mvc:hiddenmethod:filter:enabled: true	#开启页面表单的Rest功能
@RestController
public class HelloController {@RequestMapping("/bug.jpg")public String hello(){return "aaaa";}//    @RequestMapping(value = "/user",method = RequestMethod.GET)@GetMapping("/user")public String getUser(){return "GET-张三";}//    @RequestMapping(value = "/user",method = RequestMethod.POST)@PostMapping("/user")public String saveUser(){return "POST-张三";}//    @RequestMapping(value = "/user",method = RequestMethod.PUT)@PutMapping("/user")public String putUser(){return "PUT-张三";}@DeleteMapping("/user")
//    @RequestMapping(value = "/user",method = RequestMethod.DELETE)public String deleteUser(){return "DELETE-张三";}
}

sss rest 原理 (表单提交要使用REST的时候):

ssdss前提 :表单提交会带上_method=PUT (这里应该是_method=希望使用的提交方法)

ssdss1、请求过来被HiddenHttpMethodFilter拦截 (源码) :


ssdssHiddenHttpMehodFilter的核心方法:

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {//原生的servlet请求:HttpServletRequest request💦HttpServletRequest requestToUse = request;// 2、请求是否是POST请求并且正常💦if ("POST".Method()) && Attribute("exception") == null) {// 4、获取到_method的值,默认methodParam = "_method"  💦String paramValue = hodParam);if (StringUtils.hasLength(paramValue)) {//或者methodParam的前缀,并将其转换成大写,比如 delete_method,所以会获取到 DELETE String method = UpperCase(Locale.ENGLISH);//ALLOWED_METHODS == PUT、DELETE、PATCH💦if (ains(method)) {//就是一种包装,通过调用HiddenHttpMethodFilter的内部类HttpMethodRequestWrapper的💦//getMethod()方法返回输入的method而不是post💦requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);}}}filterChain.doFilter((ServletRequest)requestToUse, response);
}

sdssd s 2、 请求是否正常,并且是POST

ssdsdsddsdsdss 3、 用法: 表单method=post,隐藏域 _method=put

ssdsdsddsdsdss 4、 获取到_method的值(无论value是大写还是小写,底层都会统一转换为大写)

ssdsdsddsdsdss 5、 兼容以下请求 :PUT.DELETE. PATCH

ssdsdsddsdsdss 6、原生request(post),包装模式requesWrapper重写了getMethod方法,返回的是传入的值

ssdsdsddsdsdss 7、过滤器链放行的时候用wrapper。以后的方法调用getMethod是调用requesWrapper的。

sss【注 5】:通过源码可知,methodParam = “_method”; 但是可以通过setMethodParam(String methodParam)方法改变methodParam值,因此这时候 我们可以通过把_method 换成我们自己自定义得值,比如_m:

@Configuration(proxyBeanMethods = false)
public class config {@Beanpublic HiddenHttpMethodFilter hiddenHttpMethodFilter(){HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();hiddenHttpMethodFilter.setMethodParam("_m");return hiddenHttpMethodFilter;}
}

sss【注 6】:ALLOWED_METHODS值的设置方式,通过静态块赋值:

sss【注 7】:requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);源码:

sss【注 8】:Rest使用客户端工具,如PostMan直接发送Put、delete等方式请求,无需Filter。因为:

sss【注 9】:
@ DeleteMapping实质就是 @RequestMapping ( method = { RequestMethod.DELETE} )
@ PutMapping实质就是 @RequestMapping ( method = { RequestMethod.PUT} )
@ PostMapping实质就是 @RequestMapping ( method = { RequestMethod.POST} )
@ GetMapping实质就是 @RequestMapping ( method = { RequestMethod.GET} )

请求映射原理

dasdasdas

sssDispatcherServlet调用FrameworkServlet中的doGet和doPost

sssdoGet和doPost ==> processRequest(request, response) ==> doService(request, response)

sssdoService是一个抽象方法,并未做具体实现

sss FrameworkServlet的子类DispatcherServlet实现了doService

sssDispatcherServlet的doService ==> doDispatch(request, response)

sss请求映射流程:

sdsdsss请求进来 ==> HttpServlet的doGet和doPost

sdsdsdsdsddsdsdsss==> FrameworkServlet中的doGet和doPost

sdsdsddsdsdsddsdsdsss==> DispatcherServlet的doService

sdsdsdsddsdsdsdsdsdsdsss==> doService中调用doDispatch(request, response)

sss[注10]: SpringMVC功能分析都从 org.springframework.web.servlet.DispatcherServlet-》doDispatch()


sss找到当前请求使用哪个Handler : mappeHandler = hHandler(processedRequest); 😒
dasdas
ssshandlerMappings:处理器映射,有五个值

sss[注11]: 第一各处理器映射:RequestMappingHandlerMapping:保存了所有@RequestMapping 和handler的映射规则

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

sss1. SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;

sss2. SpringBoot自动配置了默认 的 RequestMappingHandlerMapping

sss3. 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息(在request)。(同样的请求信息只能有一个)

sdsss• 如果有就找到这个请求对应的handler

ssdss• 如果没有就是下一个 HandlerMapping

sss4. 我们需要一些自定义的映射处理,我们也可以自己给容器中放HandlerMapping。自定义 HandlerMapping (映射每一个请求到对应的Handler)

sss[注12]: getHandler就是我们寻找相应处理器方法的方法:

sss[注13]: 点击DispatcherServlet的getHandler方法,进入到AbstractHandlerMapping的getHandler方法,

sss[注14]: 再进入getHandlerInternal(request):

sss[注15]: 再进入getHandlerInternal(request)方法:就是核心部分:

sss[注16]: 通过lookupHandlerMethod(lookupPath, request)获取相应的处理方法:

本文发布于:2024-02-04 19:27:16,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170714739458788.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:「JumpServer」
下一篇:墨者学院
标签:原理   SpringBoot   Web
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23