一个基于SSM框架开发的高并发电商秒杀Web系统

Posted kukri

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个基于SSM框架开发的高并发电商秒杀Web系统相关的知识,希望对你有一定的参考价值。

0 前言

一个基于SSM框架的高并发秒杀系统采用IDEA+Maven+SSM+mysql+Redis+Jetty、Bootstrap/Jquery开发。

通过这个小项目,理清了基于SSM框架开发Web应用的流程以及常见的避坑方法,并在最后简单采用了Redis缓存以及Mysql Procedure对项目进行了高并发优化。

接下来从DAO层、Service层、Web层开发以及高并发优化4个方面梳理整个项目开发过程。

源码地址https://github.com/Allegr0/seckill

项目准备;

新建工程,用maven组织框架,从archtype:webapp中新建,在pom.xml添加相关依赖。修改默认web.xml中的servlet支持版本为3.1,在pom.xml添加项目所需依赖,并添加jetty服务器插件

1 DAO层相关开发

1.1 数据库设计与编码

  数据库DDL在main/sql/schema.sql,这里采用纯手写DDL的方式创建数据库,这样的良好习惯相当于对每次数据库的改动都留下记录,方便了项目后期维护。

1.2 DAO实体与接口编码

  分别放在org/seckill/entity目录下和org/seckill/dao目录下。  数据库中的Table <--> JavaPOJO类 Entity 是一对一的关系,数据库表对应实体类,数据库表中的列对应实体类的属性。

  由于我们采用Mybatis ORM框架,所以这里dao目录下只存放接口以及抽象方法,描述功能,具体的SQL在Mybatis的Mapper中实现。

1.3 基于Mybatis实现DAO

  Mybatis相当于其他ORM框架的优点:采用XML提供SQL,提供了足够的灵活性,Mapper自动实现DAO接口方法,并将结果自动集映射到javaPOJO。

  配置resources/mybatis-config.xml配置文件。一些mybatis特性的全局属性(使用列别名替换列名、驼峰命名转换)可以自动的把sql中的下划线命名形式转为java中的驼峰命名形式,例如:create_time (sql)<—> createTime (java)。

  在resources/mapper目录下写xml(sql语句),对应DAO中接口定义的所有抽象方法 tips:(注意Xml标签转义字符 <![CDATA[ <= ]]>、联合主键的使用、insert ignore技巧)

1.4 基于Spring托管Mybatissqlsessfactory对象

  在resources/spring 目录下编写spring-dao.xml的配置文件(注意这里jdbc.properties 最好用jdbc.username不能直接用username,否则会报错),向Spring IOC中装配dao层所需要的bean,包括数据库连接池、mybatis很关键的sqlsessionfactory对象,以及扫描DAO接口实现类并注入进IOC。

1.5 DAO层单元测试

  用command+shift+T 生成junit单元测试类,并测试。 tips:bean的自动注入用两种方法@Resource、@Autowired 。一个是按名称、一个是按类型。

  单元测试的时候有一个小坑: 异常:org.apache.ibatis.binding.BindingException。由于 DAO接口参数 -> XML SQL参数绑定的时候,由于java没有保存形参的记录。queryAll(int offset, int limit) —> querryAll(arg0, arg1),当有多个参数的时候会出现找不到参数的问题。 所以在DAO层的接口函数参数前要标注@param(“参数名") 例如:queryAll(@Param("offset") int offset, @Param("limit") int limit);

1.6 总结

  由于采用了MybatisORM框架,DAO层工作演变为:接口设计+SQL编写。代码和SQL分离,方便后期review。

  DAO层只实现相关数据库的增删改查基本功能,具体的DAO拼接等复杂逻辑在Service层完成。

2 Service层相关开发

2.1 准备工作:新建dto、exception、service三个package

  dto:数据传输层,存放一些表示数据的类型。dto和entity较像,entity是业务(数据库Table)的封装,dto是关注web和service之间的数据传递,dto层还包括了json格式的封装类。

  spring声明式事务只接收RuntimeException(运行期异常),只对运行期异常进行回滚。

2.2 秒杀Service接口设计(站在“使用者”的角度设计)

  service/SeckillService.java  秒杀接口包含4个方法:查询全部秒杀记录、查询单个秒杀记录、暴露秒杀地址、执行秒杀。配合接口中的方法,要同时设计好dto类以及异常类。

2.3 秒杀Service接口实现 

  service/impl/SeckillServiceImpl.java 。新建枚举类enums/SeckillStateEnum 存放状态,状态信息对应的常量。

  在IntelliJ idea 2017.2 中@Resourse 或者 @Autowired出现警告或者错误提示(Could not autowire. no beans of "XXX" type found.). 但是程序运行无误。可以在IDEA中配置降低此类问题的警告级别。

2.4 基于Spring托管Service实现类

   在resources/spring 目录下编写spring-service配置文件,以便向IOC装配service层的bean。通过   

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

  扫描类包,将所有标注Spring注解的@Component、@Service、@Controller、@Respository的类自动转换为bean并注入到IOC容器中,同时对代码中标注了@Autowired、@Resource的方法或成员变量根据名称或类型进行依赖注入。

2.5  使用Spring声明式事务    

  Spring声明式事务有两种常见的用法:1) tx:advice+aop命名空间,一次配置永久生效。2) @Transcational,通过注解标注需要事务的方法。

  不是所有方法都需要事务,如只有一条修改操作、只读操作不要事务控制,所以这里建议用注解控制(@Transcational)的方式标注需要事务的方法,而不建议采用tx-advice+aop命名空间对所有方法都标注事务。个人理解:当有两条以上的修改操作或select for update,才需要事务,这个还需要进一步学习mysql行级锁。 
  标注了@Transcational方法,开启一个事务,再最后return或者throw RuntimeException时才commit或rollback
      在spring-service.xml配置事务管理器,配置基于注解的声明式事务。   

2.6 集成测试

   slf4j接口的实现类logback配置:resources/logback.xml。在需要使用的测试类前声明logger变量

private final Logger logger = LoggerFactory.getLogger(this.getClass());

3 Web层相关开发

3.1 Restful接口与SpringMVC概述

  REST是英文representational state transfer(表象性状态转变)或者表述性状态转移;Rest是web服务的一种架构风格;使用HTTP,URI,XML,JSON,html等广泛流行的标准和协议;轻量级,跨平台,跨语言的架构设计;它是一种设计风格,不是一种标准,是一种思想。
      Restful架构:(1) 每一个URI代表一种资源。(2) 客户端和服务器之间,传递这种资源的某种表现层;(3) 客户端通过四个HTTP动词,队伍段资源进行操作,实现“表现层状态转化”。
  由于篇幅原因,在这里就不对Restful接口进行详细介绍
  Spring MVC框架原理
  技术分享图片

 

以上是关于一个基于SSM框架开发的高并发电商秒杀Web系统的主要内容,如果未能解决你的问题,请参考以下文章

01 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之业务分析与DAO层

Web系统大规模并发——电商秒杀与抢购

Web系统大规模并发——电商秒杀与抢购

Web系统大规模并发——电商秒杀与抢购

Web系统大规模并发——电商秒杀与抢购

Web系统大规模并发——电商秒杀与抢购