天天看點

悟空 CRM 9.0 釋出,高品質 JFinal 開源項目

悟空CRM采用全新的前後端分離模式,本倉庫代碼中已內建前端vue打包後檔案,可免去打包操作

如需調整前端代碼,請單獨下載下傳前端代碼,前端代碼在根目錄的ux檔案夾中

主要技術棧

核心架構:jfinal3.8

緩存:redis caffeine

資料庫連接配接池:Druid

工具類:hutool,fastjson,poi-ooxml

定時任務:jfinal-cron

項目建構工具:maven

Web容器:tomcat,undertow(預設)

前端MVVM架構:Vue.JS 2.5.x

路由:Vue-Router 3.x

資料互動:Axios

UI架構:Element-UI 2.6.3

悟空CRM是一個基于jfinal的開源crm系統,采用前後端分離的開發模式,提供了Aop,查詢緩存,資料庫連接配接池,定時器,excel導入導出等功能。

項目中主要有CRM,OA,項目管理,BI等子產品,通過角色,部門,菜單實作了按鈕級的功能權限控制和資料權限控制,通過将使用者登入資訊儲存至redis來實作支援項目的熱重新開機和分布式部署。

項目還擁有如下特性:

項目通過jfinal強大的AOP将權限判斷從代碼中抽離出來,使用者無需手動判斷登陸角色是否擁有權限,以下為通過權限注解在攔截器判斷使用者是否擁有通路權限

@Override
public void intercept(Invocation invocation) {
    //TODO 權限功能背景攔截
    Permissions permissions=invocation.getMethod().getAnnotation(Permissions.class);
    if(permissions!=null&&permissions.value().length>0){
        JSONObject jsonObject= Aop.get(AdminRoleService.class).auth(BaseUtil.getUserId());
        //組裝應有權限清單
        List<String> arr=queryAuth(jsonObject, "");
        boolean isRelease=false;
        for (String key : permissions.value()) {
            if(!isRelease){
                if(arr.contains(key)){
                    isRelease=true;
                }
            }
        }
        if(!isRelease){
            invocation.getController().renderJson(R.error("無權通路"));
            return;
        }
    }
    invocation.invoke();
}           

通過AOP和注解對資料進行非空校驗,無需一個個判斷參數是否為空,資料為空直接傳回

自定義分頁資料接收,自動處理分頁參數和資料對象,給controller方法加上參數

BasePageRequest,T為對象類型,然後參數就會自動組裝成分頁參數和定義的對象類,以下為實作代碼:

public class PageParaGetter extends ParaGetter<BasePageRequest> {
    public PageParaGetter(String parameterName, String defaultValue) {
        super(parameterName, defaultValue);
    }
    @Override
    protected BasePageRequest to(String s) {
        return null;
    }           
@Override
@SuppressWarnings("unchecked")
public BasePageRequest get(Action action, Controller controller) {
    Parameter[] parameters=action.getMethod().getParameters();
    Class clazz=null;
    for (Parameter parameter:parameters){
        if(BasePageRequest.class.isAssignableFrom(parameter.getType())){
            Type parameterizedType=parameter.getParameterizedType();
            if (parameterizedType instanceof ParameterizedType) {
                Type[] params = ((ParameterizedType) parameterizedType).getActualTypeArguments();
                clazz= TypeUtils.getClass(params[0]);
            }
            break;
        }
    }
    boolean isJson=controller.getHeader("Content-Type")!=null&&controller.getHeader("Content-Type").toLowerCase().contains("application/json");
    return isJson?new BasePageRequest(controller.getRawData(),clazz):new BasePageRequest(controller.getKv(),clazz);
}           

}

自定義json工廠,實作對資料的個性化解析傳回,如實作将資料傳回時将資料轉成駝峰規則,自定義某種類型的對象的傳回格式等。

可以自定義錯誤處理模闆,在出現錯誤或者其他異常的情況下,可以給予使用者一個清晰的提示,避免使用者看到一些無用的錯誤資訊等功能

檔案可以上傳到項目目錄之外,避免了重新打包項目後檔案的丢失

@Override
public void configConstant(Constants me) {
    me.setDevMode(prop.getBoolean("jfinal.devMode", true));
    me.setInjectDependency(true);
    //設定上傳檔案到哪個目錄
    me.setBaseUploadPath(BaseConstant.UPLOAD_PATH);
    me.setBaseDownloadPath(BaseConstant.UPLOAD_PATH);
    //自定義json工廠
    me.setJsonFactory(new ErpJsonFactory());
    //限制上傳100M
    me.setMaxPostSize(104857600);
}           

采用項目分層化的設計,職責分工明确,降低代碼的耦合性Hander->對指定規則的url進行捕獲或者放心Interceptor->環繞式AOP攔截,對通路權限,資料權限,參數等進行校驗,可以配置在全局,單個路由,單個controller,單個方法等上面,可進行自定義實作,對資料進行處理

Router->對不同規則的資料進行分發,不同url進入不同路由和controller

Controller->對參數進行組裝,将資料傳入到service處理後進行render傳回

Service->對業務代碼進行處理,并将資料轉入Db處理或緩存

Db->對資料庫進行操作

Render->将service傳回的資料在controller進行傳回,以及出錯後通過

SQL模闆功能,将sql寫入到xx.sql檔案中,如果sql檔案有變動,無需重新編譯打包,直接改動sql檔案中的sql即可,以下為自動掃描指定路徑下sql檔案的代碼:

private void getSqlTemplate(String path, ActiveRecordPlugin arp) {
    File file = new File(path);
    if (file.exists()) {
        File[] files = file.listFiles();
        if (files != null && files.length > 0) {
            for (File childFile : files) {
                if (childFile.isDirectory()) {
                    getSqlTemplate(childFile.getAbsolutePath(), arp);
                } else {
                    if (childFile.getName().toLowerCase().endsWith(".sql")) {
                        arp.addSqlTemplate(childFile.getAbsolutePath().replace(PathKit.getRootClassPath(), "").replace("\\", "/"));
                    }
                }
            }
        }
    }
}           

以下是系統的部分截圖:

以下為悟空CRM9.0 JAVA版部分功能系統截圖

悟空 CRM 9.0 釋出,高品質 JFinal 開源項目
悟空 CRM 9.0 釋出,高品質 JFinal 開源項目
悟空 CRM 9.0 釋出,高品質 JFinal 開源項目
悟空 CRM 9.0 釋出,高品質 JFinal 開源項目
悟空 CRM 9.0 釋出,高品質 JFinal 開源項目