新增: list和page支持关联查询,支持自定义返回结果类型,并可以在init方法中初始化返回字段类型及数据组装函数定义
调整:优化角色修改循环单个处理为批量处理,并异步进行刷新用户权限
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
package com.cool.core.base;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.lang.Editor;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.TypeUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.cool.core.enums.QueryModeEnum;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.request.CrudOption;
|
||||
import com.cool.core.request.R;
|
||||
@@ -20,6 +25,7 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
@@ -27,6 +33,8 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
/**
|
||||
* 控制层基类
|
||||
@@ -60,6 +68,12 @@ public abstract class BaseController<S extends BaseService<T>, T extends BaseEnt
|
||||
@ModelAttribute
|
||||
protected void preHandle(HttpServletRequest request,
|
||||
@RequestAttribute JSONObject requestParams) {
|
||||
String requestPath = ((ServletRequestAttributes) Objects.requireNonNull(
|
||||
RequestContextHolder.getRequestAttributes())).getRequest().getRequestURI();
|
||||
if (!requestPath.endsWith("/page") && !requestPath.endsWith("/list")) {
|
||||
// 非page或list不执行
|
||||
return;
|
||||
}
|
||||
this.pageOption.set(new CrudOption<>(requestParams));
|
||||
this.listOption.set(new CrudOption<>(requestParams));
|
||||
this.requestParams.set(requestParams);
|
||||
@@ -133,7 +147,7 @@ public abstract class BaseController<S extends BaseService<T>, T extends BaseEnt
|
||||
@PostMapping("/update")
|
||||
protected R update(@RequestBody T t, @RequestAttribute() JSONObject requestParams) {
|
||||
Long id = t.getId();
|
||||
JSONObject info = JSONUtil.parseObj(JSONUtil.toJsonStr(service.info(id)));
|
||||
JSONObject info = JSONUtil.parseObj(JSONUtil.toJsonStr(service.getById(id)));
|
||||
requestParams.forEach(info::set);
|
||||
info.set("updateTime", new Date());
|
||||
service.update(requestParams, JSONUtil.toBean(info, currentEntityClass()));
|
||||
@@ -161,7 +175,14 @@ public abstract class BaseController<S extends BaseService<T>, T extends BaseEnt
|
||||
@PostMapping("/list")
|
||||
protected R list(@RequestAttribute() JSONObject requestParams,
|
||||
@RequestAttribute(COOL_LIST_OP) CrudOption<T> option) {
|
||||
return R.ok(service.list(requestParams, option.getQueryWrapper(entityClass)));
|
||||
QueryModeEnum queryModeEnum = option.getQueryModeEnum();
|
||||
List list = (List) switch (queryModeEnum) {
|
||||
case ENTITY_WITH_RELATIONS -> service.listWithRelations(requestParams, option.getQueryWrapper(entityClass));
|
||||
case CUSTOM -> transformList(service.list(requestParams, option.getQueryWrapper(entityClass), option.getAsType()), option.getAsType());
|
||||
default -> service.list(requestParams, option.getQueryWrapper(entityClass));
|
||||
};
|
||||
invokerTransform(option, list);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,9 +196,24 @@ public abstract class BaseController<S extends BaseService<T>, T extends BaseEnt
|
||||
@RequestAttribute(COOL_PAGE_OP) CrudOption<T> option) {
|
||||
Integer page = requestParams.getInt("page", 1);
|
||||
Integer size = requestParams.getInt("size", 20);
|
||||
return R.ok(
|
||||
pageResult((Page<T>) service.page(requestParams, new Page<>(page, size),
|
||||
option.getQueryWrapper(entityClass))));
|
||||
QueryModeEnum queryModeEnum = option.getQueryModeEnum();
|
||||
Object obj = switch (queryModeEnum) {
|
||||
case ENTITY_WITH_RELATIONS -> service.pageWithRelations(requestParams, new Page<>(page, size), option.getQueryWrapper(entityClass));
|
||||
case CUSTOM -> transformPage(service.page(requestParams, new Page<>(page, size), option.getQueryWrapper(entityClass), option.getAsType()), option.getAsType());
|
||||
default -> service.page(requestParams, new Page<>(page, size), option.getQueryWrapper(entityClass));
|
||||
};
|
||||
Page pageResult = (Page) obj;
|
||||
invokerTransform(option, pageResult.getRecords());
|
||||
return R.ok(pageResult(pageResult));
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换参数,组装数据
|
||||
*/
|
||||
private void invokerTransform(CrudOption<T> option, List list) {
|
||||
if (ObjUtil.isNotEmpty(option.getTransform())) {
|
||||
option.getTransform().apply(list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,7 +221,7 @@ public abstract class BaseController<S extends BaseService<T>, T extends BaseEnt
|
||||
*
|
||||
* @param page 分页返回数据
|
||||
*/
|
||||
protected Map<String, Object> pageResult(Page<T> page) {
|
||||
protected Map<String, Object> pageResult(Page page) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
Map<String, Object> pagination = new HashMap<>();
|
||||
pagination.put("size", page.getPageSize());
|
||||
@@ -223,4 +259,21 @@ public abstract class BaseController<S extends BaseService<T>, T extends BaseEnt
|
||||
return Convert.toList(Long.class, ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 适用于自定义返回值为 map,map 的key为数据库字段,转驼峰命名
|
||||
*/
|
||||
protected List transformList(List records, Class<?> asType) {
|
||||
if (ObjUtil.isEmpty(asType) || !Map.class.isAssignableFrom(asType)) {
|
||||
return records;
|
||||
}
|
||||
List<Map> list = new ArrayList<>();
|
||||
Editor<String> keyEditor = property -> StrUtil.toCamelCase(property);
|
||||
records.forEach(o ->
|
||||
list.add(BeanUtil.beanToMap(o, new HashMap(), false, keyEditor)));
|
||||
return list;
|
||||
}
|
||||
protected Page transformPage(Page page, Class<?> asType) {
|
||||
page.setRecords(transformList(page.getRecords(), asType));
|
||||
return page;
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,15 @@ public interface BaseService<T> extends IService<T> {
|
||||
*/
|
||||
Object list(JSONObject requestParams, QueryWrapper queryWrapper);
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
*
|
||||
* @param requestParams 请求参数
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 列表信息
|
||||
*/
|
||||
<R> List<R> list(JSONObject requestParams, QueryWrapper queryWrapper, Class<R> asType);
|
||||
|
||||
/**
|
||||
* 查询所有
|
||||
* 带关联查询
|
||||
@@ -95,6 +104,16 @@ public interface BaseService<T> extends IService<T> {
|
||||
*/
|
||||
Object page(JSONObject requestParams, Page<T> page, QueryWrapper queryWrapper);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param requestParams 请求参数
|
||||
* @param page 分页信息
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 分页信息
|
||||
*/
|
||||
<R> Page<R> page(JSONObject requestParams, Page page, QueryWrapper queryWrapper, Class<R> asType);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* 带关联查询
|
||||
|
||||
@@ -78,6 +78,11 @@ public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseEntity<T>> e
|
||||
return this.list(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> List<R> list(JSONObject requestParams, QueryWrapper queryWrapper, Class<R> asType) {
|
||||
return mapper.selectListByQueryAs(queryWrapper, asType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object listWithRelations(JSONObject requestParams, QueryWrapper queryWrapper) {
|
||||
return mapper.selectListWithRelationsByQuery(queryWrapper);
|
||||
@@ -88,6 +93,12 @@ public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseEntity<T>> e
|
||||
return this.page(page, queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Page<R> page(JSONObject requestParams, Page page, QueryWrapper queryWrapper,
|
||||
Class<R> asType) {
|
||||
return mapper.paginateAs(page, queryWrapper, asType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object pageWithRelations(JSONObject requestParams, Page<T> page,
|
||||
QueryWrapper queryWrapper) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.cool.core.config;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -30,4 +32,10 @@ public class ThreadPoolConfig {
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
|
||||
@Bean(name = "cachedThreadPool")
|
||||
public ExecutorService cachedThreadPool() {
|
||||
// 创建一个虚拟线程池,每个任务使用一个虚拟线程执行
|
||||
return Executors.newCachedThreadPool();
|
||||
}
|
||||
}
|
||||
|
||||
10
src/main/java/com/cool/core/enums/QueryModeEnum.java
Normal file
10
src/main/java/com/cool/core/enums/QueryModeEnum.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.cool.core.enums;
|
||||
|
||||
/**
|
||||
* 查询模式决定返回值
|
||||
*/
|
||||
public enum QueryModeEnum {
|
||||
ENTITY, // 实体(默认)
|
||||
ENTITY_WITH_RELATIONS, // 实体关联查询(如实体字段上加 @RelationOneToMany 等注解)
|
||||
CUSTOM , // 自定义,默认为Map
|
||||
}
|
||||
@@ -2,11 +2,13 @@ package com.cool.core.request;
|
||||
|
||||
|
||||
import cn.hutool.core.annotation.AnnotationUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.enums.QueryModeEnum;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.query.QueryColumn;
|
||||
import com.mybatisflex.core.query.QueryCondition;
|
||||
@@ -14,6 +16,7 @@ import com.mybatisflex.core.query.QueryTable;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.Data;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
@@ -31,17 +34,26 @@ public class CrudOption<T> {
|
||||
private QueryColumn[] select;
|
||||
private JSONObject requestParams;
|
||||
|
||||
private QueryModeEnum queryModeEnum;
|
||||
|
||||
private Transform<List> transform;
|
||||
|
||||
public interface Transform<List> {
|
||||
void apply(List list);
|
||||
}
|
||||
|
||||
/**
|
||||
* queryModeEnum 为 CUSTOM,可设置 默认为Map
|
||||
*/
|
||||
private Class<?> asType;
|
||||
|
||||
private Environment evn;
|
||||
|
||||
public CrudOption(JSONObject requestParams) {
|
||||
this.requestParams = requestParams;
|
||||
this.queryWrapper = QueryWrapper.create();
|
||||
this.evn = SpringUtil.getBean(Environment.class);
|
||||
}
|
||||
|
||||
public CrudOption<T> fieldEq(QueryColumn... fields) {
|
||||
this.fieldEq = fields;
|
||||
return this;
|
||||
queryModeEnum = QueryModeEnum.ENTITY;
|
||||
}
|
||||
|
||||
public QueryWrapper getQueryWrapper(Class<T> entityClass) {
|
||||
@@ -53,16 +65,58 @@ public class CrudOption<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按前端传上来的字段值做eq
|
||||
*/
|
||||
public CrudOption<T> fieldEq(QueryColumn... fields) {
|
||||
this.fieldEq = fields;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按前端传上来的字段值做like
|
||||
*/
|
||||
public CrudOption<T> keyWordLikeFields(QueryColumn... fields) {
|
||||
this.keyWordLikeFields = fields;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要返回给前端的字段
|
||||
*/
|
||||
public CrudOption<T> select(QueryColumn... selects) {
|
||||
this.select = selects;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询模式决定返回值
|
||||
* 目前有三种模式,按实体查询返回、关联查询返回(实体字段上加 @RelationOneToMany 等注解)、自定义返回结果
|
||||
*/
|
||||
public CrudOption<T> queryModeEnum(QueryModeEnum queryModeEnum) {
|
||||
this.queryModeEnum = queryModeEnum;
|
||||
if (ObjUtil.equal(queryModeEnum, QueryModeEnum.CUSTOM)
|
||||
&& ObjUtil.isEmpty(asType)) {
|
||||
asType = Map.class;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义返回结果对象类型
|
||||
*/
|
||||
public CrudOption<T> asType(Class<?> asType) {
|
||||
this.asType = asType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换参数,组装数据
|
||||
*/
|
||||
public CrudOption<T> transform(Transform<List> transform) {
|
||||
this.transform = transform;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询条件
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.row.Row;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
@@ -41,6 +42,8 @@ public class BaseSysPermsServiceImpl implements BaseSysPermsService {
|
||||
|
||||
final private BaseSysDepartmentMapper baseSysDepartmentMapper;
|
||||
|
||||
final private ExecutorService cachedThreadPool;
|
||||
|
||||
@Override
|
||||
public Long[] loginDepartmentIds() {
|
||||
String username = CoolSecurityUtil.getAdminUsername();
|
||||
@@ -173,27 +176,37 @@ public class BaseSysPermsServiceImpl implements BaseSysPermsService {
|
||||
public void updatePerms(Long roleId, Long[] menuIdList, Long[] departmentIds) {
|
||||
// 更新菜单权限
|
||||
baseSysRoleMenuMapper.deleteByQuery(QueryWrapper.create().eq(BaseSysRoleMenuEntity::getRoleId, roleId));
|
||||
List<BaseSysRoleMenuEntity> batchRoleMenuList = new ArrayList<>();
|
||||
for (Long menuId : menuIdList) {
|
||||
BaseSysRoleMenuEntity roleMenuEntity = new BaseSysRoleMenuEntity();
|
||||
roleMenuEntity.setRoleId(roleId);
|
||||
roleMenuEntity.setMenuId(menuId);
|
||||
baseSysRoleMenuMapper.insert(roleMenuEntity);
|
||||
batchRoleMenuList.add(roleMenuEntity);
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(batchRoleMenuList)) {
|
||||
baseSysRoleMenuMapper.insertBatch(batchRoleMenuList);
|
||||
}
|
||||
// 更新部门权限
|
||||
baseSysRoleDepartmentMapper
|
||||
.deleteByQuery(QueryWrapper.create().eq(BaseSysRoleDepartmentEntity::getRoleId, roleId));
|
||||
List<BaseSysRoleDepartmentEntity> batchRoleDepartmentList = new ArrayList<>();
|
||||
for (Long departmentId : departmentIds) {
|
||||
BaseSysRoleDepartmentEntity roleDepartmentEntity = new BaseSysRoleDepartmentEntity();
|
||||
roleDepartmentEntity.setRoleId(roleId);
|
||||
roleDepartmentEntity.setDepartmentId(departmentId);
|
||||
baseSysRoleDepartmentMapper.insert(roleDepartmentEntity);
|
||||
batchRoleDepartmentList.add(roleDepartmentEntity);
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(batchRoleDepartmentList)) {
|
||||
baseSysRoleDepartmentMapper.insertBatch(batchRoleDepartmentList);
|
||||
}
|
||||
cachedThreadPool.submit(() -> {
|
||||
// 刷新对应角色用户的权限
|
||||
List<BaseSysUserRoleEntity> userRoles = baseSysUserRoleMapper
|
||||
.selectListByQuery(QueryWrapper.create().eq(BaseSysUserRoleEntity::getRoleId, roleId));
|
||||
for (BaseSysUserRoleEntity userRole : userRoles) {
|
||||
refreshPerms(userRole.getUserId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user