From 2746814257b065da75034c82bc9ada0b9060d58b Mon Sep 17 00:00:00 2001 From: wjl <3533384953@qq.com> Date: Tue, 29 Apr 2025 18:39:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E6=BB=9E=E7=95=99?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/workspace.xml | 1787 +---------------- src/main/java/com/controller/ExpressItem.java | 164 ++ .../java/com/controller/ExpressIteml.java | 261 +++ .../com/controller/UserManagementService.java | 263 +++ src/main/java/com/model/enums/TypeEnum.java | 31 + 5 files changed, 755 insertions(+), 1751 deletions(-) create mode 100644 src/main/java/com/controller/ExpressItem.java create mode 100644 src/main/java/com/controller/ExpressIteml.java create mode 100644 src/main/java/com/controller/UserManagementService.java create mode 100644 src/main/java/com/model/enums/TypeEnum.java diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 827e8be..fe74ca6 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -11,1747 +11,28 @@ + + - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - { + "keyToString": { + "ModuleVcsDetector.initialDetectionPerformed": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "Tomcat 服务器.Tomcat9.executor": "Run", + "git-widget-placeholder": "main", + "kotlin-language-version-configured": "true", + "last_opened_file_path": "C:/Users/Administrator/Desktop/合肥师范学院/ssm076校园快递一站式服务系统+jsp/kuaidizhan/src/main/java/com", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "project.structure.last.edited": "工件", + "project.structure.proportion": "0.15", + "project.structure.side.proportion": "0.2", + "settings.editor.selected.configurable": "configurable.group.tools", + "vue.rearranger.settings.migration": "true" } -}]]> +} + + + + @@ -1908,7 +193,7 @@ - + diff --git a/src/main/java/com/controller/ExpressItem.java b/src/main/java/com/controller/ExpressItem.java new file mode 100644 index 0000000..ad75901 --- /dev/null +++ b/src/main/java/com/controller/ExpressItem.java @@ -0,0 +1,164 @@ +import java.util.*; + +// 快递实体类(POJO) +class ExpressItem { + private String trackingNumber; // 运单号 + private String recipient; // 收件人 + private String phone; // 联系电话 + private String status; // 包裹状态 + private Date arrivalTime; // 到站时间 + private String pickupCode; // 取件码 + + public ExpressItem(String trackingNumber, String recipient, String phone) { + this.trackingNumber = trackingNumber; + this.recipient = recipient; + this.phone = phone; + this.status = "待取件"; // 默认状态 + this.arrivalTime = new Date(); + this.pickupCode = generatePickupCode(); // 自动生成取件码 + } + + // 生成4位随机取件码(0000-9999) + private String generatePickupCode() { + Random random = new Random(); + return String.format("%04d", random.nextInt(10000)); + } + + // Getter/Setter 区域(省略其他getter/setter) + public String getStatus() { return status; } + public String getPickupCode() { return pickupCode; } + // ...其他getter/setter保持原有结构 + + @Override + public String toString() { + return String.format(""" + 运单号:%s + 收件人:%s + 状态:%s + 取件码:%s + 到达时间:%tF %tT + """, trackingNumber, recipient, status, pickupCode, arrivalTime, arrivalTime); + } +} + +// 快递业务逻辑类 +class ExpressService { + private final Map database = new HashMap<>(); // 内存数据库 + private int totalPackages = 0; // 总入库计数器 + + // 快递入库(返回是否成功) + public boolean addPackage(ExpressItem item) { + if (database.containsKey(item.getTrackingNumber())) return false; // 重复检查 + database.put(item.getTrackingNumber(), item); + totalPackages++; + return true; + } + + // 标记包裹为已取件 + public boolean markAsPickedUp(String trackingNumber) { + ExpressItem item = database.get(trackingNumber); + if (item != null && "待取件".equals(item.getStatus())) { // 双重验证 + item.setStatus("已取件"); + return true; + } + return false; + } + + // 统计方法 + public int getTotalPackages() { return totalPackages; } + public int getPendingPackages() { + return (int) database.values().stream() // 使用流式计算 + .filter(item -> "待取件".equals(item.getStatus())) + .count(); + } +} + +// 控制台交互层 +public class ExpressManagementSystem { + private static final Scanner scanner = new Scanner(System.in); + private static final ExpressService service = new ExpressService(); + + public static void main(String[] args) { + while (true) { + printMenu(); + int choice = getIntInput("请选择操作:"); + + switch (choice) { + case 1 -> addPackage(); + case 2 -> pickupPackage(); + case 3 -> searchPackage(); + case 4 -> showStatistics(); + case 5 -> System.exit(0); + default -> System.out.println("无效输入!"); + } + } + } + + private static void printMenu() { + System.out.println(""" + ===== 快递站管理系统 ===== + 1. 快递入库 + 2. 快递出库 + 3. 查询快递 + 4. 统计信息 + 5. 退出系统 + """); + } + + private static void addPackage() { + System.out.println("\n--- 快递入库 ---"); + String trackingNumber = getNonEmptyInput("请输入运单号:"); + String recipient = getNonEmptyInput("请输入收件人姓名:"); + String phone = getValidPhone(); + + ExpressItem newItem = new ExpressItem(trackingNumber, recipient, phone); + System.out.println(service.addPackage(newItem) + ? "入库成功!\n取件码:" + newItem.getPickupCode() + : "该运单号已存在!"); + } + + private static void pickupPackage() { + System.out.println("\n--- 快递出库 ---"); + String trackingNumber = getNonEmptyInput("请输入运单号:"); + String inputCode = getNonEmptyInput("请输入取件码:"); + + ExpressItem item = service.getPackage(trackingNumber); + if (item == null) { + System.out.println("运单号不存在!"); + return; + } + + System.out.println(inputCode.equals(item.getPickupCode()) + ? service.markAsPickedUp(trackingNumber) + ? "取件成功!" + : "该包裹已取件!" + : "取件码错误!"); + } + + // 辅助方法区域 + private static String getNonEmptyInput(String prompt) { + while (true) { + String input = scanner.nextLine().trim(); + if (!input.isEmpty()) return input; + System.out.print("输入不能为空,请重新输入:"); + } + } + + private static String getValidPhone() { + while (true) { + String phone = scanner.nextLine().trim(); + if (phone.matches("1[3-9]\\d{9}")) return phone; // 中国手机号正则 + System.out.print("手机号格式不正确,请重新输入:"); + } + } + + private static int getIntInput(String prompt) { + while (true) { + try { + return Integer.parseInt(scanner.nextLine().trim()); + } catch (NumberFormatException e) { + System.out.print("请输入有效数字:"); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/controller/ExpressIteml.java b/src/main/java/com/controller/ExpressIteml.java new file mode 100644 index 0000000..71107e0 --- /dev/null +++ b/src/main/java/com/controller/ExpressIteml.java @@ -0,0 +1,261 @@ +import java.io.*; +import java.util.*; +import java.util.stream.Collectors; +import com.google.gson.Gson; // 需要gson库支持(添加依赖) + +/** + * 快递实体类增强版 + * 新增:包裹重量、尺寸、存放天数等属性 + */ +class ExpressIteml { + // ... [原有属性保持不变] + private double weight; // 包裹重量(kg) + private Dimension dimension; // 包裹尺寸(cm) + private int storageDays; // 存放天数 + + public ExpressItem(String trackingNumber, String recipient, String phone, + double weight, int length, int width, int height) { + // ... [原有初始化代码] + this.weight = weight; + this.dimension = new Dimension(length, width, height); + this.storageDays = 0; + } + + // 新增内部类:包裹尺寸 + static class Dimension { + int length; + int width; + int height; + + Dimension(int l, int w, int h) { + this.length = l; + this.width = w; + this.height = h; + } + + @Override + public String toString() { + return String.format("%dx%dx%d cm", length, width, height); + } + } + + // 新增业务方法:计算体积重量(航空件常用算法) + public double calculateVolumetricWeight() { + // 体积重量(kg) = 长(cm)*宽(cm)*高(cm)/6000 + return (dimension.length * dimension.width * dimension.height) / 6000.0; + } + + // Getter/Setter 区域(新增属性) + public double getWeight() { return weight; } + public Dimension getDimension() { return dimension; } + public int getStorageDays() { return storageDays; } + public void setStorageDays(int days) { this.storageDays = days; } +} + +/** + * 快递业务逻辑增强版 + * 新增:数据持久化、超时提醒、高级查询等功能 + */ +class ExpressService { + // ... [原有属性保持不变] + private final DataPersistence persistence = new DataPersistence(); + private static final int MAX_STORAGE_DAYS = 7; // 最大免费存放天数 + + public ExpressService() { + // 启动时加载持久化数据 + database = persistence.loadData(); + // 更新所有包裹的存放天数(模拟每日自动更新) + updateStorageDays(); + } + + // 新增方法:更新所有包裹的存放天数 + private void updateStorageDays() { + long today = new Date().getTime() / (24 * 3600 * 1000); + database.values().forEach(item -> { + long arrivalDay = item.getArrivalTime().getTime() / (24 * 3600 * 1000); + item.setStorageDays((int) (today - arrivalDay)); + }); + } + + // 新增方法:获取超时包裹列表 + public List getOverduePackages() { + return database.values().stream() + .filter(item -> item.getStorageDays() > MAX_STORAGE_DAYS) + .collect(Collectors.toList()); + } + + // 新增方法:按体积重量排序查询 + public List searchByVolumetricWeight(double min, double max) { + return database.values().stream() + .filter(item -> { + double volWeight = item.calculateVolumetricWeight(); + return volWeight >= min && volWeight <= max; + }) + .sorted(Comparator.comparingDouble(ExpressItem::calculateVolumetricWeight).reversed()) + .collect(Collectors.toList()); + } + + // 新增方法:批量标记为已取件 + public int batchMarkAsPickedUp(List trackingNumbers) { + return (int) trackingNumbers.stream() + .filter(tn -> { + ExpressItem item = database.get(tn); + return item != null && "待取件".equals(item.getStatus()); + }) + .peek(tn -> database.get(tn).setStatus("已取件")) + .count(); + } + + // 新增方法:获取仓库使用率统计 + public Map getStorageUsage() { + Map usage = new HashMap<>(); + long totalVolume = database.values().stream() + .mapToLong(item -> + item.getDimension().length * + item.getDimension().width * + item.getDimension().height + ).sum(); + + usage.put("totalVolume", (double) totalVolume); + usage.put("averageVolume", totalVolume / (double) database.size()); + return usage; + } + + // 新增方法:数据持久化 + public void saveData() { + persistence.saveData(database); + } +} + +/** + * 数据持久化服务类 + * 使用JSON格式进行数据存储 + */ +class DataPersistence { + private static final String DATA_FILE = "express_data.json"; + private final Gson gson = new Gson(); + + public Map loadData() { + try (Reader reader = new FileReader(DATA_FILE)) { + Type type = new com.google.gson.reflect.TypeToken>() {}.getType(); + return gson.fromJson(reader, type); + } catch (FileNotFoundException e) { + return new HashMap<>(); // 首次运行无数据文件 + } catch (Exception e) { + System.err.println("数据加载错误: " + e.getMessage()); + return new HashMap<>(); + } + } + + public void saveData(Map data) { + try (Writer writer = new FileWriter(DATA_FILE)) { + gson.toJson(data, writer); + } catch (Exception e) { + System.err.println("数据保存错误: " + e.getMessage()); + } + } +} + +/** + * 控制台交互层增强版 + * 新增:超时提醒、批量操作、数据统计等功能 + */ +public class ExpressManagementSystem { + // ... [原有属性保持不变] + private static final ExpressService service = new ExpressService(); + + private static void printAdvancedMenu() { + System.out.println(""" + ===== 高级功能菜单 ===== + 6. 批量取件操作 + 7. 查询超时包裹 + 8. 体积重量查询 + 9. 仓库使用统计 + 10. 保存并退出 + """); + } + + private static void batchPickup() { + System.out.println("\n--- 批量取件 ---"); + List trackingNumbers = new ArrayList<>(); + while (true) { + String tn = getNonEmptyInput("输入运单号(输入0结束):"); + if ("0".equals(tn)) break; + trackingNumbers.add(tn); + } + + int successCount = service.batchMarkAsPickedUp(trackingNumbers); + System.out.printf("成功取件%d个包裹\n", successCount); + } + + private static void showOverduePackages() { + System.out.println("\n--- 超时包裹列表 ---"); + List overdue = service.getOverduePackages(); + if (overdue.isEmpty()) { + System.out.println("当前没有超时包裹"); + return; + } + overdue.forEach(item -> + System.out.printf("运单号:%s 超时%d天\n", + item.getTrackingNumber(), + item.getStorageDays() - ExpressService.MAX_STORAGE_DAYS)); + } + + private static void volumetricSearch() { + System.out.println("\n--- 体积重量查询 ---"); + double min = getDoubleInput("最小体积重量(kg):"); + double max = getDoubleInput("最大体积重量(kg):"); + + List results = service.searchByVolumetricWeight(min, max); + if (results.isEmpty()) { + System.out.println("未找到匹配包裹"); + return; + } + results.forEach(item -> + System.out.printf("运单号:%s 体积重量:%.2fkg\n", + item.getTrackingNumber(), + item.calculateVolumetricWeight())); + } + + private static void showStorageStats() { + System.out.println("\n--- 仓库使用统计 ---"); + Map stats = service.getStorageUsage(); + System.out.printf("总占用体积:%,d cm³\n", stats.get("totalVolume").intValue()); + System.out.printf("平均单件体积:%,.1f cm³\n", stats.get("averageVolume")); + } + + public static void main(String[] args) { + while (true) { + printMenu(); + int choice = getIntInput("请选择操作:"); + + switch (choice) { + case 1 -> addPackage(); + case 2 -> pickupPackage(); + case 3 -> searchPackage(); + case 4 -> showStatistics(); + case 5 -> printAdvancedMenu(); + case 6 -> batchPickup(); + case 7 -> showOverduePackages(); + case 8 -> volumetricSearch(); + case 9 -> showStorageStats(); + case 10 -> { + service.saveData(); + System.exit(0); + } + default -> System.out.println("无效输入!"); + } + } + } + + // 新增方法:获取double类型输入 + private static double getDoubleInput(String prompt) { + while (true) { + try { + return Double.parseDouble(scanner.nextLine().trim()); + } catch (NumberFormatException e) { + System.out.print("请输入有效数字:"); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/controller/UserManagementService.java b/src/main/java/com/controller/UserManagementService.java new file mode 100644 index 0000000..a5b0475 --- /dev/null +++ b/src/main/java/com/controller/UserManagementService.java @@ -0,0 +1,263 @@ +import java.security.*; +import java.util.*; +import java.util.regex.*; +import javax.crypto.*; +import javax.crypto.spec.SecretKeySpec; + +/** + * 用户管理服务类 + * 实现功能:用户注册/登录、角色权限管理、密码安全、会话管理 + */ +class UserManagementService { + // 内存存储结构(实际项目应使用数据库) + private final Map userDatabase = new HashMap<>(); + private final Map activeSessions = new HashMap<>(); + private static final String SECRET_KEY = "express@Sys#Key2025"; // 加密密钥(生产环境应存储在安全配置) + + /** + * 用户注册 + * @param username 用户名(4-16位字母数字) + * @param password 明文密码(需符合复杂度要求) + * @param role 用户角色(admin/staff/customer) + * @return 注册结果 + */ + public RegistrationResult registerUser(String username, String password, String role) + throws NoSuchAlgorithmException, InvalidKeySpecException { + + // 1. 参数验证 + if (!isValidUsername(username)) { + return new RegistrationResult(false, "用户名需为4-16位字母数字"); + } + if (userDatabase.containsKey(username)) { + return new RegistrationResult(false, "用户名已存在"); + } + if (!isValidPassword(password)) { + return new RegistrationResult(false, "密码需包含大小写字母和数字,至少8位"); + } + if (!isValidRole(role)) { + return new RegistrationResult(false, "无效角色类型"); + } + + // 2. 密码加密处理 + String salt = generateSalt(); + String hashedPwd = hashPassword(password, salt); + + // 3. 创建用户对象 + User newUser = new User(username, hashedPwd, salt, role); + userDatabase.put(username, newUser); + return new RegistrationResult(true, "注册成功", newUser); + } + + /** + * 用户登录认证 + * @param username 用户名 + * @param password 明文密码 + * @return 认证结果(含会话令牌) + */ + public AuthenticationResult authenticate(String username, String password) + throws NoSuchAlgorithmException, InvalidKeySpecException { + + User user = userDatabase.get(username); + if (user == null) { + return new AuthenticationResult(false, "用户不存在"); + } + + // 验证密码 + String testHash = hashPassword(password, user.getSalt()); + if (!testHash.equals(user.getHashedPassword())) { + return new AuthenticationResult(false, "密码错误"); + } + + // 生成会话令牌(JWT风格) + String token = generateSessionToken(username); + activeSessions.put(token, new Session(token, username, new Date())); + + return new AuthenticationResult(true, "认证成功", token); + } + + /** + * 密码复杂度验证 + * @param password 待验证密码 + * @return 是否符合复杂度要求 + */ + private boolean isValidPassword(String password) { + if (password.length() < 8) return false; + + boolean hasUpper = false, hasLower = false, hasDigit = false; + for (char c : password.toCharArray()) { + if (Character.isUpperCase(c)) hasUpper = true; + else if (Character.isLowerCase(c)) hasLower = true; + else if (Character.isDigit(c)) hasDigit = true; + } + return hasUpper && hasLower && hasDigit; + } + + /** + * 生成加密盐值(16字节随机数) + */ + private String generateSalt() { + SecureRandom random = new SecureRandom(); + byte[] salt = new byte[16]; + random.nextBytes(salt); + return Base64.getEncoder().encodeToString(salt); + } + + /** + * PBKDF2密码哈希算法 + */ + private String hashPassword(String password, String salt) + throws NoSuchAlgorithmException, InvalidKeySpecException { + + int iterations = 10000; + int keyLength = 256; + char[] passwordChars = password.toCharArray(); + byte[] saltBytes = Base64.getDecoder().decode(salt); + + PBEKeySpec spec = new PBEKeySpec(passwordChars, saltBytes, iterations, keyLength); + SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); + byte[] hash = skf.generateSecret(spec).getEncoded(); + + return String.format("%d$%s$%s", + iterations, + Base64.getEncoder().encodeToString(saltBytes), + Base64.getEncoder().encodeToString(hash)); + } + + /** + * 会话令牌生成(HMAC-SHA256) + */ + private String generateSessionToken(String username) { + try { + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(SECRET_KEY.getBytes(), "HmacSHA256"); + sha256_HMAC.init(secret_key); + + String baseString = username + new Date().getTime(); + return Base64.getEncoder().encodeToString( + sha256_HMAC.doFinal(baseString.getBytes()) + ); + } catch (Exception e) { + throw new RuntimeException("令牌生成失败", e); + } + } + + /** + * 用户角色验证装饰器 + * @param requiredRole 所需权限等级 + */ + public static class RoleValidator { + private final String currentRole; + + public RoleValidator(String sessionToken) { + // 实际应从会话中获取用户角色 + this.currentRole = "customer"; // 示例值 + } + + public void validate(String requiredRole) throws InsufficientPermissionsException { + if (!currentRole.equals(requiredRole)) { + throw new InsufficientPermissionsException( + String.format("需要%s权限,当前角色:%s", requiredRole, currentRole)); + } + } + } + + /** + * 用户实体类 + */ + static class User { + private final String username; + private final String hashedPassword; + private final String salt; + private final String role; + + User(String username, String hashedPassword, String salt, String role) { + this.username = username; + this.hashedPassword = hashedPassword; + this.salt = salt; + this.role = role; + } + + // Getter方法(根据安全需求限制访问) + public String getUsername() { return username; } + public String getHashedPassword() { return hashedPassword; } + public String getSalt() { return salt; } + public String getRole() { return role; } + } + + /** + * 会话管理类 + */ + static class Session { + private final String token; + private final String username; + private final Date createdAt; + + Session(String token, String username, Date createdAt) { + this.token = token; + this.username = username; + this.createdAt = createdAt; + } + + // Getter方法 + public String getToken() { return token; } + public String getUsername() { return username; } + public Date getCreatedAt() { return createdAt; } + } + + /** + * 注册结果封装类 + */ + static class RegistrationResult { + private final boolean success; + private final String message; + private final User user; + + RegistrationResult(boolean success, String message) { + this(success, message, null); + } + + RegistrationResult(boolean success, String message, User user) { + this.success = success; + this.message = message; + this.user = user; + } + + // Getter方法 + public boolean isSuccess() { return success; } + public String getMessage() { return message; } + public User getUser() { return user; } + } + + /** + * 认证结果封装类 + */ + static class AuthenticationResult { + private final boolean success; + private final String message; + private final String token; + + AuthenticationResult(boolean success, String message) { + this(success, message, null); + } + + AuthenticationResult(boolean success, String message, String token) { + this.success = success; + this.message = message; + this.token = token; + } + + // Getter方法 + public boolean isSuccess() { return success; } + public String getMessage() { return message; } + public String getToken() { return token; } + } + + /** + * 权限不足异常 + */ + static class InsufficientPermissionsException extends SecurityException { + public InsufficientPermissionsException(String message) { + super(message); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/model/enums/TypeEnum.java b/src/main/java/com/model/enums/TypeEnum.java new file mode 100644 index 0000000..39061d8 --- /dev/null +++ b/src/main/java/com/model/enums/TypeEnum.java @@ -0,0 +1,31 @@ +package com.model.enums; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.enums.IEnum; + +/** + * 必须现在 IEnum 配置 该包扫描自动注入,查看文件 spring-mybatis.xml 参数 typeEnumsPackage + */ +public enum TypeEnum implements IEnum { + DISABLED(0, "禁用"), + NORMAL(1, "正常"); + + private final int value; + private final String desc; + + TypeEnum(final int value, final String desc) { + this.value = value; + this.desc = desc; + } + + @Override + public Serializable getValue() { + return this.value; + } + + // Jackson 注解为 JsonValue 返回中文 json 描述 + public String getDesc() { + return this.desc; + } +}