【Java后端】解决SpringBoot 中Controller层加入RequestMapping导致HTML页面的静态文件路径变化问题

关键词:[SpringBoot] [RequestMapping] [文件路径]

在这里插入图片描述

一、问题出现

@Controller
@RequestMapping("/goods")
public class GoodsController {
    @Autowired
    UserServiceImpl userService;
    @Autowired
    IGoodsService goodsService;
    /**
     * 跳转到商品列表页
     *
     * @return
     */
    @RequestMapping("/toList")
    public String toList(User user, Model model) {
        if (user == null) {
            return "login";
        }
        model.addAttribute("user", user);
        model.addAttribute("goodsList", goodsService.findGoodVo());
        return "goodsList";
    }
}

在这里插入图片描述

二、初步思考

1)如代码:控制层加了@RequestMapping("/goods")后,访问 goodsImg 的路径奇怪的变成了 http://localhost:8080/goods/img/iphone12.png,且加载不出,而我直接在地址栏输入 http://localhost:8080/img/iphone12.png却能够访问;

2)再加上,检查->网络 这里面所有的当前页面静态文件都是 http://localhost:8080/static目录下的子目录/xxx的形式,没有一个像 ihpone12.png 一样在路径中出现 /goods
在这里插入图片描述
3)我就觉得是不是路径中这个 /goods导致了这个错误;

三、逐个细化

3.1 target 文件

  • target 文件夹是用来存放项目构建后的文件和目录、jar包、war包、编译的class文件,都是maven构建时生成的;
  • 在idea的spring boot项目中,如果target目录中没有同步更新目录文件和资源就会报错;

然而我的项目中,多次运行包括删除target文件再运行,都是含有 img 文件的
在这里插入图片描述
所以肯定不是 target 文件的问题,即我的 图片 已经完成了资源构建,但是我的访问地址有问题,导致访问不到它;

3.2 @RequestMapping

本质上 RequestMapping 是起到请求映射的作用,将对应的 url (也就是 RequestMapping 的 value 值)放行,经过一顿处理,映射到某一页面(return 值);
那么:

  1. 在方法上加 RequestMapping 注解便是直接拦截这个 url;
  2. 在类上加 RequestMapping 注解便是在这个类的所有方法之前加上这层路径;

比如这个代码:

@Controller
@RequestMapping("/goods")
public class GoodsController {
    @Autowired
    UserServiceImpl userService;
    @Autowired
    IGoodsService goodsService;
    /**
     * 跳转到商品列表页
     *
     * @return
     */
    @RequestMapping("/toList")
    public String toList(User user, Model model) {
        if (user == null) {
            return "login";
        }
        model.addAttribute("user", user);
        model.addAttribute("goodsList", goodsService.findGoodVo());
        return "goodsList";
    }
}
  • 如果我访问http://localhost:8080/goods/toList时就会被放行,进入到 toList 方法中,一顿处理,映射到 goodsList 页面;
  • 如果没加 @RequestMapping("/goods")在类上,我访问http://localhost:8080/toList就进入到 toList 方法中,然后映射到 goodsList 页面;

这么一来我能理解为什么 img/iphone12.png前面会加一个 /goods,但为什么其他所有的静态文件确没加/goods?这更加让我确信是 /goods 让我无法访问 已有的 img 中的图片;

3.3 Spring 与 Themeleaf 相对路径绝对路径

