做者:nnngu
项目源代码:https://github.com/nnngu/nguSeckill前端
首先在编写Service
层代码前,咱们应该首先要知道这一层究竟是干什么的。java
Service
层主要负责业务模块的逻辑应用设计。一样是首先设计接口,再设计其实现的类,接着在Spring
的配置文件中配置其实现的关联。这样咱们就能够在应用中调用Service
接口来进行业务处理。Service
层的业务实现,具体要调用到已定义的dao
层的接口,封装Service
层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得很是简洁。git
在项目中要下降耦合的话,分层是一种很好的概念,就是各层各司其职,尽可能不作不相干的事,因此Service
层的话顾名思义就是业务逻辑,处理程序中的一些业务逻辑,以及调用dao
层的代码,这里咱们的dao
层就是链接数据库的那一层,调用关系能够这样表达:github
View(页面) > Controller(控制层) > Service(业务逻辑) > Dao(数据访问) > Database(数据库)web
首先仍是接口的设计,设计秒杀商品的接口,在com.nnngu.service.interfaces
包下创建SeckillService.java
接口文件,以下图:spring
SeckillService.java
文件里面的内容请参照项目的源代码。数据库
创建好接口以后咱们要写实现类了,在写实现类的时候咱们确定会碰到一个这样的问题,你要向前端返回json数据的话,你是返回什么样的数据好?直接返回一个数字状态码或者文字?这样设计确定是很差的,因此咱们应该向前端返回一个实体信息json,里面包含了一系列的信息,不管是哪一种状态都应该能够应对,既然是与数据库字段无关的类,那就不是PO了,因此咱们创建一个DTO数据传输类。关于常见的几种对象个人解释以下:json
PO:也就是咱们为每一张数据库表写一个实体类并发
VO:对某个页面或者展示层所须要的数据,封装成一个实体类app
BO:业务对象
DTO:跟VO的概念有点混淆,也是至关于页面须要的数据封装成一个实体类
POJO:简单的无规则java对象
在com.nnngu下创建dto包,而后创建Exposer类,这个类是秒杀时数据库那边处理的结果的对象
Exposer.java
文件里面的内容请参照项目的源代码。
定义一个基础的异常,全部的子异常继承这个异常SeckillException
package com.nnngu.exception; /** * 秒杀基础的异常 * Created by nnngu */ public class SeckillException extends RuntimeException { // 代码省略,请参照项目的源代码 ... ... }
可能会出现秒杀关闭后被秒杀状况,因此创建秒杀关闭异常SeckillCloseException
,须要继承咱们前面写的基础异常
package com.nnngu.exception; /** * 秒杀已经关闭异常,当秒杀结束就会出现这个异常 * Created by nnngu */ public class SeckillCloseException extends SeckillException{ // 代码省略,请参照项目的源代码 ... ... }
定义重复秒杀异常RepeatKillException
package com.nnngu.exception; /** * 重复秒杀异常,不须要咱们手动去try catch * Created by nnngu */ public class RepeatKillException extends SeckillException{ // 代码省略,请参照项目的源代码 ... ... }
com.nnngu.service
包下建立SeckillServiceImpl.java
类,具体代码请参照项目的源代码。
在这里咱们捕获了运行时异常,这样作的缘由就是Spring的事务默认发生了RuntimeException才会回滚,能够检测出来的异常是不会致使事务的回滚的,这样的目的就是你明知道这里会发生异常,因此你必定要进行处理。若是只是为了让编译经过的话,那捕获异常也没意思,因此这里要注意事务的回滚。
而后咱们还发现这里存在硬编码的现象,就是返回各类字符常量,例如秒杀成功,秒杀失败等等,这些字符串是能够被重复使用的,并且这样维护起来也不方便,要处处去类里面寻找这样的字符串,全部咱们使用枚举类来管理这样状态,在con.nnngu包下创建enums包,专门放置枚举类,而后再创建SeckillStatEnum枚举类。
枚举类SeckillStatEnum.java
的代码请参照项目的源代码。
在resources/spring
下创建applicationContext-service.xml
文件,用来配置Service
层
applicationContext-service.xml
的代码请参照项目的源代码。
在这里开启了基于注解的事务,常见的事务操做有如下几种方法:
在Spring早期版本中是使用ProxyFactoryBean+XMl方式来配置事务。
在Spring配置文件使用tx:advice+aop命名空间,好处就是一次配置永久生效,你无须去关心中间出的问题,不过出错了你很难找出在哪里出了问题。
序号 | 动态代理策略 | 不能被事务加强的方法 |
---|---|---|
1 | 基于JDK的动态代理 | 除了public 之外的全部方法,而且 public static 的方法也不能被加强 |
2 | 基于cglib的动态代理 | private ,static ,final 的方法 |
添加测试类SeckillServiceImplTest.java
,以下图:
SeckillServiceImplTest.java
的代码请参照项目的源代码。
测试的方法:public void getSeckillList()
测试结果以下图:
到此,咱们成功完成了Service层开发及测试。