- 浏览: 515549 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
ben_wu007:
没数据库设计 而且这样要写代码 还是做成配数据库好 ...
使用AOP做权限控制 -
邢邢色色:
支持楼主,但这本书没有讲trident,有些过时了~到amaz ...
《Storm入门》中文版 -
java_web_hack1:
我在FunctionProvider中,获取的Property ...
在Osworkflow中使用PropertySet存储业务数据 -
greemranqq:
腾飞 ~。~
Java并发和多线程译者征集 -
fantasy:
leonevo 写道hi, 我也在设计cmdb. 我觉得基于传 ...
ITSM-CMDB数据库设计-四种方案任你选
马上要告别研发了,所以写一些自己积累的经验,用来纪念4年的似水流年,本篇为第一张,用来介绍自己是如何写Service的,当然我总结的不一定合理,大家一起讨论下。
笔者认为,Service及服务层,服务可以分为功能服务和业务服务,功能服务不易改变,业务服务易改变。所以功能服务添加得多,修改的少,那么我们可以考虑不使用接口。而业务服务,修改和更新都很频繁,所以应该提取接口,用不同的实现来屏蔽业务逻辑。
1:使用断言控制输入。
使用断言来判断有效的输入,这样能够避免异常的扩散,迅速定位错误和减少BUG出现的几率。
如:
import org.springframework.util.Assert;
private boolean addAttachment(Attachment att) { Assert.notNull(att, "att对象不能为空"); }
要学会灵活运用断言,不仅仅是用来断言来判断方法的输入参数是否正确,还可以判断业务逻辑,每次方法调用的输入输出,至于何时使用需要自己根据方法自我判断。
2:只抛出RumtimeException
作为service层,自己不清楚调用方到底是谁,也不知道调用方如何使用自己的接口,那么自己写出的接口最好是抛出RumtimeException,这样调用方能够处理这个异常或者觉得处理这个异常有必要的话,就进行处理。如果使用Exception就得强制那些处理不了的调用方继续向外抛出。抛出RumtimeException的时候需要在注释里申明我抛出了该异常。
throw new RuntimeException("工作流初始化失败!");
3:在Service层做事务处理
大家都知道Service层一般是用来组合DAO,所以经常出现需要事务处理的地方,笔者建议尽量在service层做事务处理。
因为一般业务逻辑都屏蔽在service层。笔者习惯使用Spring的手动事务。
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus status) { //调用DAO按照ID删除部门 } });
4:Service接口的异常处理
对于程序异常,service能够处理的自己处理(将异常封装成自己的异常,再向外抛出也算一种处理),不能处理的继续向外抛出。
对于业务异常,以前开发的时候都会向外抛出一个用户友好的运行时异常,这种异常信息是能够直接展现给用户的,如“您添加的用户名已经存在!”,但是现在考虑到国际化,所以觉得Service的接口应该抛出错误代码,定义一个友好错误代码运行时异常,在程序出现条件错误的时候抛出错误代码。错误代码可以定义一个枚举类来实现。
/** * 错误代码定义 * * @author fangtengfei * @date 2010-3-3 */ public enum ErrorCode { /** * 用户不能重复 */ User_Not_Repeat, /** * 用户名太长 */ User_Name_Too_Long }
在Service里抛出:throw new FriendlyCodeRuntimeException(ErrorCode.User_Not_Repeat.toString());
5:必须记录日志
大家都知道,记录日志的目的,主要是当程序运行在不同的环境下,使用日志来监控程序的运行,有些异常可能会特定的环境发生,而这种环境不容易被重现,所以此时唯一能定位问题的途径就只有日志。
Service层会被各种调用方使用,特别是对外提供Service,环境更会前差万别,如何迅速并有效的定位错误变得尤其重要,所以必须记录有效的日志。
logger.error("更新文档出现出错", e);
6:写有效的注释
之所以说写有效的注释,是因为有时候,有些方法真的不需要写注释,如addUser,就不要在写注释“添加用户”这样的注释。关键是写有效的注释,注释的作用在于,调用方只看注释而不看代码就能知道如何使用接口,注释应该包括:输入参数的注释,输出参数的注释和异常的注释。特别是List<Map>,Sting[]这样的参数要严格说明,笔者认为Service作为一个核心层,注释必须非常详细。另外直观的方法名也能起到注释的作用。
/** * 批量添加文档的附件 * * @param att 附件对象,附件名长度为20,附件大小为10M * @throws FriendlyCodeRuntimeException */ private void addAttachment(Attachment... attachment)
评论
貌似这个问题曾经也是一个争得你死我活的问题,有人认为抛异常的方式浪费系统资源,影响性能,有人认为异常是符合对象编程的行为方式,而不应该再回到过去那种返回状态码的原始c编程形式。两种方式当然各有利弊,LZ你能凭你4年的经验告诉我一个准备有效的方案吗
假如不用性能工具,我们一般会用80%的时间来调整20%的性能,意思说有些性能问题是写代码的时候可以暂时忽略。
另外我认为应该使用状态码,举一个例子,工单系统需要对外提供“派发工单”的接口,这种接口一般是提供给外部系统使用的,如何处理,应该由调用方自己决定,本系统只要在接口文档里详细描述每一个状态码所代表的意义即可。
另外也衍生一个话题,即数据和展现的分层,我们写代码的时候应该将数据和展现分离,如Action只提供数据(如JSON数据),至于客户端(C,HTML,JAVA,.net)如何展现他们自己决定。
貌似这个问题曾经也是一个争得你死我活的问题,有人认为抛异常的方式浪费系统资源,影响性能,有人认为异常是符合对象编程的行为方式,而不应该再回到过去那种返回状态码的原始c编程形式。两种方式当然各有利弊,LZ你能凭你4年的经验告诉我一个准备有效的方案吗
我们现在是层内部函数调用都是采用返回一个非0的code.
但是层与层之间采用抛出业务异常exception,然后带不同的code.上层在捕获异常后先检查"特别"code(具体哪些code需要特别处理,可配置),否则就按统一的异常处理.
但是这样也有个很严重的问题,就是有时候仅仅一个code不足与提供整个错误的环境,所以在exception中不但要带一个code,还有一个Object的参数.当有需要的时候,由下层提供必要环境对象,上层再根据约定将该对象转型后使用.这种情况虽然很少,但是很恶心.
求达人讲讲这方面比较好的实践.
貌似这个问题曾经也是一个争得你死我活的问题,有人认为抛异常的方式浪费系统资源,影响性能,有人认为异常是符合对象编程的行为方式,而不应该再回到过去那种返回状态码的原始c编程形式。两种方式当然各有利弊,LZ你能凭你4年的经验告诉我一个准备有效的方案吗
非要搞一个标识放在异常里面,然后拿着这个标识去找一条国际化信息。
这个依赖是反的,个人觉得应该是国际化要考虑异常,如果发生这种异常了应该展示什么信息。而不是设计异常的时候就已经考虑了国际化。
你很有见地。
但是能否仔细阅读下我的文章,并认真思考下呢?
fantasy已经在代码里这么实现了,只不过加强版的errorCode
在Service里抛出:throw new FriendlyCodeRuntimeException(ErrorCode.User_Not_Repeat);
其实我们回想在用一些大型软件时,系统错误提示中总有看到类似“错误代码:XXX”
非要搞一个标识放在异常里面,然后拿着这个标识去找一条国际化信息。
这个依赖是反的,个人觉得应该是国际化要考虑异常,如果发生这种异常了应该展示什么信息。而不是设计异常的时候就已经考虑了国际化。
你很有见地。
但是能否仔细阅读下我的文章,并认真思考下呢?
因为工作原因,转到产品部了。
产品部就不用管研发了吗?
前期的需求,架构什么的是由产品部来做吧?这个应该也算研发。
我指的是以后写代码会非常少,最多可能是做些DEMO。
当然需求和架构是由产品部来做。
因为工作原因,转到产品部了。
产品部就不用管研发了吗?
前期的需求,架构什么的是由产品部来做吧?这个应该也算研发。
非要搞一个标识放在异常里面,然后拿着这个标识去找一条国际化信息。
这个依赖是反的,个人觉得应该是国际化要考虑异常,如果发生这种异常了应该展示什么信息。而不是设计异常的时候就已经考虑了国际化。
逻辑一多....
几乎想死.
把逻辑封在 几个函数里
发表评论
-
Google Guava官方教程(中文版)
2014-10-24 23:48 2966原文链接 译文链接 ... -
《Storm入门》中文版
2014-05-28 12:38 2351本文翻译自《Getting Star ... -
《Java 7 并发编程指南》中文版
2013-11-03 17:00 8980原文链接 作者: Javier Fernández Gonz ... -
Java NIO系列教程
2013-06-25 17:03 4186原文地址:http://tutorials.jenkov.c ... -
[并发译文]Java内存模型手册
2013-01-20 21:13 2155原文地址:http://gee.cs.oswego.edu/ ... -
[并发编程]聊聊并发
2012-12-23 03:44 2288聊聊并发系列文章是我在InfoQ发表的并发编程连载文 ... -
构建JSONP字符串
2012-09-21 10:28 23821.咱们需要一个这样的JSONP字符串 var cal ... -
聊聊并发(二)Java SE1.6中的Synchronized
2012-05-24 13:51 2114本文属于作者原创,原文发表于InfoQ中文站。 ... -
聊聊并发(一)深入分析Volatile的实现原理
2012-02-22 09:39 2860本文属于作者原创,原文发表于InfoQ中文站。 ... -
JVM运行时数据区(2011年6月的JVM规范)
2011-10-18 13:30 1970本文是《The Java Virtual Machine Sp ... -
AOP的实现机制
2011-10-18 10:15 7774附件中有本文的源代码和Pdf版。本文写的很长的原因,是不希望大 ... -
单点登录设计
2011-09-25 15:20 4704使用独立的单点登录应用程序来做单点登录,这样可扩展性和安全性会 ... -
Java虚拟机
2011-08-25 19:50 2014JVM JVM即Java虚拟机,它是一个想象中的机器,通 ... -
HttpClient
2011-08-16 15:27 5877HttpClient是一个模拟HTTP请求的工具类,目前我们在 ... -
Eclipse插件开发
2011-07-22 11:15 1889插件开发工具 我觉得进行RCP开发还是用专门的ID ... -
Opencomet之Session设计
2011-06-24 13:08 1993本文主要介绍Opencomet 里的Session设计。见附件 ... -
单元测试用例设计
2011-06-15 22:42 1552测试用例设计的原则是短,精和易读。 如何做到短: ... -
使用AOP做权限控制
2011-06-06 20:49 6747见附件! -
JAVA6可以使用字符串累加
2011-05-12 10:42 3781在JAVA6中,编译器会始终对字符串的累加操作做优化编译。 ... -
开发中的小心得
2011-02-04 01:13 1650总结一下自己在开发上的一些小心得,持续更新,欢迎大家补充! ...
相关推荐
ASP.NET Web Service是一种基于.NET Framework的简单方法,用于构建可跨平台、跨语言通信的Web应用程序。这个例子是为初学者设计的,旨在演示如何创建和使用Web Service,以及如何在ASP.NET环境中调用这些服务。 ...
环境文件的路径通常为 `/usr/lib/systemd/system/<service_name>.service.d/environment.conf`。 CentOS 7 的 systemd 服务提供了强大的自定义配置功能,允许用户根据需要定义服务的配置信息。通过编写服务配置文件...
在Android应用开发中,Service和Activity是两个非常重要的组件。Service用于在后台执行长时间运行的任务,而Activity则负责用户界面交互。在某些场景下,我们可能需要Service与Activity之间进行数据传递,例如本例中...
这里我们关注的是"自己写的service及调用",这个话题涉及到Web服务(Web Service)的概念、Eclipse IDE的使用以及Java编程语言的应用。Web服务允许不同应用程序之间的数据交换,通常基于开放标准如XML、SOAP和WSDL,...
在Android开发中,Service是四大组件之一,它用于在后台执行长时间运行的操作,不与用户交互。本教程将深入探讨Service的基础使用方法,适合初学者掌握。 首先,我们需要理解Service的基本概念。Service并非一个...
### Python编写Windows Service服务程序详解 #### 一、引言 在Windows环境下,有时我们需要创建一个后台服务程序,这类程序可以在系统启动时自动运行,并在后台持续运行而不会占用用户的桌面资源。对于开发者来说...
在windows文件服务器之间拷贝文件时,由NETWORK SERVICE账户权限控制的文件或文件夹在复制粘帖时会出现账户权限丢失的问题。次工具则是对该账户权限查找并设置相应的文件或文件夹。 W3WP.exe所使用的账户为NETWORK ...
例如,在一个Activity中,你可以这样写: ```java Intent intent = new Intent(this, MyService.class); startService(intent); ``` 这将启动名为`MyService`的服务。一旦启动,Service会经历其生命周期的...
在Android系统中,Service是四大组件之一,它与Activity、BroadcastReceiver和ContentProvider共同构成了Android应用的核心架构。Service主要用于在后台执行长时间运行的操作,而无需与用户交互。它不同于线程,...
它是利用系统的漏洞来启动一个前台的Service进程,与普通的启动方式区别在于,它不会在系统通知栏处出现一个Notification,看起来就如同运行着...反正我是信了,demo在此,欢迎指正,很少写博客,就这样吧~~~~~~~忙去了
mysql 5.7.x 所需mysqld.service文件
在Android开发中,`Service` 是一个非常关键的组件,它允许应用程序在后台长时间运行操作,即使用户没有与应用交互。`Service` 主要用于执行长时间运行的任务,如播放音乐、处理网络请求或定期同步数据。本教程将...
在Android应用开发中,`Service` 是一个非常重要的组件,它允许应用程序在后台长时间运行操作,即使用户没有与应用程序交互。本篇文章将深入探讨 `startService()` 方法的使用及其在实际案例中的应用。 ### 一、...
该工程是花了大半天时间查阅相关资料之后,在找到一个老外的demo基础上修改的,...包中并没有写访问服务端部分,这个有点累赘,和我们普通的http请求没有区别. 至于震动,铃声类的,看了下文档,都很简单,象征性的做了一下.
在Android应用开发中,`Service`是一个至关重要的组件,它允许开发者在后台执行长时间运行的操作,即使用户已经离开应用程序的界面。本篇文章将深入解析`Service`的工作原理、使用场景、启动方式以及生命周期,帮助...
QtService是一个用于实现windows服务或unix守护进程的开源项目,下载地址 本文使用QtService演示如何实现一个windows下的后台进程,可用于一些简单的windows服务程序中。 博客介绍:...
只需配合一下vo包名即可生成所有的vo 的dao 和service (当然,您的框架和我不一样只需要改下模板文件即可).本人也是学生,马上毕业了.写完这个以后,我非常深刻的理解这些框架的实现.也非常适合新手学习.附上源文件.
在Android系统中,Service是一种非常重要的组件,它允许应用程序在后台长时间运行,即使用户与应用程序的界面没有任何交互。本篇文章将深入探讨`Android Service`的实例,帮助开发者更好地理解和运用这一核心功能。 ...
在不分层的系统中,我们可以将所有的代码都写到一个地方,比如 Struts 的 Action 类。在这里,我们不仅要处理页面逻辑,还要做业务逻辑,还要做数据访问。为了更好地理解和分离 Action、Service 和 Dao 的功能,我们...
在本文中,我们将深入探讨如何使用Visual C++ (VC++) 编写Windows Service服务,并结合提供的源程序进行分析。Windows Service是一种特殊的后台应用程序,它在没有用户界面的情况下运行,通常用于执行系统级任务,如...