提交 a62b1f28 作者: 方治民

feat: 分离用户菜单权限树查询接口、快速失败状态异常类型及全局处理、新增通用类型集合转换工具方法、hutool-json 换成 fastjson 依赖等细节优化处理

上级 353782a9
...@@ -30,4 +30,7 @@ dependencies { ...@@ -30,4 +30,7 @@ dependencies {
implementation project(":basic-common:minio") implementation project(":basic-common:minio")
// FIX: minio dep // FIX: minio dep
implementation "com.squareup.okhttp3:okhttp:${okhttpVersion}" implementation "com.squareup.okhttp3:okhttp:${okhttpVersion}"
// fastjson
implementation "com.alibaba:fastjson:${fastJsonVersion}"
} }
...@@ -6,6 +6,7 @@ import com.yiring.app.constant.Code; ...@@ -6,6 +6,7 @@ import com.yiring.app.constant.Code;
import com.yiring.app.exception.CodeException; import com.yiring.app.exception.CodeException;
import com.yiring.common.core.Result; import com.yiring.common.core.Result;
import com.yiring.common.core.Status; import com.yiring.common.core.Status;
import com.yiring.common.exception.FailStatusException;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException; import javax.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -33,7 +34,7 @@ public class GlobalExceptionHandler { ...@@ -33,7 +34,7 @@ public class GlobalExceptionHandler {
* 参数校验异常 * 参数校验异常
* *
* @param e 异常信息 * @param e 异常信息
* @return 统一的校验失败信息 {@link Status#BAD_REQUEST * @return 统一的校验失败信息 {@link Status#EXPECTATION_FAILED
*/ */
@ExceptionHandler( @ExceptionHandler(
value = { BindException.class, MethodArgumentNotValidException.class, ConstraintViolationException.class } value = { BindException.class, MethodArgumentNotValidException.class, ConstraintViolationException.class }
...@@ -57,7 +58,7 @@ public class GlobalExceptionHandler { ...@@ -57,7 +58,7 @@ public class GlobalExceptionHandler {
} }
} }
return Result.no(Status.BAD_REQUEST, error); return Result.no(Status.EXPECTATION_FAILED, error);
} }
/** /**
...@@ -74,7 +75,6 @@ public class GlobalExceptionHandler { ...@@ -74,7 +75,6 @@ public class GlobalExceptionHandler {
/** /**
* 未登录异常(鉴权失败) * 未登录异常(鉴权失败)
* *
* @param e 异常信息
* @return 异常信息反馈 {@link Status#UNAUTHORIZED * @return 异常信息反馈 {@link Status#UNAUTHORIZED
*/ */
@ExceptionHandler(value = NotLoginException.class) @ExceptionHandler(value = NotLoginException.class)
...@@ -83,12 +83,6 @@ public class GlobalExceptionHandler { ...@@ -83,12 +83,6 @@ public class GlobalExceptionHandler {
} }
/** /**
* 取消请求异常(忽略)
*/
@ExceptionHandler(value = ClientAbortException.class)
public void clientAbortExceptionHandler() {}
/**
* 自定义业务异常 * 自定义业务异常
*/ */
@ExceptionHandler(value = CodeException.class) @ExceptionHandler(value = CodeException.class)
...@@ -98,6 +92,20 @@ public class GlobalExceptionHandler { ...@@ -98,6 +92,20 @@ public class GlobalExceptionHandler {
} }
/** /**
* 失败状态异常
*/
@ExceptionHandler(value = FailStatusException.class)
public Result<String> customCodeExceptionHandler(FailStatusException e) {
return Result.no(e.getStatus());
}
/**
* 取消请求异常(忽略)
*/
@ExceptionHandler(value = ClientAbortException.class)
public void clientAbortExceptionHandler() {}
/**
* 其他异常 * 其他异常
* *
* @param e 异常信息 * @param e 异常信息
......
spring: spring:
datasource: datasource:
url: jdbc:h2:mem:mockdb;DB_CLOSE_ON_EXIT=FALSE url: jdbc:h2:file:~/h2_basic;DB_CLOSE_ON_EXIT=FALSE
username: sa username: sa
password: 123456 password: 123456
jpa: jpa:
...@@ -35,3 +35,8 @@ minio: ...@@ -35,3 +35,8 @@ minio:
end-point: "http://127.0.0.1:18100" end-point: "http://127.0.0.1:18100"
bucket: basic bucket: basic
domain: ${minio.endpoint}/${minio.bucket} domain: ${minio.endpoint}/${minio.bucket}
logging:
level:
# sql bind parameter
org.hibernate.type.descriptor.sql.BasicBinder: trace
server: server:
port: 8181 port: 8181
servlet: servlet:
context-path: /basic-api context-path: /api
spring: spring:
application: application:
name: "basic-api-app" name: "basic-api-app"
profiles: profiles:
include: auth include: auth
active: dev active: mock
# DEBUG # DEBUG
debug: false debug: false
...@@ -17,4 +17,7 @@ dependencies { ...@@ -17,4 +17,7 @@ dependencies {
// hutool-core // hutool-core
implementation "cn.hutool:hutool-core:${hutoolVersion}" implementation "cn.hutool:hutool-core:${hutoolVersion}"
// fastjson
implementation "com.alibaba:fastjson:${fastJsonVersion}"
} }
/* (C) 2022 YiRing, Inc. */ /* (C) 2022 YiRing, Inc. */
package com.yiring.auth.domain.permission; package com.yiring.auth.domain.permission;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.io.Serializable; import java.io.Serializable;
import javax.persistence.*; import javax.persistence.*;
import lombok.*; import lombok.*;
...@@ -79,9 +81,22 @@ public class Permission implements Serializable { ...@@ -79,9 +81,22 @@ public class Permission implements Serializable {
@Comment("树节点标识") @Comment("树节点标识")
String tree; String tree;
/**
* 可用于扩展一些前端可能用到的路由参数
*/
@Comment("扩展元数据信息")
@Lob
@Column(columnDefinition = "JSON")
String meta;
@SuppressWarnings({ "unused" }) @SuppressWarnings({ "unused" })
public enum Type { public enum Type {
/** /**
* 目录/平台
*/
DIR,
/**
* 菜单 * 菜单
*/ */
MENU, MENU,
...@@ -91,4 +106,19 @@ public class Permission implements Serializable { ...@@ -91,4 +106,19 @@ public class Permission implements Serializable {
*/ */
BUTTON, BUTTON,
} }
public JSONObject getMetaJson() {
JSONObject meta = new JSONObject();
meta.put("title", this.name);
meta.put("icon", this.icon);
meta.put("orderNo", this.serial);
meta.put("hideMenu", this.hidden);
try {
String raw = this.meta.replace("\\", "").replaceAll("^\"(.*)\"$", "$1");
meta.putAll(JSON.parseObject(raw));
} catch (Exception ignored) {}
return meta;
}
} }
...@@ -68,8 +68,8 @@ public class User implements Serializable { ...@@ -68,8 +68,8 @@ public class User implements Serializable {
@Comment("密码") @Comment("密码")
String password; String password;
@Comment("职称") @Comment("简介")
String title; String introduction;
@Comment("头像") @Comment("头像")
String avatar; String avatar;
......
...@@ -43,14 +43,14 @@ public class RegisterParam implements Serializable { ...@@ -43,14 +43,14 @@ public class RegisterParam implements Serializable {
@Pattern(regexp = "^1[0-9]{10}$", message = "手机号码格式不正确") @Pattern(regexp = "^1[0-9]{10}$", message = "手机号码格式不正确")
String mobile; String mobile;
@ApiModelProperty(value = "头像", example = "http://img.ifzm.cn/cat.jpg") @ApiModelProperty(value = "头像", example = "https://files.catbox.moe/96nu4q.jpg")
String avatar; String avatar;
@ApiModelProperty(value = "邮箱", example = "developer@yiring.com") @ApiModelProperty(value = "邮箱", example = "developer@yiring.com")
String email; String email;
@ApiModelProperty(value = "职称", example = "平台管理员") @ApiModelProperty(value = "简介", example = "平台管理员")
String title; String introduction;
@ApiModelProperty(value = "是否启用", example = "true") @ApiModelProperty(value = "是否启用", example = "true")
Boolean enable; Boolean enable;
......
...@@ -62,4 +62,7 @@ public class PermissionParam implements Serializable { ...@@ -62,4 +62,7 @@ public class PermissionParam implements Serializable {
@ApiModelProperty(value = "父级ID", example = "0") @ApiModelProperty(value = "父级ID", example = "0")
@Builder.Default @Builder.Default
Long pid = 0L; Long pid = 0L;
@ApiModelProperty(value = "元数据", example = "{}")
String meta;
} }
/* (C) 2022 YiRing, Inc. */ /* (C) 2022 YiRing, Inc. */
package com.yiring.auth.util; package com.yiring.auth.util;
import com.sun.istack.Nullable;
import com.yiring.auth.domain.permission.Permission; import com.yiring.auth.domain.permission.Permission;
import com.yiring.auth.domain.role.Role; import com.yiring.auth.domain.role.Role;
import com.yiring.auth.vo.permission.MenuVo;
import com.yiring.auth.vo.permission.PermissionVo; import com.yiring.auth.vo.permission.PermissionVo;
import com.yiring.auth.vo.role.RoleVo; import com.yiring.auth.vo.role.RoleVo;
import com.yiring.common.util.Commons;
import java.util.*; import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.NonNull; import lombok.NonNull;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
...@@ -39,6 +43,41 @@ public class Permissions { ...@@ -39,6 +43,41 @@ public class Permissions {
} }
/** /**
* 将权限集合转换成菜单树
* @param permissions 权限集合
* @return 菜单树
*/
public static List<MenuVo> toMenuTreeVo(@Nullable List<Permission> permissions) {
List<MenuVo> list = Commons.transform(
permissions,
MenuVo.class,
(source, target) -> {
target.setMeta(source.getMetaJson());
target.setName(source.getUid());
},
Permission.Fields.meta
);
// 返回的树
ArrayList<MenuVo> roots = new ArrayList<>();
// 将数据添加到 Map
Map<Long, MenuVo> map = list.stream().collect(Collectors.toMap(MenuVo::getId, Function.identity()));
list.forEach(entity -> {
MenuVo vo = map.get(entity.getPid());
if (null == vo) {
roots.add(map.get(entity.getId()));
} else {
MenuVo parent = map.get(entity.getPid());
parent.getChildren().add(entity);
}
});
return roots;
}
/**
* 将权限集合转换成 Vo 集合 * 将权限集合转换成 Vo 集合
* @param permissions 权限集合 * @param permissions 权限集合
* @return vos * @return vos
...@@ -49,6 +88,7 @@ public class Permissions { ...@@ -49,6 +88,7 @@ public class Permissions {
.map(permission -> { .map(permission -> {
PermissionVo vo = new PermissionVo(); PermissionVo vo = new PermissionVo();
BeanUtils.copyProperties(permission, vo); BeanUtils.copyProperties(permission, vo);
vo.setMeta(permission.getMetaJson());
return vo; return vo;
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
...@@ -82,6 +122,7 @@ public class Permissions { ...@@ -82,6 +122,7 @@ public class Permissions {
.map(permission -> { .map(permission -> {
PermissionVo vo = new PermissionVo(); PermissionVo vo = new PermissionVo();
BeanUtils.copyProperties(permission, vo); BeanUtils.copyProperties(permission, vo);
vo.setMeta(permission.getMetaJson());
vo.setChildren(toTree(permissions, permission.getId())); vo.setChildren(toTree(permissions, permission.getId()));
return vo; return vo;
}) })
......
/* (C) 2021 YiRing, Inc. */ /* (C) 2021 YiRing, Inc. */
package com.yiring.auth.vo.auth; package com.yiring.auth.vo.auth;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable; import java.io.Serializable;
...@@ -25,6 +27,10 @@ public class LoginVo implements Serializable { ...@@ -25,6 +27,10 @@ public class LoginVo implements Serializable {
private static final long serialVersionUID = -8690942241103456896L; private static final long serialVersionUID = -8690942241103456896L;
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty(value = "主键", example = "1")
Long userId;
@ApiModelProperty(value = "token", example = "c68ca9c8c04b4a59afeafd2fb7c04741") @ApiModelProperty(value = "token", example = "c68ca9c8c04b4a59afeafd2fb7c04741")
String token; String token;
} }
/* (C) 2022 YiRing, Inc. */
package com.yiring.auth.vo.permission;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.yiring.auth.domain.permission.Permission;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.List;
import lombok.*;
import lombok.experimental.FieldDefaults;
/**
* 菜单输出类
* @author Jim
* @version 0.1
* 2022/3/25 17:09
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel("MenuVo")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class MenuVo implements Serializable {
private static final long serialVersionUID = -9139328772148985141L;
@JsonIgnore
Long id;
@JsonIgnore
Long pid;
@ApiModelProperty(value = "标识", example = "home")
String name;
@ApiModelProperty(value = "路径", example = "/")
String path;
@ApiModelProperty(value = "组件", example = "/home")
String component;
@ApiModelProperty(value = "权限类型", example = "MENU")
Permission.Type type;
@ApiModelProperty(value = "元数据", example = "{}")
JSONObject meta;
@ApiModelProperty(value = "子权限")
List<MenuVo> children;
}
/* (C) 2022 YiRing, Inc. */ /* (C) 2022 YiRing, Inc. */
package com.yiring.auth.vo.permission; package com.yiring.auth.vo.permission;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
...@@ -64,6 +65,9 @@ public class PermissionVo implements Serializable { ...@@ -64,6 +65,9 @@ public class PermissionVo implements Serializable {
@ApiModelProperty(value = "父级ID", example = "0") @ApiModelProperty(value = "父级ID", example = "0")
Long pid; Long pid;
@ApiModelProperty(value = "元数据", example = "{}")
JSONObject meta;
@ApiModelProperty(value = "子权限") @ApiModelProperty(value = "子权限")
List<PermissionVo> children; List<PermissionVo> children;
} }
...@@ -3,7 +3,6 @@ package com.yiring.auth.vo.user; ...@@ -3,7 +3,6 @@ package com.yiring.auth.vo.user;
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.yiring.auth.vo.permission.PermissionVo;
import com.yiring.auth.vo.role.RoleVo; import com.yiring.auth.vo.role.RoleVo;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
...@@ -39,29 +38,16 @@ public class UserInfoVo implements Serializable { ...@@ -39,29 +38,16 @@ public class UserInfoVo implements Serializable {
@ApiModelProperty(value = "用户名", example = "admin") @ApiModelProperty(value = "用户名", example = "admin")
String username; String username;
@ApiModelProperty(value = "手机号", example = "13012345678") @ApiModelProperty(value = "介绍", example = "系统管理员")
String mobile; String desc;
@ApiModelProperty(value = "邮箱", example = "developer@yiring.com") @ApiModelProperty(value = "头像", example = "https://files.catbox.moe/96nu4q.jpg")
String email;
@ApiModelProperty(value = "职称", example = "系统管理员")
String title;
@ApiModelProperty(value = "头像", example = "http://img.ifzm.cn/cat.jpg")
String avatar; String avatar;
@ApiModelProperty("角色") @ApiModelProperty("角色")
@Builder.Default @Builder.Default
List<RoleVo> roles = new ArrayList<>(0); List<RoleVo> roles = new ArrayList<>(0);
@ApiModelProperty("权限") @ApiModelProperty(value = "用户主页", example = "/dashboard/workbench")
@Builder.Default
List<PermissionVo> permissions = new ArrayList<>(0);
/**
* 通常用于前端决定登录成功后跳转到哪个模块页面
*/
@ApiModelProperty(value = "主页地址", example = "/")
String homePath; String homePath;
} }
/* (C) 2022 YiRing, Inc. */
package com.yiring.auth.vo.user;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.yiring.auth.vo.role.RoleVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import lombok.*;
import lombok.experimental.FieldDefaults;
/**
* 用户信息
* @author ifzm
* 2022/03/03 10:35
**/
@ApiModel("UserInfo")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class UserMenuListVo implements Serializable {
private static final long serialVersionUID = -5319037883240327088L;
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty(value = "主键", example = "1")
Long userId;
@ApiModelProperty(value = "真实姓名", example = "超级用户")
String realName;
@ApiModelProperty(value = "用户名", example = "admin")
String username;
@ApiModelProperty(value = "介绍", example = "系统管理员")
String desc;
@ApiModelProperty(value = "头像", example = "https://files.catbox.moe/96nu4q.jpg")
String avatar;
@ApiModelProperty("角色")
@Builder.Default
List<RoleVo> roles = new ArrayList<>(0);
@ApiModelProperty(value = "用户主页", example = "/dashboard/workbench")
String homePath;
}
...@@ -45,7 +45,7 @@ public class UserVo implements Serializable { ...@@ -45,7 +45,7 @@ public class UserVo implements Serializable {
@ApiModelProperty(value = "职称", example = "系统管理员") @ApiModelProperty(value = "职称", example = "系统管理员")
String title; String title;
@ApiModelProperty(value = "头像", example = "http://img.ifzm.cn/cat.jpg") @ApiModelProperty(value = "头像", example = "https://files.catbox.moe/96nu4q.jpg")
String avatar; String avatar;
@ApiModelProperty(value = "是否启用", example = "true") @ApiModelProperty(value = "是否启用", example = "true")
......
...@@ -70,7 +70,7 @@ public class AuthController { ...@@ -70,7 +70,7 @@ public class AuthController {
// 构建用户信息写入数据库 // 构建用户信息写入数据库
User user = User User user = User
.builder() .builder()
.title(param.getTitle()) .introduction(param.getIntroduction())
.avatar(param.getAvatar()) .avatar(param.getAvatar())
.mobile(param.getMobile()) .mobile(param.getMobile())
.realName(param.getRealName()) .realName(param.getRealName())
...@@ -120,7 +120,7 @@ public class AuthController { ...@@ -120,7 +120,7 @@ public class AuthController {
userRepository.saveAndFlush(user); userRepository.saveAndFlush(user);
// 构建用户所需信息 // 构建用户所需信息
LoginVo vo = LoginVo.builder().token(StpUtil.getTokenValue()).build(); LoginVo vo = LoginVo.builder().userId(user.getId()).token(StpUtil.getTokenValue()).build();
return Result.ok(vo); return Result.ok(vo);
} }
......
...@@ -2,21 +2,25 @@ ...@@ -2,21 +2,25 @@
package com.yiring.auth.web.user; package com.yiring.auth.web.user;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import com.yiring.auth.domain.permission.Permission;
import com.yiring.auth.domain.role.Role; import com.yiring.auth.domain.role.Role;
import com.yiring.auth.domain.role.RoleRepository; import com.yiring.auth.domain.role.RoleRepository;
import com.yiring.auth.domain.user.User; import com.yiring.auth.domain.user.User;
import com.yiring.auth.domain.user.UserRepository; import com.yiring.auth.domain.user.UserRepository;
import com.yiring.auth.param.IdsParam; import com.yiring.auth.param.IdsParam;
import com.yiring.auth.util.Permissions; import com.yiring.auth.util.Permissions;
import com.yiring.auth.vo.permission.MenuVo;
import com.yiring.auth.vo.user.UserInfoVo; import com.yiring.auth.vo.user.UserInfoVo;
import com.yiring.auth.vo.user.UserVo; import com.yiring.auth.vo.user.UserVo;
import com.yiring.common.core.Result; import com.yiring.common.core.Result;
import com.yiring.common.core.Status; import com.yiring.common.core.Status;
import com.yiring.common.exception.FailStatusException;
import com.yiring.common.param.IdParam; import com.yiring.common.param.IdParam;
import com.yiring.common.param.PageParam; import com.yiring.common.param.PageParam;
import com.yiring.common.vo.PageVo; import com.yiring.common.vo.PageVo;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
...@@ -54,30 +58,30 @@ public class UserController { ...@@ -54,30 +58,30 @@ public class UserController {
RoleRepository roleRepository; RoleRepository roleRepository;
@ApiOperation(value = "获取登录用户信息") @ApiOperation(value = "获取登录用户信息")
@GetMapping("info") @GetMapping("getUserInfo")
public Result<UserInfoVo> info() { public Result<UserInfoVo> getUserInfo() {
Long id = StpUtil.getLoginIdAsLong(); User user = getLoginUser();
Optional<User> optional = userRepository.findById(id);
if (optional.isEmpty()) {
StpUtil.logout(id);
return Result.no(Status.UNAUTHORIZED);
}
User user = optional.get();
UserInfoVo userInfoVo = UserInfoVo UserInfoVo userInfoVo = UserInfoVo
.builder() .builder()
.userId(user.getId()) .userId(user.getId())
.username(user.getUsername())
.realName(user.getRealName()) .realName(user.getRealName())
.avatar(user.getAvatar()) .avatar(user.getAvatar())
.title(user.getTitle()) .desc(user.getIntroduction())
.roles(Permissions.toRoleVos(user.getRoles())) .roles(Permissions.toRoleVos(user.getRoles()))
.permissions(Permissions.toTree(Permissions.toPermissions(user.getRoles()), 0L))
// 默认跳转到用户看板
.homePath("/dashboard/workbench")
.build(); .build();
return Result.ok(userInfoVo); return Result.ok(userInfoVo);
} }
@ApiOperation(value = "获取用户权限")
@GetMapping("getMenuList")
public Result<ArrayList<MenuVo>> getMenuList() {
User user = getLoginUser();
List<Permission> permissions = Permissions.toPermissions(user.getRoles());
List<MenuVo> vos = Permissions.toMenuTreeVo(permissions);
return Result.ok((ArrayList<MenuVo>) vos);
}
@ApiOperation(value = "分配角色") @ApiOperation(value = "分配角色")
@PostMapping("/manage/assign") @PostMapping("/manage/assign")
public Result<String> assign(@Valid IdParam idParam, @Valid IdsParam idsParam) { public Result<String> assign(@Valid IdParam idParam, @Valid IdsParam idsParam) {
...@@ -115,4 +119,19 @@ public class UserController { ...@@ -115,4 +119,19 @@ public class UserController {
PageVo<UserVo> vo = PageVo.build(data, page.getTotalElements()); PageVo<UserVo> vo = PageVo.build(data, page.getTotalElements());
return Result.ok(vo); return Result.ok(vo);
} }
/**
* 获取登录用户信息
* @return 用户信息
*/
private User getLoginUser() {
Long id = StpUtil.getLoginIdAsLong();
Optional<User> optional = userRepository.findById(id);
if (optional.isPresent()) {
return optional.get();
}
StpUtil.logout(id);
throw new FailStatusException(Status.UNAUTHORIZED);
}
} }
# Sa-Token配置 # Sa-Token配置
sa-token: sa-token:
# token名称 (同时也是cookie名称) # token名称 (同时也是cookie名称)
token-name: satoken token-name: Authorization
# token有效期,单位s 默认30天, -1代表永不过期 # token有效期,单位s 默认30天, -1代表永不过期
timeout: 2592000 timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
...@@ -15,4 +15,4 @@ sa-token: ...@@ -15,4 +15,4 @@ sa-token:
# 是否输出操作日志 # 是否输出操作日志
is-log: false is-log: false
# 是否在初始化配置时打印版本字符画 # 是否在初始化配置时打印版本字符画
is-print: false is-print: false
\ No newline at end of file
...@@ -8,9 +8,11 @@ dependencies { ...@@ -8,9 +8,11 @@ dependencies {
// swagger annotations // swagger annotations
implementation "io.swagger:swagger-annotations:${swaggerAnnotationsVersion}" implementation "io.swagger:swagger-annotations:${swaggerAnnotationsVersion}"
implementation "org.hibernate.validator:hibernate-validator:${hibernateValidatorVersion}" implementation "org.hibernate.validator:hibernate-validator:${hibernateValidatorVersion}"
// hutool-extra // hutool-extra
implementation "cn.hutool:hutool-extra:${hutoolVersion}" implementation "cn.hutool:hutool-extra:${hutoolVersion}"
// hutool-json
implementation "cn.hutool:hutool-json:${hutoolVersion}" // fastjson
implementation "com.alibaba:fastjson:${fastJsonVersion}"
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
package com.yiring.common.aspect; package com.yiring.common.aspect;
import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.yiring.common.constant.DateFormatter; import com.yiring.common.constant.DateFormatter;
import com.yiring.common.core.Result; import com.yiring.common.core.Result;
import com.yiring.common.util.Commons; import com.yiring.common.util.Commons;
...@@ -52,8 +52,8 @@ public class RequestAspect { ...@@ -52,8 +52,8 @@ public class RequestAspect {
// Print Request Log (Optional Replace: MDC) // Print Request Log (Optional Replace: MDC)
String extra = ""; String extra = "";
if (Boolean.TRUE.equals(debug)) { if (Boolean.TRUE.equals(debug)) {
extra += String.format("\nHeaders: %s", new JSONObject(ServletUtil.getHeaderMap(request)).toStringPretty()); extra += String.format("\nHeaders: %s", JSONObject.toJSONString(ServletUtil.getHeaderMap(request), true));
extra += String.format("\nParams: %s", new JSONObject(ServletUtil.getParamMap(request)).toStringPretty()); extra += String.format("\nParams: %s", JSONObject.toJSONString(ServletUtil.getParamMap(request), true));
if (result instanceof Result) { if (result instanceof Result) {
extra += extra +=
String.format( String.format(
......
/* (C) 2022 YiRing, Inc. */
package com.yiring.common.exception;
import com.yiring.common.core.Status;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.FieldDefaults;
/**
* Status 异常(用于快速失败,会进行全局异常拦截)
*
* @author Jim
* @version 0.1
* 2022/3/28 11:36
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class FailStatusException extends RuntimeException {
private static final long serialVersionUID = -4226669531686389671L;
/**
* 状态
*/
Status status;
}
/* (C) 2021 YiRing, Inc. */ /* (C) 2021 YiRing, Inc. */
package com.yiring.common.util; package com.yiring.common.util;
import java.util.Collection; import java.lang.reflect.Constructor;
import java.util.Map; import java.util.*;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import lombok.NonNull;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
/** /**
* 公共工具类 * 公共工具类
...@@ -15,6 +17,7 @@ import lombok.experimental.UtilityClass; ...@@ -15,6 +17,7 @@ import lombok.experimental.UtilityClass;
*/ */
@SuppressWarnings({ "unused" }) @SuppressWarnings({ "unused" })
@Slf4j
@UtilityClass @UtilityClass
public class Commons { public class Commons {
...@@ -79,4 +82,63 @@ public class Commons { ...@@ -79,4 +82,63 @@ public class Commons {
public boolean isNullOrEmpty(Map<?, ?> map) { public boolean isNullOrEmpty(Map<?, ?> map) {
return map == null || map.isEmpty(); return map == null || map.isEmpty();
} }
/**
* 将集合通过 BeanUtils 反射转换成指定类型集合
* @param list 原始数据集合
* @param type 目标类型
* @param ignoreProperties 忽略属性
* @param <T> 目标类型集合
* @param <S> 原类型集合
* @return 目标集合
*/
public <T, S> List<T> transform(@NonNull List<S> list, Class<T> type, String... ignoreProperties) {
return transform(list, type, null, ignoreProperties);
}
/**
* 将集合通过 BeanUtils 反射转换成指定类型集合
* @param list 原始数据集合
* @param type 目标类型
* @param fn 自定义处理函数
* @param ignoreProperties 忽略属性
* @param <T> 目标类型集合
* @param <S> 原类型集合
* @return 目标集合
*/
public <T, S> List<T> transform(
@NonNull List<S> list,
Class<T> type,
CallbackFunction<S, T> fn,
String... ignoreProperties
) {
try {
Constructor<T> declaredConstructor = type.getDeclaredConstructor();
List<T> targets = new ArrayList<>();
for (S source : list) {
// 实例化
T target = declaredConstructor.newInstance();
// 使用 BeanUtils 进行数据拷贝
BeanUtils.copyProperties(source, target, ignoreProperties);
// 通过自定义实现补充转换
if (fn != null) {
fn.apply(source, target);
}
targets.add(target);
}
return targets;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@FunctionalInterface
public interface CallbackFunction<S, T> {
void apply(S s, T t);
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论