基于springMVC的图书管理系统

进度终于来到了springMVC,下次估计就是springboot了,感觉每次开始新框架,环境都是大问题,项目一共敲四天,环境卡三天。总结一下这次碰到的问题和解决方法吧。

问题和解决方法

1、controller中return无法跳转到界面:

@restController返回数据,@Controller才能跳转界面

还得在springMvcConfig里配置好jsp的类型和位置:

2、报错:找到多个名为spring_web的片段。这是不合法的相对排序。有关详细信息,请参阅Servlet规范的第8.2.2 2c节。考虑使用绝对排序。

听信谗言(不是) 根据百度到的方法在pom.xml里瞎配置,明明已经有springmvc_web了,还是添上了spring_web,直接导致一直报错,解决方法:

在web.xml里加上代码:

<absolute-ordering />

像这样:

3、报错:java.lang.ClassNotFoundException: org.apache.jsp.index_jsp

这个搞得我烦死了,一直找不到原因,包括现在也找不到,所以我的解决方法是新建了一个项目,先把tomcat跑起来,再把代码挪过去,成功解决了。

4、报错:org.springframework.web.bind.MissingServletRequestParameterException: Required Integer parameter 'id' is not present

我代码是这么写的:

后来发现需要用@Param注明参数,像这样,顺利解决:

5、pom.xml中org.apache.maven.plugins标红

找到maven的包存放的位置,找到这个包的版本号,加进去就好了

在setting里找到maven的位置

springMVC中各配置文件作用

1. JdbcConfig

  • 作用: 配置 JDBC 数据源和事务管理。
  • 内容: 通常包括数据库连接信息(如 URL、用户名、密码)以及数据源的 bean 定义。

2. MyBatisConfig

  • 作用: 配置 MyBatis 的相关设置。
  • 内容: 包含 MyBatis 的 SqlSessionFactory、SqlSessionTemplate、Mapper 扫描等配置。

3. ServletConfig

  • 作用: 配置 Servlet 相关的内容。
  • 内容: 定义 DispatcherServlet 的初始化参数和映射 URL,通常用于配置 Spring MVC 的核心功能。

4. SpringConfig

  • 作用: 配置 Spring 的核心功能。
  • 内容: 包含 Bean 的定义、依赖注入、组件扫描等,通常用于管理整个应用程序的 bean 生命周期。

5. SpringMvcConfig

  • 作用: 配置 Spring MVC 的具体设置。
  • 内容: 包含视图解析器、静态资源处理、拦截器等 Spring MVC 特有的配置。

项目介绍

目录

代码

BookController:负责界面的数据获取及更新
package com.example.controller;

import com.example.domain.Book;
import com.example.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

//统一每一个控制器方法返回值
@RestController
@RequestMapping("/books")
public class BookController {

    @Autowired
    private BookService bookService;

    @PostMapping
    public Result save(@RequestBody Book book) {
        boolean flag = bookService.save(book);
        return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERR,flag);
    }


    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) {
        boolean flag = bookService.delete(id);
        return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERR,flag);
    }

    @PostMapping("/deleteByIds")
    public Result deleteByIds(@RequestParam("ids") List<Integer> ids) {
        boolean flag = bookService.deleteByIds(ids);
        return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR, flag);
    }

    
    @GetMapping
    public Result getAll() {
        List<Book> bookList = bookService.getAll();
        Integer code = bookList != null ? Code.GET_OK : Code.GET_ERR;
        String msg = bookList != null ? "" : "数据查询失败,请重试!";
        return new Result(code,bookList,msg);
    }

    @GetMapping("/search")
    public Result searchBooks(@RequestParam(value = "bookname", required = false) String bookname,
                              @RequestParam(value = "status", required = false) String status) {
        List<Book> bookList;
        if (bookname == null && status == null) {
            bookList = bookService.getAll(); // 获取所有图书信息
        } else {
            bookList = bookService.getByCondition(bookname, status); // 根据条件查询图书信息
        }
        Integer code = bookList != null ? Code.GET_OK : Code.GET_ERR;
        String msg = bookList != null ? "" : "数据查询失败,请重试!";
        return new Result(code, bookList, msg);
    }

}
UpdateController:负责界面跳转
package com.example.controller;

import com.example.domain.Book;
import com.example.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

//统一每一个控制器方法返回值
@Controller
@RequestMapping("/update")
public class UpdateController {
    @Autowired
    private BookService bookService;

    @GetMapping("/{id}")
    public String updateBook(@PathVariable("id") Integer id, Model model) {
        Book book = bookService.getById(id);
        model.addAttribute("book", book);
        return "update";
    }

