You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+Thymeleaf+MySQL插入数据后出现404资源找不到异常

你遇到的404错误核心是请求路径错误,同时缺少创建产品的页面模板和控制器映射,和MySQL端口无关。以下是具体问题和修复方案:

一、修复页面链接路径错误

Thymeleaf模板由Spring MVC控制器转发,不能直接访问/templates/路径,正确路径应对应控制器的@RequestMapping映射:

  1. 修改index_first.html中的产品链接:
    原代码:
<a class="btn btn-primary" href="/templates/products">products</a>

改为:

<a class="btn btn-primary" href="/products">products</a>
  1. 修改index.html中的创建产品链接:
    原代码:
<a class="btn btn-primary" href="/templates/products/create">Create Product</a>

改为(用Thymeleaf语法生成正确路径):

<a class="btn btn-primary" th:href="@{/products/create}">Create Product</a>

二、添加创建产品的模板文件

在src/main/resources/templates/products/目录下创建create.html,示例代码:

<!doctype html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Create Product</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <h1 class="text-center my-4">Create New Product</h1>
    <form th:action="@{/products/save}" method="post" enctype="multipart/form-data">
        <div class="mb-3">
            <label class="form-label">Name</label>
            <input type="text" class="form-control" name="name" required>
        </div>
        <div class="mb-3">
            <label class="form-label">Brand</label>
            <input type="text" class="form-control" name="brand" required>
        </div>
        <div class="mb-3">
            <label class="form-label">Category</label>
            <input type="text" class="form-control" name="category" required>
        </div>
        <div class="mb-3">
            <label class="form-label">Price</label>
            <input type="number" step="0.01" class="form-control" name="price" required>
        </div>
        <div class="mb-3">
            <label class="form-label">Description</label>
            <textarea class="form-control" name="description" rows="3"></textarea>
        </div>
        <div class="mb-3">
            <label class="form-label">Image</label>
            <input type="file" class="form-control" name="imageFile" accept="image/*">
        </div>
        <button type="submit" class="btn btn-primary">Save Product</button>
        <a th:href="@{/products}" class="btn btn-secondary ms-2">Cancel</a>
    </form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

三、完善ProductsController,添加创建和保存方法

修改ProductsController.java,新增访问创建页面的@GetMapping和处理表单提交的@PostMapping:

package com.boostmytool.bestStore.controllers;

import com.boostmytool.bestStore.models.Product;
import com.boostmytool.bestStore.services.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.List;

@Controller
@RequestMapping("/products")
public class ProductsController {
    @Autowired
    private ProductRepository repo;

    // 上传文件存储路径,确保static/images目录存在
    private final String UPLOAD_DIR = "src/main/resources/static/images/";

    @GetMapping({"", "/"})
    public String showProductList(Model model){
        List<Product> products = repo.findAll();
        System.out.println(products);
        for (Product product : products) {
            System.out.println("Product ID: " + product.getId() + ", Image File Name: " + product.getImageFileName());
        }
        model.addAttribute("products",products);
        return "products/index";
    }

    // 显示创建产品页面
    @GetMapping("/create")
    public String showCreateForm(){
        return "products/create";
    }

    // 保存产品
    @PostMapping("/save")
    public String saveProduct(Product product, @RequestParam("imageFile") MultipartFile file) throws IOException {
        // 设置创建时间
        product.setCreatedAt(new Date());

        // 处理图片上传
        if (!file.isEmpty()) {
            String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename();
            Path path = Paths.get(UPLOAD_DIR + fileName);
            Files.write(path, file.getBytes());
            product.setImageFileName(fileName);
        }

        repo.save(product);
        // 重定向到产品列表页
        return "redirect:/products";
    }
}

四、修复Product实体的表名错误

原Product.java中@Table(name = "templates/products")是错误的,应该对应MySQL中的表名,修改为:

@Entity
@Table(name = "products") // 数据库中的表名,不是模板路径
public class Product {
    // ... 其他代码不变
}

五、清理pom.xml重复依赖

pom.xml中重复引入了spring-boot-starter-data-jpa,删除其中一个:
原重复代码:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- ... -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

保留一个即可。

内容的提问来源于stack exchange,提问作者Suuu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 13:33:09