完善缓存基本支持功能,添加数据源、数据集、图表缓存功能

This commit is contained in:
datagear 2021-08-16 21:04:23 +08:00
parent 0f277f09e9
commit d3270a2141
38 changed files with 965 additions and 357 deletions

View File

@ -9,6 +9,8 @@ package org.datagear.management.domain;
import java.util.Date;
import org.springframework.beans.BeanUtils;
/**
* 数据分析项目实体
*
@ -16,7 +18,7 @@ import java.util.Date;
*
*/
public class AnalysisProject extends AbstractStringIdEntity
implements CreateUserEntity<String>, DataPermissionEntity<String>
implements CreateUserEntity<String>, DataPermissionEntity<String>, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -109,4 +111,13 @@ public class AnalysisProject extends AbstractStringIdEntity
return getClass().getSimpleName() + " [name=" + name + ", desc=" + desc + ", createUser=" + createUser
+ ", createTime=" + createTime + ", dataPermission=" + dataPermission + "]";
}
@Override
public AnalysisProject clone()
{
AnalysisProject entity = new AnalysisProject();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -7,13 +7,15 @@
package org.datagear.management.domain;
import org.springframework.beans.BeanUtils;
/**
* 授权
*
* @author datagear@163.com
*
*/
public class Authorization extends AbstractStringIdEntity
public class Authorization extends AbstractStringIdEntity implements CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -189,6 +191,15 @@ public class Authorization extends AbstractStringIdEntity
+ permission + ", enabled=" + enabled + "]";
}
@Override
public Authorization clone()
{
Authorization entity = new Authorization();
BeanUtils.copyProperties(this, entity);
return entity;
}
/**
* 是否无权限
*

View File

@ -10,6 +10,7 @@ package org.datagear.management.domain;
import org.datagear.analysis.ChartDataSet;
import org.datagear.analysis.DataSet;
import org.datagear.analysis.DataSetResult;
import org.springframework.beans.BeanUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;
@ -19,7 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
* @author datagear@163.com
*
*/
public class ChartDataSetVO extends ChartDataSet
public class ChartDataSetVO extends ChartDataSet implements CloneableEntity
{
public ChartDataSetVO()
{
@ -48,4 +49,12 @@ public class ChartDataSetVO extends ChartDataSet
return super.getResult();
}
@Override
public ChartDataSetVO clone()
{
ChartDataSetVO entity = new ChartDataSetVO();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2018 datagear.tech
*
* Licensed under the LGPLv3 license:
* http://www.gnu.org/licenses/lgpl-3.0.html
*/
package org.datagear.management.domain;
/**
* 可克隆实体
*
* @author datagear@163.com
*
*/
public interface CloneableEntity extends Cloneable
{
/**
* 克隆
* <p>
* 实现方法应遵循如下克隆规则
* </p>
* <p>
* 如果属性值是实体对象则应仅克隆引用否则应对属性值进行深度克隆
* </p>
*
* @return
*/
Object clone();
}

View File

@ -15,6 +15,7 @@ import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.DataSetQuery;
import org.datagear.analysis.support.AbstractCsvFileDataSet;
import org.datagear.analysis.support.CsvDirectoryFileDataSet;
import org.springframework.beans.BeanUtils;
/**
* {@linkplain CsvDirectoryFileDataSet}实体
@ -22,7 +23,7 @@ import org.datagear.analysis.support.CsvDirectoryFileDataSet;
* @author datagear@163.com
*
*/
public class CsvFileDataSetEntity extends AbstractCsvFileDataSet implements DirectoryFileDataSetEntity
public class CsvFileDataSetEntity extends AbstractCsvFileDataSet implements DirectoryFileDataSetEntity, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -226,4 +227,13 @@ public class CsvFileDataSetEntity extends AbstractCsvFileDataSet implements Dire
{
return FILE_SUPPORT.getFile(this, query);
}
@Override
public CsvFileDataSetEntity clone()
{
CsvFileDataSetEntity entity = new CsvFileDataSetEntity();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -12,6 +12,7 @@ import java.util.List;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.support.CsvValueDataSet;
import org.springframework.beans.BeanUtils;
/**
* {@linkplain CsvValueDataSet}实体
@ -19,7 +20,7 @@ import org.datagear.analysis.support.CsvValueDataSet;
* @author datagear@163.com
*
*/
public class CsvValueDataSetEntity extends CsvValueDataSet implements DataSetEntity
public class CsvValueDataSetEntity extends CsvValueDataSet implements DataSetEntity, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -108,4 +109,13 @@ public class CsvValueDataSetEntity extends CsvValueDataSet implements DataSetEnt
{
this.analysisProject = analysisProject;
}
@Override
public CsvValueDataSetEntity clone()
{
CsvValueDataSetEntity entity = new CsvValueDataSetEntity();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -9,13 +9,15 @@ package org.datagear.management.domain;
import java.io.Serializable;
import org.springframework.beans.BeanUtils;
/**
* 数据ID权限
*
* @author datagear@163.com
*
*/
public class DataIdPermission implements DataPermissionAware, Serializable
public class DataIdPermission implements DataPermissionAware, Serializable, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -56,4 +58,13 @@ public class DataIdPermission implements DataPermissionAware, Serializable
{
this.dataPermission = dataPermission;
}
@Override
public DataIdPermission clone()
{
DataIdPermission entity = new DataIdPermission();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -9,6 +9,8 @@ package org.datagear.management.domain;
import java.util.Date;
import org.springframework.beans.BeanUtils;
/**
* 数据集资源目录实体
* <p>
@ -19,7 +21,7 @@ import java.util.Date;
*
*/
public class DataSetResDirectory extends AbstractStringIdEntity
implements CreateUserEntity<String>, DataPermissionEntity<String>
implements CreateUserEntity<String>, DataPermissionEntity<String>, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -113,4 +115,13 @@ public class DataSetResDirectory extends AbstractStringIdEntity
return getClass().getSimpleName() + " [directory=" + directory + ", desc=" + desc + ", createUser=" + createUser
+ ", createTime=" + createTime + ", dataPermission=" + dataPermission + "]";
}
@Override
public DataSetResDirectory clone()
{
DataSetResDirectory entity = new DataSetResDirectory();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -15,6 +15,7 @@ import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.DataSetQuery;
import org.datagear.analysis.support.AbstractExcelDataSet;
import org.datagear.analysis.support.ExcelDirectoryFileDataSet;
import org.springframework.beans.BeanUtils;
/**
* {@linkplain ExcelDirectoryFileDataSet}实体
@ -22,7 +23,7 @@ import org.datagear.analysis.support.ExcelDirectoryFileDataSet;
* @author datagear@163.com
*
*/
public class ExcelDataSetEntity extends AbstractExcelDataSet implements DirectoryFileDataSetEntity
public class ExcelDataSetEntity extends AbstractExcelDataSet implements DirectoryFileDataSetEntity, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -225,4 +226,13 @@ public class ExcelDataSetEntity extends AbstractExcelDataSet implements Director
{
return FILE_SUPPORT.getFile(this, query);
}
@Override
public ExcelDataSetEntity clone()
{
ExcelDataSetEntity entity = new ExcelDataSetEntity();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -12,6 +12,7 @@ import java.util.Date;
import org.datagear.analysis.support.ChartWidget;
import org.datagear.analysis.support.html.HtmlChartPlugin;
import org.datagear.analysis.support.html.HtmlChartWidget;
import org.springframework.beans.BeanUtils;
/**
* HTML {@linkplain ChartWidget}实体
@ -20,7 +21,8 @@ import org.datagear.analysis.support.html.HtmlChartWidget;
*
*/
public class HtmlChartWidgetEntity extends HtmlChartWidget
implements CreateUserEntity<String>, DataPermissionEntity<String>, AnalysisProjectAwareEntity<String>
implements CreateUserEntity<String>, DataPermissionEntity<String>, AnalysisProjectAwareEntity<String>,
CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -121,4 +123,27 @@ public class HtmlChartWidgetEntity extends HtmlChartWidget
{
this.analysisProject = analysisProject;
}
@Override
public HtmlChartWidgetEntity clone()
{
HtmlChartWidgetEntity entity = new HtmlChartWidgetEntity();
BeanUtils.copyProperties(this, entity);
ChartDataSetVO[] chartDataSetVOs = entity.getChartDataSetVOs();
if (chartDataSetVOs != null && chartDataSetVOs.length != 0)
{
ChartDataSetVO[] cloned = new ChartDataSetVO[chartDataSetVOs.length];
for (int i = 0; i < chartDataSetVOs.length; i++)
{
cloned[i] = chartDataSetVOs[i].clone();
}
entity.setChartDataSetVOs(cloned);
}
return entity;
}
}

View File

@ -14,6 +14,7 @@ import org.datagear.analysis.support.JsonSupport;
import org.datagear.analysis.support.html.HtmlTplDashboardWidget;
import org.datagear.analysis.support.html.HtmlTplDashboardWidgetHtmlRenderer;
import org.datagear.util.StringUtil;
import org.springframework.beans.BeanUtils;
/**
* {@linkplain HtmlTplDashboardWidget}实体
@ -22,7 +23,8 @@ import org.datagear.util.StringUtil;
*
*/
public class HtmlTplDashboardWidgetEntity extends HtmlTplDashboardWidget
implements CreateUserEntity<String>, DataPermissionEntity<String>, AnalysisProjectAwareEntity<String>
implements CreateUserEntity<String>, DataPermissionEntity<String>, AnalysisProjectAwareEntity<String>,
CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -178,6 +180,15 @@ public class HtmlTplDashboardWidgetEntity extends HtmlTplDashboardWidget
setTemplates(splitTemplates(template));
}
@Override
public HtmlTplDashboardWidgetEntity clone()
{
HtmlTplDashboardWidgetEntity entity = new HtmlTplDashboardWidgetEntity();
BeanUtils.copyProperties(this, entity);
return entity;
}
/**
* 返回{@linkplain #TEMPLATE_SPLITTER}分隔符合并后的字符串
*

View File

@ -13,6 +13,7 @@ import java.util.List;
import org.apache.hc.client5.http.classic.HttpClient;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.support.HttpDataSet;
import org.springframework.beans.BeanUtils;
/**
* {@linkplain HttpDataSet}实体
@ -20,7 +21,7 @@ import org.datagear.analysis.support.HttpDataSet;
* @author datagear@163.com
*
*/
public class HttpDataSetEntity extends HttpDataSet implements DataSetEntity
public class HttpDataSetEntity extends HttpDataSet implements DataSetEntity, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -116,4 +117,13 @@ public class HttpDataSetEntity extends HttpDataSet implements DataSetEntity
{
this.analysisProject = analysisProject;
}
@Override
public HttpDataSetEntity clone()
{
HttpDataSetEntity entity = new HttpDataSetEntity();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -15,6 +15,7 @@ import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.DataSetQuery;
import org.datagear.analysis.support.AbstractJsonFileDataSet;
import org.datagear.analysis.support.JsonDirectoryFileDataSet;
import org.springframework.beans.BeanUtils;
/**
* {@linkplain JsonDirectoryFileDataSet}实体
@ -22,7 +23,7 @@ import org.datagear.analysis.support.JsonDirectoryFileDataSet;
* @author datagear@163.com
*
*/
public class JsonFileDataSetEntity extends AbstractJsonFileDataSet implements DirectoryFileDataSetEntity
public class JsonFileDataSetEntity extends AbstractJsonFileDataSet implements DirectoryFileDataSetEntity, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -227,4 +228,13 @@ public class JsonFileDataSetEntity extends AbstractJsonFileDataSet implements Di
{
return FILE_SUPPORT.getFile(this, query);
}
@Override
public JsonFileDataSetEntity clone()
{
JsonFileDataSetEntity entity = new JsonFileDataSetEntity();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -12,6 +12,7 @@ import java.util.List;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.support.JsonValueDataSet;
import org.springframework.beans.BeanUtils;
/**
* {@linkplain JsonValueDataSet}实体
@ -19,7 +20,7 @@ import org.datagear.analysis.support.JsonValueDataSet;
* @author datagear@163.com
*
*/
public class JsonValueDataSetEntity extends JsonValueDataSet implements DataSetEntity
public class JsonValueDataSetEntity extends JsonValueDataSet implements DataSetEntity, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -108,4 +109,13 @@ public class JsonValueDataSetEntity extends JsonValueDataSet implements DataSetE
{
this.analysisProject = analysisProject;
}
@Override
public JsonValueDataSetEntity clone()
{
JsonValueDataSetEntity entity = new JsonValueDataSetEntity();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -7,13 +7,15 @@
package org.datagear.management.domain;
import org.springframework.beans.BeanUtils;
/**
* 角色
*
* @author datagear@163.com
*
*/
public class Role extends AbstractStringIdEntity
public class Role extends AbstractStringIdEntity implements CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -90,6 +92,15 @@ public class Role extends AbstractStringIdEntity
this.enabled = enabled;
}
@Override
public Role clone()
{
Role entity = new Role();
BeanUtils.copyProperties(this, entity);
return entity;
}
/**
* 给定角色ID是否是内置角色
*

View File

@ -7,13 +7,15 @@
package org.datagear.management.domain;
import org.springframework.beans.BeanUtils;
/**
* 角色-用户
*
* @author datagear@163.com
*
*/
public class RoleUser extends AbstractStringIdEntity
public class RoleUser extends AbstractStringIdEntity implements CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -54,4 +56,13 @@ public class RoleUser extends AbstractStringIdEntity
{
this.user = user;
}
@Override
public RoleUser clone()
{
RoleUser entity = new RoleUser();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -10,6 +10,7 @@ package org.datagear.management.domain;
import java.util.Date;
import org.datagear.connection.DriverEntity;
import org.springframework.beans.BeanUtils;
/**
* 数据库模式实体
@ -18,7 +19,7 @@ import org.datagear.connection.DriverEntity;
*
*/
public class Schema extends AbstractStringIdEntity
implements CreateUserEntity<String>, DataPermissionEntity<String>, Cloneable
implements CreateUserEntity<String>, DataPermissionEntity<String>, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -190,13 +191,10 @@ public class Schema extends AbstractStringIdEntity
@Override
public Schema clone()
{
Schema schema = new Schema(this.getId(), this.title, this.url, this.user, this.password);
schema.setCreateUser(this.createUser);
schema.setCreateTime(this.createTime);
schema.setDriverEntity(this.driverEntity);
schema.setDataPermission(this.dataPermission);
Schema entity = new Schema();
BeanUtils.copyProperties(this, entity);
return schema;
return entity;
}
/**

View File

@ -13,6 +13,7 @@ import java.util.List;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.support.SqlDataSet;
import org.datagear.util.resource.ConnectionFactory;
import org.springframework.beans.BeanUtils;
/**
* {@linkplain SqlDataSet}实体
@ -20,7 +21,7 @@ import org.datagear.util.resource.ConnectionFactory;
* @author datagear@163.com
*
*/
public class SqlDataSetEntity extends SqlDataSet implements DataSetEntity
public class SqlDataSetEntity extends SqlDataSet implements DataSetEntity, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -159,4 +160,13 @@ public class SqlDataSetEntity extends SqlDataSet implements DataSetEntity
{
this.analysisProject = analysisProject;
}
@Override
public SqlDataSetEntity clone()
{
SqlDataSetEntity entity = new SqlDataSetEntity();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -15,6 +15,7 @@ import org.datagear.analysis.DataSetException;
import org.datagear.analysis.DataSetQuery;
import org.datagear.analysis.DataSetResult;
import org.datagear.analysis.support.AbstractDataSet;
import org.springframework.beans.BeanUtils;
/**
* 概要{@linkplain DataSetEntity}
@ -25,7 +26,7 @@ import org.datagear.analysis.support.AbstractDataSet;
* @author datagear@163.com
*
*/
public class SummaryDataSetEntity extends AbstractDataSet implements DataSetEntity
public class SummaryDataSetEntity extends AbstractDataSet implements DataSetEntity, CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -119,4 +120,13 @@ public class SummaryDataSetEntity extends AbstractDataSet implements DataSetEnti
{
throw new UnsupportedOperationException();
}
@Override
public SummaryDataSetEntity clone()
{
SummaryDataSetEntity entity = new SummaryDataSetEntity();
BeanUtils.copyProperties(this, entity);
return entity;
}
}

View File

@ -9,16 +9,17 @@ package org.datagear.management.domain;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.BeanUtils;
/**
* 用户实体
*
* @author datagear@163.com
*
*/
public class User extends AbstractStringIdEntity
public class User extends AbstractStringIdEntity implements CloneableEntity
{
private static final long serialVersionUID = 1L;
@ -169,6 +170,28 @@ public class User extends AbstractStringIdEntity
return nameLabel;
}
@Override
public User clone()
{
User entity = new User();
BeanUtils.copyProperties(this, entity);
return entity;
}
/**
* 拷贝对象排除密码
*
* @return
*/
public User cloneWithoutPassword()
{
User entity = clone();
entity.setPassword(null);
return entity;
}
/**
* 是否是内置管理员账号
*
@ -190,27 +213,4 @@ public class User extends AbstractStringIdEntity
{
return ADMIN_USER_ID.equals(userId);
}
/**
* 拷贝对象排除密码
*
* @param user
* @return
*/
public static User copyWithoutPassword(User user)
{
User re = new User(user.getId());
re.setName(user.getName());
re.setRealName(user.getRealName());
re.setEmail(user.getEmail());
re.setAdmin(user.isAdmin());
re.setAnonymous(user.isAnonymous());
re.setCreateTime(user.getCreateTime());
if (user.getRoles() != null)
re.setRoles(new HashSet<>(user.getRoles()));
return re;
}
}

View File

@ -9,8 +9,12 @@ package org.datagear.management.service.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.management.domain.Authorization;
@ -26,6 +30,8 @@ import org.datagear.persistence.PagingQuery;
import org.datagear.persistence.Query;
import org.datagear.util.StringUtil;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
/**
* 抽象基于Mybatis的{@linkplain DataPermissionEntityService}实现类
@ -36,6 +42,8 @@ import org.mybatis.spring.SqlSessionTemplate;
public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends DataPermissionEntity<ID>>
extends AbstractMybatisEntityService<ID, T> implements DataPermissionEntityService<ID, T>
{
private Cache permissionCache;
public AbstractMybatisDataPermissionEntityService()
{
super();
@ -51,13 +59,23 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
super(sqlSessionTemplate, dialect);
}
public Cache getPermissionCache()
{
return permissionCache;
}
public void setPermissionCache(Cache permissionCache)
{
this.permissionCache = permissionCache;
}
@Override
public int getPermission(User user, ID id)
{
List<ID> ids = new ArrayList<>(1);
ids.add(id);
List<Integer> permissions = getPermissions(user, ids, PERMISSION_NOT_FOUND);
List<Integer> permissions = getPermissions(user, ids);
return permissions.get(0);
}
@ -67,7 +85,7 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
{
List<ID> idList = Arrays.asList(ids);
List<Integer> permissions = getPermissions(user, idList, PERMISSION_NOT_FOUND);
List<Integer> permissions = getPermissions(user, idList);
int[] re = new int[permissions.size()];
@ -137,11 +155,6 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
@Override
public T getById(User user, ID id) throws PermissionDeniedException
{
return getById(user, id, true);
}
protected T getById(User user, ID id, boolean postProcessSelect) throws PermissionDeniedException
{
int permission = getPermission(user, id);
@ -151,7 +164,15 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
Map<String, Object> params = buildParamMap();
addDataPermissionParameters(params, user);
return getById(id, params, postProcessSelect);
T entity = getById(id, params);
if (entity != null)
{
entity.setDataPermission(permission);
entity = postProcessGet(entity);
}
return entity;
}
@Override
@ -165,7 +186,15 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
Map<String, Object> params = buildParamMap();
addDataPermissionParameters(params, user);
return getById(id, params);
T entity = getById(id, params);
if (entity != null)
{
entity.setDataPermission(permission);
entity = postProcessGet(entity);
}
return entity;
}
@Override
@ -214,30 +243,109 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
/**
* 获取权限列表
* <p>
* 对于没有授权的将返回{@linkplain #PERMISSION_NOT_FOUND}权限值
* </p>
*
* @param user
* @param ids
* @param permissionForAbsence
* @return
*/
protected List<Integer> getPermissions(User user, List<ID> ids, int permissionForAbsence)
protected List<Integer> getPermissions(User user, List<ID> ids)
{
int len = ids.size();
Map<ID, Integer> permissions = getCachedPermissions(user, ids);
List<ID> noCachedIds = Collections.emptyList();
if (permissions.isEmpty())
noCachedIds = ids;
else
{
for (int i = 0; i < len; i++)
{
ID id = ids.get(i);
if (!permissions.containsKey(id))
noCachedIds.add(id);
}
}
getPermissionsFromDB(user, noCachedIds, permissions);
List<Integer> re = new ArrayList<>(len);
for (int i = 0; i < len; i++)
{
ID id = ids.get(i);
Integer permission = permissions.get(id);
if (permission == null)
permission = PERMISSION_NOT_FOUND;
re.add(permission);
}
return re;
}
/**
* 获取缓存中的权限
*
* @param user
* @param ids
* @return
*/
protected Map<ID, Integer> getCachedPermissions(User user, List<ID> ids)
{
Map<ID, Integer> permissions = new HashMap<ID, Integer>();
if (this.permissionCache == null)
return permissions;
String userId = user.getId();
for (int i = 0, len = ids.size(); i < len; i++)
{
ID id = ids.get(i);
Integer permission = cacheGetPermission(id, userId);
if (permission != null)
permissions.put(id, permission);
}
return permissions;
}
/**
* 获取底层数据库的权限
*
* @param user
* @param ids
* @param permissions
*/
protected void getPermissionsFromDB(User user ,List<ID> ids, Map<ID, Integer> permissions)
{
if(ids.isEmpty())
return;
String userId = user.getId();
Map<String, Object> params = buildParamMap();
addDataPermissionParameters(params, user);
params.put("ids", ids);
List<DataIdPermission> dataPermissions = selectListMybatis("getDataIdPermissions", params);
List<Integer> re = new ArrayList<>(ids.size());
for (int i = 0, len = ids.size(); i < len; i++)
{
Integer permission = null;
String myId = ids.get(i).toString();
ID id = ids.get(i);
String idStr = id.toString();
for (DataIdPermission p : dataPermissions)
{
if (myId.equals(p.getDataId()))
if (idStr.equals(p.getDataId()))
{
permission = p.getDataPermission();
break;
@ -245,12 +353,52 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
}
if (permission == null)
permission = permissionForAbsence;
permission = PERMISSION_NOT_FOUND;
permissions.put(id, permission);
re.add(permission);
cachePutPermission(id, userId, permission);
}
}
protected Integer cacheGetPermission(ID id, String userId)
{
if (this.permissionCache == null)
return null;
ValueWrapper valueWrapper = cacheGet(this.permissionCache, toPermissionCacheKey(id));
UserIdPermissionMap upm = (valueWrapper == null ? null : (UserIdPermissionMap) valueWrapper.get());
return (upm == null ? null : upm.getPermission(userId));
}
protected void cachePutPermission(ID id, String userId, int permission)
{
if (this.permissionCache == null)
return;
Object key = toPermissionCacheKey(id);
ValueWrapper valueWrapper = cacheGet(this.permissionCache, key);
UserIdPermissionMap upm = (valueWrapper == null ? null : (UserIdPermissionMap) valueWrapper.get());
if (upm == null)
{
upm = new UserIdPermissionMap();
cachePut(this.permissionCache, key, upm);
}
return re;
upm.putPermission(userId, permission);
}
/**
* 获取指定实体ID的权限缓存关键字
*
* @param id
* @return
*/
protected Object toPermissionCacheKey(ID id)
{
return id;
}
/**
@ -279,4 +427,29 @@ public abstract class AbstractMybatisDataPermissionEntityService<ID, T extends D
params.put(DATA_PERMISSION_PARAM_MAX_PERMISSION, Authorization.PERMISSION_MAX);
params.put(DATA_PERMISSION_PARAM_UNSET_PERMISSION, Authorization.PERMISSION_NONE_START);
}
protected static class UserIdPermissionMap
{
private ConcurrentMap<String, Integer> userIdPermissions = new ConcurrentHashMap<String, Integer>();
public UserIdPermissionMap()
{
super();
}
public Integer getPermission(String userId)
{
return this.userIdPermissions.get(userId);
}
public void putPermission(String userId, Integer permission)
{
this.userIdPermissions.put(userId, permission);
}
public void clear()
{
this.userIdPermissions.clear();
}
}
}

View File

@ -12,6 +12,7 @@ import java.util.Map;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.management.domain.CloneableEntity;
import org.datagear.management.domain.Entity;
import org.datagear.management.service.EntityService;
import org.datagear.management.util.dialect.MbSqlDialect;
@ -20,6 +21,8 @@ import org.datagear.persistence.PagingQuery;
import org.datagear.persistence.Query;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.support.SimpleValueWrapper;
/**
* 抽象基于Mybatis的{@linkplain EntityService}实现类
@ -32,8 +35,16 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
{
private Cache cache = null;
/** 查询操作时缓存实体数目 */
private int cacheCountForQuery = 50;
/**
* 查询操作时缓存实体数目
* <p>
* 默认为{@code 0}不缓存查询操作结果
* </p>
* <p>
* 谨慎设置此值因为目前为了提高查询效率有些服务实现类里查询返回的并不是完全的可用的实体不能作为缓存使用比如未加载一对多值对象
* </p>
*/
private int cacheCountForQuery = 0;
public AbstractMybatisEntityService()
{
@ -102,7 +113,12 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
@Override
public T getById(ID id)
{
return getById(id, buildParamMap());
T entity = getById(id, buildParamMap());
if (entity != null)
entity = postProcessGet(entity);
return entity;
}
@Override
@ -118,45 +134,47 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
}
/**
* 获取
* 获取实体
*
* @param id
* @param params
* @return
*/
@SuppressWarnings("unchecked")
protected T getById(ID id, Map<String, Object> params)
{
T entity = null;
ValueWrapper entityWrapper = cacheGet(id);
if (entityWrapper != null)
{
entity = (T) entityWrapper.get();
}
else
{
entity = getByIdFromDB(id, params);
cachePut(id, entity);
}
return entity;
}
/**
* 从底层数据库获取实体
* <p>
* 此方法内部会执行{@linkplain #postProcessSelect(Object)}
* 此方法调用底层的{@code getById} SQL
* </p>
*
* @param id
* @param params
* @return
*/
protected T getById(ID id, Map<String, Object> params)
protected T getByIdFromDB(ID id, Map<String, Object> params)
{
return getById(id, params, true);
}
/**
* 获取
*
* @param id
* @param params
* @param postProcessSelect
* 是否内部执行{@linkplain #postProcessSelect(Object)}
* @return
*/
protected T getById(ID id, Map<String, Object> params, boolean postProcessSelect)
{
T entity = cacheGet(id);
if (entity == null)
{
params.put("id", id);
entity = selectOneMybatis("getById", params);
cachePut(id, entity);
}
if (postProcessSelect && entity != null)
entity = postProcessSelect(entity);
return entity;
params.put("id", id);
return selectOneMybatis("getById", params);
}
@Override
@ -169,6 +187,9 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
/**
* 删除
* <p>
* 此方法调用底层的{@code deleteById} SQL
* </p>
*
* @param id
* @param params
@ -184,28 +205,21 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
}
@Override
protected List<T> query(String statement, Map<String, Object> params, boolean postProcessSelects)
protected List<T> query(String statement, Map<String, Object> params)
{
List<T> list = super.query(statement, params, false);
List<T> list = super.query(statement, params);
cachePut(list);
if (postProcessSelects)
postProcessSelects(list);
cachePutQueryResult(list);
return list;
}
@Override
protected List<T> query(String statement, Map<String, Object> params, RowBounds rowBounds,
boolean postProcessSelects)
protected List<T> query(String statement, Map<String, Object> params, RowBounds rowBounds)
{
List<T> list = super.query(statement, params, rowBounds, false);
List<T> list = super.query(statement, params, rowBounds);
cachePut(list);
if (postProcessSelects)
postProcessSelects(list);
cachePutQueryResult(list);
return list;
}
@ -226,20 +240,54 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
/**
* 拷贝缓存值
* <p>
* 当从缓存中取出对象时将对象放入缓存时进行拷贝
* 当从缓存中取出对象时{@linkplain #cacheGet(Object)}将对象放入缓存时{@linkplain #cachePut(Object, Entity)}进行拷贝
* </p>
* <p>
* 此方法默认返回原对象子类应根据实际情况对象是否会被修改决定是否需要真正拷贝
* 此方法默认是现是如果{@code value}{@linkplain CloneableEntity}则返回{@linkplain CloneableEntity#clone()}否则返回原对象
* </p>
*
* @param value
* @return
*/
@SuppressWarnings("unchecked")
protected T cacheCloneValue(T value)
{
if (value instanceof CloneableEntity)
return (T) ((CloneableEntity) value).clone();
return value;
}
/**
* 获取指定实体ID的缓存关键字
*
* @param id
* @return
*/
protected Object toCacheKey(ID id)
{
return id;
}
protected ValueWrapper cacheGet(ID id)
{
if (!cacheEnabled())
return null;
ValueWrapper valueWrapper = cacheGet(getCache(), toCacheKey(id));
if (valueWrapper == null)
return null;
@SuppressWarnings("unchecked")
T value = (T) valueWrapper.get();
if (value != null)
value = cacheCloneValue(value);
return new SimpleValueWrapper(value);
}
protected void cachePut(ID id, T value)
{
if (!cacheEnabled())
@ -248,10 +296,10 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
if (value != null)
value = cacheCloneValue(value);
cachePut(getCache(), value.getId(), value);
cachePut(getCache(), toCacheKey(id), value);
}
protected void cachePut(List<T> values)
protected void cachePutQueryResult(List<T> values)
{
if (!cacheEnabled())
return;
@ -265,30 +313,17 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
if (value != null)
{
value = cacheCloneValue(value);
cachePut(getCache(), value.getId(), value);
cachePut(getCache(), toCacheKey(value.getId()), value);
}
}
}
protected T cacheGet(ID key)
{
if (!cacheEnabled())
return null;
T value = cacheGet(getCache(), key);
if (value != null)
value = cacheCloneValue(value);
return value;
}
protected void cacheEvict(ID key)
protected void cacheEvict(ID id)
{
if (!cacheEnabled())
return;
cacheEvict(getCache(), key);
cacheEvict(getCache(), toCacheKey(id));
}
protected void cacheInvalidate()
@ -298,37 +333,4 @@ public abstract class AbstractMybatisEntityService<ID, T extends Entity<ID>> ext
cacheInvalidate(getCache());
}
protected void cachePut(Cache cache, Object key, Object value)
{
if (cache == null)
return;
cache.put(key, value);
}
@SuppressWarnings("unchecked")
protected <TT> TT cacheGet(Cache cache, Object key)
{
if (cache == null)
return null;
return (TT) cache.get(key);
}
protected void cacheEvict(Cache cache, Object key)
{
if (cache == null)
return;
cache.evict(key);
}
protected void cacheInvalidate(Cache cache)
{
if (cache == null)
return;
cache.invalidate();
}
}

View File

@ -22,6 +22,8 @@ import org.datagear.persistence.Query;
import org.datagear.util.StringUtil;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
/**
* 抽象基于Mybatis的服务类
@ -143,6 +145,9 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
/**
* 更新
* <p>
* 此方法调用底层的{@code update} SQL
* </p>
*
* @param entity
* @param params
@ -184,31 +189,35 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
protected T get(T param)
{
return get(param, buildParamMap(), true);
T obj = get(param, buildParamMap());
if (obj != null)
obj = postProcessGet(obj);
return obj;
}
/**
* 获取
* <p>
* 此方法调用底层的{@code get} SQL
* </p>
*
* @param id
* @param params
* @param postProcessSelect 是否内部执行{@linkplain #postProcessSelect(Object)}
* @return
*/
protected T get(T param, Map<String, Object> params, boolean postProcessSelect)
protected T get(T param, Map<String, Object> params)
{
params.put("param", param);
T entity = selectOneMybatis("get", params);
if (postProcessSelect && entity != null)
entity = postProcessSelect(entity);
return entity;
return selectOneMybatis("get", params);
}
/**
* 查询
* <p>
* 此方法调用底层的{@code query} SQL
* </p>
*
* @param query
* @return
@ -220,6 +229,9 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
/**
* 查询
* <p>
* 此方法调用底层的{@code query} SQL
* </p>
*
* @param query
* @param params
@ -242,11 +254,18 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
{
addQueryParam(params, query);
return query(statement, params, true);
List<T> list = query(statement, params);
postProcessQuery(list);
return list;
}
/**
* 分页查询
* <p>
* 此方法调用底层的{@code pagingQuery}{@code pagingQueryCount} SQL
* </p>
*
* @param pagingQuery
* @return
@ -258,6 +277,9 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
/**
* 分页查询
* <p>
* 此方法调用底层的{@code pagingQuery}{@code pagingQueryCount} SQL
* </p>
*
* @param pagingQuery
* @param params
@ -271,7 +293,7 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
/**
* 分页查询
* <p>
* 此方法要求已定义{@code [statement]Count} SQL Mapper例如
* 此方法要求已定义{@code [statement]Count} SQL例如
* </p>
* <p>
* 如果{@code statement}{@code "pagingQuery"}那么必须已定义{@code "pagingQueryCount"}
@ -298,9 +320,11 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
List<T> list = null;
if (this.dialect.supportsPaging())
list = query(statement, params, true);
list = query(statement, params);
else
list = query(statement, params, new RowBounds(startIndex, pagingData.getPageSize()), true);
list = query(statement, params, new RowBounds(startIndex, pagingData.getPageSize()));
postProcessQuery(list);
pagingData.setItems(list);
@ -312,18 +336,11 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
*
* @param statement
* @param params
* @param postProcessSelects
* 是否内部执行{@linkplain #postProcessSelects(List)}
* @return
*/
protected List<T> query(String statement, Map<String, Object> params, boolean postProcessSelects)
protected List<T> query(String statement, Map<String, Object> params)
{
List<T> list = selectListMybatis(statement, params);
if (postProcessSelects)
postProcessSelects(list);
return list;
return selectListMybatis(statement, params);
}
/**
@ -332,56 +349,51 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
* @param statement
* @param params
* @param rowBounds
* @param postProcessSelects
* 是否内部执行{@linkplain #postProcessSelects(List)}
* @return
*/
protected List<T> query(String statement, Map<String, Object> params, RowBounds rowBounds,
boolean postProcessSelects)
protected List<T> query(String statement, Map<String, Object> params, RowBounds rowBounds)
{
List<T> list = selectListMybatis(statement, params, rowBounds);
if (postProcessSelects)
postProcessSelects(list);
return list;
return selectListMybatis(statement, params, rowBounds);
}
/**
* 后置处理查询结果列
* 后置处理查询结果列
* <p>
* 此方法对每一个元素调用{@linkplain #postProcessSelect(Object)}
* {@linkplain #query(Query)}{@linkplain #query(Query, Map)}{@linkplain #query(String, Query, Map)}
* {@linkplain #pagingQuery(PagingQuery)}{@linkplain #pagingQuery(PagingQuery, Map)}{@linkplain #pagingQuery(String, PagingQuery, Map)}
* 内部会调用此方法
* </p>
* <p>
* 子类可以重写此方法已实现特定的查询结果处理逻辑
* </p>
* <p>
* 此方法的默认实现是什么也不做
* </p>
*
* @param list
* 不会为{@code null}
*/
protected void postProcessSelects(List<T> list)
protected void postProcessQuery(List<T> list)
{
if (list == null)
return;
for (int i = 0; i < list.size(); i++)
{
T ele = list.get(i);
if (ele != null)
{
ele = postProcessSelect(ele);
list.set(i, ele);
}
}
}
/**
* 后置处理读取结果
* 后置处理获取操作结果
* <p>
* 默认为空方法子类可以重写已实现特定的查询结果处理逻辑
* {@linkplain #get(Object, Map, boolean)}{@code postProcessGet}{@code true}其内部会调用此方法
* </p>
* <p>
* 子类可以重写此方法已实现特定的获取操作结果处理逻辑
* </p>
* <p>
* 此方法的默认实现是直接返回{@code obj}
* </p>
*
* @param obj 不会为{@code null}
* @param obj
* 不会为{@code null}
* @return
*/
protected T postProcessSelect(T obj)
protected T postProcessGet(T obj)
{
return obj;
}
@ -712,6 +724,38 @@ public abstract class AbstractMybatisService<T> extends SqlSessionDaoSupport
return new HashMap<>();
}
protected ValueWrapper cacheGet(Cache cache, Object key)
{
if (cache == null)
return null;
return cache.get(key);
}
protected void cachePut(Cache cache, Object key, Object value)
{
if (cache == null)
return;
cache.put(key, value);
}
protected void cacheEvict(Cache cache, Object key)
{
if (cache == null)
return;
cache.evict(key);
}
protected void cacheInvalidate(Cache cache)
{
if (cache == null)
return;
cache.invalidate();
}
/**
* 获取sql语句的名字空间
*

View File

@ -10,6 +10,7 @@ package org.datagear.management.service.impl;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.management.domain.Authorization;
import org.datagear.management.domain.DataPermissionEntity;
@ -17,9 +18,6 @@ import org.datagear.management.domain.User;
import org.datagear.management.service.AuthorizationService;
import org.datagear.management.service.DataPermissionEntityService;
import org.datagear.management.util.dialect.MbSqlDialect;
import org.datagear.persistence.PagingData;
import org.datagear.persistence.PagingQuery;
import org.datagear.persistence.Query;
import org.mybatis.spring.SqlSessionTemplate;
/**
@ -117,34 +115,29 @@ public class AuthorizationServiceImpl extends AbstractMybatisEntityService<Strin
}
@Override
protected Authorization getById(String id, Map<String, Object> params, boolean postProcessSelect)
protected Authorization getByIdFromDB(String id, Map<String, Object> params)
{
setAuthorizationQueryContext(params);
return super.getById(id, params, postProcessSelect);
return super.getByIdFromDB(id, params);
}
@Override
protected List<Authorization> query(String statement, Query query, Map<String, Object> params)
protected List<Authorization> query(String statement, Map<String, Object> params)
{
setAuthorizationQueryContext(params);
return super.query(statement, query, params);
return super.query(statement, params);
}
@Override
protected PagingData<Authorization> pagingQuery(String statement, PagingQuery pagingQuery,
Map<String, Object> params)
protected List<Authorization> query(String statement, Map<String, Object> params, RowBounds rowBounds)
{
setAuthorizationQueryContext(params);
return super.pagingQuery(statement, pagingQuery, params);
return super.query(statement, params, rowBounds);
}
protected AuthorizationQueryContext setAuthorizationQueryContext(Map<String, Object> params)
{
AuthorizationQueryContext context = AuthorizationQueryContext.get();
params.put("queryContext", context);
return context;

View File

@ -173,8 +173,7 @@ public class DataSetEntityServiceImpl extends AbstractMybatisDataPermissionEntit
{
ProfileDataSet profileDataSet = null;
DataSetEntity entity = getById(user, id, false);
inflateParamsAndProperties(entity);
DataSetEntity entity = getById(user, id);
profileDataSet = ProfileDataSet.valueOf(entity);
@ -386,6 +385,34 @@ public class DataSetEntityServiceImpl extends AbstractMybatisDataPermissionEntit
return getById(user, id);
}
@Override
protected DataSetEntity getByIdFromDB(String id, Map<String, Object> params)
{
DataSetEntity entity = super.getByIdFromDB(id, params);
if (entity == null)
return null;
if (DataSetEntity.DATA_SET_TYPE_SQL.equals(entity.getDataSetType()))
entity = getSqlDataSetEntityById(entity.getId());
else if (DataSetEntity.DATA_SET_TYPE_JsonValue.equals(entity.getDataSetType()))
entity = getJsonValueDataSetEntityById(entity.getId());
else if (DataSetEntity.DATA_SET_TYPE_JsonFile.equals(entity.getDataSetType()))
entity = getJsonFileDataSetEntityById(entity.getId());
else if (DataSetEntity.DATA_SET_TYPE_Excel.equals(entity.getDataSetType()))
entity = getExcelDataSetEntityById(entity.getId());
else if (DataSetEntity.DATA_SET_TYPE_CsvValue.equals(entity.getDataSetType()))
entity = getCsvValueDataSetEntityById(entity.getId());
else if (DataSetEntity.DATA_SET_TYPE_CsvFile.equals(entity.getDataSetType()))
entity = getCsvFileDataSetEntityById(entity.getId());
else if (DataSetEntity.DATA_SET_TYPE_Http.equals(entity.getDataSetType()))
entity = getHttpDataSetEntityById(entity.getId());
inflateParamsAndProperties(entity);
return entity;
}
@Override
protected boolean deleteById(String id, Map<String, Object> params)
{
@ -399,44 +426,6 @@ public class DataSetEntityServiceImpl extends AbstractMybatisDataPermissionEntit
return deleted;
}
@Override
protected void postProcessSelects(List<DataSetEntity> list)
{
// XXX 查询操作仅用于展示不必完全加载
// super.postProcessSelects(list);
}
@Override
protected DataSetEntity postProcessSelect(DataSetEntity obj)
{
DataSetEntity initObj = obj;
if (DataSetEntity.DATA_SET_TYPE_SQL.equals(obj.getDataSetType()))
obj = getSqlDataSetEntityById(obj.getId());
else if (DataSetEntity.DATA_SET_TYPE_JsonValue.equals(obj.getDataSetType()))
obj = getJsonValueDataSetEntityById(obj.getId());
else if (DataSetEntity.DATA_SET_TYPE_JsonFile.equals(obj.getDataSetType()))
obj = getJsonFileDataSetEntityById(obj.getId());
else if (DataSetEntity.DATA_SET_TYPE_Excel.equals(obj.getDataSetType()))
obj = getExcelDataSetEntityById(obj.getId());
else if (DataSetEntity.DATA_SET_TYPE_CsvValue.equals(obj.getDataSetType()))
obj = getCsvValueDataSetEntityById(obj.getId());
else if (DataSetEntity.DATA_SET_TYPE_CsvFile.equals(obj.getDataSetType()))
obj = getCsvFileDataSetEntityById(obj.getId());
else if (DataSetEntity.DATA_SET_TYPE_Http.equals(obj.getDataSetType()))
obj = getHttpDataSetEntityById(obj.getId());
if (obj == null)
return null;
// 这里必须设置全限值为了效率上述子类的底层查询并未返回全限值
obj.setDataPermission(initObj.getDataPermission());
inflateParamsAndProperties(obj);
return obj;
}
protected void inflateParamsAndProperties(DataSetEntity dataSetEntity)
{
if (dataSetEntity == null)

View File

@ -17,10 +17,15 @@ import java.util.Map;
import java.util.Set;
import org.apache.ibatis.session.SqlSessionFactory;
import org.datagear.analysis.AbstractIdentifiable;
import org.datagear.analysis.ChartDataSet;
import org.datagear.analysis.ChartPluginManager;
import org.datagear.analysis.DataSet;
import org.datagear.analysis.DataSetException;
import org.datagear.analysis.DataSetParam;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.DataSetQuery;
import org.datagear.analysis.DataSetResult;
import org.datagear.analysis.support.ChartWidget;
import org.datagear.analysis.support.JsonSupport;
import org.datagear.analysis.support.html.HtmlChartPlugin;
@ -120,15 +125,38 @@ public class HtmlChartWidgetEntityServiceImpl
HtmlChartWidgetEntity entity = null;
if (context.hasUser())
entity = getById(context.getUser(), id);
entity = super.getById(context.getUser(), id);
else
entity = getById(id);
entity = super.getById(id);
if (entity == null)
return null;
inflateHtmlChartWidgetEntity(entity, true);
setHtmlChartPlugin(entity, true);
setChartDataSets(entity, true);
return entity;
}
@Override
public HtmlChartWidgetEntity getById(User user, String id) throws PermissionDeniedException
{
HtmlChartWidgetEntity entity = super.getById(user, id);
inflateHtmlChartWidgetEntity(entity, false);
return entity;
}
@Override
public HtmlChartWidgetEntity getByIdForEdit(User user, String id) throws PermissionDeniedException
{
HtmlChartWidgetEntity entity = super.getByIdForEdit(user, id);
inflateHtmlChartWidgetEntity(entity, false);
return entity;
}
@Override
public HtmlChartWidgetEntity getById(String id)
{
HtmlChartWidgetEntity entity = super.getById(id);
inflateHtmlChartWidgetEntity(entity, false);
return entity;
}
@ -195,6 +223,15 @@ public class HtmlChartWidgetEntityServiceImpl
return deleted;
}
@Override
protected HtmlChartWidgetEntity getByIdFromDB(String id, Map<String, Object> params)
{
HtmlChartWidgetEntity entity = super.getByIdFromDB(id, params);
setChartDataSetVOs(entity);
return entity;
}
protected void saveWidgetDataSetRelations(HtmlChartWidgetEntity entity)
{
Map<String, Object> delParams = buildParamMap();
@ -217,23 +254,11 @@ public class HtmlChartWidgetEntityServiceImpl
}
@Override
protected void postProcessSelects(List<HtmlChartWidgetEntity> list)
protected void postProcessQuery(List<HtmlChartWidgetEntity> list)
{
// 查询操作仅用于展示不必完全加载
if (list == null)
return;
for (HtmlChartWidgetEntity e : list)
setHtmlChartPlugin(e, false);
}
@Override
protected HtmlChartWidgetEntity postProcessSelect(HtmlChartWidgetEntity obj)
{
setHtmlChartPlugin(obj, false);
setChartDataSets(obj, false);
return obj;
inflateHtmlChartPlugin(e, false);
}
@Override
@ -250,7 +275,52 @@ public class HtmlChartWidgetEntityServiceImpl
return SQL_NAMESPACE;
}
protected void setHtmlChartPlugin(HtmlChartWidgetEntity obj, boolean forAnalysis)
protected void setChartDataSetVOs(HtmlChartWidgetEntity entity)
{
Map<String, Object> sqlParams = buildParamMap();
sqlParams.put("widgetId", entity.getId());
List<WidgetDataSetRelation> relations = selectListMybatis("getDataSetRelations", sqlParams);
List<ChartDataSetVO> chartDataSets = new ArrayList<>(relations.size());
for (int i = 0; i < relations.size(); i++)
{
ChartDataSetVO chartDataSet = toChartDataSetVO(relations.get(i));
if (chartDataSet != null)
chartDataSets.add(chartDataSet);
}
entity.setChartDataSets(chartDataSets.toArray(new ChartDataSetVO[chartDataSets.size()]));
}
protected ChartDataSetVO toChartDataSetVO(WidgetDataSetRelation relation)
{
if (relation == null || StringUtil.isEmpty(relation.getDataSetId()))
return null;
IdDataSet dataSet = new IdDataSet(relation.getDataSetId());
ChartDataSetVO chartDataSet = new ChartDataSetVO(dataSet);
chartDataSet.setPropertySigns(toPropertySigns(relation.getPropertySignsJson()));
chartDataSet.setAlias(relation.getAlias());
chartDataSet.setAttachment(relation.isAttachment());
chartDataSet.setQuery(toDataSetQuery(relation.getQueryJson()));
return chartDataSet;
}
protected void inflateHtmlChartWidgetEntity(HtmlChartWidgetEntity entity, boolean forAnalysis)
{
if (entity == null)
return;
inflateHtmlChartPlugin(entity, forAnalysis);
inflateChartDataSets(entity, forAnalysis);
}
protected void inflateHtmlChartPlugin(HtmlChartWidgetEntity obj, boolean forAnalysis)
{
HtmlChartPlugin htmlChartPlugin = obj.getHtmlChartPlugin();
@ -272,48 +342,27 @@ public class HtmlChartWidgetEntityServiceImpl
}
}
protected void setChartDataSets(HtmlChartWidgetEntity widget, boolean forAnalysis)
protected void inflateChartDataSets(HtmlChartWidgetEntity entity, boolean forAnalysis)
{
Map<String, Object> sqlParams = buildParamMap();
sqlParams.put("widgetId", widget.getId());
ChartDataSetVO[] chartDataSetVOs = entity.getChartDataSetVOs();
List<WidgetDataSetRelation> relations = selectListMybatis("getDataSetRelations", sqlParams);
if (chartDataSetVOs == null || chartDataSetVOs.length == 0)
return;
List<ChartDataSetVO> chartDataSets = new ArrayList<>(relations.size());
for (int i = 0; i < relations.size(); i++)
for (int i = 0; i < chartDataSetVOs.length; i++)
{
ChartDataSetVO chartDataSet = toChartDataSet(relations.get(i), forAnalysis);
ChartDataSetVO vo = chartDataSetVOs[i];
String dataSetId = vo.getDataSet().getId();
if (chartDataSet != null)
chartDataSets.add(chartDataSet);
DataSet dataSet = null;
if (forAnalysis)
dataSet = this.dataSetEntityService.getDataSet(dataSetId);
else
dataSet = this.dataSetEntityService.getById(dataSetId);
vo.setDataSet(dataSet);
}
widget.setChartDataSets(chartDataSets.toArray(new ChartDataSetVO[chartDataSets.size()]));
}
protected ChartDataSetVO toChartDataSet(WidgetDataSetRelation relation, boolean forAnalysis)
{
if (relation == null || StringUtil.isEmpty(relation.getDataSetId()))
return null;
DataSet dataSet = null;
if (forAnalysis)
dataSet = this.dataSetEntityService.getDataSet(relation.getDataSetId());
else
dataSet = this.dataSetEntityService.getById(relation.getDataSetId());
if (dataSet == null)
return null;
ChartDataSetVO chartDataSet = new ChartDataSetVO(dataSet);
chartDataSet.setPropertySigns(toPropertySigns(relation.getPropertySignsJson()));
chartDataSet.setAlias(relation.getAlias());
chartDataSet.setAttachment(relation.isAttachment());
chartDataSet.setQuery(toDataSetQuery(relation.getQueryJson()));
return chartDataSet;
}
@SuppressWarnings("unchecked")
@ -512,4 +561,53 @@ public class HtmlChartWidgetEntityServiceImpl
this.order = order;
}
}
protected static class IdDataSet extends AbstractIdentifiable implements DataSet
{
public IdDataSet()
{
super();
}
public IdDataSet(String id)
{
super(id);
}
@Override
public String getName()
{
return "";
}
@Override
public List<DataSetProperty> getProperties()
{
return Collections.emptyList();
}
@Override
public DataSetProperty getProperty(String name)
{
return null;
}
@Override
public List<DataSetParam> getParams()
{
return Collections.emptyList();
}
@Override
public DataSetParam getParam(String name)
{
return null;
}
@Override
public DataSetResult getResult(DataSetQuery query) throws DataSetException
{
return null;
}
}
}

View File

@ -153,7 +153,7 @@ public class HtmlTplDashboardWidgetEntityServiceImpl
}
@Override
protected void postProcessSelects(List<HtmlTplDashboardWidgetEntity> list)
protected void postProcessQuery(List<HtmlTplDashboardWidgetEntity> list)
{
// XXX 查询操作仅用于展示不必完全加载
// super.postProcessSelects(list);

View File

@ -53,7 +53,7 @@ public class RoleServiceImpl extends AbstractMybatisEntityService<String, Role>
Map<String, Object> params = buildParamMap();
params.put("userId", userId);
List<Role> roles = query("findByUserId", params, true);
List<Role> roles = query("findByUserId", params);
set.addAll(roles);

View File

@ -145,7 +145,7 @@ public class SchemaServiceImpl extends AbstractMybatisDataPermissionEntityServic
}
@Override
protected Schema postProcessSelect(Schema schema)
protected Schema postProcessGet(Schema schema)
{
if (schema.hasDriverEntity())
{
@ -187,10 +187,4 @@ public class SchemaServiceImpl extends AbstractMybatisDataPermissionEntityServic
{
return SQL_NAMESPACE;
}
@Override
protected Schema cacheCloneValue(Schema value)
{
return value.clone();
}
}

View File

@ -147,7 +147,7 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
User user = selectOneMybatis("getByName", params);
if (user != null)
postProcessSelect(user);
postProcessGet(user);
return user;
}
@ -166,7 +166,7 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
}
@Override
protected void postProcessSelects(List<User> list)
protected void postProcessQuery(List<User> list)
{
if (list == null)
return;
@ -177,7 +177,7 @@ public class UserServiceImpl extends AbstractMybatisEntityService<String, User>
}
@Override
protected User postProcessSelect(User obj)
protected User postProcessGet(User obj)
{
Set<Role> roles = this.roleService.findByUserId(obj.getId());
obj.setRoles(roles);

View File

@ -85,6 +85,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>

View File

@ -0,0 +1,68 @@
/*
* Copyright 2018 datagear.tech
*
* Licensed under the LGPLv3 license:
* http://www.gnu.org/licenses/lgpl-3.0.html
*/
package org.datagear.web.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
/**
* 缓存配置
*
* @author datagear@163.com
*
*/
@Configuration
public class CacheConfig
{
private Environment environment;
@Autowired
public CacheConfig(Environment environment)
{
super();
this.environment = environment;
}
public Environment getEnvironment()
{
return environment;
}
public void setEnvironment(Environment environment)
{
this.environment = environment;
}
@Bean
public CacheManager cacheManager()
{
CaffeineCacheManager bean = new CaffeineCacheManager();
return bean;
}
public Cache getCache(String name)
{
return this.cacheManager().getCache(name);
}
public Cache getEntityCacheBySimpleName(Class<?> clazz)
{
return getCache(clazz.getSimpleName());
}
public Cache getPermissionCacheBySimpleName(Class<?> clazz)
{
return getCache(clazz.getSimpleName() + "Permission");
}
}

View File

@ -108,6 +108,7 @@ import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -125,6 +126,7 @@ import org.springframework.security.crypto.password.PasswordEncoder;
* @author datagear@163.com
*/
@Configuration
@EnableCaching
public class CoreConfig implements InitializingBean
{
public static final String NAME_CHART_SHOW_HtmlTplDashboardWidgetHtmlRenderer = "chartShowHtmlTplDashboardWidgetHtmlRenderer";
@ -135,13 +137,16 @@ public class CoreConfig implements InitializingBean
private DataSourceConfig dataSourceConfig;
private CacheConfig cacheConfig;
private Environment environment;
@Autowired
public CoreConfig(DataSourceConfig dataSourceConfig, Environment environment)
public CoreConfig(DataSourceConfig dataSourceConfig, CacheConfig cacheConfig, Environment environment)
{
super();
this.dataSourceConfig = dataSourceConfig;
this.cacheConfig = cacheConfig;
this.environment = environment;
}
@ -155,6 +160,16 @@ public class CoreConfig implements InitializingBean
this.dataSourceConfig = dataSourceConfig;
}
public CacheConfig getCacheConfig()
{
return cacheConfig;
}
public void setCacheConfig(CacheConfig cacheConfig)
{
this.cacheConfig = cacheConfig;
}
public Environment getEnvironment()
{
return environment;
@ -462,6 +477,9 @@ public class CoreConfig implements InitializingBean
SchemaServiceImpl bean = new SchemaServiceImpl(this.sqlSessionFactory(), this.mbSqlDialect(),
this.driverEntityManager(), this.authorizationService());
bean.setCache(this.cacheConfig.getEntityCacheBySimpleName(SchemaService.class));
bean.setPermissionCache(this.cacheConfig.getPermissionCacheBySimpleName(SchemaService.class));
return bean;
}
@ -495,6 +513,10 @@ public class CoreConfig implements InitializingBean
DataSetEntityServiceImpl bean = new DataSetEntityServiceImpl(this.sqlSessionFactory(), this.mbSqlDialect(),
this.connectionSource(), this.schemaService(), this.authorizationService(), this.dataSetRootDirectory(),
this.httpClient());
bean.setCache(this.cacheConfig.getEntityCacheBySimpleName(DataSetEntityService.class));
bean.setPermissionCache(this.cacheConfig.getPermissionCacheBySimpleName(DataSetEntityService.class));
return bean;
}
@ -536,6 +558,9 @@ public class CoreConfig implements InitializingBean
this.mbSqlDialect(), this.directoryHtmlChartPluginManager(), this.dataSetEntityService(),
this.authorizationService());
bean.setCache(this.cacheConfig.getEntityCacheBySimpleName(HtmlChartWidgetEntityService.class));
bean.setPermissionCache(this.cacheConfig.getPermissionCacheBySimpleName(HtmlChartWidgetEntityService.class));
return bean;
}

