web-003(增删改查)

复现课程的注册登录及人员信息的增删改查

自我规划网站实现注册信息增删改查

admin-users代码:

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.List,com.example.personweb.model.User" %>
<%
    List<User> users = (List<User>) request.getAttribute("users");
    User currentUser = (User) session.getAttribute("currentUser");
%>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户管理 - 资料库</title>
    <link rel="stylesheet" href="<%= request.getContextPath() %>/css/site.css" />
</head>
<body>
    <!-- 顶部导航 -->
    <nav class="top-nav">
        <div class="container">
            <a href="<%= request.getContextPath() %>/home" class="nav-brand">
                <span>📚</span>
                <span>信管知识库</span>
            </a>
            <div class="nav-menu">
                <a href="<%= request.getContextPath() %>/library">文章库</a>
                <a href="<%= request.getContextPath() %>/profile">个人中心</a>
                <a href="<%= request.getContextPath() %>/manage" class="active">管理后台</a>
                <span style="color: var(--border-color); margin: 0 8px;">|</span>
                <span style="color: var(--text-muted); font-size: 0.9rem;"><%= currentUser.getUsername() %></span>
                <a href="<%= request.getContextPath() %>/logout" style="color: #dc2626;">退出</a>
            </div>
        </div>
    </nav>

        <!-- 页面头部 -->
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px;">
            <div>
                <h1 style="margin: 0;">👥 用户管理</h1>
                <p style="color: var(--text-muted); margin: 4px 0 0 0;">查看所有注册用户,管理权限和黑名单</p>
            </div>
            <div style="display: flex; gap: 12px;">
                <a href="<%= request.getContextPath() %>/manage" class="btn btn-outline">
                    ← 返回管理后台
                </a>
                <a href="<%= request.getContextPath() %>/admin/users/add" class="btn btn-primary">
                    ➕ 创建用户
                </a>
            </div>
        </div>

    <main class="container" style="padding-bottom: 60px;">
        <!-- 统计信息 -->
        <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px;">
            <div class="card" style="text-align: center; padding: 20px;">
                <div style="font-size: 2rem; color: var(--primary-color); font-weight: 700;"><%= users.size() %></div>
                <div style="color: var(--text-muted); font-size: 0.9rem;">总用户数</div>
            </div>
            <div class="card" style="text-align: center; padding: 20px;">
                <div style="font-size: 2rem; color: #16a34a; font-weight: 700;">
                    <%= users.stream().filter(u -> "ADMIN".equals(u.getRole())).count() %>
                </div>
                <div style="color: var(--text-muted); font-size: 0.9rem;">管理员</div>
            </div>
            <div class="card" style="text-align: center; padding: 20px;">
                <div style="font-size: 2rem; color: #dc2626; font-weight: 700;">
                    <%= users.stream().filter(User::isBlacklisted).count() %>
                </div>
                <div style="color: var(--text-muted); font-size: 0.9rem;">黑名单用户</div>
            </div>
        </div>

        <div class="card">
            <table class="custom-table">
                <thead>
                    <tr>
                        <th>用户ID</th>
                        <th>用户名</th>
                        <th>密码</th>
                        <th>邮箱</th>
                        <th>手机号</th>
                        <th>角色</th>
                        <th>状态</th>
                        <th>最后登录</th>
                        <th style="width: 220px;">操作</th>
                    </tr>
                </thead>
                <tbody>
                    <% for (User user : users) { %>
                        <tr>
                            <td><%= user.getUserID() %></td>
                            <td><strong><%= user.getUsername() %></strong></td>
                            <td style="font-family: monospace; color: var(--text-muted);">
                                <%= user.getPassword() != null ? "••••••••" : "-" %>
                            </td>
                            <td><%= user.getEmail() == null || user.getEmail().isEmpty() ? "-" : user.getEmail() %></td>
                            <td><%= user.getPhone() == null || user.getPhone().isEmpty() ? "-" : user.getPhone() %></td>
                            <td>
                                <span class="badge <%= "ADMIN".equals(user.getRole()) ? "role-admin" : "role-user" %>">
                                    <%= "ADMIN".equals(user.getRole()) ? "管理员" : "用户" %>
                                </span>
                            </td>
                            <td>
                                <% if (user.isBlacklisted()) { %>
                                    <span class="badge" style="background: #fee2e2; color: #dc2626;">黑名单</span>
                                <% } else { %>
                                    <span class="badge" style="background: #dcfce7; color: #16a34a;">正常</span>
                                <% } %>
                            </td>
                            <td style="color: var(--text-muted);">
                                <%= (user.getLastLoginTime() != null && !user.getLastLoginTime().isEmpty()) ? user.getLastLoginTime() : "-" %>
                            </td>
                            <td>
                                <div style="display: flex; gap: 8px; flex-wrap: wrap;">
                                    <a href="<%= request.getContextPath() %>/admin/users/edit?username=<%= user.getUsername() %>" class="btn btn-sm btn-outline" style="color: var(--primary-color); border-color: var(--primary-color);">编辑</a>
                                    <form action="<%= request.getContextPath() %>/admin/users/blacklist" method="post" style="display: inline;">
                                        <input type="hidden" name="username" value="<%= user.getUsername() %>" />
                                        <% if (user.isBlacklisted()) { %>
                                            <input type="hidden" name="action" value="remove" />
                                            <button type="submit" class="btn btn-sm btn-outline" style="color: #16a34a; border-color: #16a34a;">移出黑名单</button>
                                        <% } else { %>
                                            <input type="hidden" name="action" value="add" />
                                            <button type="submit" class="btn btn-sm btn-outline" style="color: #dc2626; border-color: #dc2626;">加入黑名单</button>
                                        <% } %>
                                    </form>
                                    <form action="<%= request.getContextPath() %>/admin/users/delete" method="post" style="display: inline;" onsubmit="return confirm('确定要删除用户 <%= user.getUsername() %> 吗?此操作不可撤销。');">
                                        <input type="hidden" name="username" value="<%= user.getUsername() %>" />
                                        <button type="submit" class="btn btn-sm" style="background: #fee2e2; color: #dc2626;">删除</button>
                                    </form>
                                </div>
                            </td>
                        </tr>
                    <% } %>
                </tbody>
            </table>
        </div>

        <!-- 数据库状态提示 -->
        <div style="margin-top: 24px; padding: 16px; background: #eff6ff; border-radius: var(--radius-md); border-left: 4px solid var(--primary-color);">
            <div style="font-weight: 600; color: var(--primary-color); margin-bottom: 4px;">💾 SQL Server 数据库连接状态</div>
            <div style="color: var(--text-muted); font-size: 0.9rem;">
                当前已连接到 SQL Server 数据库。所有用户数据已持久化到数据库,支持完整的增删改查操作。
            </div>
        </div>
    </main>

    <!-- 页脚 -->
    <footer style="background: var(--bg-card); border-top: 1px solid var(--border-color); padding: 24px 0; text-align: center; color: var(--text-muted); font-size: 0.9rem;">
        <div class="container">
            <p>武汉科技大学 · 信管资料库系统</p>
        </div>
    </footer>
