Skip to content
On this page

如何编写后台代码

低代码平台自定义后台代码有多种模式,一般业务开发只需要熟悉两种形态的自定义业务即可。* 一种是定义一个业务BO类,定义到工作流(反馈流)中,执行通用系统事件后会根据业务定义的参数在事件事件前、事件后执行。

  • 一种是独立定义一个服务Controller,供自定义业务独立实现,这个只需要熟悉系统如何操作数据库、如何创建事务、如何利用一些通用工具类即可;
  • 重点注意的是数据源切换方法;
  • 要掌握两种操作数据表的方法,mapper和sqlmapper。当使用sqlmapper时切记必须关闭数据连接session。
  • 掌握事务使用

1. 数据源切换

  • 操作Mapper前:
java
DynamicDataSource.setDataSource(dbSource);//设置指定数据源

操作后清除:

java
DynamicDataSource.clearDataSource();//清理

2. 两种数据表的操作方法

  • Mapper法
  1. 注解注入Mapper也可以:
java
@Autowired
privateToolFunctionEventSqlMappertoolFunctionEventSqlMapper;
  1. 手工注入也可以:
java
BaseService.getMapper("ToolFunction").selectAll();
  • SQLMapper法

通过制定数据源创建sqlsession,然后创建sqlmapper对象,

java
SqlSessionsession=getSession(dbSource);

SqlMappersqlMapper=newSqlMapper(session);

List<Map<String,Object>>rowList=sqlMapper.selectList(SQLPageHelper.SqlPage(getDBType(dbSource),selectSQL+fromSQL+whereSQL,orderBySQL),requestMap);

使用后一定要在finally里关闭session

java
}catch(Exceptione){

log.error("查询sql出错!",e);

Throw newException(e);

}finally{

session.close();

}

3. 事务使用:

在类的前面注入初始化事务对象

java
@Autowired

publicPlatformTransactionManagertransactionManager;

在方法体里,启用事务

java
DefaultTransactionDefinitiondef=newDefaultTransactionDefinition();

/*PROPAGATION_REQUIRES_NEW:事物隔离级别,开启新事务*/

def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);

TransactionStatusstatus=transactionManager.getTransaction(def);

完成业务后提交事务

java
transactionManager.commit(status);

利用try,将方法体异常捕捉好,异常情况rollback事务。

java
}catch(Exceptione){

transactionManager.rollback(status);

log.error("事件执行出错",e);

returnResult.failure("500","事件执行出错");

}finally{

DynamicDataSource.clearDataSource();//清理

log.info("cleandatasource");

}

4. BO案例

java
Package com.grgbanking.business.pm;    //根据命名规范放到规定目录即可

Import com.grgbanking.config.DynamicDataSource;

Import com.grgbanking.core.BaseEntity;

Import com.grgbanking.core.BaseService;

Import com.grgbanking.core.utils.E2MapUtil;

Import com.grgbanking.core.utils.Map2EntityUtil;

Import com.grgbanking.core.vo.Result;

Import com.grgbanking.modules.pm.entity.PmRecordDaily;

Import com.grgbanking.modules.util.DateUtil;

Import lombok.extern.slf4j.Slf4j;

Import org.apache.commons.lang3.time.DateUtils;

Import java.util.Date;

Import java.util.HashMap;

Import java.util.List;

Import java.util.Map;

/**

*@author[Yonsin]on[2020/9/1]

*@Description:[功能描述]

*@ModifiedBy:[修改人]on[修改日期]for[修改说明]

*/

@Slf4j

