SSM框架前后端网站显示不出来图片
先讲故事:
我开发SSM框架前后端网站显示不出来图片,我一开始图片存储在WEB-INF/static/ 目录,500错误,后来在src\main\resource文件夹下面新建一个static,用以存储图片就好了
核心原因在于 WEB-INF
目录的特殊安全性以及 Spring MVC 对静态资源处理的默认行为。
让我们详细分析一下两种情况的区别:
情况一:图片放在 WEB-INF/static/
下 (500 错误)
-
WEB-INF
目录的特殊性:-
根据 Java Servlet 规范,
WEB-INF
目录是一个受保护的目录。 -
客户端(浏览器)无法直接访问
WEB-INF
目录或其子目录下的任何文件。 这是 Servlet 容器(如 Tomcat)强制执行的安全特性。 -
这个目录通常用于存放不希望用户直接通过 URL 访问的敏感资源,比如
web.xml
、类库 (lib
)、编译后的类文件 (classes
),以及一些需要后端控制器 (Controller
) 处理才能访问的 JSP 页面。
-
-
为什么会导致 500 错误?
-
当你的前端页面(如 JSP、HTML)尝试通过类似
<img src="/your-app-context/WEB-INF/static/your-image.jpg">
的路径直接引用WEB-INF/static/
下的图片时,浏览器会向服务器发送一个对该图片的 HTTP 请求。 -
Servlet 容器(Tomcat)收到这个请求后,会识别到路径中包含
WEB-INF
。 -
由于安全限制,容器会直接拒绝这个请求,并通常返回一个
403 Forbidden
或404 Not Found
错误。 但在某些配置或框架拦截的情况下,这个拒绝行为可能会被框架捕获并处理,最终可能向上层抛出异常,导致你看到的500 Internal Server Error
。根本原因就是容器阻止了对受保护路径的直接访问。
-
情况二:图片放在 src/main/resources/static/
下 (成功)
-
src/main/resources
目录的作用:-
在 Maven/Gradle 标准的 Java Web 项目结构中,
src/main/resources
目录下的内容会被构建工具(如 Maven)原样复制到最终生成的 WAR 包的WEB-INF/classes
目录下。 -
放在
src/main/resources/static/
下的图片文件,在项目构建打包后,实际位于WEB-INF/classes/static/
目录中。这个位置是在 Java 应用的 Classpath (类路径) 上。
-
-
Spring MVC 的静态资源处理:
-
默认情况下,Spring MVC 的
DispatcherServlet
会拦截所有请求 (/
),意图将它们交给后端的Controller
处理。 -
对于静态资源(如图片、CSS、JS),显然没有对应的
Controller
。如果不对这些请求做特殊处理,DispatcherServlet
找不到处理器,就会返回404 Not Found
。 -
关键配置 (
<mvc:resources>
或WebMvcConfigurer
): 你需要在 Spring MVC 的配置文件中(通常是spring-mvc.xml
或 Java Config 类)添加静态资源映射。最常见和推荐的方式是:<mvc:resources mapping="/static/**" location="classpath:/static/" />
或者在 Java Config 中:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");} }
-
这个配置的作用:
-
mapping="/static/**"
: 它告诉 Spring MVC,任何以/static/
开头的 URL 请求(例如http://yourserver:port/your-app-context/static/images/logo.png
)都应该被当作静态资源请求处理。 -
location="classpath:/static/"
: 它告诉 Spring MVC 去类路径 (Classpath) 下的/static/
目录中查找这些静态资源文件。 -
因为你的图片被打包在
WEB-INF/classes/static/
下(即classpath:/static/
),所以 Spring MVC 能找到它们。
-
-
-
为什么这样就能访问?
-
浏览器请求
http://yourserver:port/your-app-context/static/images/logo.png
。 -
DispatcherServlet
拦截请求,发现 URL 匹配/static/**
模式。 -
根据配置,
DispatcherServlet
知道这个请求是静态资源请求,于是将控制权交给一个特殊的ResourceHttpRequestHandler
。 -
ResourceHttpRequestHandler
直接访问类路径下的/static/images/logo.png
文件(即物理位置WEB-INF/classes/static/images/logo.png
)。 -
找到文件后,Handler 读取文件内容,设置正确的 HTTP 头(如
Content-Type
),并将文件内容写入 HTTP 响应体发送回浏览器。 -
整个过程绕过了 Servlet 容器对
WEB-INF
的直接访问限制,因为 Handler 是通过 Java 的 ClassLoader 机制从类路径加载资源的,而不是让容器直接去访问WEB-INF/classes/static/
这个文件系统路径。容器本身并不知道 Handler 最终是从哪里获取到文件内容的。
-
总结关键区别
特性 | WEB-INF/static/ (失败) | src/main/resources/static/ (成功) |
---|---|---|
物理位置 (构建前) | 项目根目录/WEB-INF/static/ | 项目根目录/src/main/resources/static/ |
物理位置 (构建后) | WAR包/WEB-INF/static/ | WAR包/WEB-INF/classes/static/ (在 Classpath 上) |
客户端直接访问 | ❌ 禁止 (Servlet 容器安全限制) | ❌ 禁止 (路径在 WEB-INF/classes 下) |
访问机制 | 尝试通过 URL 直接访问容器文件系统路径 | 通过 Spring MVC ResourceHttpRequestHandler 利用 ClassLoader 从 Classpath 加载 |
所需配置 | 无 (且配置也无法绕过容器限制) | 必需 <mvc:resources> 或 WebMvcConfigurer 配置 |
结果 | 403/404/500 错误 (容器阻止访问) | 200 OK (Spring MVC 找到并发送资源) |
简单来说: 把图片放在 src/main/resources/static/
下,并正确配置 Spring MVC 的静态资源映射 (<mvc:resources>
),利用了 Spring 框架提供的机制,安全地从类路径 (WEB-INF/classes/static/
) 加载资源发送给客户端,从而避开了 Servlet 容器对直接访问 WEB-INF
路径的封锁。而直接放在 WEB-INF/static/
下,触发了容器的安全机制,导致访问失败。因此,src/main/resources/static/
是符合 Spring Boot 约定和 SSM 项目最佳实践的静态资源存放位置。