发表于: 2017-08-01 22:31:24

2 1125


今天做的事:

SSM框架的代码已经码完了,然后现在过程,逻辑实现等等也都理解了,遇到的不认识,不熟悉的知识点也都了解的差不多了,接下来就是使用jetty启动服务,然后先用postman测试一下后端接口,最后把前端页面写出来,然后将这一整套过程移植到任务一的代码逻辑上,最后将效果都展示出来,任务二就可以提交了,初步估计大概还需要个三四天,也可能提前或延后。

话不多说,先把今天学的知识罗列一下

首先service层的代码如下

这里的业务逻辑是顺接上一篇日报的

首先创建一个枚举类,用来限定范围

AppointStateEnum.java

package com.ts.enums;

/**
* Created by Administrator on 2017/07/31.
*/
public enum AppointStateEnum {

SUCCESS(1,"预约成功"),NO_NUMBER(0,"库存不足"),REPEAT_APPOINT(-1,"重复预约"),INNER_ERROR(-2,"系统异常");

   private int state;

   private String stateInfo;

   private AppointStateEnum(int state,String stateInfo){
this.state = state;
       this.stateInfo = stateInfo;
   }

public int getState(){
return state;
   }

public String getStateInfo(){
return stateInfo;
   }

public static AppointStateEnum stateOf(int index){
for(AppointStateEnum state : values()) {
if(state.getState() == index) {
return state;
           }
}
return null;
   }

}


这里将枚举的概念讲一下:

枚举

枚举就像一个限制集,当我们需要对一个值取一个特定范围时就需要使用枚举了,如果超出定义范围,就会报错(或者我们定义一个方法,不让超出范围)

枚举的values()方法;

可以将所定义的枚举类转换成一个枚举类型的数组,通过for循环遍历可以实现获取枚举的所有想得到的数据

for(enum enum_name : values()){

//method code

}


接下来我们设置一个构造器,用来区分成功和失败

AppointExecution.java

package com.ts.dto;

import com.ts.entities.Appointment;
import com.ts.enums.AppointStateEnum;

/**
* Created by Administrator on 2017/07/31.
*/
public class AppointExecution {
private long bookId;

   private int state;

   private String stateInfo;

   private Appointment appointment;

   public AppointExecution(){
}

//预约失败构造器
   public AppointExecution(long bookId, AppointStateEnum stateEnum){
this.bookId = bookId;
       this.state = stateEnum.getState();
       this.stateInfo = stateEnum.getStateInfo();
   }
//预约成功构造器
   public AppointExecution(long bookId,AppointStateEnum stateEnum,Appointment appointment){
this.bookId = bookId;
       this.state = stateEnum.getState();
       this.stateInfo = stateEnum.getStateInfo();
       this.appointment = appointment;
   }

public long getBookId() {
return bookId;
   }

public void setBookId(long bookId) {
this.bookId = bookId;
   }

public int getState() {
return state;
   }

public void setState(int state) {
this.state = state;
   }

public String getStateInfo() {
return stateInfo;
   }

public void setStateInfo(String stateInfo) {
this.stateInfo = stateInfo;
   }

public Appointment getAppointment() {
return appointment;
   }

public void setAppointment(Appointment appointment) {
this.appointment = appointment;
   }

@Override
   public String toString() {
return "AppointExecution{" +
"bookId=" + bookId +
", state=" + state +
", stateInfo='" + stateInfo + '\'' +
", appointment=" + appointment +
'}';
   }
}


接下来定义泛型

Result.java

package com.ts.dto;

/**
* Created by Administrator on 2017/08/01.
*/
//封装json对象,所有返回结果都使用它
public class Result<T> {
private boolean success;
   private T data;
   private String error;

   public Result(){
}

//成功时构造器
   public Result(boolean success,T data){
this.success = success;
       this.data =data;
   }

//错误时构造器
   public Result(boolean success,String error){
this.success = success;
       this.error = error;
   }

public boolean getSuccess() {
return success;
   }

public void setSuccess(boolean success) {
this.success = success;
   }

public T getData() {
return data;
   }

public void setData(T data) {
this.data = data;
   }

public String getError() {
return error;
   }

public void setError(String error) {
this.error = error;
   }
}


介绍一下泛型

泛型

定义格式:public class Result<T>{}

其中T代表任意类型,这个泛型指的就是,我们可以自定义T的类型,比如String,Integer等等,在新建对象时,只需要声明T为什么类型即可。当然也包括我们自定义的类。


然后是service层的接口及实现类

BookService.java

package com.ts.service;

import com.ts.dto.AppointExecution;
import com.ts.entities.Book;

import java.util.List;

/**
* Created by Administrator on 2017/07/31.
*/
public interface BookService {

//查询一本书
//    @param bookId
//    @return
   Book getById(long bookId);

   //查询所有图书
//    @return
   List<Book> getList();

   //预约图书
//    @param bookId
//    @param studentId
//    @return
   AppointExecution appoint(long bookId,long studentId);

}


BookServiceImpl.java

package com.ts.service;

