前后端完全分离初探

核心思路

后端负责业务逻辑处理, 前端负责展示逻辑的处理.

背景

  • 2013年3月,首次接触了underscore.js这个区区45k大小的js库, 在使用其提供的简单模板完成表格异步分页后,从此我开始慢慢践行前后端完全分离的架构.

  • 2013年7月,我接触到了REST这种重用HTTP应用协议的架构, 更坚定了我践行前后端分离的决心.

  • 2014年3月,国内刮起了nodeJS的风暴, 此时我采用国外的一个开源项目MEAN开发了一套完整的CMS系统, 此次开发学习到了API接口如何标准化, API具体的设计参考了github API, Instagram API.

  • 2015年1月, 公司开发新产品, 需要新开发一套支持平台及数据下发平台, 在该产品中我主要参与API的设计, 并主导开发支撑平台, 下面我就介绍下这套支撑平台.

工具

工欲善其事, 必先利其器, 先介绍下自己使用的工具

IntelliJ IDEA

强大的Java集成开发工具, 没有之一.

Webstorm

强大的HTML,CSS,Javascript集成开发工具, 没有之一.

Sublime

强大的文本编辑工具, 目前我主要用于临时文件查看, 临时json数据格式化查看, 集成了plugin后, 它的功能会吓到人.

Navicat

小巧强大的关系数据库建模工具, 相当易用.

Cornerstone

强大的版本控制客户端.

Mou

一款简洁强大的MarkDown可视化编辑工具.

Zoc6

一款强大的Linux SSH客户端工具.

Transmit

一款强大的Linux SFTP客户端可视化工具.

代理

云梯

强大的VPN, 连接稳定, 速度快, 价格实惠, 可做全局代理, 包括terminal.

项目

目的

  • 提高使用者的工作效率
  • 提高开发人员的开发效率

前端类库

vue.js

一个用于创建web交互界面的库, 主要用于数据双向绑定.

superagent.js

一个非常方便的客户端请求代理模块,可方便的使用get,post,put,delete,head动词, 异步回调中封装了http状态码和业务数据等等.

dropzone.js

一个强大的文件上传库, 可获取文件mime, 文件大小等; 针对图片可生成缩略图, 获取图片宽度,高度.

backgrid.js

一个强大的表格组件.

director.js

一个强大的前端路由库, 通过#符号进行路径组织, 结合vuecomponent可进行单页的局部模块刷新.

后端类库

spring hateoas

spring 超文本驱动库, 可根据需求返回不同的httpStatus及links.

spring framework

对架构进行分层, 目前分三层

  • web接入层: 提供API接口,对前端传过来的数据进行校验, 校验未通过的话使用spring hateoas包装返回错误消息, 校验通过的话调用业务逻辑层
  • 业务逻辑层: 该层主要处理上层传进来的数据, 调用数据访问层进行数据持久化, 该层具有强大的扩展性;

    • 对于高并发写db的操作, 可集成消息队列库(如ActiveMQ)将消息发送至队列, 采用队列依次消费减轻db写负担.
    • 对于高并发频繁读db的操作, 可集成缓存库(如redis), 把读db的操作改为先读缓存, 未命中才去读db, 这样可大大减轻数据库读负担.
    • 在该层上还可以使用spring AOP对业务进行事务控制及日志记录.
  • 数据访问层: 该层只做一件事, 对数据库中的表记录进行增删改查, 不进行业务逻辑判断.

mybatis

一个半自动ORM(对象关系映射库)库, 简单灵活, 使用原生sql, 可完成较复杂的查询.

mybatis-generator-maven-plugin

mybatis插件, 可根据数据库中的表生成JavaBean,Dao接口,Dao的xml文件, 本人修改了部分源码, 可在JavaBean中自动添加注释, 详见另一篇博文MyBatis-Generator最佳实践.

spring security

完成用户的认证和授权.

thumbnailator(注: 需翻墙)

一个Java端的图片处理库, 可完成图片压缩, 裁剪, 水印等功能.

实战

