The previous article described the DAO layer, MyBatis database connection, DAO layer interface design, as well as myBtis and Spring integration. The DAO layer is implemented by interface design, and the separation of interface and SQL implementation is convenient for maintenance. The DAO layer is only responsible for the design and implementation of the interface, and the responsible logic, namely the concatenation of one or more DAO layer interfaces, is done in the Sevice layer. This article follows the previous one and focuses on the implementation of the Service layer, integration with Spring, and how declarations declare things.

1. Interface design of Service layer

Service interfaces should be designed from the perspective of “users” and should follow three specifications: reasonable commands, clear parameters, and return results (normal interface/abnormal result). This example uses the Java high concurrency seckill API series of examples, create design of the business logic interface as follows:

Public interface SeckillService {/** * query all seckill records * @return */ List getSerkillList(); * @param seckillId * @return */ Seckill getById(long seckillId); /** * exportSeckillUrl(long seckillId); /** * exportSeckillUrl(long seckillId); /** * exportSeckillUrl(long seckillId); / ** * execute seckillexeckill */ seckillexeckill (long seckillId, long userPhone, String md5) throws SeckillException,RepeatKillException,SeckillCloseException;Copy the code

Implementation of Service interface

Directly on the code, here to talk about the second kill business logic: the first is to get the second kill list, click the list to enter the second kill details page, then get the system time, if the second kill starts, get the second kill address, click the second kill, execute the second kill. So the business logic is only designed for these four business logic. The dTO layer is used to pass response data, as well as custom exceptions, all exceptions are inherited from running exceptions, this is to facilitate spring automatic rollback, these two knowledge points, look at the source code.

package org.forezp.service.impl; @Service public class SeckillServiceImpl implements SeckillService{ private Logger logger= LoggerFactory.getLogger(this.getClass()); @autoWired private SeckillDao SeckillDao; @Autowired private SuccessKilledDao successKilledDao; //MD5 salt value MD5 private final String slat=" sFSA =32q4r23234215ERWERT^**%^SDF"; Public List getSerkillList() {return seckillDao. QueryAll (0,4); } public Seckill getById(long seckillId) { return seckillDao.queryById(seckillId); } public Exposer exportSeckillUrl(long seckillId) { Seckill seckill =seckillDao.queryById(seckillId); if(seckill==null){ return new Exposer(false,seckillId); } Date startTime=seckill.getStartTime(); Date endTime=seckill.getEndTime(); // System current time nowTime=new Date(); if(nowTime.getTime()endTime.getTime()){ return new Exposer(false,seckillId,nowTime.getTime(),startTime.getTime(),endTime.getTime()); } String md5=getMD5(seckillId); return new Exposer(true,md5,seckillId); } private String getMD5(long seckillId){ String base=seckillId+"/"+slat; String md5= DigestUtils.md5DigestAsHex(base.getBytes()); return md5; } @transactional /** * The advantages of using annotations to control Transactional methods * 1: Development teams agree ona convention to explicitly annotate the programming style of Transactional methods * 2: Keep the execution time of the transaction method as short as possible and do not intersperse with other network requests, RPC/HTTP requests or peel off the transaction method * 3: Not all methods require transactions, such as only one change operation, */ public seckillexeckill (long seckillId, long userPhone, String md5) throws SeckillException, RepeatKillException, SeckillCloseException { if(md5==null ||! md5.equals(getMD5(seckillId))){ throw new SeckillException("seckill data rewrite"); } // Execute seckill logic: reduce inventory + record purchase behavior Date nowTime=new Date(); Try {/ / record purchase behavior int insertCount = successKilledDao. InsertSuccessKilled (seckillId, userPhone); Throw new RepeatKillException("seckill repeated"); // throw new RepeatKillException("seckill repeated"); }else{int updateCount=seckillDao. ReduceNumber (seckillId,nowTime); Rollback throw new SeckillCloseException("seckill is closed"); if(updateCount<=0){rollback throw new SeckillCloseException("seckill is closed"); } else {/ / SEC kill success commit SuccessKilled SuccessKilled = successKilledDao. QueryByIdWithSeckill (seckillId, userPhone); return new SeckillExecution(seckillId, SeckillStatEnum.SUCCESS,successKilled); } } }catch(SeckillCloseException e1){ throw e1; } catch (RepeatKillException e2){ throw e2; } catch (Exception e) { logger.error(e.getMessage(),e); Throw new SeckillException("seckill inner error:"+ LLDB message ()); // throw new SeckillException("seckill inner error:"+ LLDB message ()); }} // Throw an exception to tell Spring whether to rollback. Public seckillexeckill Procedure(Long seckillId, long userPhone, String md5) { if(md5 ==null || ! md5.equals(getMD5(seckillId))){ return new SeckillExecution(seckillId,SeckillStatEnum.DATA_REWRITE); } Date killTime=new Date(); Map map=new HashMap(); map.put("seckillId",seckillId); map.put("phone",userPhone); map.put("killTime",killTime); map.put("result",null); / / execute the stored procedure, the result was assigned the try {seckillDao. KillByProcedure (map); int result=(Integer) map.get("result"); if(result==1){ SuccessKilled successKilled=successKilledDao.queryByIdWithSeckill(seckillId,userPhone); return new SeckillExecution(seckillId, SeckillStatEnum.SUCCESS,successKilled); }else{ return new SeckillExecution(seckillId,SeckillStatEnum.stateof(result)); } } catch (Exception e) { logger.error(e.getMessage(),e); return new SeckillExecution(seckillId,SeckillStatEnum.INNER_ERROE); }}}Copy the code

Sping hosting service implementation class

Spring IOC uses the object engineering pattern to manage all injected dependencies and expose a consistent access interface. When we need an object, You can just pull them directly from Spring IOC, without new and without managing their life cycles. More importantly, Spring automatically assembles dependencies, For example, the final interface controller relies on service, which relies on DAO, which relies on SessionFactory, which relies on datasource. These dependencies are managed and assembled through Spring. As long as we can easily configure and annotate it, the art of layering code and programming is fully demonstrated in the Spring framework.

This project adopts Spring IOC:

1. The XML configuration

2. Package scanning

3. The annotation annotation.

Create sping – service. The XML

To use the package scan + annotation approach, first declare the package scan in XML:



    
    Copy the code

Classes in the org,forezp.service package are then annotated. For example, if the @Service annotation declaration is a Service, @AutoWired injects the dependency required for Service.

SeckillServiceImpl implements SeckillService{// Implements Service dependency @autoWired Private SeckillDao seckillDao; @Autowired private SuccessKilledDao successKilledDao; }Copy the code

A package scan and a few simple annotations are all it takes to annotate a Service into the Spring IOC container.

4. Spring declarative things

In the second kill case, we need to use things to prevent data correctness, to prevent duplicate second kills, to prevent low inventory, surplus inventory, and so on. Using things in general requires opening things/often a series of actions, commits or rolls back. Spring declarative things, where things start, commit, etc., are hosted by Spring, we just need to focus on how to modify the data.

Configure spring declarative things in spring-service.xml:

 
    
        
        
    
    
    Copy the code

Annotate @Transactional under business logic that requires things. For example, when enabling the seckill method:

@Transactional public SeckillExecution executeSeckill(long seckillId, long userPhone, String md5) throws SeckillException, RepeatKillException, SeckillCloseException { if(md5==null ||! md5.equals(getMD5(seckillId))){ }Copy the code

Note:

The development team reached an agreement on the programming style of clearly annotating transaction methods

2: ensure that the execution time of the transaction method is as short as possible, and do not intersperse with other network requests, RPC/HTTP requests or separate from the transaction method

3: Not all methods require a transaction. If only one modification operation is performed, read-only operations do not require transaction control

Unit testing

To configure:

@contextConfiguration ({“classpath:spring/spring-dao.xml”, “classpath:spring/spring-service.xml”})

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "classpath:spring/spring-dao.xml", "classpath:spring/spring-service.xml" }) public class SeckillServiceTest { private final Logger logger=LoggerFactory.getLogger(this.getClass()); @Autowired private SeckillService seckillService; @Test public void getSerkillList() throws Exception { List list=seckillService.getSerkillList(); System.out.println(list); [Seckill{seckillId=1000, name='1000 yuan/SEC iphone6'..... omitted...]  } @Test public void getById() throws Exception { long id=1000; Seckill seckill=seckillService.getById(id); System.out.println(seckill); // Result: Seckill{seckillId=1000, name='1000 yuan/SEC iphone6', number=100, startTime=Sun Nov 01 00:00:00 CST 2015,... } } @Test public void exportSeckillUrl() throws Exception { long id=1000; Exposer exposer=seckillService.exportSeckillUrl(id); System.out.println(exposer); } @Test public void executeSeckill() throws Exception { long id=1000; long phone=13502171122L; String md5="e83eef2cc6b033ca0848878afc20e80d"; SeckillExecution execution=seckillService.executeSeckill(id,phone,md5); System.out.println(execution); }}Copy the code

This article mainly talks about the preparation and implementation of service business interface, as well as the use of XML and annotations to inject service into Spring IOC, and declarative things, have to sigh spring powerful. The next article will cover web layer development and configuration of Spring MVC. Thank you. Keep up the good work. Good night. ^_^.