不能访问webapp下的图片文件_JavaWeb技术(5):Servlet的理解(下)

4a07276c3b5de7a4eabf674aa309a0cb.png

关于Servlet如何处理静态资源:

在tomcat的conf目录下打开server.xml,里面会看到一些默认的servlet

58f9d173365d537b15ef27f3556aed23.png

tomcat自带jspservlet和defalutservlet分别用于处理jsp请求和静态资源文件,

如果你写了一个servlet,map映射为/,它会对tomcat中的default配置进行覆盖,这样就不能访问webapp下的静态资源了,

前面讲了/会覆盖tomcat中的default,那么配置成/*的话就会同时覆盖defaultservlet和jspservlet,那么此时你就连jsp都不能正确访问了,因为jsp请求不再交由tomcat处理,而是交给DispatchServlet处理,它会在你用浏览器访问时将你的jsp代码加载在页面而不是你期望的五彩斑斓的页面效果,

所以,如果你使用原生servlet来开发,请一定不要覆盖掉这两个servlet,你可以通过配置map为*.do这种方式来避免覆盖/,但这并不雅观,因为这不是restful风格,以.do结尾的请求都会经过DispatcherServlet处理早期的SpringMVC资料,他们把DispatchServlet配置成.do或者.action形式,那是因为早期的SpringMVC缺乏对静态资源的管理,如果配置成/那么所有对静态资源请求也会交给DispatchServlet处理,除非配置相应的Controller否则也会报错,所有静态资源管理的任务还是应该由tomcat中的default来管理,因此早期DispatchServlet配置成.do .action等形式来避免覆盖掉default的功能。当然现在做了优化也就没用这个了。

在springmvc中对此做出了优化,还是使用/来映射我的dispatcherservlet,然后通过另外的配置来达到已经被覆盖的defalutservlet的效果,

前面配置的/拦截了静态资源但是没有拦截jsp请求,这个时候你的jsp虽然能运行,但是其中引用的静态资源比如图片js等就没有显示出来了,这个时就要用到spring为我们提供的两个注解了:

    <mvc:default-servlet-handler/><!-- 静态资源放行 -->
    <mvc:annotation-driven></mvc:annotation-driven><!-- 开启注解支持 -->

它们结合使用产生的功效是如果DispatchServlet发现请求是一个静态资源那么会交给default servlet即交给Tomcat处理,这个时候你的jsp请求就能正确的加载了

那在SpringBoot中如何处理静态资源访问呢:

我新创建一个项目,在默认生成的static文件夹下放一张图片,然后运行项目,发现就能直接访问了:

024b972254d3d9891da722ca69f1188f.png

springboot肯定是做了相关的工作:

  1. 正确识别静态资源,而不是当成一个请求来处理
  2. 在能正确识别静态资源的情况下,配置staticPathPattern与staticLocations,让你的请求path与你想要的静态资源location正确映射

接下来说说这两点


我们知道,在springboot中,对于springmvc的自动化配置都在WebMvcAutoConfiguration中,相关的简化配置可以在其中一探究竟:

关于第一点:正确识别静态资源,而不是当成一个请求来处理

http://localhost:8080/a2.jpg实际上就是走的controller映射,但controller并没有这个mapping,处理方式是加上:

<mvc:default-servlet-handler/><!-- 静态资源放行 -->
配置了这个就相当于启用了DefaultServletHttpRequestHandler
这个Handler也是用来处理静态文件的,它会尝试映射/。
当DispatcherServelt映射/时,并且没有找到合适的
Handler来处理请求时,就会交给DefaultServletHttpRequestHandler 来处理。

而在springboot中DefaultServletHttpRequestHandler会被DefaultServletHandlerConfigurer自动启用,而DefaultServletHandlerConfigurer又会被WebMvcConfigurationSupport自动启用:

3e17c778989a5f15c389c1873e210dc0.png

f0047403f9b81bd0d9e8cb21a90e31bd.png

走到这步,springboot已经能正确识别静态资源了!


关于第二点:在能正确识别静态资源的情况下,配置staticPathPattern与staticLocations,让你的请求path与你想要的静态资源location正确映射

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
	String staticPathPattern = this.mvcProperties.getStaticPathPattern();
	if (!registry.hasMappingForPattern(staticPathPattern)) {
		customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
				.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
				.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
	}
}

staticPathPattern 是静态资源url路径匹配:

/**
  * Path pattern used for static resources.
  */
private String staticPathPattern = "/**";

getResourceLocations(this.resourceProperties.getStaticLocations())是默认静态资源位置:

/**
  * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
  * /resources/, /static/, /public/].
  */
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;

这里已经有四个路径了,但是还有第五个:

private static final String[] SERVLET_LOCATIONS = { "/" };

static String[] getResourceLocations(String[] staticLocations) {
	String[] locations = new String[staticLocations.length + SERVLET_LOCATIONS.length];
	System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length);
	System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length, SERVLET_LOCATIONS.length);
	return locations;
}

这个"/"作用于webapp,但由于我么是springboot项目,基本用不到webapp,所以作用不大

如果默认的静态资源过滤策略不能满足需求,我们可以自定义过滤策略:

1.在配置文件中配置:

# 如果多个使用,隔开
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=classpath:/static/

2.实现WebMvcConfigurer:

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/");
    }
}

配置了这些就相当于springmvc中如下配置:

<!-- 设置静态资源不过滤 -->
<mvc:resources location="/css/" mapping="/css/**" />
<mvc:resources location="/img/" mapping="/img/**" />
<mvc:resources location="/js/" mapping="/js/**" />
<mvc:resources location="/plugins/" mapping="/plugins/**" />

走到这步,SpringBoot已经能正确映射静态资源了!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值