再来看一下 我 WebMvcConfigurer:

    /**
     * 保证静态资源能够被访问
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    }

我已经将 所有对静态资源访问的路径(/**)都映射为 /static/了,那无论是 http://localhost:8080/goods/img/iphone12.png 还是 http://localhost:8080/img/iphone12.png 应该都是去访问 static 文件夹下的东西;

https://blog.csdn.net/CatAndBeer/article/details/108460781 这篇文章指出是 页面中 相对路径的原因导致 RequestMapping 在资源上面多加了一层目录,页面中使用绝对路径即可;

但实际上我页面中都用的绝对路径

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>商品列表</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <!-- jquery -->
    <script type="text/javascript" th:src="@{/js/jquery.min.js}"></script>
    <!-- bootstrap -->
    <link rel="stylesheet" type="text/css" th:href="@{/bootstrap/css/bootstrap.min.css}"/>
    <script type="text/javascript" th:src="@{/bootstrap/js/bootstrap.min.js}"></script>
    <!-- jquery-validator -->
    <script type="text/javascript" th:src="@{/jquery-validation/jquery.validate.min.js}"></script>
    <script type="text/javascript" th:src="@{/jquery-validation/localization/messages_zh.min.js}"></script>
    <!-- layer -->
    <script type="text/javascript" th:src="@{/layer/layer.js}"></script>
    <!-- md5.js -->
    <script type="text/javascript" th:src="@{/js/md5.min.js}"></script>
    <!-- common.js -->
    <script type="text/javascript" th:src="@{/js/common.js}"></script>
</head>
<body>
<div class="panel panel-default" style="height:100%;background-color:rgba(222,222,222,0.8)">
    <div class="panel-heading">秒杀商品列表</div>
    <table class="table" id="goodslist">
        <tr>
            <td>商品名称</td>
            <td>商品图片</td>
            <td>商品原价</td>
            <td>秒杀价</td>
            <td>库存数量</td>
            <td>详情</td>
        </tr>
        <tr th:each="goods,goodsStat : ${goodsList}">
            <td th:text="${goods.goodsName}"></td>
            <td><img th:src="@{${goods.goodsImg}}" width="100" height="100"/></td>
            <td th:text="${goods.goodsPrice}"></td>
            <td th:text="${goods.seckillPrice}"></td>
            <td th:text="${goods.stockCount}"></td>
            <td><a th:href="'/goods/toDetail/'+${goods.id}">详情</a></td>
        </tr>
    </table>
</div>
</body>
</html>

th:src="@{xxx路径}" 表示在 xxx路径 前加上上下文路径,那不就是绝对路径么;

3.4 关于 配置类 和 约定的配置

  • @EnableWebMvc 默认会将这里配置类 覆盖 MVC事先约定的配置;
  • SpringBoot 中 MVC 约定的配置就是 /**,但这里我们有了配置类,覆盖约定的配置 @EnableWebMvc 就是启动你这个配置类;
    在这里插入图片描述

所以,这里要么不加 @EnableWebMvc,让 SpringBoot 用自己的 MVC 配置,要么就是加上 @EnableWebMvc,然后在类里面把这个静态资源映射也给写上;
在这里插入图片描述
但这两个不是我问题所在,因为我 target 文件中已有 img文件夹和两张图片,所以必然不是这里的问题

四、一个尝试

其实,通过第三部分,我确定是 路径的 /goods导致的问题,而其他静态资源不受影响,就 img 受影响,那我就把注意力放在 页面上的路径,其实是可以发现:
在这里插入图片描述
这两个红框地方,唯一的区别就是在 上下文路径后有没有一个 /,所以我进行尝试:

        <tr th:each="goods,goodsStat : ${goodsList}">
            <td th:text="${goods.goodsName}"></td>
            <td><img th:src="@{${'/'+goods.goodsImg}}" width="100" height="100"/></td>
            <td th:text="${goods.goodsPrice}"></td>
            <td th:text="${goods.seckillPrice}"></td>
            <td th:text="${goods.stockCount}"></td>
            <td><a th:href="'/goods/toDetail/'+${goods.id}">详情</a></td>
        </tr>

加上了斜杠 /,emmm
在这里插入图片描述
然后就恢复正常了????
这说明https://blog.csdn.net/CatAndBeer/article/details/108460781 该文章说的没错,的确是绝对路径的原因,我一开始疏忽大意,但是 加上 / 和 不加 / 为什么会让两个路径完全不同:

  • 加上 / ,我的图片路径:http://localhost:8080/img/iphone12.png
  • 不加 /,我的图片路径:http://localhost:8080/goods/img/iphone12.png

我很想知道其中的原因😭😭😭

五、深入思考—html页面中相对路径

html页面中相对路径有两种:

  1. /test/page1,这是相对于服务器根路径而言的,以之前的例子为例,使用结果就是直接从8080以后开始替换,如http://localhost:8080/test/page1

  2. test/page2,这是相对于当前路径而言的,比如当前路径为http://localhost:8080/test/page1,那么替换以后就是

绝对路径:

绝对路径就是直接http://localhost:8080/test/page1,十分简单,但是也相当于写死了

http://localhost:8080/test/test/page,在这种情况下也有对应的语法,../表示上级目录,./表示当前目录,如test/page2就相当于./test/page2,如果写成../test/page2,那么替换后的路径就是http://localhost:8080/test/page了;

这么一想就清楚了:

  • 我不加/,表示相对当前路径,即当前 url + /img/iphone12.png = http://localhost:8080/goods/img/iphone12.png
  • 我加上/,表示相对服务器根路径,http://localhost:8080/img/iphone12.png,这样的话,经过 MVC 配置的静态资源映射就直接变成了 http://localhost:8080/static/img/iphone12.png

所以,这实际上跟 Themeleaf 并没有多大关系,因为去掉 @{},只要加上 /,我依旧可以访问静态资源:

  <tr th:each="goods,goodsStat : ${goodsList}">
        <td th:text="${goods.goodsName}"></td>
        <td><img th:src="${'/'+goods.goodsImg}" width="100" height="100"/></td>
        <td th:text="${goods.goodsPrice}"></td>
        <td th:text="${goods.seckillPrice}"></td>
        <td th:text="${goods.stockCount}"></td>
        <td><a th:href="'/goods/toDetail/'+${goods.id}">详情</a></td>
    </tr>

在这里插入图片描述

但为什么 http://localhost:8080/goods/img/iphone12.png就不能匹配 /**映射到 /static/呢?难道是认为他不是获取静态资源?

貌似是的,因为成功时 如下显示:
在这里插入图片描述
失败时:
在这里插入图片描述
失败时,路径为 http://localhost:8080/goods/img/iphone12.png,我认为 这意味着它发出一个非获取静态资源的请求给 SpringBoot,SpringBoot 去找 Controller,没找到,所以这个响应不了;

所以,我标题是起错了嘛 😂,是HTML相对路径的问题,就当是顺便普及知识;

六、注意点

  • 问题的解决在于 HTML 页面的相对路径,细节没把握好;
  • 项目Debug时,最好关闭 浏览器的 缓存,否则可能导致非正确方法解决问题的情况;
    在这里插入图片描述

参考文章

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
要在SpringBoot实现跳转到静态HTML页面,可以使用控制器(Controller)的方式来实现。具体的实现步骤如下: 1. 在SpringBoot项目的resources文件夹下创建一个static文件夹,用来存放静态HTML文件。 2. 在控制器添加一个请求映射(RequestMapping)注解,并指定需要跳转的静态HTML页面路径。 3. 在方法体使用ModelAndView返回静态HTML页面的名称。 示例代码如下: ```java @Controller public class HtmlController { @RequestMapping("/index") public ModelAndView index() { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index.html"); return modelAndView; } } ``` 在上面的代码,我们定义了一个控制器类HtmlController,并在其添加了一个请求映射注解@RequestMapping("/index"),表示当访问http://localhost:8080/index时,将会执行index()方法。 在index()方法,我们使用ModelAndView类来指定需要跳转的静态HTML页面名称,即modelAndView.setViewName("index.html")。 最后返回ModelAndView对象即可。 需要注意的是,SpringBoot默认情况下会将静态文件放置在classpath下的static目录,如果需要更改静态文件的存放位置,可以在application.properties添加以下配置: ```properties # 指定静态文件存放位置 spring.resources.static-locations=classpath:/static/,file:/usr/local/static/ ``` 上面的配置表示将静态文件放置在classpath下的static目录和本地磁盘的/usr/local/static/目录下。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值