Public class PmUserTimeBO{    //无需继承或重写任何方法

Public Result`<?>compute(Map<String,Object>mp)throwsException{   //必须要返回  Result<?>`对象,方法参数必须是Map<String,Object>

for(Map.Entry<String,Object>entry:mp.entrySet()){

log.info("computeKey="+entry.getKey()+",Value="+entry.getValue());

}

Stringdaily_id=(String)mp.get("daily_id");

Stringuser_id=(String)mp.get("user_id");

Objectrecord_date=mp.get("record_date");

//不能直接对象操作,这样热加载修改对象还是拿到旧对象

PmRecordDailyquery=newPmRecordDaily();

query.setUser_id(user_id);

if(null!=record_date)query.setRecord_date(record_dateinstanceofDate?(Date)record_date:(record_dateinstanceofLong?newDate((Long)record_date):DateUtil.parse((String)record_date)));

//

try{

DynamicDataSource.setDataSource("pm");    //标记切换数据源

List`<PmRecordDaily>`ls=BaseService.getMapper("PmRecordDaily").select(query);  //BaseService.getMapper创建Mapper对象

DynamicDataSource.clearDataSource();

if(ls!=null&&ls.size()!=0){

Doublemax=0.0;

for(PmRecordDailydaily:ls){

Doubletime=daily.getTask_time();

if(time==null)time=0.0;

max+=time;

}

log.info("max======"+String.valueOf(max));

if(max>24)

Return Result.failure("500","当日累计工时【"+(Math.round(max*100)/100)+"】超过一天24小时,请确认工时是否正确!");

}

}catch(Exceptione){

Return Result.failure("500","PmUserTimeBO计算累计工时出现未知错误!");

}

Return Result.success();

}

}

5. Controller案例

java
Package com.grgbanking.modules.tool.web;

Import com.alibaba.fastjson.JSON;

Import com.alibaba.fastjson.JSONArray;

Import com.alibaba.fastjson.JSONObject;

Import com.grgbanking.MemCache;

Import com.grgbanking.config.DynamicDataSource;

Import com.grgbanking.core.BaseController;

Import com.grgbanking.core.TreeBean;

Import com.grgbanking.core.utils.*;

Import  com.grgbanking.core.vo.Result;

importcom.grgbanking.modules.tool.entity.ToolFunction;

Import lombok.extern.slf4j.Slf4j;

Import org.apache.commons.lang.StringEscapeUtils;

Import org.springframework.stereotype.Controller;

Import org.springframework.ui.Model;

Import org.springframework.web.bind.annotation.GetMapping;

Import org.springframework.web.bind.annotation.RequestMapping;

Import org.springframework.web.bind.annotation.RequestParam;

Import org.springframework.web.bind.annotation.ResponseBody;

Import javax.servlet.http.HttpServletRequest;

Import javax.sql.DataSource;

Import java.io.File;

Import java.nio.file.Files;

Import java.nio.file.Path;

Import java.nio.file.Paths;

Import java.nio.file.attribute.BasicFileAttributes;

Import java.sql.*;

Import java.util.ArrayList;

Import java.util.HashMap;

Import java.util.List;

Import java.util.Map;

/**

*@Description:IMS

*@author[Yonsin]on[2020年11月11日上午10:39:37]

*@ModifiedBy:[修改人]on[修改日期]for[修改说明]

*/

@Slf4j

@Controller

@RequestMapping("/filemanager")

