轻量级业务逻辑处理框架

编写程序的时候,随着需求和业务的增加,代码的维护会越来越困难,如何做到可扩展,易维护呢?一个比较好的方案就是提高代码的复用率,抽取易变的部分统一维护,以降耦。

 
代码框架一般可以分为两类,一类是业务逻辑的抽象,主要用于提高业务逻辑代码的复用率,比如不同业务对某个规则的验证。另外一类是处理流程的抽象,主要用于降耦,即对修改关闭,对扩展开放。新增的业务不影响原来的业务。当然,更多的是将两者的合理糅合。
 
先从第一类开始。
无论是webservice还是http请求形式的服务,我们的程序的提供服务的时候,都是有一个入口,一个出口,通过一个请求获取到一个响应,在这个请求和响应中间,程序处理业务逻辑,提供一定的功能(服务)。那么在这个过程中程序会做什么?
一般分为四个阶段,
一是参数的转换,就是把请求转换为系统内部的请求实体。对webservice来说,可能是这样,其他系统调用我们的系统是通过一个BizRequest,那么在这个阶段,我们把bizRequest转换为我们系统的内部实体类,bizRequestEntity。这样做的好处就是隔离外部系统和系统内部的变化,我们的业务的变化,不需要影响到外围系统。
二是参数的校验,对参数格式和是否必需的校验。一个比较好的建议是对一些必需的参数统一返回一个非法参数的错误码。但是在系统内的日志里面需要打印具体那个参数的问题,方便查询问题。、
三是主要业务逻辑的处理。主要逻辑建议使用逻辑处理框架(process framwork)。如果业务涉及数据库事务,建议在处理框架中使用spring的事务模板TransactionTemplate.
四是对主要业务逻辑处理后返回结果的解析和处理。通过主要业务逻辑返回的错误码构建返回给调用方的响应,或者做一些其他操作,比如通知第三方结果(比如下发短信通知用户)。
在一个控制器中处理的这四个阶段应该做到很好的封装,在这个控制器中应该看到很少的代码逻辑(逻辑几乎都在第三阶段),比较明显的一个效果是,你会发现你记录日志的代码跟这四个阶段的代码行数相差不多,甚至有超过。一个比较好的日志记录建议是,在一个单独的日志文件中,记录整个流程的一个简要日志,即通过一个重要参数,比如用户的ID,可以很容易的追踪到用户到达了那个阶段,那个阶段有什么问题。在另外一个日志中记录一些比较重要的信息和参数。方便更加细致的寻找问题。
 
对主要逻辑的处理,可以细化成三个阶段,初始化,校验,处理。
初始化主要是构建主要参数对象,比如一笔订单构建一个Order对象,或者咨询其他系统对某些参数赋值,针对某个需求,可以增加一个初始化处理类。校验主要是对初始化后的各个参数做业务校验,比如说用户的状态不能是已注销。针对某个需求,可以很方便的增加校验。处理,则是对其他系统的调用或者数据的落地。在这三个阶段,可以把每一个需求或者每一个校验都区分开,这样每个原子性的校验就可以被其他业务逻辑复用。从而实现程序的易扩展,高复用,易维护。
public abstract class AbstractPreBizProcessTemplate implements BizPreProcessTemplate {


    private List<PreBizProcessInitializer> initList      = new ArrayList<PreBizProcessInitializer>();

    private List<PreBizProcessValidator>   validatorList = new ArrayList<PreBizProcessValidator>();

    private List<PreBizProcessorHandler>   handlerList   = new ArrayList<PreBizProcessorHandler>();

