同样查看WebMVCAutoConfiguration源码如下:
@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {if (!this.resourceProperties.isAddMappings()) {logger.debug("Default resource handling disabled");return;}Integer cachePeriod = this.resourceProperties.getCachePeriod();if (!registry.hasMappingForPattern("/webjars/**")) {customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/").setCachePeriod(cachePeriod));}// 对静态资源文件映射支持String staticPathPattern = this.mvcProperties.getStaticPathPattern();if (!registry.hasMappingForPattern(staticPathPattern)) {customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern).addResourceLocations(this.resourceProperties.getStaticLocations()).setCachePeriod(cachePeriod));}}
具体支持代码如下:
String staticPathPattern = this.mvcProperties.getStaticPathPattern();if (!registry.hasMappingForPattern(staticPathPattern)) {customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern).addResourceLocations(this.resourceProperties.getStaticLocations()).setCachePeriod(cachePeriod));}
第一步拿到staticPathPattern;
/*** Path pattern used for static resources.*/private String staticPathPattern = "/**";
第二步如果资源请求没有对应映射,就添加资源处理器及资源找寻位置并设置缓存
if (!registry.hasMappingForPattern(staticPathPattern)) {customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern).addResourceLocations(this.resourceProperties.getStaticLocations()).setCachePeriod(cachePeriod));}
页面静态化技术。其中 staticLocations在ResourceProperties类中,源码如下:
/*** Properties used to configure resource handling.** @author Phillip Webb* @author Brian Clozel* @author Dave Syer* @author Venil Noronha* @since 1.1.0*/
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties implements ResourceLoaderAware {private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" };private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {"classpath:/META-INF/resources/", "classpath:/resources/","classpath:/static/", "classpath:/public/" };private static final String[] RESOURCE_LOCATIONS;static {RESOURCE_LOCATIONS = new String[CLASSPATH_RESOURCE_LOCATIONS.length+ SERVLET_RESOURCE_LOCATIONS.length];System.arraycopy(SERVLET_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, 0,SERVLET_RESOURCE_LOCATIONS.length);System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS,SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length);}/*** Locations of static resources. Defaults to classpath:[/META-INF/resources/,* /resources/, /static/, /public/] plus context:/ (the root of the servlet context).*/private String[] staticLocations = RESOURCE_LOCATIONS;
即:"/**"
访问当前项目的任何资源,只要没有匹配的处理映射,则都去静态资源的文件夹找映射
"classpath:/META‐INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/":当前项目的根路径
如下图,访问static/asserts/img/bootstrap-solid.svg:
URL : http://localhost:8083/asserts/img/bootstrap-solid.svg;
docker映射配置文件。这里注意URL上面不要添加静态资源文件夹(路径)的名字,如static、public等等。
代码如下:
@Beanpublic WelcomePageHandlerMapping welcomePageHandlerMapping(ResourceProperties resourceProperties) {return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage(),this.mvcProperties.getStaticPathPattern());}
注册了WelcomePageHandlerMappingBean来处理项目的默认欢迎页面,构造器有两个参数,第一个是项目中存在的欢迎页资源,第二个是静态资源路径映射规则。
① 获取欢迎页资源
其中跟踪resourceProperties.getWelcomePage()源码:
public Resource getWelcomePage() {for (String location : getStaticWelcomePageLocations()) {Resource resource = this.resourceLoader.getResource(location);try {if (resource.exists()) {resource.getURL();return resource;}}catch (Exception ex) {// Ignore}}return null;}
即找到存在的欢迎页的资源,继续跟getStaticWelcomePageLocations()源码:
private String[] getStaticWelcomePageLocations() {String[] result = new String[this.staticLocations.length];for (int i = 0; i < result.length; i++) {String location = this.staticLocations[i];if (!location.endsWith("/")) {location = location + "/";}result[i] = location + "index.html";}return result;}
静态处理演示数据?即 欢迎页的位置为第【1】部分中静态资源文件路径下的index.html。
如下所示:
"classpath:/META‐INF/resources/index.html",
"classpath:/resources/index.html",
"classpath:/static/index.html",
"classpath:/public/index.html"
"/":/index.html
② 静态路径映射规则
/*** Path pattern used for static resources.*/private String staticPathPattern = "/**";
③ WelcomePageHandlerMapping类
static final class WelcomePageHandlerMapping extends AbstractUrlHandlerMapping {private static final Log logger = LogFactory.getLog(WelcomePageHandlerMapping.class);private WelcomePageHandlerMapping(Resource welcomePage,String staticPathPattern) {if (welcomePage != null && "/**".equals(staticPathPattern)) {logger.info("Adding welcome page: " + welcomePage);ParameterizableViewController controller = new ParameterizableViewController();controller.setViewName("forward:index.html");setRootHandler(controller);setOrder(0);}}@Overridepublic Object getHandlerInternal(HttpServletRequest request) throws Exception {for (MediaType mediaType : getAcceptedMediaTypes(request)) {if (mediaType.includes(MediaType.TEXT_HTML)) {return super.getHandlerInternal(request);}}return null;}private List<MediaType> getAcceptedMediaTypes(HttpServletRequest request) {String acceptHeader = request.getHeader(HttpHeaders.ACCEPT);return MediaType.parseMediaTypes(StringUtils.hasText(acceptHeader) ? acceptHeader : "*/*");}}
总结:项目访问时,请求如http://localhost:8083/,则SpringBoot会从静态资源文件路径下找index.html,如果存在一个这样的资源,就转发请求到该页面。
SpringBoot同样对项目浏览器图标请求映射做了默认配置。浏览器图片即项目访问时,浏览器页面上呈现的图标,如CSDN图标如下
加载静态文件失败怎么处理?
代码如下:
@Configuration@ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)public static class FaviconConfiguration {private final ResourceProperties resourceProperties;public FaviconConfiguration(ResourceProperties resourceProperties) {this.resourceProperties = resourceProperties;}@Beanpublic SimpleUrlHandlerMapping faviconHandlerMapping() {SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",faviconRequestHandler()));return mapping;}@Beanpublic ResourceHttpRequestHandler faviconRequestHandler() {ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();requestHandler.setLocations(this.resourceProperties.getFaviconLocations());return requestHandler;}}
跟踪源码this.resourceProperties.getFaviconLocations()如下:
List<Resource> getFaviconLocations() {List<Resource> locations = new ArrayList<Resource>(this.staticLocations.length + 1);if (this.resourceLoader != null) {for (String location : this.staticLocations) {locations.add(this.resourceLoader.getResource(location));}}locations.add(new ClassPathResource("/"));return Collections.unmodifiableList(locations);}
即在静态资源文件下找所有的favicon.ico !
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态