Public classToolFIleManagerControllerextendsBaseController{   //继承BaseController

@ResponseBody

@RequestMapping("/dirTree")

Public List`<TreeBean>`dirTree(HttpServletRequestrequest)throwsException{     //前端树控件要求返回对象为List`<TreeBean>`,这样能直接替代通用树方法

Map<String,Object>requestMap=Map2EntityUtil.request2Map(request);//       //一般建议所有方法都是直接Request来接收,然后根据这个Map转换工具类来转换为Map对象

log.info("/filemanager/dirTreebegin:");

StringdirPath=(String)requestMap.get("dirPath");

//拼装树型数据对象

List`<TreeBean>`result=newArrayList`<TreeBean>`();

if(StringUtils.isEmpty(dirPath))returnresult;

try{

Filedir=newFile(dirPath);

log.info("dirPath:"+dirPath+"=="+dir.isDirectory());

if(dir.isDirectory()){

File[]files=dir.listFiles();

for(Filefile:files){

if(file.isDirectory()){

TreeBeanbean=newTreeBean();

//根据设置来取真实值

Stringid=file.getAbsolutePath();

bean.setId(id);

bean.setPId(dirPath);

File[]subfiles=file.listFiles();

Boolean hasSub=false;

Int fileNum=0;

for(Filesubfile:subfiles){

if(subfile.isDirectory()){

hasSub=true;

}else{

fileNum++;

}

}

bean.setParent(hasSub);

//显示值

bean.setName(file.getName()+(fileNum>0?"["+fileNum+"]":""));

result.add(bean);

}

}

}

}catch(Exceptione){

log.error("获取目录结构报错!",e);

}

Return result;

}

@ResponseBody

@RequestMapping("/getFileList")

Public Result<?>getFileList(HttpServletRequestrequest)throwsException{ //一般的前端Jquery方法调用后台会统一返回Result对象

Map<String,Object>requestMap=Map2EntityUtil.request2Map(request);//

for(Map.Entry<String,Object>entry:requestMap.entrySet()){

log.info("Key="+entry.getKey()+",Value="+entry.getValue());

}

StringdirPath=(String)requestMap.get("dirPath");

Resultresult=Result.success();

List<Map<String,String>>datals=newArrayList<Map<String,String>>();

try{

Filedir=newFile(dirPath);

File[]files=dir.listFiles();

for(Filefile:files){

if(file.isDirectory())continue;

Map<String,String>mp=newHashMap<String,String>();

mp.put("file_name",file.getName());

mp.put("file_path",file.getAbsolutePath());

mp.put("file_size",FileUtils.getPrintSize(file.length()));

Pathp=Paths.get(file.getAbsolutePath());

BasicFileAttributesatt=Files.readAttributes(p,BasicFileAttributes.class);//获取文件的属性

mp.put("create_time",DateUtils.formatDateTime(newDate(att.creationTime().toMillis())));

mp.put("lastmodified_time",DateUtils.formatDateTime(newDate(att.lastModifiedTime().toMillis())));

datals.add(mp);

}

result.setData(datals);

}catch(Exceptione){

log.error("获取文件列表报错!",e);

result.setSuccess(false);

result.setCode("500");

result.setMsg(e.getMessage());

}

Return result;

}

/**

*获取codeEditor文件内容

*@paramrequest

*@return

*/

@ResponseBody

@RequestMapping("/getFileContent")

Public Result<?>readFileContent(HttpServletRequestrequest){

Map<String,Object>requestMap=Map2EntityUtil.request2Map(request);//

Stringfilepath=(String)requestMap.get("filepath");

//StringfunId=(String)requestMap.get("funId");

log.info("codeEditor::::::"+filepath);

StringBuilderfilebody=newStringBuilder("");

if(StringUtils.isEmpty(filepath)){

Return Result.failure("500","文件路径不能为空!");

}

try{

filebody=FileUtils.readFile2String(filepath);

}catch(Exceptione){

log.error("",e);

}

Resultresult=newResult();

result.setData(filebody.toString());

result.setSuccess(true);

Return result;

}

/**

*保存codeEditor文件内容

*@paramrequest

*@return

*/

@ResponseBody

@RequestMapping("/saveFileContent")

Public Result<?>saveFileContent(HttpServletRequestrequest){

Map<String,Object>requestMap=Map2EntityUtil.request2Map(request);//

Stringfilepath=(String)requestMap.get("filepath");

log.info("codeEditor::::::"+filepath);

if(StringUtils.isEmpty(filepath)){

Return Result.failure("500","文件路径不能为空!");

}

Stringfilecontent=(String)requestMap.get("filecontent");

filecontent=StringEscapeUtils.unescapeHtml(filecontent);

Stringallpath=filepath.substring(0,filepath.lastIndexOf("/")+1);

Stringnewfilename=filepath.substring(filepath.lastIndexOf("/")+1);

FileUtils.createUTF8File(allpath,newfilename,filecontent,false);

Resultresult=newResult();

result.setMsg("保存成功!");

result.setSuccess(true);

Return result;

}

}