com.diboot.core.controller.BaseController Maven / Gradle / Ivy
/*
* Copyright (c) 2015-2020, www.dibo.ltd ([email protected]).
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.diboot.core.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.diboot.core.binding.Binder;
import com.diboot.core.binding.QueryBuilder;
import com.diboot.core.binding.cache.BindingCacheManager;
import com.diboot.core.binding.helper.WrapperHelper;
import com.diboot.core.binding.parser.PropInfo;
import com.diboot.core.config.BaseConfig;
import com.diboot.core.config.Cons;
import com.diboot.core.data.query.BaseCriteria;
import com.diboot.core.dto.RelatedDataDTO;
import com.diboot.core.exception.BusinessException;
import com.diboot.core.service.BaseService;
import com.diboot.core.util.*;
import com.diboot.core.vo.LabelValue;
import com.diboot.core.vo.Pagination;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Controller的父类
* @author [email protected]
* @version 2.0
* @date 2019/01/01
*/
public class BaseController {
private static final Logger log = LoggerFactory.getLogger(BaseController.class);
@Autowired
protected HttpServletRequest request;
/**
* 根据DTO构建查询QueryWrapper (根据BindQuery注解构建相应的查询条件,DTO中的非空属性均参与构建)
* @param entityOrDto Entity对象或者DTO对象 (属性若无BindQuery注解,默认构建为为EQ相等条件)
* @return
*/
protected QueryWrapper buildQueryWrapperByDTO(DTO entityOrDto) throws Exception{
return QueryBuilder.toQueryWrapper(entityOrDto);
}
/**
* 根据DTO构建查询QueryWrapper (根据BindQuery注解构建相应的查询条件,DTO中的非空属性均参与构建)
* @param entityOrDto Entity对象或者DTO对象 (属性若无BindQuery注解,默认构建为为EQ相等条件)
* @param pagination 分页,如按关联表中的字段排序时需传入pagination
* @return
*/
protected QueryWrapper buildQueryWrapperByDTO(DTO entityOrDto, Pagination pagination) throws Exception{
return QueryBuilder.toQueryWrapper(entityOrDto, pagination);
}
/**
* 根据请求参数构建查询QueryWrapper (根据BindQuery注解构建相应的查询条件,url中的请求参数参与构建)
* @param entityOrDto Entity对象或者DTO对象 (属性若无BindQuery注解,默认构建为为EQ相等条件)
* @return
*/
@Deprecated
protected QueryWrapper buildQueryWrapperByQueryParams(DTO entityOrDto) throws Exception{
return QueryBuilder.toQueryWrapper(entityOrDto, extractQueryParams());
}
/**
* 根据请求参数构建查询QueryWrapper (根据BindQuery注解构建相应的查询条件,url中的请求参数参与构建)
* @param entityOrDto Entity对象或者DTO对象 (属性若无BindQuery注解,默认构建为为EQ相等条件)
* @param pagination 分页,如按关联表中的字段排序时需传入pagination
* @return
*/
@Deprecated
protected QueryWrapper buildQueryWrapperByQueryParams(DTO entityOrDto, Pagination pagination) throws Exception{
return QueryBuilder.toQueryWrapper(entityOrDto, extractQueryParams(), pagination);
}
/**
* 获取请求参数Map
* @return
*/
protected Map getParamsMap() throws Exception{
return getParamsMap(null);
}
/**
* 获取请求参数Map
* @return
*/
private Map getParamsMap(List paramList) throws Exception{
Map result = new HashMap<>(8);
Enumeration paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()){
String paramName = (String) paramNames.nextElement();
// 如果非要找的参数,则跳过
if(V.notEmpty(paramList) && !paramList.contains(paramName)){
continue;
}
String[] values = request.getParameterValues(paramName);
if(V.notEmpty(values)){
if(values.length == 1){
if(V.notEmpty(values[0])){
String paramValue = java.net.URLDecoder.decode(values[0], Cons.CHARSET_UTF8);
result.put(paramName, paramValue);
}
}
else{
String[] valueArray = new String[values.length];
for(int i=0; i extractQueryParams(){
Map paramValueMap = convertParams2Map();
if(V.notEmpty(paramValueMap)){
return paramValueMap.keySet();
}
return Collections.EMPTY_SET;
}
/**
* 将请求参数值转换为Map
* @return
*/
protected Map convertParams2Map(){
Map result = new HashMap<>(8);
if(request == null){
return result;
}
Enumeration paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()){
String paramName = (String) paramNames.nextElement();
String[] values = request.getParameterValues(paramName);
if(V.notEmpty(values)){
if(values.length == 1){
if(V.notEmpty(values[0])){
result.put(paramName, values[0]);
}
}
else{
// 多个值需传递到后台SQL的in语句
result.put(paramName, values);
}
}
}
return result;
}
/**
* 自动转换为VO并绑定关联关系
*
* @param entityList
* @param voClass
* @param
* @return
*/
@Deprecated
protected List convertToVoAndBindRelations(List entityList, Class voClass) {
// 转换为VO
List voList = Binder.convertAndBindRelations(entityList, voClass);
return voList;
}
/**
* RelatedData获取相应对象数据
*
* @param relatedDataDTO
* @return labelValue集合
*/
protected List loadRelatedData(RelatedDataDTO relatedDataDTO) {
return loadRelatedData(relatedDataDTO, null, null);
}
/**
* 通用的RelatedData获取数据
*
* @param relatedDataDTO 相应的relatedDataDTO
* @param parentId 父级值
* @param keyword 搜索关键词
* @return labelValue集合
*/
protected List loadRelatedData(RelatedDataDTO relatedDataDTO, @Nullable String parentId, @Nullable String keyword) {
if (!relatedDataSecurityCheck(relatedDataDTO)) {
log.warn("relatedData安全检查不通过: {}", JSON.stringify(relatedDataDTO));
return Collections.emptyList();
}
String entityClassName = relatedDataDTO.getTypeClassName();
Class> entityClass = BindingCacheManager.getEntityClassBySimpleName(entityClassName);
if (V.isEmpty(entityClass)) {
throw new BusinessException("exception.business.baseController.loadRelatedData.nullEntityClass");
}
BaseService> baseService = ContextHolder.getBaseServiceByEntity(entityClass);
if (baseService == null) {
throw new BusinessException("exception.business.baseController.loadRelatedData.nullServiceClass");
}
PropInfo propInfoCache = BindingCacheManager.getPropInfoByClass(entityClass);
Function field2column = field -> {
if (V.notEmpty(field)) {
String column = propInfoCache.getColumnByField(field);
if (V.notEmpty(column)) {
return column;
} else {
throw new BusinessException("exception.business.baseController.loadRelatedData.noField");
}
}
return null;
};
String label = field2column.apply(S.defaultIfBlank(relatedDataDTO.getLabel(), "label"));
String idColumn = propInfoCache.getIdColumn();
List columns = new ArrayList<>();
columns.add(label);
columns.add(idColumn);
if (V.notEmpty(relatedDataDTO.getExt())) {
columns.add(field2column.apply(relatedDataDTO.getExt()));
}
// 构建查询条件
QueryWrapper> queryWrapper = Wrappers.query();
// 构建排序
WrapperHelper.buildOrderBy(queryWrapper, relatedDataDTO.getOrderBy(), field2column);
// tree
if (V.notEmpty(relatedDataDTO.getParent())) {
String parentColumn = field2column.apply(relatedDataDTO.getParent());
Class> parentFieldType = propInfoCache.getFieldTypeByColumn(parentColumn);
Function parentIdTypeConversion = pid -> V.isEmpty(pid) ? null : parentFieldType == Long.class ? Long.valueOf(pid) : pid;
String parentPathColumn = field2column.apply(relatedDataDTO.getParentPath());
// 动态根点 限制(需同时指定parentPath属性)
Serializable rootId;
if(V.notEmpty(relatedDataDTO.getConditions())) {
Optional parentCriteriaOpt = relatedDataDTO.getConditions().stream().filter(criteria -> criteria.getField().equals(relatedDataDTO.getParent())).findFirst();
if(parentCriteriaOpt.isPresent()) {
rootId = parentIdTypeConversion.apply(S.valueOf(parentCriteriaOpt.get().getValue()));
relatedDataDTO.removeCondition(relatedDataDTO.getParent());
}
else {
rootId = null;
}
}
else {
rootId = null;
}
boolean isDynamicRoot = !parentIdTypeConversion.apply(Cons.TREE_ROOT_ID).equals(rootId) && V.isNoneEmpty(rootId, parentPathColumn);
if (isDynamicRoot) {
Object rootNode = baseService.getEntity(rootId);
if (rootNode == null) {
return Collections.emptyList();
}
String parentPath = S.valueOf(BeanUtils.getProperty(rootNode, relatedDataDTO.getParentPath()));
queryWrapper.and(query -> {
query.likeRight(parentPathColumn, V.isEmpty(parentPath) ? S.valueOf(rootId) : parentPath + Cons.SEPARATOR_COMMA + rootId);
query.or().eq(idColumn, rootId);
});
}
if (V.notEmpty(parentId)) {
// 加载其节点相应下一层节点列表
queryWrapper.eq(parentColumn, parentIdTypeConversion.apply(parentId));
} else if (V.isNoneEmpty(keyword, relatedDataDTO.getParentPath())) {
// tree 模糊搜索(未指定或无parentPath属性及不支持tree搜索)
List