feat: standardize backend API with unified response and Swagger

- 完善 HttpStatus 添加业务错误码常量(用户/权限/数据/系统/文件/业务模块)
- 完善 BaseController 添加 success(Object data) 方法
- 完善 TableDataInfo 添加 long 类型和带状态码的构造函数
- 增强 GlobalExceptionHandler 添加更多异常处理(参数缺失/解析失败/资源未找到)
- 优化 SwaggerConfig 添加多模块分组支持(系统/监控/图书/股票)
- 为 SysUserController 和 AccountController 添加完整的 Swagger 注解
feature/20260628/refactor-frontend-modernization
Lxy 3 weeks ago
parent f4b034970b
commit 6c8511f7e8

@ -20,6 +20,10 @@ import com.ruoyi.booksystem.domain.Account;
import com.ruoyi.booksystem.service.IAccountService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
/**
* Controller
@ -27,6 +31,7 @@ import com.ruoyi.common.core.page.TableDataInfo;
* @author ruoyi
* @date 2023-12-18
*/
@Api(tags = "交易账户管理")
@RestController
@RequestMapping("/booksystem/account")
public class AccountController extends BaseController
@ -37,6 +42,7 @@ public class AccountController extends BaseController
/**
*
*/
@ApiOperation("查询交易账户列表")
@PreAuthorize("@ss.hasPermi('booksystem:account:list')")
@GetMapping("/list")
public TableDataInfo list(Account account)
@ -49,6 +55,7 @@ public class AccountController extends BaseController
/**
*
*/
@ApiOperation("导出交易账户数据")
@PreAuthorize("@ss.hasPermi('booksystem:account:export')")
@Log(title = "交易账户", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ -62,6 +69,8 @@ public class AccountController extends BaseController
/**
*
*/
@ApiOperation("获取交易账户详细信息")
@ApiImplicitParam(name = "id", value = "账户ID", required = true, dataType = "Long", paramType = "path", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermi('booksystem:account:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
@ -72,6 +81,7 @@ public class AccountController extends BaseController
/**
*
*/
@ApiOperation("新增交易账户")
@PreAuthorize("@ss.hasPermi('booksystem:account:add')")
@Log(title = "交易账户", businessType = BusinessType.INSERT)
@PostMapping
@ -83,6 +93,7 @@ public class AccountController extends BaseController
/**
*
*/
@ApiOperation("修改交易账户")
@PreAuthorize("@ss.hasPermi('booksystem:account:edit')")
@Log(title = "交易账户", businessType = BusinessType.UPDATE)
@PutMapping
@ -94,6 +105,8 @@ public class AccountController extends BaseController
/**
*
*/
@ApiOperation("删除交易账户")
@ApiImplicitParam(name = "ids", value = "账户ID列表", required = true, dataType = "Long[]", paramType = "path")
@PreAuthorize("@ss.hasPermi('booksystem:account:remove')")
@Log(title = "交易账户", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")

@ -30,12 +30,17 @@ import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
/**
*
*
* @author ruoyi
*/
@Api(tags = "用户管理")
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController
@ -52,6 +57,7 @@ public class SysUserController extends BaseController
/**
*
*/
@ApiOperation("查询用户列表")
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/list")
public TableDataInfo list(SysUser user)
@ -61,6 +67,7 @@ public class SysUserController extends BaseController
return getDataTable(list);
}
@ApiOperation("导出用户数据")
@Log(title = "用户管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:user:export')")
@PostMapping("/export")
@ -71,6 +78,7 @@ public class SysUserController extends BaseController
util.exportExcel(response, list, "用户数据");
}
@ApiOperation("导入用户数据")
@Log(title = "用户管理", businessType = BusinessType.IMPORT)
@PreAuthorize("@ss.hasPermi('system:user:import')")
@PostMapping("/importData")
@ -83,6 +91,7 @@ public class SysUserController extends BaseController
return AjaxResult.success(message);
}
@ApiOperation("下载用户导入模板")
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response)
{
@ -93,6 +102,8 @@ public class SysUserController extends BaseController
/**
*
*/
@ApiOperation("获取用户详细信息")
@ApiImplicitParam(name = "userId", value = "用户ID", dataType = "Long", paramType = "path", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping(value = { "/", "/{userId}" })
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
@ -114,6 +125,7 @@ public class SysUserController extends BaseController
/**
*
*/
@ApiOperation("新增用户")
@PreAuthorize("@ss.hasPermi('system:user:add')")
@Log(title = "用户管理", businessType = BusinessType.INSERT)
@PostMapping
@ -141,6 +153,7 @@ public class SysUserController extends BaseController
/**
*
*/
@ApiOperation("修改用户")
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping
@ -164,6 +177,7 @@ public class SysUserController extends BaseController
/**
*
*/
@ApiOperation("删除用户")
@PreAuthorize("@ss.hasPermi('system:user:remove')")
@Log(title = "用户管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{userIds}")
@ -179,6 +193,7 @@ public class SysUserController extends BaseController
/**
*
*/
@ApiOperation("重置用户密码")
@PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/resetPwd")
@ -193,6 +208,7 @@ public class SysUserController extends BaseController
/**
*
*/
@ApiOperation("修改用户状态")
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/changeStatus")
@ -206,6 +222,8 @@ public class SysUserController extends BaseController
/**
*
*/
@ApiOperation("获取用户授权角色")
@ApiImplicitParam(name = "userId", value = "用户ID", dataType = "Long", paramType = "path", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping("/authRole/{userId}")
public AjaxResult authRole(@PathVariable("userId") Long userId)
@ -221,6 +239,11 @@ public class SysUserController extends BaseController
/**
*
*/
@ApiOperation("用户授权角色")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户ID", dataType = "Long", paramType = "query", dataTypeClass = Long.class),
@ApiImplicitParam(name = "roleIds", value = "角色ID列表", dataType = "Long[]", paramType = "query")
})
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.GRANT)
@PutMapping("/authRole")

