`

我是如何写Service的【转】

    博客分类:
  • java
阅读更多

原文:  http://www.iteye.com/topic/606348

 

马上要告别研发了,所以写一些自己积累的经验,用来纪念4年的似水流年,本篇为第一张,用来介绍自己是如何写Service的,当然我总结的不一定合理,大家一起讨论下。

 

笔者认为,Service及服务层,服务可以分为功能服务和业务服务,功能服务不易改变,业务服务易改变。所以功能服务添加得多,修改的少,那么我们可以考虑不使用接口。而业务服务,修改和更新都很频繁,所以应该提取接口,用不同的实现来屏蔽业务逻辑。

 

1:使用断言控制输入。

使用断言来判断有效的输入,这样能够避免异常的扩散,迅速定位错误和减少BUG出现的几率。

如:

Java代码 复制代码
  1. import org.springframework.util.Assert;  
import org.springframework.util.Assert;
Java代码 复制代码
  1. private boolean addAttachment(Attachment att) {   
  2.   Assert.notNull(att, "att对象不能为空");   
  3. }  
private boolean addAttachment(Attachment att) {
  Assert.notNull(att, "att对象不能为空");
}

要学会灵活运用断言,不仅仅是用来断言来判断方法的输入参数是否正确,还可以判断业务逻辑,每次方法调用的输入输出,至于何时使用需要自己根据方法自我判断。

 

2:只抛出RumtimeException

作为service层,自己不清楚调用方到底是谁,也不知道调用方如何使用自己的接口,那么自己写出的接口最好是抛出RumtimeException,这样调用方能够处理这个异常或者觉得处理这个异常有必要的话,就进行处理。如果使用Exception就得强制那些处理不了的调用方继续向外抛出。抛出RumtimeException的时候需要在注释里申明我抛出了该异常。

Java代码 复制代码
  1. throw new RuntimeException("工作流初始化失败!");  
throw new RuntimeException("工作流初始化失败!");

 

3:在Service层做事务处理

大家都知道Service层一般是用来组合DAO,所以经常出现需要事务处理的地方,笔者建议尽量在service层做事务处理。

因为一般业务逻辑都屏蔽在service层。笔者习惯使用Spring的手动事务。

Java代码 复制代码
  1. new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {      
  2.             protected void doInTransactionWithoutResult(TransactionStatus status) {      
  3.                 //调用DAO按照ID删除部门      
  4.             }      
  5. });     
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {   
            protected void doInTransactionWithoutResult(TransactionStatus status) {   
                //调用DAO按照ID删除部门   
            }   
});   

 

 

4:Service接口的异常处理

对于程序异常,service能够处理的自己处理(将异常封装成自己的异常,再向外抛出也算一种处理),不能处理的继续向外抛出。

对于业务异常,以前开发的时候都会向外抛出一个用户友好的运行时异常,这种异常信息是能够直接展现给用户的,如“您添加的用户名已经存在!”,但是现在考虑到国际化,所以觉得Service的接口应该抛出错误代码,定义一个友好错误代码运行时异常,在程序出现条件错误的时候抛出错误代码。错误代码可以定义一个枚举类来实现。

Java代码 复制代码
  1. /**  
  2.  * 错误代码定义  
  3.  *  
  4.  * @author fangtengfei  
  5.  * @date   2010-3-3  
  6.  */  
  7. public enum ErrorCode {   
  8.     /**  
  9.      * 用户不能重复  
  10.      */  
  11.     User_Not_Repeat,   
  12.     /**  
  13.      * 用户名太长  
  14.      */  
  15.     User_Name_Too_Long   
  16. }  
/**
 * 错误代码定义
 *
 * @author fangtengfei
 * @date   2010-3-3
 */
public enum ErrorCode {
	/**
	 * 用户不能重复
	 */
	User_Not_Repeat,
	/**
	 * 用户名太长
	 */
	User_Name_Too_Long
}
Java代码 复制代码
  1. 在Service里抛出:throw new FriendlyCodeRuntimeException(ErrorCode.User_Not_Repeat.toString());  
在Service里抛出:throw new FriendlyCodeRuntimeException(ErrorCode.User_Not_Repeat.toString());

  

 

5:必须记录日志

  大家都知道,记录日志的目的,主要是当程序运行在不同的环境下,使用日志来监控程序的运行,有些异常可能会特定的环境发生,而这种环境不容易被重现,所以此时唯一能定位问题的途径就只有日志。

Service层会被各种调用方使用,特别是对外提供Service,环境更会前差万别,如何迅速并有效的定位错误变得尤其重要,所以必须记录有效的日志。

Java代码 复制代码
  1. logger.error("更新文档出现出错", e);  
logger.error("更新文档出现出错", e);

 

 6:写有效的注释

之所以说写有效的注释,是因为有时候,有些方法真的不需要写注释,如addUser,就不要在写注释“添加用户”这样的注释。关键是写有效的注释,注释的作用在于,调用方只看注释而不看代码就能知道如何使用接口,注释应该包括:输入参数的注释,输出参数的注释和异常的注释。特别是List<Map>,Sting[]这样的参数要严格说明,笔者认为Service作为一个核心层,注释必须非常详细。另外直观的方法名也能起到注释的作用。

Java代码 复制代码
  1. /**  
  2. * 批量添加文档的附件   
  3.  
  4. * @param att 附件对象,附件名长度为20,附件大小为10M  
  5. * @throws FriendlyCodeRuntimeException  
  6.  */  
  7. private void addAttachment(Attachment... attachment)  
/**
* 批量添加文档的附件 
* 
* @param att 附件对象,附件名长度为20,附件大小为10M
* @throws FriendlyCodeRuntimeException
 */
private void addAttachment(Attachment... attachment)

 

 

 

 

 

分享到:
评论

相关推荐

    service的启动方式

    在Android系统中,Service是四大组件之一,它主要用于在后台执行长时间运行的操作,不提供用户界面。Service的启动方式主要有两种:进程内通信(Local Service)和服务绑定(Bound Service),这两种方式都涉及到...

    C#创建windows服务/写wvebServer 接口

    private ServiceInstaller service; public ProjectInstaller() { process = new ServiceProcessInstaller(); service = new ServiceInstaller(); process.Account = ServiceAccount.LocalSystem; service....

    android demo,service的源代码的实现。

    使用`startService()`方法可以启动一个Service,此操作会在Service的`onStartCommand()`方法中回调,每调用一次`startService()`,就会向Service发送一个新的Intent,Service会根据Intent的意图进行处理。...

    ASP.NET AJAX深入浅出系列课程(14):Profile Service的实现方式与扩展

    ASP.NET AJAX Profile Service是.NET Framework 2.0及以上版本中的一项功能,用于在Web应用程序中存储和检索用户的个性化设置。这个服务允许开发者为每个用户提供一个持久化的数据存储空间,而无需进行复杂的数据库...

    Service Mesh在有赞的实践与发展25页.pdf

    不过也提到了默认使用hessian序列化,不需要写IDL,这对Java生态而言是一种更加友好的跨语言通信方式。 在服务发现和服务注册之后,服务之间需要建立长连接以进行数据包的透传,这时负载均衡和服务路由就显得尤为...

    springMVC基本配置(Controller+Service+Dao)

    Spring容器会在启动时扫描所有带有`@Component`(包括`@Controller`、`@Service`、`@Repository`)注解的类,并将它们纳入管理范围。 5. **配置文件**: 配置SpringMVC通常涉及以下文件: - `web.xml`:定义...

    Oracle Service Bus 11g Development Cookbook

    书中对各种公司和产品的商标信息使用了恰当的大小写,但出版社声明无法保证这些信息的准确性,这主要是因为商标信息可能会随着时间发生变化。 书中介绍了几位作者的背景信息。Guido Schmutz是Oracle Fusion ...

    ReadService.7z

    本项目“ReadService.7z”专注于利用Java来读取Excel文件,然后向其中写入数据,并最终生成一个新的Excel文件。在这个过程中,我们可能会涉及到几个关键的技术点和API,包括但不限于Apache POI库、JSON数据格式以及...

    app更新,实现service下载.zip

    在Android开发中,"app更新,实现service下载"是一个常见的需求,它涉及到用户应用程序的自动或手动更新过程,以及在后台使用Service组件进行文件下载的技术。Service是Android四大组件之一,用于执行长时间运行的...

    SOA 下的基于Axis2和Tuscany的web service

    服务的业务逻辑可以写在这个实现类中。 接下来,Tuscany ESB可以在服务之间起到中介作用,处理服务间的通信,包括消息转换、路由、事务管理和安全控制等。通过Tuscany,开发者可以定义服务之间的交互流程,实现服务...

    Web Service jar包

    本文将深入探讨Web Service jar包,包括其重要性、工作原理以及如何在项目中使用它们。 首先,Web Service jar包是Java开发Web服务的核心组件,包含了一系列的类库和API,使得开发者能够创建、部署和消费Web服务。...

    Java利用Freemarker模板自动生成dto、dao、rowmapper、bo、service代码

    Service层是业务逻辑的核心,它封装了BO和DAO的调用,对外提供服务接口。生成服务层代码时,会包含一系列业务服务方法,这些方法可能会调用DAO来完成数据持久化,同时结合BO进行业务逻辑处理。 在实际项目中,...

    XML WEB Service开发

    XML文档还必须遵循一定的命名规则,例如元素和属性名称是大小写敏感的,并且必须以字母或下划线开头。 **02 XML基础.ppt** 这部分内容可能涵盖了XML的基本语法,包括元素、属性、注释、实体引用、命名空间等。可能...

    sap Web Service开发配置文档.doc

    调用Web Service的代码通常写在ABAP类或报告中,使用服务代理对象的方法进行实际调用。开发者需要设置必要的参数,然后执行服务代理的方法,获取返回结果。 ### 第三章 数据交换格式 数据交换格式是Web Service...

    背景音乐service的实现_20152100025唐福梅1

    本案例中,开发者唐福梅在"我的日记本"App的基础上,利用Service来播放背景音乐,并尝试解决播放过程中遇到的问题。 【知识点详解】 1. **Service基础**: - Service是Android四大组件之一,用于在后台执行长时间...

    Service-GIS与面向服务的地理信息共享.docx

    Service-GIS(Service-Oriented Geographical Information System)与面向服务的地理信息共享是一种现代GIS技术的发展趋势,它旨在解决传统地理信息共享存在的问题,如数据损失、可视化一致性、效率低下、更新延迟和...

    摩托罗拉车台手台GM300/M120 /SM50/SM120 写频教程

    设置车台的功率需要在主菜单下按F2键,进入SERVICE MENU菜单,再按F2键,进入ALJGNMENT MENU,最后按F7键进入功率调整功能菜单。 五、外部接口针脚软件设置 外部接口针脚软件设置需要在主菜单下按F4键,再按F2键,...

    易语言驱动级读写内存源码,易语言驱动级读写内存模块

    易语言驱动级读写内存模块源码,驱动级读写内存模块,加载驱动_,卸载驱动_,与驱动程序通信_,键码转换,CreateServiceA,OpenServiceA,StartServiceA,CloseServiceHandle,CreateFileA,ControlService,OpenSCManagerA,...

    WCF和webservice例子

    本文将深入探讨两种常见的Web服务实现方式:Windows Communication Foundation (WCF) 和 Web Service(通常指的是ASMX或SOAP Web服务)。我们将通过一个名为"WCFDemo"的压缩包文件中的例子来阐述它们的核心概念、...

    Axis2的OMElement SOAP XML报文节点首字母小写转大写(注意,是节点,不是节点元素的值) java

    要实现节点首字母小写转大写的转换,我们需要遍历整个SOAP XML报文的OMElement树,并对每个节点进行处理。 以下是一个可能的Java代码实现步骤: 1. 创建一个递归方法,接收OMElement作为参数。 2. 在方法内部,...

Global site tag (gtag.js) - Google Analytics