做过很多的项目,我们通常需要通过一点设计模式来解决一些稍微复杂的问题。比如说读取一个data,有多行数据文件。在读取过程中可能会出现些特殊情况,要求是,假如出现以外情况,需要把已经读取的数据写到数据库里,而出错的位置需要记录在系统中,下次读取的时候从这个位置往下,这个记录出错位置并且下次执行,这些基础的服务,可能是在框架中做处理,而不需要让编写业务程序的程序员知道这些。
设计:
可能我们只需要写一个IBaseBatchController接口,提供一些开放的接口。供程序员使用,可能是这样的
public interface IBaseBatchController{
public int execute();
}
外面的程序就是通过这个方法去调用。
比如说IBaseBatchController cc = new AAABatchController():
cc.execute();
我们需要解决的问题是在interface和实现类中间加一个AbstractBaseCatchController,目标就是在中间做基础的服务。
public void execute(String[] args){
try {
init(args);
if (getSyntaxCheckFirst()) {
// file first before doing biz processing
boolean validationOK = validateSyntax();
if (validationOK) {
initFileHandler(args);
processSingleFile(args);
} else {
updateTxInfo(IBatchStatusConstant.JOB_STATUS_ABORTED);
}
} else {
processSingleFile(args);
}
} catch (Exception e) {
throw new ECustomsUnChkException(e);
}
}
protected void processSingleFile(String args[]){
try
{
List errList = null;
errList = parseHeader();
if(errList != null && errList.size() != 0)
{
processError(errList);
if(isAbortOnHeaderFail()) {
throw new BatchAbortProcessingException(HEADER_FAIL_MSG);
}
}
int commitCount = 0;
boolean notEndofContent = true;
do
{
if(logger.isInfoEnabled()) {
logger.info("Commit count:" + (commitCount + 1));
}
try
{
parseBatchContent();
}
catch(ECustomsChkException e)
{
if(e.getMessage().equals(BATCH_EOF)) {
notEndofContent = false;
}
else {
throw e;
}
}
commitCount++;
} while(notEndofContent && !fileAbortIndicator);
if(fileAbortIndicator) {
throw new BatchAbortProcessingException(RECORD_FAIL_MSG);
}
errList = parseTrailer();
if(errList != null && errList.size() != 0)
{
processError(errList);
if(isAbortOnTrailerFail()) {
throw new BatchAbortProcessingException(TRAILER_FAIL_MSG);
}
}
updateTxInfo(IBatchStatusConstant.JOB_STATUS_COMPLETED);
}
catch (BatchAbortProcessingException e) {
updateTxInfo(IBatchStatusConstant.JOB_STATUS_ABORTED, e.getMessage());
throw new ECustomsUnChkException(e);
}
catch(Exception e)
{
updateTxInfo(IBatchStatusConstant.JOB_STATUS_ABORTED);
logger.error(this, e);
throw new ECustomsUnChkException(e);
}
public abstract parseBatchContent();//供实现类实现用。比如决定数据存放在什么表里。
public List parseHeader() throws ECustomsChkException, IOException {
debug("parseHeader");
results = readHeader();
List errorList = null;
if (results != null) {
errorList = results.getErrorList();
} else {
ErrorRecInfo errInfo = new ErrorRecInfo();
errInfo.setErrorMessage("Invalid file, file has no content");
errorList = new ArrayList();
errorList.add(errInfo);
}
return errorList;
}
}
需要做的是,在parsecontent方法里写处理数据的业务逻辑,解析出来的数据写到什么表里。
题外话,假设是通过Spring来管理bean的话,
假设需要在AbstractBaseCatchController 里通过注入的方式添加某些bean的话,那么请在AAABatchController实现类一并定义。
<bean id="invStatementMgr" parent="txProxyTemplate">
<property name="target">
<bean
class="ecustoms.ics.app.inventory.biz.InventoryStatementMgr">
<property name="dao">---------------是在AbstractBatchController 里。
<ref local="inventoryStatementDAO" />
</property>
<property name="syntaxCheckCmd">---------------是在AbstractBatchController 里。
<ref bean="inventorySyntaxCheckCmd" />
</property>
<property name="bizValidationCmd">
<ref local="inventoryBizValidationCmd" />
</property>
<property name="uploadDao">---------------是在AbstractBatchController 里。
<bean class="ecustoms.ics.app.upload.dao.UploadDAO" />
</property>
<property name="notificationMgr" ref="notificationMgr" />---------------是在AbstractBatchController 里。
<property name="referenceDao">
<bean class="ecustoms.ics.app.ref.dao.ReferenceDAO" />-------------定义在实现类InventoryStatementMgr里。
</property>
<property name="contactMgr" ref="ContactMgr"/>
<property name="userMgr" ref="userMgr"/>
<property name="aaMgr" ref="aaManager"/>
</bean>
</property>
</bean>