@ -43,7 +43,68 @@ public class SwaggerConfig
private String pathMapping;
/**
* API
* API
*/
@Bean
public Docket createSystemApi()
{
return createDocket("系统管理", "com.ruoyi.web.controller.system", pathMapping);
}
/**
* API
*/
@Bean
public Docket createMonitorApi()
{
return createDocket("系统监控", "com.ruoyi.web.controller.monitor", pathMapping);
}
/**
* API
*/
@Bean
public Docket createBookSystemApi()
{
return createDocket("图书系统", "com.ruoyi.booksystem.controller", pathMapping);
}
/**
* API
*/
@Bean
public Docket createStockSystemApi()
{
return createDocket("股票系统", "com.ruoyi.stocksystem.controller", pathMapping);
}
/**
* API
*/
private Docket createDocket(String groupName, String basePackage, String pathMapping)
{
return new Docket(DocumentationType.OAS_30)
.groupName(groupName)
// 是否启用Swagger
.enable(enabled)
// 用来创建该API的基本信息展示在文档的页面中自定义展示的信息
.apiInfo(apiInfo())
// 设置哪些接口暴露给Swagger展示
.select()
// 扫描所有有注解的api用这种方式更灵活
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
// 扫描指定包
.apis(RequestHandlerSelectors.basePackage(basePackage))
.paths(PathSelectors.any())
.build()
/* 设置安全模式swagger可以设置访问token */
.securitySchemes(securitySchemes())
.securityContexts(securityContexts())
.pathMapping(pathMapping);
}
/**
* API
*/
@Bean
public Docket createRestApi()
@ -115,7 +176,7 @@ public class SwaggerConfig
// 设置标题
.title("标题摸金分析系统_接口文档")
// 描述
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
.description("描述:若依管理系统后端 API 接口文档,包含系统管理、系统监控、图书系统、股票系统等模块。")
// 作者信息
.contact(new Contact(ruoyiConfig.getName(), null, null))
// 版本

