同步1.9.0

This commit is contained in:
Jerry
2021-09-01 20:08:27 +08:00
parent 6e84b4234c
commit 4f4995e6f0
198 changed files with 4017 additions and 1500 deletions

View File

@@ -77,20 +77,23 @@
<orderEntry type="library" name="Maven: com.alibaba:druid-spring-boot-starter:1.2.6" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:druid:1.2.6" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-boot-starter:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-annotation:3.4.2" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring-boot-starter:2.1.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.4.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.4.6" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:1.3.2" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-core:1.1.5" level="project" />
<orderEntry type="library" name="Maven: javax.persistence:persistence-api:1.0" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-base:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-weekend:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-extra:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring-boot-autoconfigure:2.1.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-starter:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.5" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-autoconfigure:1.3.0" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper:5.2.0" level="project" />
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:3.2" level="project" />

View File

@@ -97,9 +97,9 @@
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>${mybatis-mapper.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>

View File

@@ -0,0 +1,16 @@
package com.orange.demo.common.core.annotation;
import java.lang.annotation.*;
/**
* 主要用于标记逻辑删除字段。
*
* @author Jerry
* @date 2020-08-08
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DeletedFlagColumn {
}

View File

@@ -27,7 +27,7 @@ import java.util.Map;
@Slf4j
public class DataSourceResolveAspect {
private Map<Class<? extends DataSourceResolver>, DataSourceResolver> resolverMap = new HashMap<>();
private final Map<Class<? extends DataSourceResolver>, DataSourceResolver> resolverMap = new HashMap<>();
/**
* 所有配置MyDataSourceResovler注解的Service实现类。

View File

@@ -10,8 +10,6 @@ import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.io.Serializable;
/**
* 字典缓存同步的AOP。该AOP的优先级必须比事务切面的优先级高因此会在事务外执行该切面的代码。
*
@@ -41,23 +39,23 @@ public class DictCacheSyncAspect {
Object arg = joinPoint.getArgs()[0];
if ("saveNew".equals(methodName)) {
Object data = joinPoint.proceed();
BaseDictService<Object, Serializable> service =
(BaseDictService<Object, Serializable>) joinPoint.getTarget();
BaseDictService<Object, Object> service =
(BaseDictService<Object, Object>) joinPoint.getTarget();
// 这里参数必须使用saveNew方法的返回对象因为里面包含实际主键值。
service.putDictionaryCache(data);
return data;
} else if ("update".equals(methodName)) {
Object data = joinPoint.proceed();
BaseDictService<Object, Serializable> service =
(BaseDictService<Object, Serializable>) joinPoint.getTarget();
BaseDictService<Object, Object> service =
(BaseDictService<Object, Object>) joinPoint.getTarget();
// update的方法返回的是boolean因此这里的参数需要使用第一个参数即可。
service.putDictionaryCache(arg);
return data;
} else {
// remove
BaseDictService<Object, Serializable> service =
(BaseDictService<Object, Serializable>) joinPoint.getTarget();
service.removeDictionaryCache((Serializable) arg);
BaseDictService<Object, Object> service =
(BaseDictService<Object, Object>) joinPoint.getTarget();
service.removeDictionaryCache(arg);
return joinPoint.proceed();
}
}

View File

@@ -2,7 +2,6 @@ package com.orange.demo.common.core.base.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.annotation.*;
import com.orange.demo.common.core.base.mapper.BaseModelMapper;
import com.orange.demo.common.core.base.service.IBaseService;
import com.orange.demo.common.core.constant.AggregationKind;
@@ -19,7 +18,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
import javax.persistence.Id;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.LinkedList;
@@ -38,7 +37,7 @@ import java.util.stream.Collectors;
* @date 2020-08-08
*/
@Slf4j
public abstract class BaseController<M, V, K extends Serializable> {
public abstract class BaseController<M, V, K> {
/**
* 当前Service关联的主Model实体对象的Class。
@@ -69,7 +68,7 @@ public abstract class BaseController<M, V, K extends Serializable> {
domainVoClass = (Class<V>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
Field[] fields = ReflectUtil.getFields(modelClass);
for (Field field : fields) {
if (null != field.getAnnotation(TableId.class)) {
if (null != field.getAnnotation(Id.class)) {
idFieldName = field.getName();
break;
}

View File

@@ -1,8 +1,10 @@
package com.orange.demo.common.core.base.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.additional.insert.InsertListMapper;
import tk.mybatis.mapper.annotation.RegisterMapper;
import tk.mybatis.mapper.common.Mapper;
import java.util.List;
import java.util.Map;
@@ -14,7 +16,8 @@ import java.util.Map;
* @author Jerry
* @date 2020-08-08
*/
public interface BaseDaoMapper<M> extends BaseMapper<M> {
@RegisterMapper
public interface BaseDaoMapper<M> extends Mapper<M>, InsertListMapper<M> {
/**
* 根据指定的表名、显示字段列表、过滤条件字符串和分组字段,返回聚合计算后的查询结果。

View File

@@ -1,8 +1,8 @@
package com.orange.demo.common.core.base.model;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import javax.persistence.Column;
import java.util.Date;
/**
@@ -17,24 +17,24 @@ public class BaseModel {
/**
* 创建者Id。
*/
@TableField(value = "create_user_id")
@Column(name = "create_user_id")
private Long createUserId;
/**
* 创建时间。
*/
@TableField(value = "create_time")
@Column(name = "create_time")
private Date createTime;
/**
* 更新者Id。
*/
@TableField(value = "update_user_id")
@Column(name = "update_user_id")
private Long updateUserId;
/**
* 更新时间。
*/
@TableField(value = "update_time")
@Column(name = "update_time")
private Date updateTime;
}

View File

@@ -1,7 +1,6 @@
package com.orange.demo.common.core.base.service;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.orange.demo.common.core.constant.GlobalDeletedFlag;
import com.orange.demo.common.core.exception.MyRuntimeException;
import com.orange.demo.common.core.cache.DictionaryCache;
@@ -9,8 +8,8 @@ import com.orange.demo.common.core.object.TokenData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import java.io.Serializable;
import java.util.*;
/**
@@ -23,7 +22,7 @@ import java.util.*;
* @date 2020-08-08
*/
@Slf4j
public abstract class BaseDictService<M, K extends Serializable> extends BaseService<M, K> implements IBaseDictService<M, K> {
public abstract class BaseDictService<M, K> extends BaseService<M, K> implements IBaseDictService<M, K> {
/**
* 缓存池对象。
@@ -90,7 +89,15 @@ public abstract class BaseDictService<M, K extends Serializable> extends BaseSer
if (tenantIdField != null) {
ReflectUtil.setFieldValue(data, tenantIdField, TokenData.takeFromRequest().getTenantId());
}
return mapper().updateById(data) == 1;
if (deletedFlagFieldName != null) {
try {
setDeletedFlagMethod.invoke(data, GlobalDeletedFlag.NORMAL);
} catch (Exception e) {
log.error("Failed to call reflection [setDeletedFlagMethod] in BaseDictService.update.", e);
throw new MyRuntimeException(e);
}
}
return mapper().updateByPrimaryKey(data) == 1;
}
/**
@@ -102,7 +109,7 @@ public abstract class BaseDictService<M, K extends Serializable> extends BaseSer
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(K id) {
return mapper().deleteById(id) == 1;
return this.removeById(id);
}
/**
@@ -111,16 +118,15 @@ public abstract class BaseDictService<M, K extends Serializable> extends BaseSer
* @param id 主键Id。
* @return 主键关联的数据不存在返回null。
*/
@SuppressWarnings("unchecked")
@Override
public M getById(Serializable id) {
M data = dictionaryCache.get((K) id);
public M getById(K id) {
M data = dictionaryCache.get(id);
if (data != null) {
return data;
}
data = super.getById(id);
if (data != null) {
this.dictionaryCache.put((K) id, data);
this.dictionaryCache.put(id, data);
}
return data;
}
@@ -214,10 +220,8 @@ public abstract class BaseDictService<M, K extends Serializable> extends BaseSer
List<M> dataList = this.getInList((Set<K>) inFilterValues);
return dataList.size() == inFilterValues.size();
}
String columnName = this.safeMapToColumnName(inFilterField);
QueryWrapper<M> queryWrapper = new QueryWrapper<>();
queryWrapper.in(columnName, inFilterValues);
return mapper().selectCount(queryWrapper) == inFilterValues.size();
Example e = this.makeDefaultInListExample(inFilterField, inFilterValues, null);
return mapper().selectCountByExample(e) == inFilterValues.size();
}
/**

View File

@@ -1,10 +1,5 @@
package com.orange.demo.common.core.base.service;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSONObject;
import com.orange.demo.common.core.annotation.*;
@@ -13,7 +8,6 @@ import com.orange.demo.common.core.base.client.BaseClient;
import com.orange.demo.common.core.constant.AggregationKind;
import com.orange.demo.common.core.constant.AggregationType;
import com.orange.demo.common.core.constant.GlobalDeletedFlag;
import com.orange.demo.common.core.exception.InvalidDataFieldException;
import com.orange.demo.common.core.exception.MyRuntimeException;
import com.orange.demo.common.core.exception.RemoteDataBuildException;
import com.orange.demo.common.core.object.*;
@@ -27,14 +21,20 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.lang.reflect.Modifier;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.*;
import java.util.function.Function;
import java.util.function.Consumer;
import java.util.function.Supplier;
import static java.util.stream.Collectors.*;
@@ -47,7 +47,7 @@ import static java.util.stream.Collectors.*;
* @date 2020-08-08
*/
@Slf4j
public abstract class BaseService<M, K extends Serializable> extends ServiceImpl<BaseDaoMapper<M>, M> implements IBaseService<M, K> {
public abstract class BaseService<M, K> implements IBaseService<M, K> {
/**
* 当前Service关联的主Model实体对象的Class。
*/
@@ -156,11 +156,6 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
private static final String AND_OP = " AND ";
@Override
public BaseDaoMapper<M> getBaseMapper() {
return mapper();
}
/**
* 构造函数在实例化的时候一次性完成所有有关主Model对象信息的加载。
*/
@@ -168,7 +163,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
public BaseService() {
modelClass = (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
idFieldClass = (Class<K>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
this.tableName = modelClass.getAnnotation(TableName.class).value();
this.tableName = modelClass.getAnnotation(Table.class).name();
Field[] fields = ReflectUtil.getFields(modelClass);
for (Field field : fields) {
initializeField(field);
@@ -176,10 +171,10 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
}
private void initializeField(Field field) {
if (idFieldName == null && null != field.getAnnotation(TableId.class)) {
if (idFieldName == null && null != field.getAnnotation(Id.class)) {
idFieldName = field.getName();
TableId c = field.getAnnotation(TableId.class);
idColumnName = c == null ? idFieldName : c.value();
Column c = field.getAnnotation(Column.class);
idColumnName = c == null ? idFieldName : c.name();
setIdFieldMethod = ReflectUtil.getMethod(
modelClass, "set" + StringUtils.capitalize(idFieldName), idFieldClass);
getIdFieldMethod = ReflectUtil.getMethod(
@@ -187,18 +182,21 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
}
if (updateTimeFieldName == null && null != field.getAnnotation(JobUpdateTimeColumn.class)) {
updateTimeFieldName = field.getName();
updateTimeColumnName = this.safeMapToColumnName(updateTimeFieldName);
Column c = field.getAnnotation(Column.class);
updateTimeColumnName = c == null ? updateTimeFieldName : c.name();
}
if (deletedFlagFieldName == null && null != field.getAnnotation(TableLogic.class)) {
if (deletedFlagFieldName == null && null != field.getAnnotation(DeletedFlagColumn.class)) {
deletedFlagFieldName = field.getName();
deletedFlagColumnName = this.safeMapToColumnName(deletedFlagFieldName);
Column c = field.getAnnotation(Column.class);
deletedFlagColumnName = c == null ? deletedFlagFieldName : c.name();
setDeletedFlagMethod = ReflectUtil.getMethod(
modelClass, "set" + StringUtils.capitalize(deletedFlagFieldName), Integer.class);
}
if (tenantIdFieldName == null && null != field.getAnnotation(TenantFilterColumn.class)) {
tenantIdField = field;
tenantIdFieldName = field.getName();
tenantIdColumnName = this.safeMapToColumnName(tenantIdFieldName);
Column c = field.getAnnotation(Column.class);
tenantIdColumnName = c == null ? tenantIdFieldName : c.name();
}
}
@@ -221,6 +219,31 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
return false;
}
/**
* 基于主键Id删除数据。如果包含逻辑删除字段则进行逻辑删除。
*
* @param id 主键Id值。
* @return true删除成功false数据不存在。
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean removeById(K id) {
if (this.deletedFlagFieldName == null) {
return mapper().deleteByPrimaryKey(id) == 1;
}
try {
Example e = new Example(modelClass);
Example.Criteria c = e.createCriteria().andEqualTo(idFieldName, id);
c.andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL);
M data = modelClass.newInstance();
setDeletedFlagMethod.invoke(data, GlobalDeletedFlag.DELETED);
return mapper().updateByExampleSelective(data, e) == 1;
} catch (Exception ex) {
log.error("Failed to call reflection method in BaseService.removeById.", ex);
throw new MyRuntimeException(ex);
}
}
/**
* 根据过滤条件删除数据。
*
@@ -230,7 +253,25 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
@Transactional(rollbackFor = Exception.class)
@Override
public Integer removeBy(M filter) {
return mapper().delete(new QueryWrapper<>(filter));
if (deletedFlagFieldName == null) {
return mapper().delete(filter);
}
Example e = new Example(modelClass);
Example.Criteria c = e.createCriteria();
Field[] fields = ReflectUtil.getFields(modelClass);
for (Field field : fields) {
if (field.getAnnotation(Transient.class) == null) {
this.assembleCriteriaByFilter(filter, field, c);
}
}
try {
M deletedObject = modelClass.newInstance();
this.setDeletedFlagMethod.invoke(deletedObject, GlobalDeletedFlag.DELETED);
return mapper().updateByExampleSelective(deletedObject, e);
} catch (Exception ex) {
log.error("Failed to call reflection method in BaseService.removeBy.", ex);
throw new MyRuntimeException(ex);
}
}
/**
@@ -258,8 +299,27 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
if (fieldName.equals(this.idFieldName)) {
return this.existId((K) fieldValue);
}
String columnName = MyModelUtil.mapToColumnName(fieldName, modelClass);
return mapper().selectCount(new QueryWrapper<M>().eq(columnName, fieldValue)) == 1;
Example e = new Example(modelClass);
e.createCriteria().andEqualTo(fieldName, fieldValue);
return mapper().selectCountByExample(e) == 1;
}
/**
* 获取主键Id关联的数据。
*
* @param id 主键Id
* @return 主键关联的数据不存在返回null。
*/
@Override
public M getById(K id) {
if (deletedFlagFieldName == null) {
return mapper().selectByPrimaryKey(id);
}
Example e = new Example(modelClass);
e.createCriteria()
.andEqualTo(idFieldName, id)
.andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL);
return mapper().selectOneByExample(e);
}
/**
@@ -275,9 +335,12 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
if (filterField.equals(idFieldName)) {
return this.getById((K) filterValue);
}
String columnName = this.safeMapToColumnName(filterField);
QueryWrapper<M> queryWrapper = new QueryWrapper<M>().eq(columnName, filterValue);
return mapper().selectOne(queryWrapper);
Example e = new Example(modelClass);
Example.Criteria c = e.createCriteria().andEqualTo(filterField, filterValue);
if (deletedFlagFieldName != null) {
c.andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL);
}
return mapper().selectOneByExample(e);
}
/**
@@ -302,7 +365,12 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
*/
@Override
public List<M> getAllList() {
return mapper().selectList(Wrappers.emptyWrapper());
if (deletedFlagFieldName == null) {
return mapper().selectAll();
}
Example e = new Example(modelClass);
e.createCriteria().andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL);
return mapper().selectByExample(e);
}
/**
@@ -313,11 +381,14 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
*/
@Override
public List<M> getAllListByOrder(String... orderByProperties) {
String[] columns = new String[orderByProperties.length];
for (int i = 0; i < orderByProperties.length; i++) {
columns[i] = this.safeMapToColumnName(orderByProperties[i]);
Example e = new Example(modelClass);
for (String orderByProperty : orderByProperties) {
e.orderBy(orderByProperty);
}
return mapper().selectList(new QueryWrapper<M>().orderByAsc(columns));
if (deletedFlagFieldName != null) {
e.and().andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL);
}
return mapper().selectByExample(e);
}
/**
@@ -346,8 +417,8 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
if (CollectionUtils.isEmpty(inFilterValues)) {
return true;
}
String column = this.safeMapToColumnName(inFilterField);
return mapper().selectCount(new QueryWrapper<M>().in(column, inFilterValues)) == inFilterValues.size();
Example e = this.makeDefaultInListExample(inFilterField, inFilterValues, null);
return mapper().selectCountByExample(e) == inFilterValues.size();
}
/**
@@ -386,12 +457,8 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
if (CollectionUtils.isEmpty(inFilterValues)) {
return new LinkedList<>();
}
String column = this.safeMapToColumnName(inFilterField);
QueryWrapper<M> queryWrapper = new QueryWrapper<M>().in(column, inFilterValues);
if (StringUtils.isNotBlank(orderBy)) {
queryWrapper.last(orderBy);
}
return mapper().selectList(queryWrapper);
Example e = this.makeDefaultInListExample(inFilterField, inFilterValues, orderBy);
return mapper().selectByExample(e);
}
/**
@@ -402,7 +469,16 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
*/
@Override
public int getCountByFilter(M filter) {
return mapper().selectCount(new QueryWrapper<>(filter));
if (deletedFlagFieldName == null) {
return mapper().selectCount(filter);
}
try {
setDeletedFlagMethod.invoke(filter, GlobalDeletedFlag.NORMAL);
return mapper().selectCount(filter);
} catch (Exception e) {
log.error("Failed to call reflection [setDeletedFlagMethod] in BaseService.getCountByFilter.", e);
throw new MyRuntimeException(e);
}
}
/**
@@ -424,7 +500,42 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
*/
@Override
public List<M> getListByFilter(M filter) {
return mapper().selectList(new QueryWrapper<>(filter));
if (filter == null) {
return this.getAllList();
}
if (deletedFlagFieldName == null) {
return mapper().select(filter);
}
try {
setDeletedFlagMethod.invoke(filter, GlobalDeletedFlag.NORMAL);
return mapper().select(filter);
} catch (Exception ex) {
log.error("Failed to call reflection code of BaseService.getListByFilter.", ex);
throw new MyRuntimeException(ex);
}
}
private void assembleCriteriaByFilter(M filter, Field field, Example.Criteria c) {
int modifiers = field.getModifiers();
// transient类型的字段不能作为查询条件
int transientMask = 128;
if ((modifiers & transientMask) != 0 || Modifier.isStatic(modifiers)) {
return;
}
if (field.getName().equals(deletedFlagFieldName)) {
c.andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL);
} else {
ReflectUtil.setAccessible(field);
try {
Object o = field.get(filter);
if (o != null) {
c.andEqualTo(field.getName(), field.get(filter));
}
} catch (IllegalAccessException ex) {
log.error("Failed to call reflection code of BaseService.getListByFilter.", ex);
throw new MyRuntimeException(ex);
}
}
}
/**
@@ -436,14 +547,17 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
*/
@Override
public List<M> getListByParentId(String parentIdFieldName, K parentId) {
QueryWrapper<M> queryWrapper = new QueryWrapper<>();
String parentIdColumn = this.safeMapToColumnName(parentIdFieldName);
Example e = new Example(modelClass);
Example.Criteria c = e.createCriteria();
if (parentId != null) {
queryWrapper.eq(parentIdColumn, parentId);
c.andEqualTo(parentIdFieldName, parentId);
} else {
queryWrapper.isNull(parentIdColumn);
c.andIsNull(parentIdFieldName);
}
return mapper().selectList(queryWrapper);
if (deletedFlagFieldName != null) {
c.andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL);
}
return mapper().selectByExample(e);
}
/**
@@ -473,21 +587,32 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
*/
@Override
public List<M> getListByCondition(List<String> selectList, M filter, String whereClause, String orderBy) {
QueryWrapper<M> queryWrapper = new QueryWrapper<>(filter);
Example e = new Example(modelClass);
Example.Criteria c = null;
if (CollectionUtils.isNotEmpty(selectList)) {
String[] columns = new String[selectList.size()];
for (int i = 0; i < selectList.size(); i++) {
columns[i] = this.safeMapToColumnName(selectList.get(i));
}
queryWrapper.select(columns);
}
if (StringUtils.isNotBlank(whereClause)) {
queryWrapper.apply(whereClause);
String[] selectFields = new String[selectList.size()];
selectList.toArray(selectFields);
e.selectProperties(selectFields);
}
if (StringUtils.isNotBlank(orderBy)) {
queryWrapper.last(" ORDER BY " + orderBy);
e.setOrderByClause(orderBy);
}
return mapper().selectList(queryWrapper);
if (filter != null) {
c = e.createCriteria();
Field[] fields = ReflectUtil.getFields(modelClass);
for (Field field : fields) {
if (field.getAnnotation(Transient.class) == null) {
this.assembleCriteriaByFilter(filter, field, c);
}
}
}
if (StringUtils.isNotBlank(whereClause)) {
if (c == null) {
c = e.createCriteria();
}
c.andCondition(whereClause);
}
return mapper().selectByExample(e);
}
/**
@@ -592,7 +717,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
*
* @param resultList 主表实体对象列表。数据集成将直接作用于该对象列表。
* @param relationParam 实体对象数据组装的参数构建器。
* @param batchSize 每批集成的记录数量。小于等于时将不做分批处理。
* @param batchSize 每批集成的记录数量。小于等于0时将不做分批处理。
*/
@Override
public void buildRelationForDataList(List<M> resultList, MyRelationParam relationParam, int batchSize) {
@@ -613,7 +738,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
*
* @param resultList 主表实体对象列表。数据集成将直接作用于该对象列表。
* @param relationParam 实体对象数据组装的参数构建器。
* @param batchSize 每批集成的记录数量。小于等于时将不做分批处理。
* @param batchSize 每批集成的记录数量。小于等于0时将不做分批处理。
* @param ignoreFields 该集合中的字段,即便包含注解也不会在当前调用中进行数据组装。
*/
@Override
@@ -786,10 +911,9 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
continue;
}
Object masterIdValue = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField);
String masterIdColumn = this.safeMapToColumnName(relationStruct.masterIdField.getName());
Map<String, Object> filterMap = new HashMap<>(1);
filterMap.put(masterIdColumn, masterIdValue);
List<?> manyToManyList = relationStruct.manyToManyMapper.selectByMap(filterMap);
Example e = new Example(relationStruct.relationManyToMany.relationModelClass());
e.createCriteria().andEqualTo(relationStruct.masterIdField.getName(), masterIdValue);
List<?> manyToManyList = relationStruct.manyToManyMapper.selectByExample(e);
ReflectUtil.setFieldValue(dataObject, relationStruct.relationField, manyToManyList);
}
}
@@ -1180,7 +1304,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
if (CollectionUtils.isEmpty(masterIdSet)) {
continue;
}
BaseService<Object, Serializable> relationService = relationStruct.localService;
BaseService<Object, Object> relationService = relationStruct.localService;
List<Object> relationList =
relationService.getInList(relationStruct.relationOneToOne.slaveIdField(), masterIdSet);
MyModelUtil.makeOneToOneRelation(
@@ -1189,8 +1313,8 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
if (withDict && relationStruct.relationOneToOne.loadSlaveDict()
&& CollectionUtils.isNotEmpty(relationList)) {
@SuppressWarnings("unchecked")
BaseService<Object, Serializable> proxyTarget =
(BaseService<Object, Serializable>) AopTargetUtil.getTarget(relationService);
BaseService<Object, Object> proxyTarget =
(BaseService<Object, Object>) AopTargetUtil.getTarget(relationService);
// 关联常量字典
proxyTarget.buildConstDictForDataList(relationList, ignoreFields);
// 关联本地字典。
@@ -1219,14 +1343,14 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
}
Object id = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField);
if (id != null) {
BaseService<Object, Serializable> relationService = relationStruct.localService;
BaseService<Object, Object> relationService = relationStruct.localService;
Object relationObject = relationService.getOne(relationStruct.relationOneToOne.slaveIdField(), id);
ReflectUtil.setFieldValue(dataObject, relationStruct.relationField, relationObject);
// 仅仅当需要加载从表字典关联时,才去加载。
if (withDict && relationStruct.relationOneToOne.loadSlaveDict() && relationObject != null) {
@SuppressWarnings("unchecked")
BaseService<Object, Serializable> proxyTarget =
(BaseService<Object, Serializable>) AopTargetUtil.getTarget(relationService);
BaseService<Object, Object> proxyTarget =
(BaseService<Object, Object>) AopTargetUtil.getTarget(relationService);
// 关联常量字典
proxyTarget.buildConstDictForData(relationObject, ignoreFields);
// 关联本地字典。
@@ -1258,7 +1382,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
.collect(toSet());
// 从主表集合中抽取主表关联字段的集合再以in list形式去从表中查询。
if (CollectionUtils.isNotEmpty(masterIdSet)) {
BaseService<Object, Serializable> relationService = relationStruct.localService;
BaseService<Object, Object> relationService = relationStruct.localService;
List<Object> relationList =
relationService.getInList(relationStruct.relationOneToMany.slaveIdField(), masterIdSet);
MyModelUtil.makeOneToManyRelation(
@@ -1283,7 +1407,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
}
Object id = ReflectUtil.getFieldValue(dataObject, relationStruct.masterIdField);
if (id != null) {
BaseService<Object, Serializable> relationService = relationStruct.localService;
BaseService<Object, Object> relationService = relationStruct.localService;
Set<Object> masterIdSet = new HashSet<>(1);
masterIdSet.add(id);
List<Object> relationObject = relationService.getInList(
@@ -1611,6 +1735,23 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void saveInternal(List<M> dataList, Supplier<K> idGenerator, Consumer<List<M>> batchInserter) {
if (CollectionUtils.isEmpty(dataList)) {
return;
}
dataList.stream().filter(c -> ReflectUtil.getFieldValue(c, idFieldName) == null)
.forEach(o -> ReflectUtil.setFieldValue(o, idFieldName, idGenerator.get()));
if (batchInserter != null) {
batchInserter.accept(dataList);
} else {
for (M data : dataList) {
mapper().insert(data);
}
}
}
/**
* 缺省实现返回null在进行一对多和多对多聚合计算时没有额外的自定义过滤条件。如有需要需子类自行实现。
*
@@ -1658,97 +1799,32 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
}
/**
* 因为Mybatis Plus中QueryWrapper的条件方法都要求传入数据表字段名因此提供该函数将
* Java实体对象的字段名转换为数据表字段名如果不存在会抛出异常。
* 另外在MyModelUtil.mapToColumnName有一级缓存对于查询过的对象字段都会放到缓存中
* 下次映射转换的时候,会直接从缓存获取。
* 通过(In-list)条件和orderBy条件构建Example对象以供后续的查询操作使用。
*
* @param fieldName Java实体对象的字段
* @return 对应的数据表字段名
* @param inFilterField 参与(In-list)过滤的Java字段。
* @param inFilterValues 参与(In-list)过滤的字段值集合
* @param orderBy 排序字段。
* @param <T> in 属性字段的类型。
* @return 构建后的Example对象。
*/
protected String safeMapToColumnName(String fieldName) {
String columnName = MyModelUtil.mapToColumnName(fieldName, modelClass);
if (columnName == null) {
throw new InvalidDataFieldException(modelClass.getSimpleName(), fieldName);
protected <T> Example makeDefaultInListExample(String inFilterField, Collection<T> inFilterValues, String orderBy) {
Set<T> inFilterValueSet;
Example e = new Example(modelClass);
if (StringUtils.isNotBlank(orderBy)) {
e.setOrderByClause(orderBy);
}
return columnName;
}
/**
* 因为Mybatis Plus在update的时候不能将实体对象中值为null的字段更新为null
* 而且忽略更新,在全部更新场景下,这个是非常重要的,所以我们写了这个函数绕开这一问题。
* 该函数会遍历实体对象中,所有不包含@Transient注解没有transient修饰符的字段如果
* 当前对象的该字段值为null则会调用UpdateWrapper的set方法将该字段赋值为null。
* 相比于其他重载方法该方法会将参数中的主键id设置到UpdateWrapper的过滤条件中。
*
* @param o 实体对象。
* @param id 实体对象的主键值。
* @return 创建后的UpdateWrapper。
*/
protected UpdateWrapper<M> createUpdateQueryForNullValue(M o, K id) {
UpdateWrapper<M> uw = createUpdateQueryForNullValue(o, modelClass);
try {
M filter = modelClass.newInstance();
this.setIdFieldMethod.invoke(filter, id);
uw.setEntity(filter);
} catch (Exception e) {
log.error("Failed to call reflection code of BaseService.createUpdateQueryForNullValue.", e);
throw new MyRuntimeException(e);
if (inFilterValues instanceof Set) {
inFilterValueSet = (Set<T>) inFilterValues;
} else {
inFilterValueSet = new HashSet<>(inFilterValues.size());
inFilterValueSet.addAll(inFilterValues);
}
return uw;
}
/**
* 因为Mybatis Plus在update的时候不能将实体对象中值为null的字段更新为null
* 而且忽略更新,在全部更新场景下,这个是非常重要的,所以我们写了这个函数绕开这一问题。
* 该函数会遍历实体对象中,所有不包含@Transient注解没有transient修饰符的字段如果
* 当前对象的该字段值为null则会调用UpdateWrapper的set方法将该字段赋值为null。
*
* @param o 实体对象。
* @return 创建后的UpdateWrapper。
*/
protected UpdateWrapper<M> createUpdateQueryForNullValue(M o) {
return createUpdateQueryForNullValue(o, modelClass);
}
/**
* 因为Mybatis Plus在update的时候不能将实体对象中值为null的字段更新为null
* 而且忽略更新,在全部更新场景下,这个是非常重要的,所以我们写了这个函数绕开这一问题。
* 该函数会遍历实体对象中,所有不包含@Transient注解没有transient修饰符的字段如果
* 当前对象的该字段值为null则会调用UpdateWrapper的set方法将该字段赋值为null。
*
* @param o 实体对象。
* @param clazz 实体对象的class。
* @return 创建后的UpdateWrapper。
*/
public static <T> UpdateWrapper<T> createUpdateQueryForNullValue(T o, Class<T> clazz) {
UpdateWrapper<T> uw = new UpdateWrapper<>();
Field[] fields = ReflectUtil.getFields(clazz);
List<String> nullColumnList = new LinkedList<>();
for (Field field : fields) {
TableField tableField = field.getAnnotation(TableField.class);
if (tableField == null || tableField.exist()) {
int modifiers = field.getModifiers();
// transient类型的字段不能作为查询条件静态字段和逻辑删除都不考虑。
int transientMask = 128;
if ((modifiers & transientMask) == 1
|| Modifier.isStatic(modifiers)
|| field.getAnnotation(TableLogic.class) != null) {
continue;
}
// 仅当实体对象参数中当前字段值为null的时候才会赋值给UpdateWrapper。
// 以便在后续的更新中可以将这些null字段的值设置到数据库表对应的字段中。
if (ReflectUtil.getFieldValue(o, field) == null) {
nullColumnList.add(MyModelUtil.safeMapToColumnName(field.getName(), clazz));
}
}
Example.Criteria c = e.createCriteria();
c.andIn(inFilterField, inFilterValueSet);
if (deletedFlagFieldName != null) {
c.andEqualTo(deletedFlagFieldName, GlobalDeletedFlag.NORMAL);
}
if (CollectionUtils.isNotEmpty(nullColumnList)) {
for (String nullColumn : nullColumnList) {
uw.set(nullColumn, null);
}
}
return uw;
return e;
}
@SuppressWarnings("unchecked")
@@ -1838,7 +1914,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
relationStruct.localService = ApplicationContextHolder.getBean(
StringUtils.uncapitalize(relationOneToOne.slaveServiceName()));
} else {
relationStruct.localService = (BaseService<Object, Serializable>)
relationStruct.localService = (BaseService<Object, Object>)
ApplicationContextHolder.getBean(relationOneToOne.slaveServiceClass());
}
localRelationOneToOneStructList.add(relationStruct);
@@ -1854,7 +1930,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
relationStruct.localService = ApplicationContextHolder.getBean(
StringUtils.uncapitalize(relationOneToMany.slaveServiceName()));
} else {
relationStruct.localService = (BaseService<Object, Serializable>)
relationStruct.localService = (BaseService<Object, Object>)
ApplicationContextHolder.getBean(relationOneToMany.slaveServiceClass());
}
localRelationOneToManyStructList.add(relationStruct);
@@ -1901,7 +1977,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
relationStruct.localService =
ApplicationContextHolder.getBean(StringUtils.uncapitalize(relationDict.slaveServiceName()));
} else {
relationStruct.localService = (BaseService<Object, Serializable>)
relationStruct.localService = (BaseService<Object, Object>)
ApplicationContextHolder.getBean(relationDict.slaveServiceClass());
}
localRelationDictStructList.add(relationStruct);
@@ -1923,7 +1999,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
relationStruct.localService = ApplicationContextHolder.getBean(
StringUtils.uncapitalize(relationOneToManyAggregation.slaveServiceName()));
} else {
relationStruct.localService = (BaseService<Object, Serializable>)
relationStruct.localService = (BaseService<Object, Object>)
ApplicationContextHolder.getBean(relationOneToManyAggregation.slaveServiceClass());
}
localRelationOneToManyAggrStructList.add(relationStruct);
@@ -1942,7 +2018,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
relationStruct.localService = ApplicationContextHolder.getBean(
StringUtils.uncapitalize(relationManyToManyAggregation.slaveServiceName()));
} else {
relationStruct.localService = (BaseService<Object, Serializable>)
relationStruct.localService = (BaseService<Object, Object>)
ApplicationContextHolder.getBean(relationManyToManyAggregation.slaveServiceClass());
}
localRelationManyToManyAggrStructList.add(relationStruct);
@@ -2335,7 +2411,7 @@ public abstract class BaseService<M, K extends Serializable> extends ServiceImpl
static class LocalRelationStruct extends RelationStruct {
private Field equalOneToOneRelationField;
private BaseService<Object, Serializable> localService;
private BaseService<Object, Object> localService;
private BaseDaoMapper<Object> manyToManyMapper;
private Map<Object, String> dictMap;
private RelationDict relationDict;

View File

@@ -1,6 +1,5 @@
package com.orange.demo.common.core.base.service;
import java.io.Serializable;
import java.util.List;
/**
@@ -11,7 +10,7 @@ import java.util.List;
* @author Jerry
* @date 2020-08-08
*/
public interface IBaseDictService<M, K extends Serializable> extends IBaseService<M, K> {
public interface IBaseDictService<M, K> extends IBaseService<M, K> {
/**
* 重新加载数据库中所有当前表数据到系统内存。

View File

@@ -1,10 +1,10 @@
package com.orange.demo.common.core.base.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.orange.demo.common.core.object.MyRelationParam;
import java.io.Serializable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* 所有Service的接口。
@@ -14,7 +14,15 @@ import java.util.*;
* @author Jerry
* @date 2020-08-08
*/
public interface IBaseService<M, K extends Serializable> extends IService<M>{
public interface IBaseService<M, K> {
/**
* 基于主键Id删除数据。如果包含逻辑删除字段则进行逻辑删除。
*
* @param id 主键Id值。
* @return true删除成功false数据不存在。
*/
boolean removeById(K id);
/**
* 根据过滤条件删除数据。
@@ -42,6 +50,14 @@ public interface IBaseService<M, K extends Serializable> extends IService<M>{
*/
boolean existId(K id);
/**
* 获取主键Id关联的数据。
*
* @param id 主键Id。
* @return 主键关联的数据不存在返回null。
*/
M getById(K id);
/**
* 返回符合 filterField = filterValue 条件的一条数据。
*
@@ -218,7 +234,7 @@ public interface IBaseService<M, K extends Serializable> extends IService<M>{
*
* @param resultList 主表实体对象列表。数据集成将直接作用于该对象列表。
* @param relationParam 实体对象数据组装的参数构建器。
* @param batchSize 每批集成的记录数量。小于等于时将不做分批处理。
* @param batchSize 每批集成的记录数量。小于等于0时将不做分批处理。
*/
void buildRelationForDataList(List<M> resultList, MyRelationParam relationParam, int batchSize);
@@ -236,7 +252,7 @@ public interface IBaseService<M, K extends Serializable> extends IService<M>{
*
* @param resultList 主表实体对象列表。数据集成将直接作用于该对象列表。
* @param relationParam 实体对象数据组装的参数构建器。
* @param batchSize 每批集成的记录数量。小于等于时将不做分批处理。
* @param batchSize 每批集成的记录数量。小于等于0时将不做分批处理。
* @param ignoreFields 该集合中的字段,即便包含注解也不会在当前调用中进行数据组装。
*/
void buildRelationForDataList(
@@ -274,4 +290,16 @@ public interface IBaseService<M, K extends Serializable> extends IService<M>{
* 仅仅在spring boot 启动后的监听器事件中调用缓存所有service的关联关系加速后续的数据绑定效率。
*/
void loadLocalRelationStruct();
/**
* 内部使用的批量保存方法。在使用前要确保清楚该方法的实现功能。
* 该方法通常用于从表数据的批量更新,为了保证已有数据的主键不变,我们通常会在执行该方法前,根据主表的关联数据,
* 删除从表中的数据。之后在迭代参数dataList并将没有主键值的对象视为新对象该方法将为这些新对象生成主键值。
* 其他包含主键值的对象为已有对象不做任何修改。填充主键后将dataList集合中的数据批量插入到数据表。
*
* @param dataList 待操作的数据列表。
* @param idGenerator 主键值生成器方法。
* @param batchInserter 批量插入方法。
*/
void saveInternal(List<M> dataList, Supplier<K> idGenerator, Consumer<List<M>> batchInserter);
}

View File

@@ -29,6 +29,9 @@ public class FeignConfig implements RequestInterceptor {
requestTemplate.header(TokenData.REQUEST_ATTRIBUTE_NAME, tokenData);
}
String traceId = ContextUtil.getHttpRequest().getHeader(ApplicationConstant.HTTP_HEADER_TRACE_ID);
if (StringUtils.isBlank(traceId)) {
traceId = (String) ContextUtil.getHttpRequest().getAttribute(ApplicationConstant.HTTP_HEADER_TRACE_ID);
}
if (StringUtils.isNotBlank(traceId)) {
requestTemplate.header(ApplicationConstant.HTTP_HEADER_TRACE_ID, traceId);
}

View File

@@ -0,0 +1,59 @@
package com.orange.demo.common.core.constant;
import java.util.HashMap;
import java.util.Map;
/**
* App 登录的设备类型。
*
* @author Jerry
* @date 2020-08-08
*/
public final class AppDeviceType {
/**
* 移动端 (如果不考虑区分android或ios的可以使用该值)
*/
public static final int MOBILE = 0;
/**
* android
*/
public static final int ANDROID = 1;
/**
* iOS
*/
public static final int IOS = 2;
/**
* 微信公众号和小程序
*/
public static final int WEIXIN = 3;
/**
* PC WEB
*/
public static final int WEB = 4;
private static final Map<Object, String> DICT_MAP = new HashMap<>(5);
static {
DICT_MAP.put(MOBILE, "移动端");
DICT_MAP.put(ANDROID, "Android");
DICT_MAP.put(IOS, "iOS");
DICT_MAP.put(WEIXIN, "微信");
DICT_MAP.put(WEB, "PC WEB");
}
/**
* 判断参数是否为当前常量字典的合法值。
*
* @param value 待验证的参数值。
* @return 合法返回true否则false。
*/
public static boolean isValid(Integer value) {
return value != null && DICT_MAP.containsKey(value);
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/
private AppDeviceType() {
}
}

View File

@@ -55,4 +55,8 @@ public class LoginUserInfo {
* 登录时间。
*/
private Date loginTime;
/**
* 登录设备类型。
*/
private Integer deviceType;
}

View File

@@ -131,7 +131,7 @@ public class ResponseResult<T> {
* @return 返回创建的ResponseResult实例对象
*/
public static <T> ResponseResult<T> error(String errorCode, String errorMessage) {
return new ResponseResult<>(false, errorCode, errorMessage);
return new ResponseResult<>(errorCode, errorMessage);
}
/**
@@ -213,8 +213,8 @@ public class ResponseResult<T> {
}
private ResponseResult(boolean success, String errorCode, String errorMessage) {
this.success = success;
private ResponseResult(String errorCode, String errorMessage) {
this.success = false;
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}

View File

@@ -37,6 +37,10 @@ public class TokenData {
* 仅当系统支持uaa时可用否则可以直接忽略该字段。保留该字段是为了保持单体和微服务通用代码部分的兼容性。
*/
private Long deptId;
/**
* 用户的部门岗位Id。多个岗位之间逗号分隔。仅当系统支持岗位时有值。
*/
private String deptPostIds;
/**
* 租户Id。
* 仅当系统支持uaa时可用否则可以直接忽略该字段。保留该字段是为了保持单体和微服务通用代码部分的兼容性。
@@ -54,6 +58,10 @@ public class TokenData {
* 用户显示名称。
*/
private String showName;
/**
* 设备类型。参考 AppDeviceType。
*/
private Integer deviceType;
/**
* 标识不同登录的会话Id。
*/

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.orange.demo.common.core.constant.AppDeviceType;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
@@ -168,6 +169,24 @@ public class MyCommonUtil {
return new String[]{};
}
/**
* 获取请求头中的设备信息。
*
* @return 设备类型具体值可参考AppDeviceType常量类。
*/
public static int getDeviceType() {
// 缺省都按照Web登录方式设置如果前端header中的值为不合法值这里也不会报错而是使用Web缺省方式。
int deviceType = AppDeviceType.WEB;
String deviceTypeString = ContextUtil.getHttpRequest().getHeader("deviceType");
if (StrUtil.isNotBlank(deviceTypeString)) {
Integer type = Integer.valueOf(deviceTypeString);
if (AppDeviceType.isValid(type)) {
deviceType = type;
}
}
return deviceType;
}
/**
* 私有构造函数,明确标识该常量类的作用。
*/

View File

@@ -2,19 +2,22 @@ package com.orange.demo.common.core.util;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.annotation.*;
import com.orange.demo.common.core.exception.InvalidDataFieldException;
import com.orange.demo.common.core.annotation.*;
import com.orange.demo.common.core.exception.MyRuntimeException;
import com.orange.demo.common.core.object.TokenData;
import com.orange.demo.common.core.object.Tuple2;
import com.orange.demo.common.core.upload.UploadStoreInfo;
import com.google.common.base.CaseFormat;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import tk.mybatis.mapper.entity.Example;
import javax.persistence.Column;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.lang.reflect.Modifier;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@@ -204,20 +207,8 @@ public class MyModelUtil {
if (field == null) {
return null;
}
TableField c = field.getAnnotation(TableField.class);
String columnName = null;
if (c == null) {
TableId id = field.getAnnotation(TableId.class);
if (id != null) {
columnName = id.value();
}
}
if (columnName == null) {
columnName = c == null ? CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fieldName) : c.value();
if (StringUtils.isBlank(columnName)) {
columnName = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fieldName);
}
}
Column c = field.getAnnotation(Column.class);
String columnName = c == null ? fieldName : c.name();
// 这里缺省情况下都是按照整型去处理,因为他覆盖太多的类型了。
// 如Integer/Long/Double/BigDecimal可根据实际情况完善和扩充。
String typeName = field.getType().getSimpleName();
@@ -240,8 +231,8 @@ public class MyModelUtil {
* @return Model对象对应的数据表名称。
*/
public static String mapToTableName(Class<?> modelClazz) {
TableName t = modelClazz.getAnnotation(TableName.class);
return t == null ? null : t.value();
Table t = modelClazz.getAnnotation(Table.class);
return t == null ? null : t.name();
}
/**
@@ -614,6 +605,43 @@ public class MyModelUtil {
return isMap ? BeanUtil.beanToMap(model) : model;
}
/**
* 转换过滤对象到与其等效的Example对象。
*
* @param filterModel 过滤对象。
* @param modelClass 过滤对象的Class对象。
* @param <T> 过滤对象类型。
* @return 转换后的Example对象。
*/
public static <T> Example convertFilterModelToExample(T filterModel, Class<T> modelClass) {
if (filterModel == null) {
return null;
}
Example e = new Example(modelClass);
Example.Criteria c = e.createCriteria();
Field[] fields = ReflectUtil.getFields(modelClass);
for (Field field : fields) {
if (field.getAnnotation(Transient.class) == null) {
int modifiers = field.getModifiers();
// transient类型的字段不能作为查询条件
if ((modifiers & 128) != 0 || Modifier.isStatic(modifiers)) {
continue;
}
ReflectUtil.setAccessible(field);
try {
Object o = field.get(filterModel);
if (o != null) {
c.andEqualTo(field.getName(), field.get(filterModel));
}
} catch (IllegalAccessException ex) {
log.error("Failed to call reflection code.", ex);
throw new MyRuntimeException(ex);
}
}
}
return e;
}
/**
* 获取上传字段的存储信息。
*

View File

@@ -27,6 +27,17 @@ public class RedisKeyUtil {
return "SESSIONID__" + loginName + "_";
}
/**
* 获取指定用户Id和登录设备类型的session缓存的键前缀。
*
* @param loginName 指定的用户登录名。
* @param deviceType 设备类型。
* @return session缓存的键前缀。
*/
public static String getSessionIdPrefix(String loginName, int deviceType) {
return "SESSIONID__" + loginName + "_" + deviceType + "_";
}
/**
* 计算SessionId返回存储于Redis中的键。
*

View File

@@ -64,20 +64,23 @@
<orderEntry type="library" name="Maven: com.alibaba:druid-spring-boot-starter:1.2.6" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:druid:1.2.6" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-boot-starter:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-annotation:3.4.2" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring-boot-starter:2.1.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.4.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.4.6" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:1.3.2" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-core:1.1.5" level="project" />
<orderEntry type="library" name="Maven: javax.persistence:persistence-api:1.0" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-base:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-weekend:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-extra:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring-boot-autoconfigure:2.1.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-starter:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.5" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-autoconfigure:1.3.0" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper:5.2.0" level="project" />
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:3.2" level="project" />

View File

@@ -65,20 +65,23 @@
<orderEntry type="library" name="Maven: com.alibaba:druid-spring-boot-starter:1.2.6" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:druid:1.2.6" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-boot-starter:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-annotation:3.4.2" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring-boot-starter:2.1.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.4.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.4.6" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:1.3.2" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-core:1.1.5" level="project" />
<orderEntry type="library" name="Maven: javax.persistence:persistence-api:1.0" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-base:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-weekend:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-extra:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring-boot-autoconfigure:2.1.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-starter:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.5" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-autoconfigure:1.3.0" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper:5.2.0" level="project" />
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:3.2" level="project" />

View File

@@ -82,20 +82,23 @@
<orderEntry type="library" name="Maven: com.alibaba:druid-spring-boot-starter:1.2.6" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:druid:1.2.6" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-boot-starter:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:3.4.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-annotation:3.4.2" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring-boot-starter:2.1.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.3.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.4.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.2.14.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.4.6" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:1.3.2" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-core:1.1.5" level="project" />
<orderEntry type="library" name="Maven: javax.persistence:persistence-api:1.0" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-base:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-weekend:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-extra:1.1.5" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring-boot-autoconfigure:2.1.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-starter:1.3.0" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:2.1.3" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.5" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-autoconfigure:1.3.0" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper:5.2.0" level="project" />
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:3.2" level="project" />