    public Result process(PreBizContext preBizContext) {


        Result result = new Result(false);
        String methodName = "process";
        try {
            for (PreBizProcessInitializer initProcessor : initList) {

                initProcessor.init(preBizContext);

            }

            for (PreBizProcessValidator validator : validatorList) {

                validator.validate(preBizContext);
 
            }

        
            for (PreBizProcessorHandler handler : handlerList) {

                handler.handler(preBizContext);

            }
	    result.setSuccess(true);} 
	catch (PreBizProcessException e) {
            ErrorEnum errorEnum = ((PreBizProcessException) e).getErrorEnum();

            if (errorEnum == null) {
                errorEnum = ErrorEnum.BIZ_PROC_ERROR;
            }
          
            result.setErrorEnum(errorEnum);
        } catch (Exception e) {
        
            result.setErrorEnum(ErrorEnum.SYSTEM_ERROR);

        } finally {
      

        }
        return result;
    }

可以使用XML配置或者标注:
<bean id="testTemplate" class="com.TestTemplate">
    <property name="initList">
      <list merge="true">
        <ref local="testInitializer"/>
      </list>
    </property>

    <property name="validatorList">
      <list merge="true">
        <ref local="testValidator"/>
      </list>
    </property>

    <property name="handlerList">
      <list merge="true">
        <ref local="testHandler"/>
      </list>
    </property>
  </bean>

标注:
@Target( { ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface TemplateMethod {
    String[] value() default {};

    String[] inits() default {};

    String[] valis() default {};

    String[] handlers() default {};
}

public class TestTemplate extends AbstractProcessTemplate implements InitializingBean,
                                                         BeanFactoryAware {

    private DefaultListableBeanFactory factory;

    @TemplateMethod(inits = { "inits1", "inits2" }, valis = { "vali1", "vali2" })
    public void processBiz1() {
        Context txt = new Context();
        ChargeResult re = this.process(txt);
        //        System.out.println(re);
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean-->" + this.getClass().getName() + "::"
                           + this.getInits().size());
        TemplateUtil.initProcessTemlates(factory);
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.factory = (DefaultListableBeanFactory) beanFactory;
    }
}
public final class TemplateUtil {

    public static void initProcessTemlates(ListableBeanFactory factory) {
        System.out.println("initTemplate");
        processInit(factory);
    }

    @SuppressWarnings("unchecked")
    private static void processInit(ListableBeanFactory factory) {
        Map<Object, Object> allTemplateClasses = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            factory, AbstractProcessTemplate.class);
        Map<Object, Object> allInitClasses = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            factory, Initor.class);
        Map<Object, Object> allValiClasses = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            factory, Validator.class);
        Map<Object, Object> allHandlerClasses = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            factory, Handler.class);

        for (Object key : allTemplateClasses.keySet()) {
            Object value = allTemplateClasses.get(key);
            if (AnnotationUtils.findAnnotation(value.getClass(), TemplateClass.class) != null) {

                AbstractProcessTemplate templateClass = (AbstractProcessTemplate) value;

                if (!templateClass.getInits().isEmpty() || !templateClass.getValis().isEmpty()
                    || !templateClass.getHandlers().isEmpty()) {
                    return;
                }

                Method[] methods = templateClass.getClass().getDeclaredMethods();

                for (Method method : methods) {
                    TemplateMethod temMethod = AnnotationUtils.findAnnotation(method,
                        TemplateMethod.class);
                    if (temMethod != null) {
                        String[] values = temMethod.value();
                        String[] inits = temMethod.inits();
                        String[] valis = temMethod.valis();
                        String[] handlers = temMethod.handlers();
                        if (values != null && values.length > 0) {
                            findBizBeans(allInitClasses, templateClass, values);
                            findBizBeans(allValiClasses, templateClass, values);
                            findBizBeans(allHandlerClasses, templateClass, values);
                        }
                        if (inits != null && inits.length > 0) {
                            findBizBeans(allInitClasses, templateClass, inits);
                        }
                        if (valis != null && valis.length > 0) {
                            findBizBeans(allValiClasses, templateClass, valis);
                        }
                        if (handlers != null && handlers.length > 0) {
                            findBizBeans(allHandlerClasses, templateClass, handlers);
                        }

                    }
                }
                System.out.println("注册完成后:" + templateClass + ":" + templateClass.getInits().size()
                                   + ":" + templateClass.getValis().size() + ":"
                                   + templateClass.getHandlers().size());
            }
        }
    }

    private static void findBizBeans(Map<Object, Object> allClasses,
                                     AbstractProcessTemplate templateClass,
                                     String[] annotiedBeanNames) {
        for (String beanName : annotiedBeanNames) {
            Object bizBean = allClasses.get(beanName);
            if (bizBean instanceof Initor) {
                Initor realInitor = (Initor) bizBean;
                templateClass.getInits().add(realInitor);
            } else if (bizBean instanceof Validator) {
                Validator realVali = (Validator) bizBean;
                templateClass.getValis().add(realVali);
            } else if (bizBean instanceof Handler) {
                Handler realhander = (Handler) bizBean;
                templateClass.getHandlers().add(realhander);
            }
        }
    }
}



 
对新扩展的每一个业务,只需要新增一个模板类继承抽象模板类即可。几乎对每一个单独的初始化器,验证器和处理器都可以被很好的复用。
每一个业务都新增一个模板,每个模板实际上都没有做什么东西,是不是有点多余?如果我使用一个标志来区分不同的业务,那么在一个模板里面是不是就可以只用一个模板了?确实可以,但是那样框架会变得相当重量级,这个框架后面会讲到。
比较轻量级的解决方案可以是这样:新增一个工厂类,并使用spring配置简化bean的管理,将每个不用业务的模板注入到工厂类的map中,通过业务传入key值寻找到对应的处理模板。
<bean id="testFactory" class="TestProcessorFactory">
		<property name="processorTemplates">
			<map>
				<entry key="test">
					<ref local="testProcessTemplate"/>
				</entry>
			</map>
		</property>
</bean>
public class PayProcessorFactory {
    private Map<String, PayProcessor> processors = new HashMap<String, PayProcessor>();

    /**
     * 根据业务场景获取对应的处理器
     * @param bizType 业务场景
     * @return
     */
    public PayProcessor getProcessor(String bizType) {
        return processors.get(StringUtil.trim(bizType));
    }

    public void setProcessors(Map<String, PayProcessor> processors) {
        this.processors = processors;
    }

}


或者这么做
public class TestTemplate extends AbstractProcessTemplate implements InitializingBean,
                                                         BeanFactoryAware {

    private DefaultListableBeanFactory factory;

    @TemplateMethod(inits = { "inits1", "inits2" }, valis = { "vali1", "vali2" })
    public void processBiz1() {
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean-->" + this.getClass().getName() + "::"
                           + this.getInits().size());
        TemplateUtil.initProcessTemlates(factory);
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.factory = (DefaultListableBeanFactory) beanFactory;
    }

    public String getSupportedBizType() {
        return "test";
    }
}
public class TemplateFactory {
    private static Set<BizProcessTemplate> templates = new HashSet<BizProcessTemplate>();

    public static BizProcessTemplate getPerperTemplate(String bizType) {

        for (BizProcessTemplate template : templates) {
            if (StringUtils.equals(bizType, template.getSupportedBizType())) {
                return template;
            }
        }
        return null;
    }
}


如果你想使用多个模板,可以这么做:
 
public interface BizProcessTemplate2 {

    ChargeResult process(Context txt);

    boolean canProcess(List<Class<BizProcessTemplate2>> supportedTemplateClasses);
}
public class TemplateProcessor {
    private static Set<BizProcessTemplate2> templates = new HashSet<BizProcessTemplate2>();

    public static void getProperTemplates(List<Class<BizProcessTemplate2>> supportedTemplates) {
        for (BizProcessTemplate2 template : templates) {
            if (template.canProcess(supportedTemplates)) {
                template.process(new Context());
            }
        }
    }
}


这个框架同时也是另外一种轻量级框架,结合你的业务,可以考虑下。
 
如果你的业务足够简单,懒的使用这么繁琐的框架,那么可以尝试下这种处理方式,以一个web请求为例:
 
public class WebBizProcessHelper {

    private static Logger LOGGER = LoggerFactory.getLogger(WebBizProcessHelper.class);

    /**
     * 处理业务逻辑,注意:<font color=red>WebBizCallBack的泛型类需要与第一个参数所表示的类一致,且能够被实例化</font>
     * <br>比如:<br>
     * <code>
     * new WebBizProcessHelper().process(<font color=red>TbSignatoryParameterBean.class</font>,
            new WebBizCallBack<<font color=red>TbSignatoryParameterBean</font>>() {
                //...
            };
     * </code>
     * @param paramBeanRequestClass
     * @param webBizCallBack
     * @return
     */
    @SuppressWarnings("unchecked")
    public String process(Class<?> paramBeanRequestClass, WebBizCallBack webBizCallBack) {
        Object request = null;
        try {
            request = BeanUtils.instantiateClass(paramBeanRequestClass);
            processInitialize(webBizCallBack, request);
            processValidate(webBizCallBack, request);
            return processHande(webBizCallBack, request);
        } catch (WebBizException e) {
            try {
                return webBizCallBack.processWebBizException(request, e);
            } catch (Exception e1) {
                LOGGER.error("WebBizProcessHelper#processWebBizException出现异常!phase:" + e.getPhase()
                             + ",request:" + request + ",errorMsg:" + e1.getMessage());
            }
        } catch (Exception e) {
            LOGGER.error("WebBizProcessHelper#process出现异常!" + ",request:" + request + ",errorMsg:"
                         + e.getMessage());
        }
        return VelocityTemplateNameConstants.ERROR_VM;
    }

    /**
     * 
     * @param webBizCallBack
     * @param request
     * @throws WebBizException
     */
    @SuppressWarnings("unchecked")
    private String processHande(WebBizCallBack webBizCallBack, Object request)
                                                                              throws WebBizException {
        try {
            return webBizCallBack.handle(request);
        } catch (Exception e) {
            convetAllException2WebBizExceptoin(WebBizPhaseEnum.HANDLE_PHASE, e);
        }
        return VelocityTemplateNameConstants.ERROR_VM;
    }

    /**
     * 
     * @param webBizCallBack
     * @param request
     * @throws WebBizException
     */
    @SuppressWarnings("unchecked")
    private void processValidate(WebBizCallBack webBizCallBack, Object request)
                                                                               throws WebBizException {
        try {
            webBizCallBack.validate(request);
        } catch (Exception e) {
            convetAllException2WebBizExceptoin(WebBizPhaseEnum.VALIDATE_PHASE, e);
        }
    }

    /**
     * 
     * @param webBizCallBack
     * @param request
     * @throws WebBizException
     */
    @SuppressWarnings("unchecked")
    private void processInitialize(WebBizCallBack webBizCallBack, Object request)
                                                                                 throws WebBizException {
        try {
            webBizCallBack.initialize(request);
        } catch (Exception e) {
            convetAllException2WebBizExceptoin(WebBizPhaseEnum.INITIALIZE_PHASE, e);
        }
    }

    /**
     * 转换后默认是系统异常
     * @param e
     * @throws WebBizException
     * @throws Exception
     */
    private void convetAllException2WebBizExceptoin(WebBizPhaseEnum phase, Exception e)
                                                                                       throws WebBizException {
        if (e instanceof WebBizException) {
            throw (WebBizException) e;
        }
        throw new WebBizException(phase, e, ErrorEnum.SYSTEM_ERROR.getErrorMessage());
    }

    /**
     * 业务处理回调接口
     * @author jiatao
     * @version $Id: WebBizProcessHelper.java, v 0.1 2012-12-12 上午09:03:00 wb-jiatao Exp $
     */
    public interface WebBizCallBack<K> {

        /**
         * 业务逻辑初始化
         * @param paramBean
         * @throws WebBizException
         */
        void initialize(K paramBean) throws WebBizException;

        /**
         * 业务逻辑验证
         * @param paramBean
         * @throws WebBizException
         */
        void validate(K paramBean) throws WebBizException;

        /**
         * 业务逻辑处理
         * @param paramBean
         * @return
         * @throws WebBizException
         */
        String handle(K paramBean) throws WebBizException;

        /**
         * 处理各阶段抛出的异常
         * @param paramBean
         * @param WebBizException
         * @return
         */
        String processWebBizException(K paramBean, WebBizException WebBizException);
    }

    /**
     * 业务处理阶段
     * @author jiatao
     * @version $Id: WebBizProcessHelper.java, v 0.1 2012-12-12 上午09:02:45 wb-jiatao Exp $
     */
    public enum WebBizPhaseEnum {
        INITIALIZE_PHASE, VALIDATE_PHASE, HANDLE_PHASE, PROCESS_EXCEPTION_PHASE;
    }

    /**
     * 显示错误页面
     * @param modelMap
     * @param webBizexception
     * @return
     */
    public static String showErrorVM(final ModelMap modelMap, WebBizException webBizexception) {
        return showErrorVM(modelMap, webBizexception.getMessage());
    }

    /**
     * 显示错误页面
     * @param modelMap
     * @param webBizexception
     * @return
     */
    public static String showErrorVM(final ModelMap modelMap, String errorMsg) {
        modelMap.addAttribute(ModelMapKeyConstants.ERROR_MESSAGE, errorMsg);
        return VelocityTemplateNameConstants.ERROR_VM;
    }

}


在你的Controller里面,可以这么做:
@RequestMapping(method = RequestMethod.GET)
    public String testBizProcess(final ModelMap modelMap, final HttpServletRequest request) {
       
        LogManageUtil.processLog(test, "enter", request.getParameter("s"),
            "", "");
        LogManageUtil.monitorLog(request.getParameter("s"), "test", "arrive",
            "Y", request.getParameter("t"), "", "t", "t");

        return new WebBizProcessHelper().process(ParameterBean.class,
            new WebBizCallBack<ParameterBean>() {

                public void initialize(ParameterBean paramBean) throws WebBizException {
                    initParameterBean(paramBean, request);
                   
                    if (LOGGER.isInfoEnabled()) {
                        LOGGER.info("t:" + t);
                    }
                }

                public void validate(ParameterBean paramBean) throws WebBizException {
                    ValiResult valiResult = validateManagr.validate(paramBean);
                    if (LOGGER.isInfoEnabled()) {
                        LOGGER.info("能否签约结果:" + signatoryPayResult
                                    + paramBean.getSign_alipay_user_id());
                    }
                    if (!valiResult.isSuccess()) {
                        throw new WebBizException(WebBizPhaseEnum.VALIDATE_PHASE,
                            "errorMsg");
                    }
                }

                public String handle(TbSignatoryParameterBean paramBean) throws WebBizException {
                    LogManageUtil.processLog(t, "success", paramBean
                        .getT(), "", "");

                    LogManageUtil.monitorLog(request.getParameter("t"), "t",
                        "finished", "Y", request.getParameter("t"), "", "t",
                        "t");

                    return VelocityTemplateNameConstants.T_VM;
                }

                public String processWebBizException(tParameterBean paramBean,
                                                     WebBizException WebBizException) {
                    if (LOGGER.isInfoEnabled()) {
                        LOGGER.info("处理失败:" + WebBizException.getPhase()
                                    + WebBizException.getMessage()
                                    + paramBean.getT());
                    }
                    LogManageUtil.failLog(T, "failture:webBizException", paramBean
                        .T(), "", WebBizException.getPhase()
                                                       + WebBizException.getMessage());
                    return WebBizProcessHelper.showErrorVM(modelMap, WebBizException);
                }

            });

    }


【基本介绍】 现在网上的恶意软件越来越多,前些日子网络行业协会点名了十大流氓软件,这些软件的特点大多是强制安装,而且不容易卸载。恶意软件清理助手即是针对这种情况编写的,恶意软件清理助手可以完全清除数百种恶意软件,清理时最好在Windows的安全模式下进行! 【软件特点】 软件目前可以卸载下列软件: 1、一搜工具条 2、完美网译通 3、CNIC中文上网 4、博采网摘 5、百度搜霸 6、3721上网助手 7、Dudu下载加速器 8、很棒小秘书 9、网络猪 10、划词搜索 11、eBay工具条 12、娱乐心空 13、Yahoo助手(原3721) 14、搜狗 15、彩信通 16、天下搜索 17、U88财富快车 18、唯刊 19、完美网译通 20、协和医院弹出广告 21、Yahoo助手 22、一搜工具条 23、娱乐心空 24、YOK工具条 25、桌面传媒(Desktop Media) 26、酷站导航 27、QQ尾巴病毒 28、hws木马(病毒) 29、Irjit木马 30、jiaozhu木马(病毒) 31、MSIBM 32、千橡(mop)播霸 33、ZCom娱乐 34、syscast弹出广告插件 35、开心运程速递 36、SCIntruder 37、地址栏直通车 38、IpSec(Msdc32)木马 39、青娱乐 40、百搜工具条 41、百狗搜索 42、spoolsv木马病毒 43、HotBar工具条 44、VVZ收藏夹 45、NB46工具栏 46、忆多多 47、NetCount 48、IE-Bar 49、酷桌面 50、DeskAdTop弹出广告 51、DoDoor RRS订阅助手 52、Adplus/Msplus病毒 53、MicroShdocvw/Shdocvw2 54、BHORun 55、快搜 56、哇哇资讯 57、网蜜/MySec 58、通用搜索/ROOGOO(病毒) 59、KooWo/YHBO 60、如意搜 61、tanip 62、MyIEHelper 63、88dog 64、鸡毛信 65、WinLogin/BenBen 66、159定向搜索 67、KService木马 68、51上网导航 69、TT33定向搜索 70、迷你屁屁狗 71、短信狂人 72、易搜工具条 73、MyWebSearch 74、CQQAdrplus 75、MicroQC 76、Winpub/Systems 77、Ceston/伪Windows XP Vista 78、ODBINT/伪Yahoo Bar 79、thememms/exupmms 80、UPDATE2 81、QQHelper 82、伪Taskmgr 83、DMPlay 84、asp121 85、SUpdate2 86、搜狗PXP加速引擎 87、极速搜索 88、LoadService 89、5940工具条 90、PopWin 91、msdll 92、explorar/internet 93、cctmv病毒 94、Racole 95、CPush/NewAdPopup 96、CpapView 97、InteSearch 98、AdHelper/酷标 99、Nvwrseng/WinLogon 100、Rundll/7939 101、AspwsWin 102、HttpReq/BizG 103、NFSWZWin32 104、老大搜索 105、hohoplug 106、mssnmp16 107、虎翼DIY吧 108、左看 109、伪Services.exe 110、lhtefx 111、svhost32 112、Sy病毒 113、伪GoogleBar 114、cfg.IEHelper 115、WindowService 116、Amvda 117、Flash_Player 118、Jvmlts 119、万能搜索 120、PCTools 122、ddlook 123、WinStar 124、ToolBar888 125、LinkMedia 126、RealUpdate 127、Winla 128、伪lsass.exe 129、伪系统服务 130、POPNT/Winampi 131、IeLunch弹出广告 132、Stdupnet 133、JetSpeed 134、91cast 135、TAdKiller 136、WinFilter 137、ADSL 138、4199 139、伪WinLogon 140、伪Office 141、kvtkaj 142、mallgoo2 143、firendnet 144、cnne 145、WebWork 146、Telecharger 147、cnwin 148、xeklsk 149、ravshell 150、E5B14242 151、伪csrss 152、Lzx
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值