Unverified Commit bb4762ba authored by Mazc's avatar Mazc Committed by GitHub
Browse files

Merge pull request #41 from dibo-software/develop

Develop
Showing with 269 additions and 84 deletions
+269 -84
......@@ -11,7 +11,7 @@ diboot 2.0版本,实现: diboot-core全新内核 + diboot-devtools代码生成
## 一、 diboot-core: 精简优化内核
全新精简内核,(基于diboot-core 2.x版本的CRUD和简单关联的常规功能实现,代码量比1.x版本减少60%+),主要实现:
全新精简内核,(基于diboot-core 2.x版本的CRUD和简单关联的常规功能实现,代码量比1.x版本减少70%+),主要实现:
#### 1. 单表CRUD无SQL
> 基于Mybatis-Plus实现(Mybatis-Plus具备通用Mapper方案和灵活的查询构造器)
#### 2. 关联查询无SQL(注解自动绑定)
......
package com.diboot.component.excel.converter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import java.math.BigDecimal;
public class BigDecimalConverter implements Converter<BigDecimal> {
@Override
public Class supportJavaTypeKey() {
return BigDecimal.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.NUMBER;
}
@Override
public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
BigDecimal value = null;
String colName = contentProperty.getHead().getHeadNameList().get(0);//当前列
try {
value = cellData.getNumberValue();
} catch (Exception e) {
throw new Exception("["+colName+"]列数据格式有误,请填写正确的浮点型数据");
}
return value;
}
@Override
public CellData convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
return new CellData(value);
}
}
package com.diboot.component.excel.utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.diboot.component.excel.entity.BaseExcelDataEntity;
import com.diboot.component.excel.listener.BaseExcelDataListener;
import com.diboot.core.util.V;
......@@ -81,4 +82,22 @@ public class EasyExcelHelper {
return true;
}
/**
* 简单将数据写入excel文件,列宽自适应数据长度
* @param filePath
* @param clazz
* @param dataList
* @param <T>
* @return
*/
public static <T extends BaseExcelDataEntity> boolean simpleWriteWithAdaptColumnWidth(String filePath, Class<T> clazz, List dataList) throws Exception{
try {
EasyExcel.write(filePath, clazz).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet().doWrite(dataList);
} catch (Exception e) {
logger.error("数据写入excel文件失败",e);
return false;
}
return true;
}
}
package com.diboot.component.file.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.diboot.core.entity.BaseEntity;
import org.hibernate.validator.constraints.Length;
......
......@@ -19,7 +19,7 @@ public class Message extends BaseExtEntity {
private String businessType;
@TableField
private String businessId;
private Long businessId;
@TableField
private String sender;
......@@ -45,5 +45,7 @@ public class Message extends BaseExtEntity {
@TableField
private String response;
@TableField
private Long createBy;
}
......@@ -255,7 +255,7 @@ public class RelationsBinder {
return null;
}
// 根据entity获取Service
IService service = ContextHelper.getServiceByEntity(entityClass);
IService service = ContextHelper.getIServiceByEntity(entityClass);
if(service == null){
log.error("未能识别到Entity: "+entityClass.getName()+" 的Service实现!");
}
......
......@@ -3,6 +3,7 @@ package com.diboot.core.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.binding.QueryBuilder;
import com.diboot.core.binding.RelationsBinder;
import com.diboot.core.config.Cons;
import com.diboot.core.util.S;
import com.diboot.core.util.V;
......@@ -161,6 +162,20 @@ public class BaseController {
return result;
}
/**
* 自动转换为VO并绑定关联关系
*
* @param entityList
* @param voClass
* @param <VO>
* @return
*/
protected <VO> List<VO> convertToVoAndBindRelations(List entityList, Class<VO> voClass) {
// 转换为VO
List<VO> voList = RelationsBinder.convertAndBind(entityList, voClass);
return voList;
}
/***
* 打印所有参数信息
* @param request
......
package com.diboot.core.controller;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.diboot.core.binding.RelationsBinder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.entity.BaseEntity;
import com.diboot.core.service.BaseService;
import com.diboot.core.util.ContextHelper;
import com.diboot.core.util.V;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.Pagination;
import com.diboot.core.vo.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.ResolvableType;
import org.springframework.validation.BindingResult;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/***
* 增删改查通用管理功能-父类
* CRUD增删改查通用RestController-父类
* @author Mazhicheng
* @version 2.0
* @date 2019/01/01
*/
public abstract class BaseCrudRestController extends BaseController {
public class BaseCrudRestController<E extends BaseEntity, VO extends Serializable> extends BaseController {
private static final Logger log = LoggerFactory.getLogger(BaseCrudRestController.class);
/**
* Entity,VO对应的class
*/
private Class<E> entityClass;
private Class<VO> voClasss;
/**
* Service实现类
*/
private BaseService baseService;
/**
* 获取service实例
*
* 查询ViewObject,用于字类重写的方法
* @param id
* @param request
* @return
* @throws Exception
*/
protected abstract BaseService getService();
protected JsonResult getViewObject(Serializable id, HttpServletRequest request) throws Exception{
VO vo = (VO)getService().getViewObject(id, getVOClass());
return new JsonResult(vo);
}
/***
* 获取某资源的集合
* 获取某VO资源的集合,用于字类重写的方法
* <p>
* url参数示例: /dictionary/list?pageSize=20&pageIndex=1&orderBy=itemValue&type=GENDAR
* url参数示例: /${bindURL}?pageSize=20&pageIndex=1&orderBy=itemValue&type=GENDAR
* </p>
* @return JsonResult
* @throws Exception
*/
protected JsonResult getEntityList(Wrapper queryWrapper) throws Exception {
protected JsonResult getViewObjectList(E entity, Pagination pagination, HttpServletRequest request) throws Exception {
QueryWrapper<E> queryWrapper = super.buildQueryWrapper(entity);
// 查询当前页的数据
List entityList = getService().getEntityList(queryWrapper);
List<VO> voList = getService().getViewObjectList(queryWrapper, pagination, getVOClass());
// 返回结果
return new JsonResult(Status.OK, entityList);
return new JsonResult(Status.OK, voList).bindPagination(pagination);
}
/***
* 获取某资源的集合
* <p>
* url参数示例: /dictionary/list?pageSize=20&pageIndex=1&orderBy=itemValue&type=GENDAR
* </p>
* @return JsonResult
/**
* 获取符合查询条件的全部数据(不分页)
* @param queryWrapper
* @return
* @throws Exception
*/
protected JsonResult getEntityListWithPaging(Wrapper queryWrapper, Pagination pagination) throws Exception {
protected JsonResult getEntityList(Wrapper queryWrapper) throws Exception {
// 查询当前页的数据
List entityList = getService().getEntityList(queryWrapper, pagination);
List entityList = getService().getEntityList(queryWrapper);
// 返回结果
return new JsonResult(Status.OK, entityList).bindPagination(pagination);
return new JsonResult(Status.OK, entityList);
}
/***
* 获取某VO资源的集合
* 获取符合查询条件的某页数据(有分页)
* <p>
* url参数示例: /dictionary/list?pageSize=20&pageIndex=1&orderBy=itemValue&type=GENDAR
* url参数示例: /${bindURL}?pageSize=20&pageIndex=1
* </p>
* @return JsonResult
* @throws Exception
*/
protected <T> JsonResult getVOListWithPaging(Wrapper queryWrapper, Pagination pagination, Class<T> clazz) throws Exception {
protected JsonResult getEntityListWithPaging(Wrapper queryWrapper, Pagination pagination) throws Exception {
// 查询当前页的数据
List<T> voList = getService().getViewObjectList(queryWrapper, pagination, clazz);
List entityList = getService().getEntityList(queryWrapper, pagination);
// 返回结果
return new JsonResult(Status.OK, voList).bindPagination(pagination);
return new JsonResult(Status.OK, entityList).bindPagination(pagination);
}
/***
* 创建资源对象
* 创建资源对象,用于字类重写的方法
* @param entity
* @param result
* @return JsonResult
* @throws Exception
*/
protected JsonResult createEntity(BaseEntity entity, BindingResult result) throws Exception {
protected JsonResult createEntity(E entity, BindingResult result, HttpServletRequest request) throws Exception {
// Model属性值验证结果
if (result != null && result.hasErrors()) {
return new JsonResult(Status.FAIL_VALIDATION, super.getBindingError(result));
......@@ -111,13 +128,14 @@ public abstract class BaseCrudRestController extends BaseController {
}
/***
* 根据ID更新资源对象
* 根据ID更新资源对象,用于字类重写的方法
* @param entity
* @param result
* @return JsonResult
* @throws Exception
*/
protected JsonResult updateEntity(BaseEntity entity, BindingResult result) throws Exception {
protected JsonResult updateEntity(Serializable id, E entity, BindingResult result,
HttpServletRequest request) throws Exception {
// Entity属性值验证结果
if (result.hasErrors()) {
return new JsonResult(Status.FAIL_VALIDATION, super.getBindingError(result));
......@@ -144,12 +162,12 @@ public abstract class BaseCrudRestController extends BaseController {
}
/***
* 根据id删除资源对象
* 根据id删除资源对象,绑定了URL的方法 用于字类重写的方法
* @param id
* @return
* @throws Exception
*/
protected JsonResult deleteEntity(Serializable id) throws Exception {
protected JsonResult deleteEntity(Serializable id, HttpServletRequest request) throws Exception {
if (id == null) {
return new JsonResult(Status.FAIL_INVALID_PARAM, "请选择需要删除的条目!");
}
......@@ -175,20 +193,6 @@ public abstract class BaseCrudRestController extends BaseController {
}
}
/**
* 自动转换为VO并绑定关联关系
*
* @param entityList
* @param voClass
* @param <VO>
* @return
*/
protected <VO> List<VO> convertToVoAndBindRelations(List entityList, Class<VO> voClass) {
// 转换为VO
List<VO> voList = RelationsBinder.convertAndBind(entityList, voClass);
return voList;
}
//============= 供子类继承重写的方法 =================
/***
* 创建前的相关处理
......@@ -235,4 +239,59 @@ public abstract class BaseCrudRestController extends BaseController {
return null;
}
/**
* 得到service
* @return
*/
protected BaseService getService() {
if(this.baseService == null){
Class<E> clazz = getEntityClass();
if(clazz != null){
this.baseService = ContextHelper.getBaseServiceByEntity(clazz);
}
if(this.baseService == null){
log.warn("Entity: {} 无对应的Service定义,请检查!", clazz.getName());
}
}
return this.baseService;
}
/**
* 获取Entity的class
* @return
*/
protected Class<E> getEntityClass(){
if(this.entityClass == null){
initEntityVOClass();
}
return this.entityClass;
}
/**
* 获取VO的class
* @return
*/
protected Class<VO> getVOClass(){
if(this.voClasss == null){
initEntityVOClass();
}
return this.voClasss;
}
/**
* 初始化Entity和VO的class
*/
private void initEntityVOClass(){
try{
ResolvableType resolvableType = ResolvableType.forClass(this.getClass()).getSuperType();
ResolvableType[] types = resolvableType.getSuperType().getGenerics();
if(V.notEmpty(types)){
this.entityClass = (Class<E>) types[0].resolve();
this.voClasss = (Class<VO>) types[1].resolve();
}
}
catch (Exception e){
log.warn("初始化Entity,VO class异常: "+ e.getMessage());
}
}
}
\ No newline at end of file
......@@ -61,15 +61,6 @@ public abstract class BaseEntity implements Serializable {
this.deleted = deleted;
}
/***
* 是否为新建
* @return
*/
@JSONField(serialize = false)
public boolean isNew(){
return getId() != null;
}
/***
* model对象转为map
* @return
......
......@@ -5,7 +5,10 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.entity.Dictionary;
import com.diboot.core.mapper.DictionaryMapper;
import com.diboot.core.service.DictionaryService;
import com.diboot.core.util.*;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.IGetter;
import com.diboot.core.util.ISetter;
import com.diboot.core.util.V;
import com.diboot.core.vo.DictionaryVO;
import com.diboot.core.vo.KeyValue;
import org.slf4j.Logger;
......
package com.diboot.core.util;
import com.baomidou.mybatisplus.extension.service.IService;
import com.diboot.core.service.BaseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
......@@ -37,6 +38,10 @@ public class ContextHelper implements ApplicationContextAware {
* Entity-对应的Service缓存
*/
private static Map<String, IService> ENTITY_SERVICE_CACHE = null;
/**
* Entity-对应的BaseService缓存
*/
private static Map<String, BaseService> ENTITY_BASE_SERVICE_CACHE = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
......@@ -106,11 +111,21 @@ public class ContextHelper implements ApplicationContextAware {
}
/**
* 根据Entity获取对应的Service
* 根据Entity获取对应的Service (已废弃,请调用getIServiceByEntity)
* @param entity
* @return
*/
@Deprecated
public static IService getServiceByEntity(Class entity){
return getIServiceByEntity(entity);
}
/**
* 根据Entity获取对应的IService实现
* @param entity
* @return
*/
public static IService getIServiceByEntity(Class entity){
if(ENTITY_SERVICE_CACHE == null){
ENTITY_SERVICE_CACHE = new ConcurrentHashMap<>();
Map<String, IService> serviceMap = getApplicationContext().getBeansOfType(IService.class);
......@@ -126,6 +141,27 @@ public class ContextHelper implements ApplicationContextAware {
return ENTITY_SERVICE_CACHE.get(entity.getName());
}
/**
* 根据Entity获取对应的BaseService实现
* @param entity
* @return
*/
public static BaseService getBaseServiceByEntity(Class entity){
if(ENTITY_BASE_SERVICE_CACHE == null){
ENTITY_BASE_SERVICE_CACHE = new ConcurrentHashMap<>();
Map<String, BaseService> serviceMap = getApplicationContext().getBeansOfType(BaseService.class);
if(V.notEmpty(serviceMap)){
for(Map.Entry<String, BaseService> entry : serviceMap.entrySet()){
String entityClassName = getEntityClassByServiceImpl(entry.getValue().getClass());
if(V.notEmpty(entityClassName)){
ENTITY_BASE_SERVICE_CACHE.put(entityClassName, entry.getValue());
}
}
}
}
return ENTITY_BASE_SERVICE_CACHE.get(entity.getName());
}
/**
* 根据Service实现类的bean解析出Entity类名
* @param currentClass
......
......@@ -5,7 +5,6 @@ import com.diboot.core.binding.RelationsBinder;
import com.diboot.core.util.JSON;
import com.diboot.core.util.V;
import diboot.core.test.StartupApplication;
import diboot.core.test.binder.entity.Department;
import diboot.core.test.binder.entity.User;
import diboot.core.test.binder.service.DepartmentService;
import diboot.core.test.binder.service.UserService;
......
package diboot.core.test.binder.vo;
import com.diboot.core.binding.annotation.BindDict;
import com.diboot.core.binding.annotation.BindField;
import diboot.core.test.binder.entity.Department;
import diboot.core.test.binder.entity.Organization;
import diboot.core.test.binder.entity.User;
/**
......
......@@ -4,14 +4,12 @@
<div class="hero">
<p class="action">
<a :href="$withBase('/guide/diboot-core/安装.html')" class="button white">快速上手</a>
<!--
<i class="fa fa-2x fa-play-circle" aria-hidden="true"></i>
<i class="fa fa-2x fa-play-circle" aria-hidden="true"></i>
<a href="javascript:;" class="button has-icon" @click="showVideo">
<img class="icon" src="/play-circle.png" alt="">
<img class="icon" src="../public/play-circle.png" alt="">
了解 diboot 2.0
</a>
-->
</p>
</div>
<div class="custom content">
......@@ -19,13 +17,13 @@
<div class="feature" style="max-width: 35%;">
<h2>diboot-core 精简高效内核</h2>
<p>
<ul>
<li>单表CRUD无SQL</li>
<li>关联查询无SQL - 注解自动绑定</li>
<li>数据字典无SQL - 注解自动绑定</li>
<li>Entity/DTO自动转换查询对象</li>
<li>常用工具类的最佳实践封装</li>
</ul>
<ul>
<li>单表CRUD无SQL</li>
<li>关联查询无SQL - 注解自动绑定</li>
<li>数据字典无SQL - 注解自动绑定</li>
<li>Entity/DTO自动转换查询对象</li>
<li>常用工具类的最佳实践封装</li>
</ul>
</p>
</div>
<div class="feature" style="max-width: 60%">
......@@ -61,13 +59,15 @@
<div class="footer-item">
</div>
</div>
<p class="copy-right">© 2015-2019 <a href="http://www.dibo.ltd">苏州帝博信息技术有限公司</a></p></p>
<p class="copy-right">© 2015-2019 <a href="http://www.dibo.ltd">苏州帝博信息技术有限公司</a></p>
</div>
</div>
<div class="modal-cover" v-show="showModal" @click="closeModal">
<div class="modal-content">
<iframe width='100%' height='100%' src="//player.bilibili.com/player.html?aid=35545861&cid=62326072&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
<div class="modal-content" @click="onModalContentClick($event)">
<video src="https://diboot.oss-cn-shanghai.aliyuncs.com/file/%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8diboot%E4%B8%8E%E5%85%B3%E8%81%94%E6%BC%94%E7%A4%BA_%E5%AD%97%E5%B9%95.mp4?nsukey=Z8MYZulBJM0GZXYNQgYGJGxRDvYMIWMsGj%2FkV%2BQpZD2aN7hsk7hreW1mXv71kxX7W5Sd61warYIPAAT4xDifYZEv3cQiiQiVW%2BqF%2FqomaxhPm1ht5jV5YkWLGiwcqQKeHmN5jn9%2FRWzaWTNweSZjWuif%2FZIciG6BX8UddZ0klnyyGfrtdB2eWCBAh%2F5n5rMPGdyUhYXAzzDsdPtyBxcY7w%3D%3D"
class="homeVideo" id="homeVideo" height="666" controls>
</video>
</div>
</div>
</div>
......@@ -84,9 +84,15 @@
methods: {
showVideo () {
this.showModal = true
document.querySelector("#homeVideo").play()
},
closeModal () {
this.showModal = false
document.querySelector("#homeVideo").pause()
},
onModalContentClick(e){
e.preventDefault()
e.stopPropagation()
}
}
}
......@@ -229,13 +235,15 @@ a.button.white {
box-shadow: 0 0 5px black;
}
.modal-content{
z-index: 1100;
position: fixed;
width: 1180px;
height: 666px;
top: 50%;
left: 50%;
margin-top: -333px;
margin-left: -590px;
z-index: 1100;
background-color: white;
position: fixed;
left: 10%;
top: 10%;
box-shadow: 0 0 15px black;
}
.donate-image{
......
......@@ -21,4 +21,17 @@ MySQL、MariaDB、ORACLE、SQLServer、PostgreSQL
参考样例 [diboot-core-example](https://github.com/dibo-software/diboot-v2-example/tree/master/diboot-core-example)
> 如果您使用diboot-devtools,diboot-core会被自动引入,无需再配置依赖。
\ No newline at end of file
> 如果您使用diboot-devtools,diboot-core会被自动引入,无需再配置依赖。
## 相关依赖
* **javax.servlet-api**(javax.servlet:javax.servlet-api:4.0.1)
* **spring-boot-starter-web**(org.springframework.boot:spring-boot-starter-web:2.1.8.RELEASE)
* **mybatis-plus-boot-starter**(com.baomidou:mybatis-plus-boot-starter:3.2.0)
* **commons-io**(commons-io:commons-io:2.6)
* **commons-lang3**(org.apache.commons:commons-lang3:3.8.1)
* **fastjson**(com.alibaba:fastjson:1.2.60)
:::tip
以上依赖在引入diboot-core-starter依赖的项目中,可以不再引入。
:::
......@@ -7,5 +7,7 @@
"build": "vuepress build ./"
},
"author": "yang",
"license": "Apache-2.0"
"license": "Apache-2.0",
"dependencies": {
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment