springboot系列--web相关知识探索一

幼儿园里的山大王 2024-10-11 08:03:01 阅读 82

一、web知识探索概述

一、探索大纲

 二、SpringMVC原理流程图

二、springmvc自动配置

springboot在底层自动帮我们配置好了mvc所需要的各个组件。当然,我们也可以自己定制化相关组件。

可参考官方文档:

 三、静态资源探究

一、静态资源存放位置

静态资源一般是存放在当前类路径下(classpath),在 Spring Boot 中既指程序在打包前的<code>/java/目录加上/resource目录,也指程序在打包后生成的/classes/目录。两者实际上指的是同一个目录,里面包含的文件内容一模一样。

一、只要静态资源放在类路径下: <code>/static(或 /public 或 /resources 或 /META-INF/resources )的目录

访问 : 当前项目根路径/ + 静态资源名  就能访问到对应路径下的静态资源。

二、原理:

当前项目根路径/ + 静态资源名,为什么就能访问到静态资源,springboot是怎么知道我们只要找静态资源,而不是找请求呢。

1、首相,可以准备一张叫做a.jpg的图片放置到/static路径下,然后再准备一个接口,请求路径就是当前项目根路径/ + a.jpg,然后请求当前项目根路径/ + a.jpg   这个路径会发现,这个时候返回的是a接口返回的数据。