@ -86,4 +86,63 @@ public class HttpStatus
*
*/
public static final int NOT_IMPLEMENTED = 501;
/**
*
*/
public static final int WARN = 601;
// ==================== 业务错误码 (1000-9999) ====================
/**
* (1000-1999)
*/
public static final int USER_NOT_FOUND = 1001;
public static final int USER_PASSWORD_ERROR = 1002;
public static final int USER_ACCOUNT_DISABLED = 1003;
public static final int USER_ACCOUNT_LOCKED = 1004;
public static final int USER_ALREADY_EXISTS = 1005;
public static final int USER_CAPTCHA_ERROR = 1006;
public static final int USER_CAPTCHA_EXPIRED = 1007;
/**
* (2000-2999)
*/
public static final int PERMISSION_DENIED = 2001;
public static final int ROLE_NOT_FOUND = 2002;
public static final int MENU_NOT_FOUND = 2003;
public static final int DEPT_NOT_FOUND = 2004;
public static final int POST_NOT_FOUND = 2005;
/**
* (3000-3999)
*/
public static final int DATA_NOT_FOUND = 3001;
public static final int DATA_ALREADY_EXISTS = 3002;
public static final int DATA_FORMAT_ERROR = 3003;
public static final int DATA_VALIDATION_FAILED = 3004;
/**
* (4000-4999)
*/
public static final int CONFIG_NOT_FOUND = 4001;
public static final int DICT_NOT_FOUND = 4002;
public static final int NOTICE_NOT_FOUND = 4003;
/**
* (5000-5999)
*/
public static final int FILE_UPLOAD_FAILED = 5001;
public static final int FILE_TYPE_NOT_ALLOWED = 5002;
public static final int FILE_SIZE_EXCEEDED = 5003;
public static final int FILE_NOT_FOUND = 5004;
/**
* (6000-6999)
*/
public static final int ACCOUNT_NOT_FOUND = 6001;
public static final int ACCOUNT_ALREADY_EXISTS = 6002;
public static final int ACCOUNT_BALANCE_INSUFFICIENT = 6003;
public static final int STOCK_NOT_FOUND = 6004;
public static final int OPERATION_FAILED = 6005;
}

@ -106,6 +106,14 @@ public class BaseController
return AjaxResult.success(message);
}
/**
*
*/
public AjaxResult success(Object data)
{
return AjaxResult.success(data);
}
/**
*
*/

@ -43,6 +43,34 @@ public class TableDataInfo implements Serializable
this.total = total;
}
/**
* long
*
* @param list
* @param total
*/
public TableDataInfo(List<?> list, long total)
{
this.rows = list;
this.total = total;
}
/**
*
*
* @param list
* @param total
* @param code
* @param msg
*/
public TableDataInfo(List<?> list, long total, int code, String msg)
{
this.rows = list;
this.total = total;
this.code = code;
this.msg = msg;
}
public long getTotal()
{
return total;

@ -5,10 +5,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.resource.NoResourceFoundException;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.DemoModeException;
@ -111,4 +114,45 @@ public class GlobalExceptionHandler
{
return AjaxResult.error("演示模式,不允许操作");
}
/**
*
*/
@ExceptionHandler(MissingServletRequestParameterException.class)
public AjaxResult handleMissingServletRequestParameterException(MissingServletRequestParameterException e)
{
log.error("请求参数缺失: {}", e.getParameterName());
return AjaxResult.error("请求参数缺失: " + e.getParameterName());
}
/**
*
*/
@ExceptionHandler(HttpMessageNotReadableException.class)
public AjaxResult handleHttpMessageNotReadableException(HttpMessageNotReadableException e)
{
log.error("请求参数解析失败: {}", e.getMessage());
return AjaxResult.error("请求参数格式错误");
}
/**
*
*/
@ExceptionHandler(NoResourceFoundException.class)
public AjaxResult handleNoResourceFoundException(NoResourceFoundException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',资源未找到", requestURI);
return AjaxResult.error(HttpStatus.NOT_FOUND, "请求资源不存在");
}
/**
*
*/
@ExceptionHandler(IllegalArgumentException.class)
public AjaxResult handleIllegalArgumentException(IllegalArgumentException e)
{
log.error("非法参数: {}", e.getMessage());
return AjaxResult.error(e.getMessage());
}
}

Loading…
Cancel
Save