import com.ts.dao.AppointmentDao;
import com.ts.dao.BookDao;
import com.ts.dto.AppointExecution;
import com.ts.entities.Appointment;
import com.ts.entities.Book;
import com.ts.enums.AppointStateEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
* Created by Administrator on 2017/07/31.
*/
@Service
public class BookServiceImpl implements BookService{

@Autowired
   private BookDao bookDao;

   @Autowired
   private AppointmentDao appointmentDao;

   @Override
   public Book getById(long bookId){
return bookDao.queryById(bookId);
   }

@Override
   public List<Book> getList(){
return bookDao.queryAll(0,1000);
   }

@Override
   @Transactional
   /**
    * 使用注解控制事务方法的优点: 1.开发团队达成一致约定,明确标注事务方法的编程风格
    * 2.保证事务方法的执行时间尽可能短,不要穿插其他网络操作,RPC/HTTP请求或者剥离到事务方法外部
    * 3.不是所有的方法都需要事务,如只有一条修改操作,只读操作不需要事务控制
    */
   public AppointExecution appoint(long bookId,long studentId){
try{
//减库存
           int update = bookDao.reduceNumber(bookId);
           if(update<=0){
//库存不足
               return new AppointExecution(bookId, AppointStateEnum.NO_NUMBER);
           } else{
//执行预约操作
               int insert = appointmentDao.insertAppointment(bookId,studentId);
               if(insert<=0){
//重复预约
                   return new AppointExecution(bookId,AppointStateEnum.REPEAT_APPOINT);
               }else{
//预约成功
                   Appointment appointment = appointmentDao.queryByKeyWithBook(bookId,studentId);

                   return new AppointExecution(bookId,AppointStateEnum.SUCCESS,appointment);

               }
}

}catch(Exception e){

return new AppointExecution(bookId,AppointStateEnum.INNER_ERROR);
       }
}

}


这里使用了事务,但是并没有使用事务回滚功能,现在暂时没接触到,不过是个很重要的功能,以后会深入学习

然后是service层的配置文件

spring-service.xml

<?xml version="1.0" encoding="UTF-8"?>
   <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
          xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context.xsd
   http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx/spring-tx.xsd">

       <!-- 扫描service包下所有使用注解的类型 -->
       <context:component-scan base-package="com.ts.service"/>

           <!-- 配置事务管理器 -->
           <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
               <!-- 注入数据库连接池 -->
               <property name="dataSource" ref="dataSource"></property>
           </bean>

           <!-- 配置基于注解的声明式事务 -->
       <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

   <import resource="spring-dao.xml"/>
   </beans>

可以看到这里使用了配置事务的相关标签


最后是service测试类

import com.ts.dto.AppointExecution;
import com.ts.service.BookService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

/**
* Created by Administrator on 2017/07/31.
*/
public class BookServiceImplTest extends BaseTest {
@Autowired
   private BookService bookService;

   @Test
   public void testAppoint() throws Exception{
long bookId = 1001;
       long studentId = 123456789L;
       AppointExecution execution = bookService.appoint(bookId,studentId);
       System.out.println(execution);
   }
}

这个测试类有一个逻辑上的bug

就是每次执行事务,即使重复预约也会出现扣除图书数量的操作,没有实现事务回滚,造成数据丢失,但是鉴于能力有限,时间有限,就暂时没有解决这个逻辑bug


最后,到这里已经实现了三层架构的BLL以及DAL两层了,就差UI层了,不过前端页面还没写,后端接口也还没测,就先不贴controller的代码了。


然后贴一下今天了解的其他知识点

标签<context:component-scan base-package=""/>

组件自动扫描机制,会在包路径下寻找标注注解的类,并把这些类纳入Spring容器中管理。这样就极大简化了xml文件中对于bean定义的配置,压缩文件大小。


几个注解

@RequestMapping

用来处理请求地址映射的注解,用于类或方法上;

有如下六个属性:

1.value:指定请求实际地址,url

2.method:指定请求方法,GET,PUT,POST,DELETE等

3.consumes:指定处理请求的提交内容类型,如application/json, text/html

4.produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回

5.params:指定request中必须包含某些参数值时,才让该方法处理

6.headers:指定request中必须包含某些特定的header值,才能让该方法处理请求


@PathVariable 处理request uri部分的注解

如@RequestMapping("/{booId}")中的booId就需要使用@PathVariable绑定传过来的值到方法参数上


@ModelAttribute用于方法上时

通常用来处理@RequestMapping之前,为请求绑定一个需要从后台查询的model

这里顺便提一下model.addAttribute(“sss”,sss)——渲染

这个方法就是向前台视图传递参数


@Responsebody表示该方法的返回结果直接写入HTTP response body中

一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@Responsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@Responsebody后,会直接返回json数据。


mybatis使用@Param注解时,在配置文件中可以使用${}的格式,如果没有该注解,必须使用#{}

这些都在controller的代码块中,之后的日报会贴出来


明天计划:测完后端接口,开始写前端页面,用jetty启动服务。


问题:暂无


收获:一些知识点,以及看了一点业务逻辑。


返回列表 返回列表
评论

    分享到