feat(admin-server): 添加管理员相关功能
- 新增 Admin 实体类 - 添加 AdminMapper 接口及 XML 配置 - 实现 AdminService 接口及其实现类 - 创建 AdminController 控制器 - 增加全局异常处理器和统一返回结果封装 - 集成 MyBatis-Plus 和 Swagger
This commit is contained in:
parent
3b12e9ece2
commit
8e3e8fc8b8
10
pom.xml
10
pom.xml
|
|
@ -44,6 +44,11 @@
|
|||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-boot-starter</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
||||
|
|
@ -54,6 +59,11 @@
|
|||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.5.12</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package com.example.admin_server;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.example.admin_server.mapper")
|
||||
public class AdminServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
package com.example.admin_server.common;
|
||||
|
||||
import com.example.admin_server.enums.ResultCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
|
||||
/**
|
||||
* 全局异常处理器,统一将异常转换为 Result 返回
|
||||
*/
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
/**
|
||||
* 参数校验异常(@Valid)
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public Result<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
|
||||
String message = ex.getBindingResult().getFieldErrors().stream()
|
||||
.findFirst()
|
||||
.map(err -> err.getField() + " " + err.getDefaultMessage())
|
||||
.orElse(ResultCode.VALIDATE_ERROR.getMsg());
|
||||
log.warn("@Valid参数校验失败: {}", message);
|
||||
return Result.of(ResultCode.VALIDATE_ERROR, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数绑定异常(普通对象绑定)
|
||||
*/
|
||||
@ExceptionHandler(BindException.class)
|
||||
public Result<?> handleBindException(BindException ex) {
|
||||
String message = ex.getFieldErrors().stream()
|
||||
.findFirst()
|
||||
.map(err -> err.getField() + " " + err.getDefaultMessage())
|
||||
.orElse(ResultCode.VALIDATE_ERROR.getMsg());
|
||||
log.warn("参数绑定失败: {}", message);
|
||||
return Result.of(ResultCode.VALIDATE_ERROR, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个参数校验(@Validated)
|
||||
*/
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public Result<?> handleConstraintViolationException(ConstraintViolationException ex) {
|
||||
String message = ex.getConstraintViolations().stream()
|
||||
.findFirst()
|
||||
.map(ConstraintViolation::getMessage)
|
||||
.orElse(ResultCode.VALIDATE_ERROR.getMsg());
|
||||
log.warn("@Validated参数校验失败: {}", message);
|
||||
return Result.of(ResultCode.VALIDATE_ERROR, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求体不可读
|
||||
*/
|
||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
||||
public Result<?> handleHttpMessageNotReadable(HttpMessageNotReadableException ex) {
|
||||
log.warn("消息不可读: {}", ex.getMessage());
|
||||
return Result.of(ResultCode.VALIDATE_ERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 兜底异常
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
public Result<?> handleException(Exception ex) {
|
||||
log.error("系统异常", ex);
|
||||
return Result.of(ResultCode.SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.example.admin_server.common;
|
||||
|
||||
import com.example.admin_server.enums.ResultCode;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Result<T> {
|
||||
|
||||
private Integer code;
|
||||
private String msg;
|
||||
private T data;
|
||||
|
||||
private Result() {}
|
||||
|
||||
/** 成功:无数据 */
|
||||
public static <T> Result<T> ok() {
|
||||
return restResult(null, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
|
||||
}
|
||||
|
||||
/** 成功:有数据 */
|
||||
public static <T> Result<T> ok(T data) {
|
||||
return restResult(data, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
|
||||
}
|
||||
|
||||
/** 成功:指定 msg 和 data */
|
||||
public static <T> Result<T> ok(String msg, T data) {
|
||||
return restResult(data, ResultCode.SUCCESS.getCode(), msg);
|
||||
}
|
||||
|
||||
/** 失败:默认错误码与信息 */
|
||||
public static <T> Result<T> fail() {
|
||||
return restResult(null, ResultCode.FAIL.getCode(), ResultCode.FAIL.getMsg());
|
||||
}
|
||||
|
||||
/** 失败:指定信息 */
|
||||
public static <T> Result<T> fail(String msg) {
|
||||
return restResult(null, ResultCode.FAIL.getCode(), msg);
|
||||
}
|
||||
|
||||
/** 失败:指定错误码与信息 */
|
||||
public static <T> Result<T> fail(Integer code, String msg) {
|
||||
return restResult(null, code, msg);
|
||||
}
|
||||
|
||||
/** 通用:使用枚举返回 */
|
||||
public static <T> Result<T> of(ResultCode resultCode) {
|
||||
return restResult(null, resultCode.getCode(), resultCode.getMsg());
|
||||
}
|
||||
|
||||
/** 通用:使用枚举 + 自定义提示 */
|
||||
public static <T> Result<T> of(ResultCode resultCode, String msg) {
|
||||
return restResult(null, resultCode.getCode(), msg);
|
||||
}
|
||||
|
||||
/** 通用:使用枚举 + 返回数据 */
|
||||
public static <T> Result<T> of(ResultCode resultCode, T data) {
|
||||
return restResult(data, resultCode.getCode(), resultCode.getMsg());
|
||||
}
|
||||
|
||||
/** 统一创建返回结构 */
|
||||
private static <T> Result<T> restResult(T data, int code, String msg) {
|
||||
Result<T> result = new Result<>();
|
||||
result.setCode(code);
|
||||
result.setMsg(msg);
|
||||
result.setData(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 是否成功 */
|
||||
public boolean isSuccess() {
|
||||
return this.code != null && this.code.equals(ResultCode.SUCCESS.getCode());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.example.admin_server.controller.admin;
|
||||
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 后台管理员表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author FallingCliff
|
||||
* @since 2025-05-24
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin")
|
||||
public class AdminController {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.example.admin_server.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ResultCode {
|
||||
|
||||
SUCCESS(200, "成功"),
|
||||
FAIL(500, "失败"),
|
||||
UNAUTHORIZED(401, "未授权"),
|
||||
FORBIDDEN(403, "禁止访问"),
|
||||
NOT_FOUND(404, "资源不存在"),
|
||||
VALIDATE_ERROR(400, "参数校验失败"),
|
||||
SERVER_ERROR(503, "服务器内部错误");
|
||||
|
||||
private final int code;
|
||||
private final String msg;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.example.admin_server.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.admin_server.model.entity.Admin;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 后台管理员表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author FallingCliff
|
||||
* @since 2025-05-24
|
||||
*/
|
||||
public interface AdminMapper extends BaseMapper<Admin> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package com.example.admin_server.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 后台管理员表
|
||||
* </p>
|
||||
*
|
||||
* @author FallingCliff
|
||||
* @since 2025-05-24
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("admin")
|
||||
@ApiModel(value="Admin对象", description="后台管理员表")
|
||||
public class Admin implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty(value = "主键ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "用户名")
|
||||
@TableField("username")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty(value = "密码")
|
||||
@TableField("password")
|
||||
private String password;
|
||||
|
||||
@ApiModelProperty(value = "姓名")
|
||||
@TableField("real_name")
|
||||
private String realName;
|
||||
|
||||
@ApiModelProperty(value = "邮箱")
|
||||
@TableField("email")
|
||||
private String email;
|
||||
|
||||
@ApiModelProperty(value = "手机号")
|
||||
@TableField("phone")
|
||||
private String phone;
|
||||
|
||||
@ApiModelProperty(value = "头像")
|
||||
@TableField("avatar")
|
||||
private String avatar;
|
||||
|
||||
@ApiModelProperty(value = "状态:0禁用,1正常")
|
||||
@TableField("status")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "是否为超级管理员:1是,0否")
|
||||
@TableField("is_super")
|
||||
private Integer isSuper;
|
||||
|
||||
@ApiModelProperty(value = "上次登录IP")
|
||||
@TableField("last_login_ip")
|
||||
private String lastLoginIp;
|
||||
|
||||
@ApiModelProperty(value = "上次登录时间")
|
||||
@TableField("last_login_time")
|
||||
private LocalDateTime lastLoginTime;
|
||||
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
@TableField("create_time")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@ApiModelProperty(value = "更新时间")
|
||||
@TableField("update_time")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.example.admin_server.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.example.admin_server.model.entity.Admin;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 后台管理员表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author FallingCliff
|
||||
* @since 2025-05-24
|
||||
*/
|
||||
public interface IAdminService extends IService<Admin> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.example.admin_server.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.example.admin_server.mapper.AdminMapper;
|
||||
import com.example.admin_server.model.entity.Admin;
|
||||
import com.example.admin_server.service.IAdminService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 后台管理员表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author FallingCliff
|
||||
* @since 2025-05-24
|
||||
*/
|
||||
@Service
|
||||
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements IAdminService {
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.example.admin_server.mapper.AdminMapper">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="com.example.admin_server.model.entity.Admin">
|
||||
<id column="id" property="id" />
|
||||
<result column="username" property="username" />
|
||||
<result column="password" property="password" />
|
||||
<result column="real_name" property="realName" />
|
||||
<result column="email" property="email" />
|
||||
<result column="phone" property="phone" />
|
||||
<result column="avatar" property="avatar" />
|
||||
<result column="status" property="status" />
|
||||
<result column="is_super" property="isSuper" />
|
||||
<result column="last_login_ip" property="lastLoginIp" />
|
||||
<result column="last_login_time" property="lastLoginTime" />
|
||||
<result column="create_time" property="createTime" />
|
||||
<result column="update_time" property="updateTime" />
|
||||
</resultMap>
|
||||
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue