编写程序的时候,随着需求和业务的增加,代码的维护会越来越困难,如何做到可扩展,易维护呢?一个比较好的方案就是提高代码的复用率,抽取易变的部分统一维护,以降耦。
代码框架一般可以分为两类,一类是业务逻辑的抽象,主要用于提高业务逻辑代码的复用率,比如不同业务对某个规则的验证。另外一类是处理流程的抽象,主要用于降耦,即对修改关闭,对扩展开放。新增的业务不影响原来的业务。当然,更多的是将两者的合理糅合。
先从第一类开始。
无论是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); } }); }
相关推荐
2. **性能卓越**:由于其轻量级的特性,CI在处理请求时的性能表现优秀,启动速度快,内存占用低。 3. **低学习曲线**:对于初学者,CI的结构清晰,代码规范,是学习PHP框架的理想选择。 4. **安全防护**:内置了防止...
它以其轻量级、模块化的设计理念,极大地简化了Java应用程序的构建,尤其在Web应用开发领域中,Spring扮演着至关重要的角色。 Spring框架的核心特性包括依赖注入(Dependency Injection,DI)和面向切面编程...
PHP MVC(Model-View-Controller)框架是一种设计模式,常用于构建动态的、结构清晰的Web应用程序。在PHP世界中,MVC模式被广泛应用...轻量级框架则在这些优点的基础上,以更小的体积和更快的速度满足小型项目的需求。
**WPF轻量级MVVM框架入门2.1.2** 在Windows Presentation Foundation(WPF)开发中,MVVM(Model-View-ViewModel)模式是一种常见的设计模式,它有助于实现应用程序的视图与业务逻辑之间的解耦。MVVM通过数据绑定、...
Java EE互联网轻量级框架整合开发,主要集中在SSM框架的使用上,即Spring MVC、Spring和MyBatis的集成,以及Redis缓存技术的引入。这个主题旨在提高Web应用的开发效率,优化性能,同时降低项目的复杂度。 首先,...
"基于轻量级Java EE框架的异常处理研究" 本文研究了基于轻量级Java EE框架的异常处理机制,通过对Struts2、Spring和Hibernate三个框架的分析,探讨了在不同的层次(数据层、业务层、表现层)中的异常处理方式,并...
关键字驱动测试是另一种常见的轻量级框架设计,它强调将业务逻辑和测试逻辑分离。在QTP中,可以通过创建自定义函数库,将复杂的操作抽象为简单的关键字,然后在测试脚本中调用这些关键字,提高代码的可读性和可维护...
在Java EE领域,轻量级框架的使用已经成为现代企业级应用程序开发的标准。这些框架通过简化开发过程、提高可维护性和可扩展性,极大地提升了开发效率。"javaEE轻量级框架应用与开发"这本书,结合清华大学出版社的...
“一款轻量级的FLEX MVC开发框架”指的是该资源提供了一个针对Adobe Flex应用的轻量级模型-视图-控制器(MVC)架构的开发框架。Flex是基于ActionScript 3的开放源代码SDK,用于构建富互联网应用程序(RIA)。MVC模式...
《Android轻量级数据库框架解析》 在移动应用开发领域,Android系统以其开源、免费的特性,成为了全球最受欢迎的操作系统之一。在Android应用中,数据存储是不可或缺的一部分,而SQLite作为Android内置的关系型...
《Java EE轻量级框架应用与开发 S2SH》是一本深入探讨Java企业级应用程序开发的书籍,由QST青软实训编著,并由清华大学出版社出版。本书主要聚焦于S2SH框架,即Struts2、Spring和Hibernate的集成,这三大框架在Java ...
### JavaEE轻量级框架应用与开发——S2SH知识点详解 #### 一、书籍概述 《JavaEE轻量级框架应用与开发——S2SH》由QST青软实训编著,清华大学出版社出版,是一本针对JavaEE轻量级框架进行深入探讨的专业教材。本书...
总的来说,IDP平台中的轻量级业务框架研究与设计是针对传统重量级框架在实际应用中遇到的问题,提出的一种解决方案。通过引入脚本驱动的业务逻辑处理方式,不仅可以提高系统的性能,还能简化开发流程,降低维护成本...
【JavaEE轻量级框架6个实验报告】是针对Java企业级应用开发中轻量级框架的学习和实践,由史胜辉、王春明、卢培军三位作者编著,适用于期末作业或项目实践。本报告包含六个核心实验,旨在通过实际操作来深入理解和...
EasyValidation 3.0 是一个轻量级的验证框架,主要设计用于简化应用程序中的数据验证过程。这个框架的出现旨在帮助开发者快速、高效地检查输入数据的有效性,从而提高代码的可读性和维护性。在本文中,我们将深入...
【H+_blewpfn_php轻量级架构】是一种基于PHP的轻量级框架,它旨在为小型项目,如个人博客,提供快速、简洁的开发环境。这个框架的设计理念是简化开发流程,降低学习曲线,让开发者能更专注于业务逻辑,而非底层实现...
《互联网轻量级SSM框架解密:Spring、MVC、Mybatis源码深度剖析》 在当前的Java开发领域,Spring、Spring MVC和Mybatis是广泛应用的轻量级框架,构成了SSM(Spring、SpringMVC、Mybatis)集成框架,为开发者提供了...
因此,通过注解实现的轻量级安全认证框架应运而生,它简化了权限管理的流程,使得开发者能够更专注于业务逻辑。 首先,我们需要了解Spring MVC的`@RequestMapping`注解。这个注解用于映射HTTP请求到处理方法,它...
《深入Spring2:轻量级J2EE开发框架原理与实践》是一本专注于Spring2版本的权威指南,它详尽地介绍了Spring框架的核心特性和实际应用。Spring作为Java开发领域中的一个基石,以其轻量级、模块化和依赖注入特性,极大...