</body>
</html>

过程中遇到的问题:

1.数据库无法连接,终端显示报错

2.springboot找不到路径,显示white error 报错

如何解决的问题:

1.未将数据库具体信息放入application.properties,重新进行了ai检查,成功运行,显示该界面

2.spring boot路径问题

遇到的报错是 Spring MVC 在启动时初始化请求映射处理器( requestMappingHandlerMapping )失败,核心原因是多个控制器类或方法定义了完全相同的请求路径(URL),导致框架无法区分该由哪个方法处理请求。

这类问题通常出现在以下场景:

代码生成工具(如 MyBatis Generator、JHipster)生成了多个 Controller,它们的路径前缀或方法路径完全一致;

手动复制粘贴代码后未修改 @RequestMapping 或 @GetMapping 等注解中的路径;

继承或重写父类方法时,子类未覆盖或未修改路径,导致与父类路径冲突。

解决方法如下:

定位冲突的 Controller

查看完整的错误日志(通常在终端或输出窗口),找到类似以下的提示:

Ambiguous mapping. Cannot map 'xxxController' method ... to { /api/xxx}: There is already 'yyyController' bean method ... mapped.这会明确告诉你哪两个 Controller 或方法路径冲突了。

修改路径避免重复

为每个 Controller 添加唯一的前缀,例如:

@RestController

@RequestMapping("/api/user") // 用户模块

public class UserController { ... }

@RestController

@RequestMapping("/api/order") // 订单模块

public class OrderController { ... }

或者在方法级别细化路径,例如:

@GetMapping("/list") // 用户列表

public List listUsers() { ... }

@GetMapping("/orders/list") // 订单列表

public List listOrders() { ... }

检查并清理重复代码

如果你使用了代码生成工具,检查生成的 Controller 是否有重复的类或方法。可以全局搜索 @RequestMapping 或 @GetMapping ,确认没有相同路径的定义。

重启项目验证

修改完成后,重新启动 Spring Boot 应用,观察是否还有报错。如果仍有问题,可尝试清理项目缓存(如 Maven 的 mvn clean 或 Gradle 的 gradle clean )后再启动。

小插曲:本月copilot额度使用完了,但是找到了更加便捷的ai.