@@ -1,11 +1,13 @@ | |||||
package cc.smtweb.system.bpm.spring; | |||||
package cc.smtweb.system.bpm.web; | |||||
import cc.smtweb.framework.core.annotation.SwService; | import cc.smtweb.framework.core.annotation.SwService; | ||||
import cc.smtweb.framework.core.annotation.SwStartListener; | |||||
import cc.smtweb.framework.core.cache.CacheManager; | import cc.smtweb.framework.core.cache.CacheManager; | ||||
import cc.smtweb.framework.core.common.SwConsts; | import cc.smtweb.framework.core.common.SwConsts; | ||||
import cc.smtweb.framework.core.db.cache.ModelTableCache; | import cc.smtweb.framework.core.db.cache.ModelTableCache; | ||||
import cc.smtweb.framework.core.db.impl.DatabaseUtil; | import cc.smtweb.framework.core.db.impl.DatabaseUtil; | ||||
import cc.smtweb.framework.core.db.vo.ModelCatalog; | import cc.smtweb.framework.core.db.vo.ModelCatalog; | ||||
import cc.smtweb.framework.core.mvc.controller.IStartListener; | |||||
import cc.smtweb.framework.core.mvc.service.TreeHelper; | import cc.smtweb.framework.core.mvc.service.TreeHelper; | ||||
import cc.smtweb.framework.core.systask.TaskStartEvent; | import cc.smtweb.framework.core.systask.TaskStartEvent; | ||||
import cc.smtweb.framework.core.systask.WebStartedEvent; | import cc.smtweb.framework.core.systask.WebStartedEvent; | ||||
@@ -19,12 +21,14 @@ import org.springframework.stereotype.Component; | |||||
/** | /** | ||||
* Created by Akmm at 2022/7/8 19:57 | * Created by Akmm at 2022/7/8 19:57 | ||||
*/ | */ | ||||
@Component | |||||
@Order(SwConsts.DEFAULT_ORDER + 1) | |||||
public class BpmStartedListener implements ApplicationListener<ApplicationStartedEvent> { | |||||
@SwStartListener() | |||||
public class BpmStartedListener implements IStartListener { | |||||
public int order() { | |||||
return SwConsts.DEFAULT_ORDER + 1; | |||||
} | |||||
@Override | @Override | ||||
public void onApplicationEvent(ApplicationStartedEvent event) { | |||||
public void run() { | |||||
//初始化数据库 | //初始化数据库 | ||||
new DatabaseUtil(true, false).checkDb(); | new DatabaseUtil(true, false).checkDb(); | ||||
//初始化缓存 | //初始化缓存 |
@@ -497,6 +497,13 @@ public class ModelFormHelper { | |||||
} else { | } else { | ||||
field.put("maxlength", 0); | field.put("maxlength", 0); | ||||
} | } | ||||
Map lookup = (Map)field.get("lookup"); | |||||
if (lookup!=null){ | |||||
long widgetId = MapUtil.readLong(lookup, "widgetId",-1L); | |||||
if(widgetId>0){ | |||||
setWidget.add(widgetId); | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -520,7 +527,7 @@ public class ModelFormHelper { | |||||
col.put("editor", dtb != null ? dtb.editor: SwEnum.EditorType.INPUT.value); | col.put("editor", dtb != null ? dtb.editor: SwEnum.EditorType.INPUT.value); | ||||
if (field.getLink() == 0L) return; | if (field.getLink() == 0L) return; | ||||
Set<ModelForm> set = ModelFormCache.getInstance().getListByTable(field.getLink(), SwEnum.FormType.WIDGET.value); | Set<ModelForm> set = ModelFormCache.getInstance().getListByTable(field.getLink(), SwEnum.FormType.WIDGET.value); | ||||
if (set == null || set.isEmpty()) return; | if (set == null || set.isEmpty()) return; | ||||
ModelForm form = set.iterator().next(); | ModelForm form = set.iterator().next(); | ||||
@@ -166,7 +166,7 @@ public class FlowInstance { | |||||
getProcInstDao().updateEntity(procInst); | getProcInstDao().updateEntity(procInst); | ||||
buildBillLog(FlowConst.Button.HANDLE.value, actInst, null); | buildBillLog(FlowConst.Button.HANDLE.value, actInst, null); | ||||
// comp.transCallback(FlowConst.FlowOptType.RETAKE.value, act_inst, null); | |||||
listener.handle(actInst); | |||||
} | } | ||||
//从页面参数加载流程实例 | //从页面参数加载流程实例 | ||||
@@ -509,6 +509,7 @@ public class FlowInstance { | |||||
getProcInstDao().updateEntity(procInst); | getProcInstDao().updateEntity(procInst); | ||||
buildBillLog(FlowConst.Button.SUBMIT.value, actInst, listInsertTask); | buildBillLog(FlowConst.Button.SUBMIT.value, actInst, listInsertTask); | ||||
listener.submit(actInst, listInsertTask); | |||||
} | } | ||||
@@ -569,7 +570,7 @@ public class FlowInstance { | |||||
getProcInstDao().updateEntity(procInst); | getProcInstDao().updateEntity(procInst); | ||||
buildBillLog(FlowConst.Button.SUBMIT.value, actInst, listInsertTask); | buildBillLog(FlowConst.Button.SUBMIT.value, actInst, listInsertTask); | ||||
// comp.transCallback(FlowConst.Button.SUBMIT.value, actInst, listInsertTask); | |||||
listener.submit(actInst, listInsertTask); | |||||
} | } | ||||
@@ -613,7 +614,7 @@ public class FlowInstance { | |||||
getProcInstDao().updateEntity(procInst); | getProcInstDao().updateEntity(procInst); | ||||
buildBillLog(FlowConst.Button.DISUSE.value, actInst, null); | buildBillLog(FlowConst.Button.DISUSE.value, actInst, null); | ||||
// comp.transCallback(FlowConst.FlowOptType.DISUSE.value, actInst, null); | |||||
listener.disuse(actInst); | |||||
} | } | ||||
/** | /** | ||||
@@ -714,6 +715,7 @@ public class FlowInstance { | |||||
new_acts.clear(); | new_acts.clear(); | ||||
new_acts.add(old_act); | new_acts.add(old_act); | ||||
buildBillLog(FlowConst.Button.RETAKE.value, actInst, new_acts); | buildBillLog(FlowConst.Button.RETAKE.value, actInst, new_acts); | ||||
listener.retake(actInst, new_acts); | |||||
// comp.transCallback(FlowConst.Button.RETAKE.value, actInst, new_acts); | // comp.transCallback(FlowConst.Button.RETAKE.value, actInst, new_acts); | ||||
} else { | } else { | ||||
List<Task> new_acts = provider.findAfterTasks(actInst.getId()); | List<Task> new_acts = provider.findAfterTasks(actInst.getId()); | ||||
@@ -739,7 +741,7 @@ public class FlowInstance { | |||||
getProcInstDao().updateEntity(procInst); | getProcInstDao().updateEntity(procInst); | ||||
buildBillLog(FlowConst.Button.RETAKE.value, actInst, new_acts); | buildBillLog(FlowConst.Button.RETAKE.value, actInst, new_acts); | ||||
// comp.transCallback(FlowConst.FlowOptType.RETAKE.value, actInst, new_acts); | |||||
listener.retake(actInst, new_acts); | |||||
} | } | ||||
} | } | ||||
@@ -788,6 +790,7 @@ public class FlowInstance { | |||||
getProcInstDao().updateEntity(procInst); | getProcInstDao().updateEntity(procInst); | ||||
buildBillLog(FlowConst.Button.REJECT.value, actInst, new_acts); | buildBillLog(FlowConst.Button.REJECT.value, actInst, new_acts); | ||||
listener.reject(actInst, new_acts); | |||||
// comp.transCallback(FlowConst.FlowOptType.REJECT.value, actInst, new_acts); | // comp.transCallback(FlowConst.FlowOptType.REJECT.value, actInst, new_acts); | ||||
} | } | ||||
@@ -831,44 +834,10 @@ public class FlowInstance { | |||||
make_acts.add(make_act); | make_acts.add(make_act); | ||||
buildBillLog(FlowConst.Button.REJECT.value, actInst, make_acts); | buildBillLog(FlowConst.Button.REJECT.value, actInst, make_acts); | ||||
// comp.transCallback(FlowConst.FlowOptType.REJECT.value, actInst, make_acts); | |||||
listener.reject(actInst, make_acts); | |||||
} | } | ||||
/** | /** | ||||
* 办理 | |||||
* | |||||
* @throws Exception | |||||
*/ | |||||
/* | |||||
public void handler(AbsBillWfComponent comp) { | |||||
String user_id = context.getLoginInfo().getUserId(); | |||||
//校验权限,当前人员有权限干不,没权限直接抛异常 | |||||
checkPermission(); | |||||
if (actInst.getStatu() != FlowConst.ActivityStatu.WAIT.value) { | |||||
throw new BizException("当前任务非待办状态,不能办理失败!"); | |||||
} | |||||
ActinstDao actDao = new ActinstDao(); | |||||
actInst.setHandler(user_id); | |||||
actInst.setStartTime(DateUtil.nowDateTimeLong()); | |||||
actInst.setStatu(FlowConst.ActivityStatu.HANDLE.value); | |||||
procInst.setTaskId(actInst.getEntityId()); | |||||
procInst.setTaskName(ActivityEntityBuffer.getInstance().getNameById(actInst.getActId())); | |||||
procInst.setStatu(FlowConst.InstanceStatu.RUNING.value); | |||||
actDao.update(actInst); | |||||
new ProcinstDao().update(procInst); | |||||
buildBillLog(FlowConst.FlowOptType.HANDLER.value, actInst, null); | |||||
// comp.transCallback(FlowConst.FlowOptType.RETAKE.value, act_inst, null); | |||||
} | |||||
*/ | |||||
/** | |||||
* 状态变更,构建日志 | * 状态变更,构建日志 | ||||
*/ | */ | ||||
protected void buildBillLog(final String flow_opt, Task srcTask, List<Task> dstTasks) { | protected void buildBillLog(final String flow_opt, Task srcTask, List<Task> dstTasks) { | ||||
@@ -1,6 +1,9 @@ | |||||
package cc.smtweb.system.bpm.web.engine.flow; | package cc.smtweb.system.bpm.web.engine.flow; | ||||
import cc.smtweb.framework.core.common.SwMap; | import cc.smtweb.framework.core.common.SwMap; | ||||
import cc.smtweb.system.bpm.web.engine.flow.entity.Task; | |||||
import java.util.List; | |||||
/** | /** | ||||
* Created by Akmm at 2022-08-20 16:12 | * Created by Akmm at 2022-08-20 16:12 | ||||
@@ -9,4 +12,16 @@ import cc.smtweb.framework.core.common.SwMap; | |||||
public class FlowListener { | public class FlowListener { | ||||
//设置条件计算参数 | //设置条件计算参数 | ||||
public void setExprParam(SwMap param){} | public void setExprParam(SwMap param){} | ||||
//提交 | |||||
public void submit(Task srcTask, List<Task> dstTasks) {} | |||||
//取回 | |||||
public void retake(Task srcTask, List<Task> dstTasks) {} | |||||
//驳回 | |||||
public void reject(Task srcTask, List<Task> dstTasks) {} | |||||
//办理,签收 | |||||
public void handle(Task srcTask) {} | |||||
//作废 | |||||
public void disuse(Task srcTask) {} | |||||
} | } |
@@ -18,10 +18,9 @@ | |||||
<#list fields as filter> | <#list fields as filter> | ||||
{ | { | ||||
"id": "id${newId()}", | "id": "id${newId()}", | ||||
"type": "fx-${filter.editor}", | |||||
"type": "${filter.editor}", | |||||
"props": { | "props": { | ||||
"label": "${filter.label}", | "label": "${filter.label}", | ||||
"type": "text", | |||||
<#if filter.maxlength gt 0> | <#if filter.maxlength gt 0> | ||||
"maxlength": ${filter.maxlength}, | "maxlength": ${filter.maxlength}, | ||||
</#if> | </#if> | ||||
@@ -31,6 +30,13 @@ | |||||
"affixError": false, | "affixError": false, | ||||
"dataset": "${filter.dataset}", | "dataset": "${filter.dataset}", | ||||
"field": "${filter.id}", | "field": "${filter.id}", | ||||
<#if filter.lookup??> | |||||
"lookup": { | |||||
<#list filter.lookup as k, v> | |||||
"${k}": "${v}" <#if k_has_next>,</#if> | |||||
</#list> | |||||
}, | |||||
</#if> | |||||
"name": "${filter.name}" | "name": "${filter.name}" | ||||
}, | }, | ||||
"events": {} | "events": {} | ||||
@@ -39,10 +39,9 @@ | |||||
<#list fields as filter > | <#list fields as filter > | ||||
{ | { | ||||
"id": "id${newId()}", | "id": "id${newId()}", | ||||
"type": "fx-${filter.editor}", | |||||
"type": "${filter.editor}", | |||||
"props": { | "props": { | ||||
"label": "${filter.label}", | "label": "${filter.label}", | ||||
"type": "text", | |||||
<#if filter.maxlength gt 0 > | <#if filter.maxlength gt 0 > | ||||
"maxlength": ${filter.maxlength}, | "maxlength": ${filter.maxlength}, | ||||
</#if> | </#if> | ||||
@@ -50,6 +49,13 @@ | |||||
"labelWidth": 100, | "labelWidth": 100, | ||||
"dataset": "${filter.dataset}", | "dataset": "${filter.dataset}", | ||||
"field": "${filter.id}", | "field": "${filter.id}", | ||||
<#if filter.lookup??> | |||||
"lookup": { | |||||
<#list filter.lookup as k, v> | |||||
"${k}": "${v}" <#if k_has_next>,</#if> | |||||
</#list> | |||||
}, | |||||
</#if> | |||||
"name": "${filter.name}" | "name": "${filter.name}" | ||||
}, | }, | ||||
"events": {} | "events": {} | ||||
@@ -156,15 +156,22 @@ | |||||
"id": "id${newId()}", | "id": "id${newId()}", | ||||
<#if (dfield.readonly = true)> | <#if (dfield.readonly = true)> | ||||
"type": "fx-text", | "type": "fx-text", | ||||
"disabled": true, | |||||
<#else> | <#else> | ||||
"type": "fx-${dfield.editor}", | |||||
"type": "${dfield.editor}", | |||||
</#if> | </#if> | ||||
"props": { | "props": { | ||||
"label": "${dfield.label}", | "label": "${dfield.label}", | ||||
"type": "text", | |||||
"dataset": "${dfield.dataset}", | "dataset": "${dfield.dataset}", | ||||
"field": "${dfield.id}", | "field": "${dfield.id}", | ||||
"required": "${field.required}", | |||||
"required": "${dfield.required}", | |||||
<#if dfield.lookup??> | |||||
"lookup": { | |||||
<#list dfield.lookup as k, v> | |||||
"${k}": "${v}" <#if k_has_next>,</#if> | |||||
</#list> | |||||
}, | |||||
</#if> | |||||
<#if dfield.maxlength gt 0> | <#if dfield.maxlength gt 0> | ||||
"maxlength": ${dfield.maxlength}, | "maxlength": ${dfield.maxlength}, | ||||
</#if> | </#if> | ||||
@@ -3,7 +3,9 @@ package cc.smtweb.framework.core; | |||||
import cc.smtweb.framework.core.cache.CacheManager; | import cc.smtweb.framework.core.cache.CacheManager; | ||||
import cc.smtweb.framework.core.common.SwConsts; | import cc.smtweb.framework.core.common.SwConsts; | ||||
import cc.smtweb.framework.core.db.impl.DatabaseUtil; | import cc.smtweb.framework.core.db.impl.DatabaseUtil; | ||||
import cc.smtweb.framework.core.mvc.controller.IStartListener; | |||||
import cc.smtweb.framework.core.mvc.controller.scan.ApplicationScanner; | import cc.smtweb.framework.core.mvc.controller.scan.ApplicationScanner; | ||||
import cc.smtweb.framework.core.mvc.controller.scan.BeanManager; | |||||
import cc.smtweb.framework.core.systask.TaskStartEvent; | import cc.smtweb.framework.core.systask.TaskStartEvent; | ||||
import cc.smtweb.framework.core.systask.WebStartedEvent; | import cc.smtweb.framework.core.systask.WebStartedEvent; | ||||
import lombok.SneakyThrows; | import lombok.SneakyThrows; | ||||
@@ -13,24 +15,32 @@ import org.springframework.context.ConfigurableApplicationContext; | |||||
import org.springframework.core.annotation.Order; | import org.springframework.core.annotation.Order; | ||||
import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
import java.util.Comparator; | |||||
import java.util.List; | |||||
/** | /** | ||||
* 执行接口扫描任务 | * 执行接口扫描任务 | ||||
*/ | */ | ||||
@Component | @Component | ||||
@Order(SwConsts.DEFAULT_ORDER) | @Order(SwConsts.DEFAULT_ORDER) | ||||
public class CoreApplicationStartedListener implements ApplicationListener<ApplicationStartedEvent> { | public class CoreApplicationStartedListener implements ApplicationListener<ApplicationStartedEvent> { | ||||
@SneakyThrows | |||||
@Override | |||||
public void onApplicationEvent(ApplicationStartedEvent event) { | |||||
System.out.println("onApplicationEvent============="); | |||||
ConfigurableApplicationContext applicationContext = event.getApplicationContext(); | |||||
applicationContext.publishEvent(new TaskStartEvent()); | |||||
//包扫描 | |||||
ApplicationScanner.scan(applicationContext); | |||||
@SneakyThrows | |||||
@Override | |||||
public void onApplicationEvent(ApplicationStartedEvent event) { | |||||
System.out.println("onApplicationEvent============="); | |||||
ConfigurableApplicationContext applicationContext = event.getApplicationContext(); | |||||
// 通知 controller 正式使用 | |||||
applicationContext.publishEvent(new WebStartedEvent()); | |||||
System.out.println("start end============="); | |||||
} | |||||
applicationContext.publishEvent(new TaskStartEvent()); | |||||
//包扫描 | |||||
ApplicationScanner.scan(applicationContext); | |||||
List<IStartListener> list = BeanManager.getInstance().getStartListeners(); | |||||
list.sort(Comparator.comparingInt(IStartListener::order)); | |||||
for (IStartListener sl : list) { | |||||
sl.run(); | |||||
} | |||||
// 通知 controller 正式使用 | |||||
applicationContext.publishEvent(new WebStartedEvent()); | |||||
SwConsts.SysParam.SYS_STARTED = true; | |||||
System.out.println("start end============="); | |||||
} | |||||
} | } |
@@ -7,6 +7,9 @@ import org.springframework.context.annotation.Bean; | |||||
import org.springframework.context.annotation.ComponentScan; | import org.springframework.context.annotation.ComponentScan; | ||||
import org.springframework.context.annotation.Configuration; | import org.springframework.context.annotation.Configuration; | ||||
import org.springframework.scheduling.annotation.EnableScheduling; | import org.springframework.scheduling.annotation.EnableScheduling; | ||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | |||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; | |||||
/** | /** | ||||
* @author kevin | * @author kevin | ||||
@@ -14,7 +17,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; | |||||
@Configuration | @Configuration | ||||
@ComponentScan | @ComponentScan | ||||
@EnableScheduling | @EnableScheduling | ||||
public class CoreAutoConfiguration { | |||||
public class CoreAutoConfiguration implements WebMvcConfigurer { | |||||
/** | /** | ||||
* ID生成器的分步式机器码(1-1023) | * ID生成器的分步式机器码(1-1023) | ||||
*/ | */ | ||||
@@ -30,4 +33,9 @@ public class CoreAutoConfiguration { | |||||
public ControllerConfig coreControllerConfig() { | public ControllerConfig coreControllerConfig() { | ||||
return new ControllerConfig("core", "cc.smtweb.framework.core"); | return new ControllerConfig("core", "cc.smtweb.framework.core"); | ||||
} | } | ||||
@Override | |||||
public void addInterceptors(InterceptorRegistry registry) { | |||||
registry.addInterceptor(new CoreInterceptor()); | |||||
} | |||||
} | } |
@@ -0,0 +1,30 @@ | |||||
package cc.smtweb.framework.core; | |||||
import cc.smtweb.framework.core.common.SwConsts; | |||||
import cc.smtweb.framework.core.exception.BizException; | |||||
import org.springframework.web.servlet.HandlerInterceptor; | |||||
import org.springframework.web.servlet.ModelAndView; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
/** | |||||
* Created by Akmm at 2022-08-24 10:53 | |||||
*/ | |||||
public class CoreInterceptor implements HandlerInterceptor { | |||||
@Override | |||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { | |||||
if (!SwConsts.SysParam.SYS_STARTED) throw new BizException("系统启动中,请稍候..."); | |||||
return HandlerInterceptor.super.preHandle(request, response, handler); | |||||
} | |||||
@Override | |||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { | |||||
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); | |||||
} | |||||
@Override | |||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { | |||||
HandlerInterceptor.super.afterCompletion(request, response, handler, ex); | |||||
} | |||||
} |
@@ -0,0 +1,16 @@ | |||||
package cc.smtweb.framework.core.annotation; | |||||
import java.lang.annotation.ElementType; | |||||
import java.lang.annotation.Retention; | |||||
import java.lang.annotation.RetentionPolicy; | |||||
import java.lang.annotation.Target; | |||||
/** | |||||
* 启动监听,order为执行顺序,请按SWConsts.DEFAULT_ORDER + XXX | |||||
* @author zhenggm | |||||
*/ | |||||
@Retention(RetentionPolicy.RUNTIME) | |||||
@Target({ElementType.TYPE}) | |||||
public @interface SwStartListener { | |||||
// int order() default 0; | |||||
} |
@@ -4,8 +4,14 @@ package cc.smtweb.framework.core.common; | |||||
* Created by Akmm at 2022/3/23 9:46 | * Created by Akmm at 2022/3/23 9:46 | ||||
*/ | */ | ||||
public interface SwConsts { | public interface SwConsts { | ||||
class SysParam { | |||||
//系统启动完成 | |||||
public static boolean SYS_STARTED = false; | |||||
} | |||||
//开发调试模式 | //开发调试模式 | ||||
boolean SYS_DEBUG = true; | boolean SYS_DEBUG = true; | ||||
int DEFAULT_ORDER = 1; | int DEFAULT_ORDER = 1; | ||||
//缓存中:树节点按parent的key | //缓存中:树节点按parent的key | ||||
String KEY_PARENT_ID = "pr"; | String KEY_PARENT_ID = "pr"; | ||||
@@ -0,0 +1,11 @@ | |||||
package cc.smtweb.framework.core.mvc.controller; | |||||
/** | |||||
* Created by Akmm at 2022-08-24 09:26 | |||||
* 启动监听 | |||||
*/ | |||||
public interface IStartListener { | |||||
//启动执行顺序 | |||||
int order(); | |||||
void run(); | |||||
} |
@@ -20,38 +20,39 @@ import java.util.Map; | |||||
/** | /** | ||||
* 服务方法调用管理,通过url进行API调用 | * 服务方法调用管理,通过url进行API调用 | ||||
* | |||||
* @author xkliu | * @author xkliu | ||||
*/ | */ | ||||
@Slf4j | @Slf4j | ||||
public class MethodAccessManager { | public class MethodAccessManager { | ||||
private Map<String, IMethodAccess> controllers; | |||||
private IBeanContext beanContext; | |||||
private PermInterceptor permInterceptor; | |||||
private SchedulerTaskManager schedulerTaskManager; | |||||
private MethodAccess[] destroyMethods; | |||||
@Getter | |||||
private CacheManager cacheManager; | |||||
public MethodAccessManager(RedisManager redisManager, CacheManager cacheManager) { | |||||
permInterceptor = new PermInterceptor(redisManager); | |||||
this.cacheManager = cacheManager; | |||||
} | |||||
// 执行控制器方法 | |||||
Object invoke(String url, Map<String, Object> params, String body, HttpServletRequest request, HttpServletResponse response) throws Exception { | |||||
// 调用普通方法 | |||||
private Map<String, IMethodAccess> controllers; | |||||
private IBeanContext beanContext; | |||||
private PermInterceptor permInterceptor; | |||||
private SchedulerTaskManager schedulerTaskManager; | |||||
private MethodAccess[] destroyMethods; | |||||
@Getter | |||||
private CacheManager cacheManager; | |||||
public MethodAccessManager(RedisManager redisManager, CacheManager cacheManager) { | |||||
permInterceptor = new PermInterceptor(redisManager); | |||||
this.cacheManager = cacheManager; | |||||
} | |||||
// 执行控制器方法 | |||||
Object invoke(String url, Map<String, Object> params, String body, HttpServletRequest request, HttpServletResponse response) throws Exception { | |||||
// 调用普通方法 | |||||
// String url = module + "/" + service + "/" + method; | // String url = module + "/" + service + "/" + method; | ||||
IMethodAccess methodAccess = controllers.get(url); | |||||
IMethodAccess methodAccess = controllers.get(url); | |||||
if (methodAccess != null) { | |||||
permInterceptor.preHandle(request, methodAccess.getPerm()); | |||||
if (methodAccess != null) { | |||||
permInterceptor.preHandle(request, methodAccess.getPerm()); | |||||
return methodAccess.invoke(beanContext, params, body, request); | |||||
} | |||||
return methodAccess.invoke(beanContext, params, body, request); | |||||
} | |||||
// TODO 调用默认方法 | |||||
// TODO 调用默认方法 | |||||
// url = module + "/" + service + "/"; | // url = module + "/" + service + "/"; | ||||
// | // | ||||
// methodAccess = controllers.get(url); | // methodAccess = controllers.get(url); | ||||
@@ -63,43 +64,43 @@ public class MethodAccessManager { | |||||
// return methodAccess.invoke(beanContext, params, body, request, response); | // return methodAccess.invoke(beanContext, params, body, request, response); | ||||
// } | // } | ||||
return R.error(404, "not find api:" + url); | |||||
} | |||||
public void init(BeanManager beanManager, ISwCache<Long, PermChecker> cache) { | |||||
this.beanContext = beanManager.getBeanContext(); | |||||
this.controllers = beanManager.getControllers(); | |||||
this.destroyMethods = beanManager.loadDestroyMethods(); | |||||
this.permInterceptor.setCache(cache); | |||||
// 启动定时任务 | |||||
this.schedulerTaskManager = SchedulerTaskManager.build(beanContext, beanManager.getTasks()); | |||||
if (this.schedulerTaskManager != null) { | |||||
// 设置用于外部服务调用 | |||||
SchedulerManager schedulerManager = this.beanContext.getBean(SchedulerManager.class); | |||||
if (schedulerManager != null) { | |||||
schedulerManager.install(this.schedulerTaskManager); | |||||
} else { | |||||
log.error("not find spring bean schedulerManager"); | |||||
} | |||||
return R.error(404, "not find api:" + url); | |||||
} | } | ||||
} | |||||
void showdown() { | |||||
// 强行关闭定时任务 | |||||
if (this.schedulerTaskManager != null) { | |||||
this.schedulerTaskManager.shutdown(); | |||||
public void init(BeanManager beanManager, ISwCache<Long, PermChecker> cache) { | |||||
this.beanContext = beanManager.getBeanContext(); | |||||
this.controllers = beanManager.getControllers(); | |||||
this.destroyMethods = beanManager.loadDestroyMethods(); | |||||
this.permInterceptor.setCache(cache); | |||||
// 启动定时任务 | |||||
this.schedulerTaskManager = SchedulerTaskManager.build(beanContext, beanManager.getTasks()); | |||||
if (this.schedulerTaskManager != null) { | |||||
// 设置用于外部服务调用 | |||||
SchedulerManager schedulerManager = this.beanContext.getBean(SchedulerManager.class); | |||||
if (schedulerManager != null) { | |||||
schedulerManager.install(this.schedulerTaskManager); | |||||
} else { | |||||
log.error("not find spring bean schedulerManager"); | |||||
} | |||||
} | |||||
} | } | ||||
if (destroyMethods != null) { | |||||
for (MethodAccess methodAccess : destroyMethods) { | |||||
try { | |||||
methodAccess.invoke(beanContext); | |||||
} catch (Exception e) { | |||||
log.error(methodAccess.fullName(), e); | |||||
void showdown() { | |||||
// 强行关闭定时任务 | |||||
if (this.schedulerTaskManager != null) { | |||||
this.schedulerTaskManager.shutdown(); | |||||
} | |||||
if (destroyMethods != null) { | |||||
for (MethodAccess methodAccess : destroyMethods) { | |||||
try { | |||||
methodAccess.invoke(beanContext); | |||||
} catch (Exception e) { | |||||
log.error(methodAccess.fullName(), e); | |||||
} | |||||
} | |||||
} | } | ||||
} | |||||
} | } | ||||
} | |||||
} | } |
@@ -1,6 +1,8 @@ | |||||
package cc.smtweb.framework.core.mvc.controller.scan; | package cc.smtweb.framework.core.mvc.controller.scan; | ||||
import cc.smtweb.framework.core.exception.SwException; | |||||
import cc.smtweb.framework.core.mvc.controller.IActionManager; | import cc.smtweb.framework.core.mvc.controller.IActionManager; | ||||
import cc.smtweb.framework.core.mvc.controller.IStartListener; | |||||
import cc.smtweb.framework.core.mvc.controller.access.ControllerAccess; | import cc.smtweb.framework.core.mvc.controller.access.ControllerAccess; | ||||
import cc.smtweb.framework.core.mvc.controller.access.IMethodAccess; | import cc.smtweb.framework.core.mvc.controller.access.IMethodAccess; | ||||
import cc.smtweb.framework.core.mvc.controller.access.MethodAccess; | import cc.smtweb.framework.core.mvc.controller.access.MethodAccess; | ||||
@@ -17,145 +19,163 @@ import java.util.Map; | |||||
@Slf4j | @Slf4j | ||||
public class BeanManager implements IActionManager { | public class BeanManager implements IActionManager { | ||||
private ApplicationContext applicationContext; | |||||
private List<ControllerAccess> beans = new ArrayList<>(); | |||||
private Map<Class<?>, Object> beanMap = new HashMap<>(); | |||||
private List<ControllerAccess> singletonServices = new ArrayList<>(); | |||||
@Getter | |||||
private Map<String, IMethodAccess> controllers = new HashMap<>(); | |||||
@Getter | |||||
private BeanContext beanContext; | |||||
@Getter | |||||
private List<SchedulerMethodAccess> tasks = new ArrayList<>(); | |||||
private List<OrderMethodAccess> constructMethods = new ArrayList<>(); | |||||
private List<OrderMethodAccess> destroyMethods = new ArrayList<>(); | |||||
private List<IMethodAccess> beanMethods = new ArrayList<>(); | |||||
private Map<String, Class<?>> mapTableClass = new HashMap<>(); | |||||
private static BeanManager instance = null; | |||||
static { | |||||
instance = new BeanManager(); | |||||
} | |||||
public static BeanManager getInstance() { | |||||
return instance; | |||||
} | |||||
private BeanManager() { | |||||
} | |||||
public void install(ApplicationContext applicationContext) { | |||||
this.applicationContext = applicationContext; | |||||
beanContext = new BeanContext(beanMap, applicationContext); | |||||
} | |||||
private ApplicationContext applicationContext; | |||||
private List<ControllerAccess> beans = new ArrayList<>(); | |||||
private Map<Class<?>, Object> beanMap = new HashMap<>(); | |||||
private List<ControllerAccess> singletonServices = new ArrayList<>(); | |||||
@Getter | |||||
private Map<String, IMethodAccess> controllers = new HashMap<>(); | |||||
@Getter | |||||
private BeanContext beanContext; | |||||
@Getter | |||||
private List<SchedulerMethodAccess> tasks = new ArrayList<>(); | |||||
private List<OrderMethodAccess> constructMethods = new ArrayList<>(); | |||||
private List<OrderMethodAccess> destroyMethods = new ArrayList<>(); | |||||
private List<IMethodAccess> beanMethods = new ArrayList<>(); | |||||
private Map<String, Class<?>> mapTableClass = new HashMap<>(); | |||||
private List<IStartListener> listStartListener = new ArrayList<>(); | |||||
private static BeanManager instance = null; | |||||
static { | |||||
instance = new BeanManager(); | |||||
} | |||||
public void init() throws Exception { | |||||
// 读取DbEngine,用以初始化 EntityDao | |||||
beanContext.init(); | |||||
public static BeanManager getInstance() { | |||||
return instance; | |||||
} | |||||
// 自动设置@SwBean注解对象的@SwParam注解属性 | |||||
for (ControllerAccess controllerAccess: beans) { | |||||
Object bean = controllerAccess.getSingletonInstance(); | |||||
addBeanMap(controllerAccess.getBeanType(), bean); | |||||
private BeanManager() { | |||||
} | } | ||||
// 映射单例Bean字段值 | |||||
for (ControllerAccess controllerAccess: beans) { | |||||
controllerAccess.initSingletonFields(beanContext, null); | |||||
public void install(ApplicationContext applicationContext) { | |||||
this.applicationContext = applicationContext; | |||||
beanContext = new BeanContext(beanMap, applicationContext); | |||||
} | } | ||||
for (IMethodAccess methodAccess: beanMethods) { | |||||
Object bean = methodAccess.invoke(beanContext); | |||||
addBeanMap(methodAccess.getReturnType(), bean); | |||||
log.debug("[smt]init bean:" + methodAccess.getReturnType() + " by " + methodAccess.fullName()); | |||||
public void init() throws Exception { | |||||
// 读取DbEngine,用以初始化 EntityDao | |||||
beanContext.init(); | |||||
// 自动设置@SwBean注解对象的@SwParam注解属性 | |||||
for (ControllerAccess controllerAccess : beans) { | |||||
Object bean = controllerAccess.getSingletonInstance(); | |||||
addBeanMap(controllerAccess.getBeanType(), bean); | |||||
} | |||||
// 映射单例Bean字段值 | |||||
for (ControllerAccess controllerAccess : beans) { | |||||
controllerAccess.initSingletonFields(beanContext, null); | |||||
} | |||||
for (IMethodAccess methodAccess : beanMethods) { | |||||
Object bean = methodAccess.invoke(beanContext); | |||||
addBeanMap(methodAccess.getReturnType(), bean); | |||||
log.debug("[smt]init bean:" + methodAccess.getReturnType() + " by " + methodAccess.fullName()); | |||||
} | |||||
// 映射单例控制器字段值 | |||||
for (ControllerAccess controllerAccess : singletonServices) { | |||||
controllerAccess.initSingletonFields(beanContext, null); | |||||
} | |||||
// 执行初始化方法 | |||||
constructMethods.sort((a, b) -> a.order - b.order); | |||||
for (OrderMethodAccess orderMethodAccess : constructMethods) { | |||||
IMethodAccess methodAccess = orderMethodAccess.methodAccess; | |||||
methodAccess.invoke(beanContext); | |||||
} | |||||
} | } | ||||
// 映射单例控制器字段值 | |||||
for (ControllerAccess controllerAccess: singletonServices) { | |||||
controllerAccess.initSingletonFields(beanContext, null); | |||||
private void addBeanMap(Class<?> beanType, Object bean) { | |||||
if (bean != null) { | |||||
beanMap.put(beanType, bean); | |||||
} | |||||
} | } | ||||
// 执行初始化方法 | |||||
constructMethods.sort((a, b) -> a.order - b.order); | |||||
IMethodAccess putIfAbsent(String url, IMethodAccess methodAccess) { | |||||
return controllers.putIfAbsent(url, methodAccess); | |||||
} | |||||
for (OrderMethodAccess orderMethodAccess: constructMethods) { | |||||
IMethodAccess methodAccess = orderMethodAccess.methodAccess; | |||||
methodAccess.invoke(beanContext); | |||||
void addBean(ControllerAccess controllerAccess) { | |||||
this.beans.add(controllerAccess); | |||||
} | } | ||||
} | |||||
private void addBeanMap(Class<?> beanType, Object bean) { | |||||
if (bean != null) { | |||||
beanMap.put(beanType, bean); | |||||
void addSingletonController(ControllerAccess controllerAccess) { | |||||
this.singletonServices.add(controllerAccess); | |||||
} | } | ||||
} | |||||
IMethodAccess putIfAbsent(String url, IMethodAccess methodAccess) { | |||||
return controllers.putIfAbsent(url, methodAccess); | |||||
} | |||||
void addTask(SchedulerMethodAccess schedulerMethodAccess) { | |||||
this.tasks.add(schedulerMethodAccess); | |||||
} | |||||
void addBean(ControllerAccess controllerAccess) { | |||||
this.beans.add(controllerAccess); | |||||
} | |||||
void addConstruct(int order, MethodAccess methodAccess) { | |||||
constructMethods.add(new OrderMethodAccess(order, methodAccess)); | |||||
} | |||||
void addSingletonController(ControllerAccess controllerAccess) { | |||||
this.singletonServices.add(controllerAccess); | |||||
} | |||||
void addDestroy(int order, MethodAccess methodAccess) { | |||||
destroyMethods.add(new OrderMethodAccess(order, methodAccess)); | |||||
} | |||||
void addTask(SchedulerMethodAccess schedulerMethodAccess) { | |||||
this.tasks.add(schedulerMethodAccess); | |||||
} | |||||
public MethodAccess[] loadDestroyMethods() { | |||||
if (destroyMethods.isEmpty()) { | |||||
return null; | |||||
} | |||||
void addConstruct(int order, MethodAccess methodAccess) { | |||||
constructMethods.add(new OrderMethodAccess(order, methodAccess)); | |||||
} | |||||
destroyMethods.sort((a, b) -> b.order - a.order); | |||||
void addDestroy(int order, MethodAccess methodAccess) { | |||||
destroyMethods.add(new OrderMethodAccess(order, methodAccess)); | |||||
} | |||||
int size = destroyMethods.size(); | |||||
MethodAccess[] result = new MethodAccess[size]; | |||||
for (int i = 0; i < size; i++) { | |||||
result[i] = destroyMethods.get(i).methodAccess; | |||||
} | |||||
public MethodAccess[] loadDestroyMethods() { | |||||
if (destroyMethods.isEmpty()) { | |||||
return null; | |||||
return result; | |||||
} | } | ||||
destroyMethods.sort((a, b) -> b.order - a.order); | |||||
int size = destroyMethods.size(); | |||||
MethodAccess[] result = new MethodAccess[size]; | |||||
for (int i = 0; i < size; i++) { | |||||
result[i] = destroyMethods.get(i).methodAccess; | |||||
void addBeanMethod(IMethodAccess methodAccess) { | |||||
this.beanMethods.add(methodAccess); | |||||
} | } | ||||
return result; | |||||
} | |||||
void addStartListener(Class<?> clazz) { | |||||
if (!IStartListener.class.isAssignableFrom(clazz)) { | |||||
throw new SwException("启动监听类必须实现IStartListener接口!"); | |||||
} | |||||
try { | |||||
IStartListener startListener = (IStartListener) clazz.newInstance(); | |||||
listStartListener.add(startListener); | |||||
} catch (Exception e) { | |||||
throw new SwException(e); | |||||
} | |||||
} | |||||
void addBeanMethod(IMethodAccess methodAccess) { | |||||
this.beanMethods.add(methodAccess); | |||||
} | |||||
public List<IStartListener> getStartListeners() { | |||||
return listStartListener; | |||||
} | |||||
@Override | |||||
public boolean api(String url, IMethodAccess methodAccess) { | |||||
return this.putIfAbsent(url, methodAccess) == null; | |||||
} | |||||
@Override | |||||
public boolean api(String url, IMethodAccess methodAccess) { | |||||
return this.putIfAbsent(url, methodAccess) == null; | |||||
} | |||||
public void addTableClass(String tableName, Class<?> clzz) { | |||||
mapTableClass.put(tableName, clzz); | |||||
} | |||||
public void addTableClass(String tableName, Class<?> clzz) { | |||||
mapTableClass.put(tableName, clzz); | |||||
} | |||||
public Class<?> getTableClass(String tableName) { | |||||
return mapTableClass.get(tableName); | |||||
} | |||||
public Class<?> getTableClass(String tableName) { | |||||
return mapTableClass.get(tableName); | |||||
} | |||||
private static class OrderMethodAccess { | |||||
private final int order; | |||||
private final MethodAccess methodAccess; | |||||
private static class OrderMethodAccess { | |||||
private final int order; | |||||
private final MethodAccess methodAccess; | |||||
OrderMethodAccess(int order, MethodAccess methodAccess) { | |||||
this.order = order; | |||||
this.methodAccess = methodAccess; | |||||
OrderMethodAccess(int order, MethodAccess methodAccess) { | |||||
this.order = order; | |||||
this.methodAccess = methodAccess; | |||||
} | |||||
} | } | ||||
} | |||||
} | } |
@@ -99,6 +99,11 @@ public class ClassParser { | |||||
if (swTable != null) { | if (swTable != null) { | ||||
beanManager.addTableClass(swTable.value(), clazz); | beanManager.addTableClass(swTable.value(), clazz); | ||||
} | } | ||||
SwStartListener startListener = clazz.getAnnotation(SwStartListener.class); | |||||
if (startListener != null) { | |||||
beanManager.addStartListener(clazz); | |||||
} | |||||
} | } | ||||
private ControllerAccess buildControllerAccess(Class<?> clazz, boolean alwaysCreate) { | private ControllerAccess buildControllerAccess(Class<?> clazz, boolean alwaysCreate) { | ||||