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

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

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.