    // 处理修改后提交的表单
    @PostMapping("/{id}")
    public String processUpdateBook(@PathVariable("id") Integer id, @ModelAttribute Book book) {
        System.out.println("processUpdateBook"+id);

        book.setId(id);
        long timestamp = System.currentTimeMillis();
        // 创建SimpleDateFormat对象,并设置日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 将时间戳转换为字符串
        String formattedTimestamp = sdf.format(new Date(timestamp));
        book.setEntry_time(formattedTimestamp);
        bookService.update(book);
        return "redirect:/"; // 修改后重定向到书籍列表页面
    }
    @PostMapping("/changeStatus/{id}/{status}")
    public String updateBookStatus(@PathVariable("id") Integer id,@PathVariable("status") String status) {


        boolean flag = bookService.updateBookStatus(id, status);
        return "redirect:/"; // 修改后重定向到书籍列表页面

    }


}

index.jsp:首页

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<c:set var="pagePath" value="${pageContext.request.contextPath}" />

<!DOCTYPE html>
<html>
<head>
    <jsp:include page="head.jsp">
        <jsp:param value="图书管理系统" name="title" />
    </jsp:include>
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <style>
        .borrowed-book {
            background-color: yellow;
        }
        .navbar {
            text-align: center;
            background: #080808;
            padding: 10px;
        }
        .navbar-buttons a {
            margin: 0 10px;
            text-decoration: none;
            color: #333;
        }
        .search-container {
            text-align: center;
            margin: 20px 0;
        }
        #booksTable {
            width: 100%;
            border-collapse: collapse;
        }
        #booksTable th, #booksTable td {
            border: 1px solid #ddd;
            padding: 8px;
        }
        #booksTable th {
            background-color: #f2f2f2;
        }
        a:link {
            text-decoration: none;
        }
        a:hover {
            color: green;
        }
        .footer {
            text-align: center;
            margin: 20px 0;
            font-size: 18px;
        }
    </style>
</head>
<body>

<div class="navbar">
    <h1 style="margin-right: 1100px;color: #f1f1f1">图书管理系统</h1>
    <div class="navbar-buttons" style="margin-left: 1200px;">
        <a href="add.jsp" style="color: aliceblue">新增图书</a>
        <a href="index.jsp" style="color: aliceblue">返回</a>
    </div>
</div>

<form id="searchForm" action="/books/search" method="get">
    <div class="search-container">
        <input type="text" name="bookname" placeholder="输入图书名进行查询">
        状态:
        <select name="status">
            <option value="可借阅">可借阅</option>
            <option value="已借出">已借出</option>
        </select>
        <input type="submit" value="搜索"/>
    </div>
</form>

<form action="/books/deleteByIds" method="post" id="deleteForm">
    <table id="booksTable" align="center">
        <thead>
        <tr>
            <th><label for="select-all-checkbox">全选</label><input type="checkbox" id="select-all-checkbox" class="select-checkbox"></th>
            <th>序号</th>
            <th>书名</th>
            <th>作者</th>
            <th>出版社</th>
            <th>价格</th>
            <th>状态</th>
            <th>入馆时间</th>
            <th>借阅/归还</th>
<%--            <th>归还</th>--%>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>
        <c:if test="${not empty books}">
            <c:forEach items="${books}" var="book">
                <tr class="${book.status == '已借出' ? 'borrowed-book' : ''}">
                    <td><input type="checkbox" name="ck" class="select-checkbox" value="${book.id}"/></td>
                    <td>${book.id}</td>
                    <td>${book.bookname}</td>
                    <td>${book.author}</td>
                    <td>${book.introduce}</td>
                    <td>${book.price}</td>
                    <td>${book.status}</td>
                    <td>${book.entry_time}</td>
                    <td>
                        <button type="button" onclick="handleBorrowReturn('${book.id}', '${book.status}')">${book.status == '已借出' ? '归还' : '借阅'}</button>
                    </td>
                    <td>
                        <button><a href="javascript:void(0)" onclick="deleteBook('${book.id}')">删除</a></button>
                        <button><a href="javascript:void(0)" onclick="updateBook('${book.id}')">修改</a></button>
                    </td>
                </tr>
            </c:forEach>
        </c:if>
        </tbody>
    </table>
    <input type="submit" value="批量删除" onclick="return del()">
</form>

<div class="footer">
    图书总数量: <span id="totalBooksCount">${fn:length(books)}</span> 件
</div>

<script>
    $(document).ready(function() {
        $.ajax({
            url: '/books',
            type: 'GET',
            success: function(response) {
                if (response.code === 20041) {
                    updateBooksTable(response.data);
                } else {
                    alert('获取图书列表失败!');
                }
            },
            error: function() {
                alert('获取图书列表失败!请重试!');
            }
        });

        $('#searchForm').submit(function(event) {
            event.preventDefault();
            $.ajax({
                url: '/books/search',
                type: 'GET',
                data: $(this).serialize(),
                success: function(response) {
                    if (response.code === 20041) {
                        const books = response.data;
                        updateBooksTable(books);
                        $('#totalBooksCount').text(books.length);
                    } else {
                        alert('搜索失败!');
                    }
                },
                error: function() {
                    alert('搜索失败,请重试!');
                }
            });
        });

        function updateBooksTable(books) {
            $('#booksTable tbody').empty();
            if (books.length === 0) {
                $('#booksTable tbody').append('<tr><td colspan="10">没有找到图书</td></tr>');
                $('#totalBooksCount').text(0);
                return;
            }
            $.each(books, function(index, book) {
                $('#booksTable tbody').append(
                    `<tr class="${book.status == '已借出' ? 'borrowed-book' : ''}">
                        <td><input type="checkbox" name="ck" class="select-checkbox" value="${book.id}"/></td>
                        <td>${book.id}</td>
                        <td>${book.bookname}</td>
                        <td>${book.author}</td>
                        <td>${book.introduce}</td>
                        <td>${book.price}</td>
                        <td>${book.status}</td>
                        <td>${book.entry_time}</td>
                        <%--<td>--%>
                        <%--    <button type="button" onclick="handleBorrowReturn('${book.id}', '${book.status}','借阅',)">借阅</button>--%>
                        <%--</td>--%>
                        <%--<td>--%>
                        <%--    <button type="button" onclick="handleBorrowReturn('${book.id}', '${book.status}','归还')">归还</button>--%>
                        <%--</td>--%>
                        <td>
                            <button type="button" onclick="handleBorrowReturn('${book.id}', '${book.status}')">${book.status == '已借出' ? '归还' : '借阅'}</button>
                        </td>
                        <td>
                            <button><a href="javascript:void(0)" onclick="deleteBook('${book.id}')">删除</a></button>
                            <button><a href="javascript:void(0)" onclick="updateBook('${book.id}')">修改</a></button>
                        </td>
                    </tr>`
                );
            });
            $('#totalBooksCount').text(books.length);
        }
    });
    function updateBook(bookId) {
        if (confirm('您确定要修改这本书的信息吗?')) {
            window.location.href = '/update/' + bookId; // 注意路径与Controller定义保持一致
        }
    }
    $('#select-all-checkbox').change(function() {
        const isChecked = $(this).is(':checked');
        $('.select-checkbox').prop('checked', isChecked);
    });

    $(document).on('change', '.select-checkbox', function() {
        const allCheckboxes = $('.select-checkbox');
        const allChecked = allCheckboxes.length === allCheckboxes.filter(':checked').length;
        $('#select-all-checkbox').prop('checked', allChecked);
    });

    function deleteBook(bookId) {
        if (confirm('确定要删除这本书吗?')) {
            $.ajax({
                url: '/books/' + bookId,
                type: 'DELETE',
                success: function(response) {
                    if (response.code === 20021) {
                        alert('删除成功!');
                        window.location.href = '';
                    } else {
                        alert('删除失败!');
                    }
                },
                error: function() {
                    alert('删除失败,请重试!');
                }
            });
        }
    }

    function del() {
        const selectedIds = [];
        $('input[name="ck"]:checked').each(function() {
            selectedIds.push($(this).val());
        });

        if (selectedIds.length === 0) {
            alert('请选择要删除的图书!');
            return false;
        }

        if (confirm('确定要删除选中的图书吗?')) {
            $.ajax({
                url: '/books/deleteByIds',
                type: 'POST',
                data: { ids: selectedIds },
                traditional: true,
                success: function(response) {
                    if (response.code === 20021) {
                        alert('批量删除成功!');
                        window.location.href = '';

                        // 重新获取图书数据
                        // loadBooks(); // 删除成功后重新加载图书列表

                    } else {
                        alert('批量删除失败!');
                    }
                },
                error: function() {
                    alert('批量删除失败,请重试!');
                }
            });
        }

        return false;
    }

    function handleBorrowReturn(bookId, currentStatus) {
        let newStatus;
        let action;
        if (currentStatus === '可借阅') {
            newStatus = '已借出';
            action='借阅';
        } else if (currentStatus === '已借出') {
            newStatus = '可借阅';
            action='归还';
        }

        $.ajax({
            url: `/update/changeStatus/${bookId}/${newStatus}`,
            type: 'POST',
            success: function(response) {
                alert(action+'成功!');
                window.location.reload();
            },
            error: function() {
                alert('操作失败,请重试!');
            }
        });

    }
</script>

</body>
</html>

界面

基于springMVC的图书管理系统录屏

整完了,总结完了就可以忘掉这个项目了哈哈哈哈。 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值