如何提高使用者的工作效率?

  • 使用者看见就知道怎么使用
  • 为使用者自动完成部分可推导的表单填写
  • 拥有尽可能全的提示

如何提高开发人员的开发效率?

  • 技术选型时权衡考虑学习曲线与其提供的功能
  • 设计一套通用的可扩展的架构
  • 对常用操作及模块进行封装.

目前, 后端中将数据访问层和业务逻辑层中常用的方法封装成了泛型接口, 并使用抽象类来实现最基础的逻辑, 开发人员如果觉得指定方法无法满足需求, 可重写指定方法或使用新方法. 具体封装如下:


/** * GenericDao : 封装通用dao操作, 服务于GenericService * * @author http://arccode.net * @since 2014-12-03 */ public interface GenericDao<Model, PK> { /** * 插入 * * @param model */ int insertSelective(Model model); /** * 删除 * * @param id */ int deleteByPrimaryKey(PK id); /** * 更新 * * @param model */ int updateByPrimaryKeySelective(Model model); /** * 查询单条记录 * * @param id */ Model selectByPrimaryKey(PK id); /** * 分页查询 * @param page * @param model * @return */ List selectAndPage(Page<Model> page, Model model); }
/**
 * GenericService : 所有自定义Service的顶级接口,封装常用的增删查改操作
 *
 * Model : 代表数据库中的表映射的Java对象类型
 * PK :代表对象的主键类型
 *
 * @author http://arccode.net
 * @since 2014-12-03
 */
public interface GenericService<Model, PK> {

    /**
     * 分页获取集合, 带过滤功能
     * @param page 分页对象
     * @param model 分页条件, eg: model.name = "zhangsan", 对应sql语句为where name like %zhangsan%
     * @return
     */
    List getModels(Page<Model> page, Model model);

    /**
     * 新增
     * @param model
     * @return
     */
    Integer addModel(Model model);

    /**
     * 删除
     * @param id
     * @return
     */
    Integer removeModelById(PK id);

    /**
     * 修改
     * @param model
     * @return
     */
    Integer modifyModelById(Model model);

    /**
     * 根据主键id获取单条记录详情
     * @param id
     * @return
     */
    Model getModelById(PK id);

}

/**
 * GenericServiceSupport : 通用接口的实现类
 *
 * @author http://arccode.net
 * @since 2014-12-03
 */
public abstract class GenericServiceSupport<Model, PK>  implements GenericService<Model, PK>{

    /**
     * 定义成抽象方法,由子类实现,完成dao的注入
     * @return
     */
    public abstract GenericDao<Model, PK> getDao();

    @Override
    public List getModels(Page<Model> page, Model model) {
        return getDao().selectAndPage(page, model);
    }

    @Override
    public Integer addModel(Model model) {
        return getDao().insertSelective(model);
    }

    @Override
    public Integer removeModelById(PK id) {
        return getDao().deleteByPrimaryKey(id);
    }

    @Override
    public Integer modifyModelById(Model model) {
        return getDao().updateByPrimaryKeySelective(model);
    }

    @Override
    public Model getModelById(PK id) {
        return getDao().selectByPrimaryKey(id);
    }
}

熟练使用该模式, 开发一套业务逻辑的增删改查, 那速度是相当快.

针对前段也做了一些组件式的封装, 表格采用backgrid.js完成展示及分页操作, 只需要在html文件指定位置写入两个带id的html元素(一个用于展示表格, 一个用于分页), 之后copy写好的js模板, 在js中修改属性便可快速完成表格异步分页.

接下来将陆续发布实战干货.

本系列文章

  • 前后端完全分离初探
  • 前后端完全分离之API设计
  • 前后端完全分离之安全认证与授权-上
  • 前后端完全分离之安全认证与授权-下
  • 前后端完全分离之前端模块化开发
  • 前后端完全分离之前端路由系统
  • 前后端完全分离之后端面向服务的模块化开发

原文出自 前后端完全分离之API设计, 欢迎转载, 转载请注明出处.

阅读 18.8k

推荐阅读
arccode
用户专栏

积累技术,努力工作,坚持学习,认真生活。

55 人关注
3 篇文章
专栏主页