2、原理就是,请求的时候资源默认映射到/**,也就是说请求根据当前项目根路径/,然后找这个路径下所有的接口,看看那个接口的路径是a.jpg的,看看Controller能不能处理,不能处理的话,就将所有请求又都交给静态资源处理器,静态资源处理器就会到指定路径下找一个叫 a.jpg的资源,如果静态资源也找不到则响应404页面。

二、改变默认的静态资源路径

一、静态资源访问前缀

默认情况下是无前缀的,如果需要改变,可以在yaml配置中加入:

spring:

  mvc:

    static-path-pattern: /res/**

二、改变资源存放位置

 静态资源默认是存放在/static(或 /public 或 /resources 或 /META-INF/resources )的目录下,我们也可以改变他的位置,这个时候就只能放在a这个目录下才能访问到了,放在其他位置上一律访问不到。如果想加入更多文件夹位置,只需要在数组中用逗号隔离就可以。

spring:

  resources:

    static-locations: [classpath:/a/]

三、webjars资源

一、什么是webjars

其实就是把js、css这些东西,弄成了一个jar包,导入到项目中使用。比如:在pom文件中导入对应的jqery文件jar包,就可以在项目中使用。

二、访问路径 

按照官方文档所说,如果需要访问对应的webjar中的资源,路径需要从/webjars/**开始,然后拼接上webjar下面的文件路径以及目标名,即http://localhost:8080/webjars/jquery/3.5.1/jquery.js

四、欢迎页支持

Spring Boot 支持静态和模板化的欢迎页面。它首先在配置的静态内容位置查找 index.html 文件。如果没有找到,它会寻找 index 模板(例如写一个能够处理index请求idea接口,最终跳回index页面)。如果找到任何一个,它会自动用作应用程序的欢迎页面。

访问项目根路径就可以访问到欢迎页。

一、静态资源路径下 index.html

   1、 可以配置静态资源路径,但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问

spring:

#  mvc:

#    static-path-pattern: /res/**   这个会导致welcome page功能失效

  resources:

    static-locations: [classpath:/haha/]

二、controller能处理/index

五、自定义Favicon 

favicon.ico 放在静态资源目录下即可。以后访问每个页面都会显示这个图标

spring:

#  mvc:

#    static-path-pattern: /res/**   这个会导致 Favicon 功能失效

四、静态资源配置原理 

一、SpringBoot启动默认加载 META-INF/spring.factories 路径下的所有xxxAutoConfiguration 类(自动配置类),这个时候SpringMvc功能的自动配置类 WebMvcAutoConfiguration就被加载到容器中。

二、springboot加载了WebMvcAutoConfiguration后给容器中配置了那些组件,可参考WebMvcAutoConfiguration类。

一、OrderedHiddenHttpMethodFilter组件,主要是兼容rest风格请求

@Bean

@ConditionalOnMissingBean({HiddenHttpMethodFilter.class})

@ConditionalOnProperty(

prefix = "spring.mvc.hiddenmethod.filter",

name = {"enabled"},

matchIfMissing = false

)

public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {

return new OrderedHiddenHttpMethodFilter();

}

二、OrderedFormContentFilter组件,表达内容过滤器

@Bean

@ConditionalOnMissingBean({FormContentFilter.class})

@ConditionalOnProperty(

prefix = "spring.mvc.formcontent.filter",

name = {"enabled"},

matchIfMissing = true

)

public OrderedFormContentFilter formContentFilter() {

return new OrderedFormContentFilter();

}

三、 WebMvcAutoConfigurationAdapter内部配置类。

一、@EnableConfigurationProperties注解在这个类的作用

在这个类上方有一个注解@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class, WebProperties.class}),说明这个配置文件的相关属性和这三个类进行了绑定,也就是说我们可以在yaml文件中配置绑定的数据,这个配置文件对应的组件就会产生不同的功能。

1、WebMvcProperties==spring.mvc

2、ResourceProperties==spring.resources

3、WebProperties==spring.web

二、有参构造器赋值 

这个WebMvcAutoConfigurationAdapter类只有一个有参构造器,也就是说这个类的成员属性都是通过这个有参构造器赋值的。 有参构造器所有参数的值都会从容器中找

<code>

//WebProperties webProperties;可以获取和spring.resources绑定的所有的值的对象

//WebMvcProperties mvcProperties 获取和spring.mvc绑定的所有的值的对象

//ListableBeanFactory beanFactory Spring的beanFactory

//HttpMessageConverters 找到所有的HttpMessageConverters

//ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器。=========

//DispatcherServletPath

//ServletRegistrationBean 给应用注册Servlet、Filter....

public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {

this.mvcProperties = mvcProperties;

this.beanFactory = beanFactory;

this.messageConvertersProvider = messageConvertersProvider;

this.resourceHandlerRegistrationCustomizer = (ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();

this.dispatcherServletPath = dispatcherServletPath;

this.servletRegistrations = servletRegistrations;

this.mvcProperties.checkConfiguration();

}

 三、WebMvcAutoConfigurationAdapter内部配置类里面往容器中加入了视图解析器

@Bean

@ConditionalOnMissingBean

public InternalResourceViewResolver defaultViewResolver() {

InternalResourceViewResolver resolver = new InternalResourceViewResolver();

resolver.setPrefix(this.mvcProperties.getView().getPrefix());

resolver.setSuffix(this.mvcProperties.getView().getSuffix());

return resolver;

}

四、EnableWebMvcConfiguration内部配置类

一、资源处理的默认规则

这个类绑定了@EnableConfigurationProperties({WebProperties.class}),其中成员属性通过有参构造方法进行复制,会在容器中找到对应类型的值。

// ResourceProperties 继承了WebProperties.Resources资源类

public EnableWebMvcConfiguration(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, WebProperties webProperties, ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider, ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ListableBeanFactory beanFactory) {

this.resourceProperties = (WebProperties.Resources)(resourceProperties.hasBeenCustomized() ? resourceProperties : webProperties.getResources());

this.mvcProperties = mvcProperties;

this.webProperties = webProperties;

this.mvcRegistrations = (WebMvcRegistrations)mvcRegistrationsProvider.getIfUnique();

this.resourceHandlerRegistrationCustomizer = (ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();

this.beanFactory = beanFactory;

}

 静态资源处理规则主要是这个方法:

protected void addResourceHandlers(ResourceHandlerRegistry registry) {

super.addResourceHandlers(registry);

// 如果addMappings为false,则禁用了静态资源,默认为true,else才是静态资源请求规则

if (!this.resourceProperties.isAddMappings()) {

logger.debug("Default resource handling disabled");

} else {

ServletContext servletContext = this.getServletContext();

// 这个方法是先从缓存中获取webjars,单位为秒,并且注册一下路径作为访问规则,这个只是webjar的规则

this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");

// 这个是先从缓存中获取静态资源,并且注册一下路径作为访问规则,若没有再yaml中配置默认是/**,例如localhost:80/a.jpg,就会默认在指定路径下查找,代码有设置默认值,这里就不放了。如果再yaml文件中配置了,就会按照配置的路劲来。

this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {

registration.addResourceLocations(this.resourceProperties.getStaticLocations());

if (servletContext != null) {

// 这里是如果有在yaml文件中配置,static-path-pattern属性,就会按照配置上的来。

registration.addResourceLocations(new Resource[]{new ServletContextResource(servletContext, "/")});

}

});

}

}

spring:

  resources:

    add-mappings: false   禁用所有静态资源规则

默认静态资源访问路径

二、欢迎页规则

当前类下会由一个方法注入欢迎页配置规则。请求进来会经过前端控制器,然后前端控制器就会去请求处理器映射器,通过处理器映射器找到能够处理的handle,然后通过反射去调用。而欢迎页的处理则是在处理器映射器这一步做了业务处理。

<code> @Bean

public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {

// 主要规则在这个有参构造方法里面,this.getWelcomePage()这个路径和静态资源路径,系统给以同一个默认路径。this.mvcProperties.getStaticPathPattern()这个默认是/**

WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());

welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));

welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());

return welcomePageHandlerMapping;

}

WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {

// 如果欢迎页不为空,同时请求路径符合/** (指的就是项目根路径/index.html,其中index.html指的就是欢迎页,项目根路径指的就是localhost:80,或者是域名),这个时候就能访问到欢迎页,也就是说如果yaml配置了static-path-pattern: /res/**就无法访问到欢迎页

if (welcomePage != null && "/**".equals(staticPathPattern)) {

logger.info("Adding welcome page: " + welcomePage);

this.setRootViewName("forward:index.html");

} else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {

// 如果只有欢迎页,但是请求路径不符和,则会去调用Controller找到/index结尾的接口

logger.info("Adding welcome page template: index");

this.setRootViewName("index");

}

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。