View File

@ -275,7 +275,7 @@ public class ChartController extends AbstractChartPluginAwareController implemen
if (isEmpty(entity.getId()))
{
entity.setId(IDUtil.randomIdOnTime20());
entity.setCreateUser(User.copyWithoutPassword(user));
entity.setCreateUser(user.cloneWithoutPassword());
inflateHtmlChartWidgetEntity(entity, request);
checkSaveEntity(entity);

View File

@ -178,7 +178,7 @@ public class DataSetController extends AbstractSchemaConnController
User user = WebUtils.getUser(request, response);
dataSet.setId(IDUtil.randomIdOnTime20());
dataSet.setCreateUser(User.copyWithoutPassword(user));
dataSet.setCreateUser(user.cloneWithoutPassword());
ResponseEntity<OperationMessage> responseEntity = checkSaveSqlDataSetEntity(request, dataSet);
@ -214,7 +214,7 @@ public class DataSetController extends AbstractSchemaConnController
User user = WebUtils.getUser(request, response);
dataSet.setId(IDUtil.randomIdOnTime20());
dataSet.setCreateUser(User.copyWithoutPassword(user));
dataSet.setCreateUser(user.cloneWithoutPassword());
ResponseEntity<OperationMessage> responseEntity = checkSaveJsonValueDataSetEntity(request, dataSet);
@ -251,7 +251,7 @@ public class DataSetController extends AbstractSchemaConnController
User user = WebUtils.getUser(request, response);
dataSet.setId(IDUtil.randomIdOnTime20());
dataSet.setCreateUser(User.copyWithoutPassword(user));
dataSet.setCreateUser(user.cloneWithoutPassword());
ResponseEntity<OperationMessage> responseEntity = checkSaveJsonFileDataSetEntity(request, dataSet);
@ -290,7 +290,7 @@ public class DataSetController extends AbstractSchemaConnController
User user = WebUtils.getUser(request, response);
dataSet.setId(IDUtil.randomIdOnTime20());
dataSet.setCreateUser(User.copyWithoutPassword(user));
dataSet.setCreateUser(user.cloneWithoutPassword());
ResponseEntity<OperationMessage> responseEntity = checkSaveExcelDataSetEntity(request, dataSet);
@ -329,7 +329,7 @@ public class DataSetController extends AbstractSchemaConnController
User user = WebUtils.getUser(request, response);
dataSet.setId(IDUtil.randomIdOnTime20());
dataSet.setCreateUser(User.copyWithoutPassword(user));
dataSet.setCreateUser(user.cloneWithoutPassword());
ResponseEntity<OperationMessage> responseEntity = checkSaveCsvValueDataSetEntity(request, dataSet);
@ -367,7 +367,7 @@ public class DataSetController extends AbstractSchemaConnController
User user = WebUtils.getUser(request, response);
dataSet.setId(IDUtil.randomIdOnTime20());
dataSet.setCreateUser(User.copyWithoutPassword(user));
dataSet.setCreateUser(user.cloneWithoutPassword());
ResponseEntity<OperationMessage> responseEntity = checkSaveCsvFileDataSetEntity(request, dataSet);
@ -406,7 +406,7 @@ public class DataSetController extends AbstractSchemaConnController
User user = WebUtils.getUser(request, response);
dataSet.setId(IDUtil.randomIdOnTime20());
dataSet.setCreateUser(User.copyWithoutPassword(user));
dataSet.setCreateUser(user.cloneWithoutPassword());
ResponseEntity<OperationMessage> responseEntity = checkSaveHttpDataSetEntity(request, dataSet);

View File

@ -16,7 +16,6 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.datagear.management.domain.User;
import org.datagear.util.Global;
import org.datagear.util.version.Version;
import org.datagear.util.version.VersionContent;
@ -97,7 +96,7 @@ public class MainController extends AbstractController
public String main(HttpServletRequest request, HttpServletResponse response, Model model)
{
request.setAttribute("disableRegister", this.disableRegister);
request.setAttribute("currentUser", User.copyWithoutPassword(WebUtils.getUser(request, response)));
request.setAttribute("currentUser", WebUtils.getUser(request, response).cloneWithoutPassword());
request.setAttribute("currentVersion", Global.VERSION);
resolveDetectNewVersionScript(request, response);

View File

@ -110,7 +110,7 @@ public class SchemaController extends AbstractSchemaConnTableController
schema.setId(IDUtil.randomIdOnTime20());
schema.setCreateTime(new Date());
schema.setCreateUser(User.copyWithoutPassword(user));
schema.setCreateUser(user.cloneWithoutPassword());
getSchemaService().add(user, schema);

View File

@ -119,7 +119,7 @@ public class UserController extends AbstractController
this.userService.add(user);
return buildOperationMessageSaveSuccessResponseEntity(request, User.copyWithoutPassword(user));
return buildOperationMessageSaveSuccessResponseEntity(request, user.cloneWithoutPassword());
}
@RequestMapping("/edit")
@ -157,7 +157,7 @@ public class UserController extends AbstractController
this.userService.update(user);
return buildOperationMessageSaveSuccessResponseEntity(request, User.copyWithoutPassword(user));
return buildOperationMessageSaveSuccessResponseEntity(request, user.cloneWithoutPassword());
}
@RequestMapping("/view")