web前端 静态资源 访问不到 的处理办法
问题:对于一个简单的form表单,url究竟应该如何填写?
1、url的各部分组成
对于地址:http://192.168.1.1:8080/hello/index.html
其中:分解为三部分
- 服务器地址: http://192.168.1.1:8080
- WEB应用上下文: /hello
- 网页或请求: /index.html
2、form表单中的action
HTML协议中要求,form的action属性,以“/”开头是绝对路径,不以“/”开头的是相对路径。
绝对路径是相对于服务器地址而言的。所以记住,很多时候一个斜杠就代表已经写了 http://192.168.1.1:8080这么多东西
相对路径是相对于当前网页或请求而言的。
根目录代表的是从最底层目录访问到当前目录,即绝对路径;
"./" 代表当前目录,"../"代表上级目录,"/"代表Web应用的根目录
- 无“/”,代表是相对于web应用根目录,即http://localhost:8080/tomcat配置的虚拟目录/
- 有“/”,代表是相对于web站点根目录,即http://localhost:8080/
3、具体写法:
例如:
Web Application的context是hello
http://localhost:8080/hello/index.html是欢迎页。
现在我的一个Controller的映射为@RequestMapping(“/fileUp”)。
如果页面的form中的action=“/fileUp”,转向的URL为http://localhost:8080/fileUp,是无效的。
以下是有效的写法,会转向“http://localhost:8080/hello/fileUp”:
- action=“/hello/fileUp”
- action=“./fileUp”
- action=“fileUp” 无“/” 直接跳转到对于的资源名,这个也常见
4、RequestMapper(“/fileUp”) 这里的 / 可加可不加,但都是从上下文开始,而不是从服务器地址开始
web容器启动的时候,(org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping)会扫描Controller注解找到所有的Handler(这里把处理器就称为Handler,等会儿好理解)类,拿到所有的Handler类之后,会遍历这些Handler类,并且遍历这个Handler类中所有带RequestMapping的方法,同时把类和方法的路径拼起来(框架叫做combine,联结在一起,注意:Handler类可以不要RequestMapping),在这个过程中,会判断路径的最前面是否有斜线(/),如果没有,会拼一个斜线(/)
5、例子
重点理解下面的语句(针对action):
无“/”,代表是相对于web应用根目录,即http://localhost:8080/tomcat配置的虚拟目录/
有“/”,代表是相对于web站点根目录,即http://localhost:8080/
前端:
<form action="student/zhangsan/20" method="post"> <input type="submit" value="注册学生"> </form>
后端:
/** * 创建资源 Post请求方式 * http://localhost:8080/myboot/student/zhangsan/20 */ @PostMapping("/student/{name}/{age}") public String createStudent( @PathVariable("name") String name, @PathVariable("age") Integer age){ return "创建资源 student: name="+name+"#age="+age; }
以上内容转自:https://blog.csdn.net/YiGeiGiaoGiao/article/details/128750622
现在描述下我的问题:
1.直接访问没问题:截图如下
访问地址:http://localhost:8080/spring_mvc/index.jsp
2.跳转就访问不到
访问地址:http://localhost:8080/spring_mvc/charpter07/logion
@Controller @RequestMapping("/charpter07") public class Charpter07Controler { @GetMapping("/logion") public String logion(){ System.out.println("跳转到logion.jsp"); return "forward:/index.jsp"; } }
也就是说我们配置
href="layui/css/layui.css"
src="layui/layui.js"
是相对路径。直接访问没问题,但是如果一旦经过了跳转,静态资源的访问路径就变成了
http://localhost:8080/spring_mvc/charpter07/layui/css/layui.css
http://localhost:8080/spring_mvc/charpter07/layui/layui.js
因此就会出现找不到的问题:
最终解决办法:通过添加绝对路径访问(如下图),这样,不管是直接访问,还是转发到此页面,访问路径就都是
http://localhost:8080/spring_mvc/layui/css/layui.css
http://localhost:8080/spring_mvc/layui/layui.js
此处给一个有意义的参考:https://www.cnblogs.com/jimisun/p/9418247.html
总结:一切找不到的问题,基本都是路径问题,要深入理解 路径(前端、后端)问题的本质 才能解决问题!
追加:
后来在springmvc中添加了拦截器,静态资源又访问不到了。
解决办法记录如下:
方式一:修改拦截器,放行静态资源:
/** * @authour cyf * 2023/7/17 16:22 * 登录拦截器 */ public class CheckLogionInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestURI = request.getRequestURI(); //此处判断需要放行的静态资源 if(requestURI.endsWith(".js") || requestURI.endsWith(".css") || requestURI.endsWith(".js") || requestURI.endsWith(".eot") || requestURI.endsWith(".svg") || requestURI.endsWith(".ttf") || requestURI.endsWith(".woff") || requestURI.endsWith(".woff2") ){ System.out.println("放行静态资源"); return true; } HttpSession session = request.getSession(); Object username = session.getAttribute("havaLogion"); //如果没有登录重定向到 logion 页面 if(!StringUtils.hasLength((String) username)){ String contextPath = request.getContextPath(); response.sendRedirect(contextPath+"/charpter07/logion"); //会直接转发到post方法 //request.getRequestDispatcher("/charpter07/logion").forward(request, response); return false; } return true; } }
方式二:在 web.xml 添加配置到最顶端,使用默认sevlet 进行静态资源处理
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!--default servlet处理静态资源--> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.eot</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.svg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.ttf</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.woff</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.woff2</url-pattern> </servlet-mapping> <!--配置springmvc--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--配置spring--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param> <!--配置编码:如果配置了多个过滤器,那么字符编码过滤器一定要在最前面,否则失效--> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <!-- <servlet-name>dispatcherServlet</servlet-name>--> <url-pattern>/*</url-pattern> </filter-mapping> <!--处理html 不支持 put delete--> <filter> <filter-name>hiddenFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenFilter</filter-name> <!--<servlet-name>dispatcherServlet</servlet-name>--> <url-pattern>/*</url-pattern> </filter-mapping> <!--过滤jsp 不处理put delete 的自定义过滤器,只能过滤 FORWARD--> <filter> <filter-name>restFilter</filter-name> <filter-class>com.mvc.filter.RestFilter</filter-class> </filter> <filter-mapping> <filter-name>restFilter</filter-name> <url-pattern>/*</url-pattern> <!--注意:只过滤转发--> <dispatcher>FORWARD</dispatcher> </filter-mapping> </web-app>
方式三:在配置拦截器的springmvc的配置xml里,放行静态资源的文件夹,这需要吧所有静态资源放在一个文件夹里管理,否则,放行路径就得写很多了,配置如下:
推荐
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--设置springmvc 扫描路径--> <context:component-scan base-package="com.mvc.controler"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!--默认视图解析器-配上前缀和后缀,简化逻辑视图名称 (视图模板?)--> <!-- org.springframework.web.servlet.DispatcherServlet 同一目录的 .properties 里 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver"> <property name="prefix" value="/WEB-INF/"></property> <property name="suffix" value=".jsp"></property> </bean> <!--视图控制器 (立即访问) path:映射路径 view-name:访问名称 也会走 viewResolver 注意:1.使用了这个标签后必须配置 <mvc:annotation-driven /> 否则会造成所有的@Controller注解无法解析,导致404错误 2.如果请求存在处理器,则这个标签对应的请求处理将不起作用。因为请求是先去找处理器处理,如果找不到才会去找这个标签配置 --> <!-- <mvc:view-controller path="/" view-name="main"></mvc:view-controller>--> <!-- 保证静态资源和动态请求都能够访问 --> <mvc:annotation-driven></mvc:annotation-driven> <!--访闻静态资源 此配置表示 我们自己配置的请求由controller来处理,但是不能请求的处理交由tomcat来处理 静态资源可以访问,但是动态请求无法访问 --> <mvc:default-servlet-handler/> <!-- 当配置了类型转换器,需要配置FormattingConversionServiceFactoryBean才能同时支持格式化和类型转换--> <mvc:annotation-driven conversion-service="conversionServiceName"></mvc:annotation-driven> <bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean" id="conversionServiceName"> <property name="converters"> <set> <bean class="com.mvc.converter.MyDateConverter" id="converter"></bean> </set> </property> </bean> <!--基于CommonsMultipartResolver 文件上传解析器--> <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"> <!--设置编码格式--> <property name="defaultEncoding" value="utf-8"></property> <!--文件上传最大字节数--> <property name="maxUploadSize" value="#{1024*1024}"></property> </bean> <!--配置拦截器--> <mvc:interceptors> <!--直接配置一个bean会拦截springmvc的所有请求--> <bean class="com.mvc.interceptor.MyInterceptor"></bean> <!-- 如果不是所有的请求都要拦截,可以加一个<mvc:interceptor>--> <mvc:interceptor> <!--需要拦截请求--> <mvc:mapping path="/**"/> <!--不需要拦截的请求 (只会拦截get请求)--> <mvc:exclude-mapping path="/charpter07/logion"/> <!--放行静态资源文件夹--> <mvc:exclude-mapping path="/static/**"/> <bean class="com.mvc.interceptor.CheckLogionInterceptor" id="logionInterceptor"></bean> </mvc:interceptor> <!--国际化三:配置拦截器进行 请求参数 ?locale=zh_CN 必须携带locale参数--> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean> </mvc:interceptors> <!--设置国际化支持,配置国际化资源文件 id="messageSource“不能乱取名--> <bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource"> <!--setBaseNames()--> <property name="basenames"> <array> <value>i18n.logion</value> </array> </property> </bean> <!-- 使用SessionLocaleResolver,保持local状态,会从session中获取local对象 id="localeResolver"只能叫localeResolver,为了覆盖springmvc默认AcceptHeaderLocaleResolver 不配制的话默认使用的是 AcceptHeaderLocaleResolver,会从请求头里获取“Aceept-Language” 国际化二:SessionLocaleResolver 替换默认的 AcceptHeaderLocaleResolver --> <bean class="org.springframework.web.servlet.i18n.SessionLocaleResolver" id="localeResolver"></bean> </beans>
本例将资源放在 static 文件夹下,供大家参考。当然你有多个过滤器,那么每个过滤器都需要对 static 文件夹进行放行处理,或者静态资源没有统一在一个文件夹里,那么拦截器里就要进行多个路径的放行了!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!