项目起步阶段

  • 一、需求分析
    • 1.1 项目介绍
    • 1.2 项目功能架构图
  • 二、系统设计
    • 2.1 开发模式
    • 2.2 技术
    • 2.3 微服务模块划分
    • 2.4 数据库表结构分析
  • 三、RESTful风格
    • 3.1 接口规范
    • 3.2 请求返回响应码
  • 四、项目开发准备
    • 4.1 开发环境
    • 4.2 MySQL建库建表
      • 4.2.1 在CentOS 7安装docker 1.12.6 后
      • 4.2.2 Navicat连接Centos系统中Docker数据库
      • 4.2.3 设计文章数据库
    • 4.3 接口测试工具
  • 五、项目工程搭建
    • 5.1 父工程搭建
      • 5.1.1 创建Maven项目并导入依赖
    • 5.2 搭建公共子模块
      • 5.2.1 搭建子模块步骤
      • 5.2.2 创建公共实体类和工具类
        • 分布式ID生成器
  • 总结

学习目标:
【了解】十次方项目需求
【了解】前后端分离开发模式
【掌握】理解RESTful
【掌握】项目开发环境搭建
【掌握】父工程、公共模块的搭建


一、需求分析

1.1 项目介绍

1024项目主要是一个针对于程序员的一个社交平台,包括头条、问答、活动、交友、吐槽、招聘六大频道。类似于CSND博客网站。

1.2 项目功能架构图


二、系统设计

2.1 开发模式

①前后端分离的开发模式
②基于springcloud的微服务架构
③开发模型:敏捷开发
核心思想:以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。

2.2 技术

后端:Spring Boot + Spring Cloud + MyBatis Plus + MySQL
前端:Node.js + NUXT + elementUI + Vue

2.3 微服务模块划分


微服务划分:按功能模块划分

2.4 数据库表结构分析


分库分表设计:
1、随着单库中的数据量越来越大,相应的,查询所需要的时间也越来越多,这个时候,相当于数据的处理遇到了瓶颈
2、单库发生意外的时候,需要修复的是所有的数据,而多库中的一个库发生意外的时候,只需要修复一个库


三、RESTful风格

RESTful:表现层状态转化

3.1 接口规范

  • 项目使用HTTP方法:GET、POST、PUT、DELETE
    幂等性:不论你请求多少次,资源的状态是一样的。
    安全性:请求不会对资源造成改变。
  • 3.2 GET:获取表示
  • 3.3 POST:创建子资源
  • 3.4 PUT:通过替换方式更新资源
  • 3.5 DELETE:删除资源

3.2 请求返回响应码


四、项目开发准备

4.1 开发环境

  • 系统 CentOS 7
  • 容器 docker
  • Java版本 JDK 1.8
  • 数据库 MySQL 5.7
  • 开发工具 IDEA
  • 项目构建工具 Maven

4.2 MySQL建库建表

4.2.1 在CentOS 7安装docker 1.12.6 后

(1) 下载镜像

docker pull centos/mysql-57-centos7

(2) 创建容器

//name 容器名字;
//-p 3306:3306 宿主机3306端口映射到容器3306端口
//-e 指定参数 mysql的root用户密码为root
//镜像名字centos/mysql-57-centos7docker run -id --name=tensquare_mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root centos/mysql-57-centos7

(3) docker 常用命令

//版本号查询命令
docker -v
//docker运行状态查询命令
systemctl status docker
//重看镜像
docker images
//查看当前正在使用的容器
docker ps

4.2.2 Navicat连接Centos系统中Docker数据库

4.2.3 设计文章数据库

4.3 接口测试工具

Postman是一款强大的网页调试工具

  • 能够发送任何类型的HTTP请求(GET/HEAD/POST/PUT…)
  • 附带任意数量的参数

五、项目工程搭建

5.1 父工程搭建

继承
继承
article依赖common
common
parent
article

5.1.1 创建Maven项目并导入依赖

(1) IDEA新建Maven父工程tensquare_parent
(2) 不勾选Create from archetype
(3) 修改pom.xml文件,添加以下内容

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.4.RELEASE</version><relativePath/></parent>
​<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><mybatisplus-spring-boot-starter.version>1.0.5</mybatisplus-spring-boot-starter.version><mybatisplus.version>2.2.0</mybatisplus.version><fastjson.version>1.2.39</fastjson.version><gson.version>2.8.0</gson.version></properties>
​<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><repositories><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><snapshots><enabled>true</enabled></snapshots></repository><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository></repositories>
​<pluginRepositories><pluginRepository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><snapshots><enabled>true</enabled></snapshots></pluginRepository><pluginRepository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></pluginRepository></pluginRepositories>

5.2 搭建公共子模块

5.2.1 搭建子模块步骤

(1) 右键点击父工程tensquare_parent,选择 New -> Module 弹出窗口选择Maven ,点击next按钮
(2) ArtifacetId填写tensquare_common,点击next按钮,完成
(3)同时在子模块src/main/java/entity文件夹中创建三个类:

PageResult.java

package entity;import java.util.List;/*** @author AntonTony* @version 1.0* @GitHub https://github.com/AntonTony*///分页结果集
public class PageResult<T> {private Long total;private List<T> rows;   //泛型//public PageResult() {}public PageResult(Long total, List<T> rows) {this.total = total;this.rows = rows;}public Long getTotal() {return total;}public void setTotal(Long total) {this.total = total;}public List<T> getRows() {return rows;}public void setRows(List<T> rows) {this.rows = rows;}@Overridepublic String toString() {return "PageResult{" +"total=" + total +", rows=" + rows +'}';}
}

Result.java

package entity;//通用结果集
public class Result {private Boolean flag;private Integer code;private String message;private Object data;//三个构造方法public Result() {}public Result(Boolean flag, Integer code, String message) {this.flag = flag;this.code = code;this.message = message;}public Result(Boolean flag, Integer code, String message, Object data) {this.flag = flag;this.code = code;this.message = message;this.data = data;}//getter、setter方法public Boolean getFlag() {return flag;}public void setFlag(Boolean flag) {this.flag = flag;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}//toString@Overridepublic String toString() {return "Result{" +"flag=" + flag +", code=" + code +", message='" + message + '\'' +", data=" + data +'}';}
}

StatusCode.java

package entity;/*** @author AntonTony* @version 1.0* @GitHub https://github.com/AntonTony*/
//状态码维护类
public class StatusCode {public static final int OK=20000;//成功public static final int ERROR =20001;//失败public static final int LOGINERROR =20002;//用户名或密码错误public static final int ACCESSERROR =20003;//权限不足public static final int REMOTEERROR =20004;//远程调用失败public static final int REPERROR =20005;//重复操作
}

5.2.2 创建公共实体类和工具类

分布式ID生成器

原因:不能使用数据库本身的自增功能来产生主键值,原因是生产环境为分片部署的。需要使用snowflaka(雪花)算法生成唯一的主键值
原理:因为二进制里第一个 bit 为如果是 1,那么都是负数,但是我们生成的 id 都是正数,所以第一个 bit 统一都是 0;41 bit表示的是时间戳,单位是毫秒;通过工作机器ID区别服务器;序列号是某个机房某台机器上这一毫秒内同时生成的 id 的序号;
- 41bit的时间戳可以支持该算法使用到2082年

  • 10bit的工作机器id可以支持1024台机器
  • 序列号支持1毫秒产生4096个自增序列id
  • 整体上按照时间自增排序
  • 整个分布式系统内不会产生ID碰撞

IdWorker.java

package util;import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;/*** <p>名称:IdWorker.java</p>* <p>描述:分布式自增长ID生成器</p>** <pre>*     Twitter的 Snowflake JAVA实现方案* </pre>* 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用:* 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000* 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,* 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),* 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。* 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),* 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。* <p>* 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))** @author Polim*/
public class IdWorker {// 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)private final static long twepoch = 1288834974657L;// 机器标识位数private final static long workerIdBits = 5L;// 数据中心标识位数private final static long datacenterIdBits = 5L;// 机器ID最大值private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);// 数据中心ID最大值private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);// 毫秒内自增位private final static long sequenceBits = 12L;// 机器ID偏左移12位private final static long workerIdShift = sequenceBits;// 数据中心ID左移17位private final static long datacenterIdShift = sequenceBits + workerIdBits;// 时间毫秒左移22位private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;private final static long sequenceMask = -1L ^ (-1L << sequenceBits);/* 上次生产id时间戳 */private static long lastTimestamp = -1L;// 0,并发控制private long sequence = 0L;private final long workerId;// 数据标识id部分private final long datacenterId;public IdWorker(){this.datacenterId = getDatacenterId(maxDatacenterId);this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);}/*** @param workerId*            工作机器ID* @param datacenterId*            序列号*/public IdWorker(long workerId, long datacenterId) {if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}/*** 获取下一个ID** @return*/public synchronized long nextId() {long timestamp = timeGen();if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}if (lastTimestamp == timestamp) {// 当前毫秒内,则+1sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {// 当前毫秒内计数满了,则等待下一秒timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0L;}lastTimestamp = timestamp;// ID偏移组合生成最终的ID,并返回IDlong nextId = ((timestamp - twepoch) << timestampLeftShift)| (datacenterId << datacenterIdShift)| (workerId << workerIdShift) | sequence;return nextId;}private long tilNextMillis(final long lastTimestamp) {long timestamp = this.timeGen();while (timestamp <= lastTimestamp) {timestamp = this.timeGen();}return timestamp;}private long timeGen() {return System.currentTimeMillis();}/*** <p>* 获取 maxWorkerId* </p>*/protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {StringBuffer mpid = new StringBuffer();mpid.append(datacenterId);String name = ManagementFactory.getRuntimeMXBean().getName();if (!name.isEmpty()) {/** GET jvmPid*/mpid.append(name.split("@")[0]);}/** MAC + PID 的 hashcode 获取16个低位*/return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);}/*** <p>* 数据标识id部分* </p>*/protected static long getDatacenterId(long maxDatacenterId) {long id = 0L;try {InetAddress ip = InetAddress.getLocalHost();NetworkInterface network = NetworkInterface.getByInetAddress(ip);if (network == null) {id = 1L;} else {byte[] mac = network.getHardwareAddress();id = ((0x000000FF & (long) mac[mac.length - 1])| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;id = id % (maxDatacenterId + 1);}} catch (Exception e) {System.out.println(" getDatacenterId: " + e.getMessage());}return id;}}

总结

通过这篇博文你已具备以下知识:

  • 了解十次方项目需求;
  • 了解前后端分离开发模式
  • 理解RESTful
  • 完成项目开发环境搭建
  • 完成父工程、公共模块的搭建
  • 了解分布式ID生成器的使用

十次方项目开发系列【1】:项目介绍和工程搭建相关推荐

  1. 十次方项目开发系列【8】:对评论点赞功能开发 Redis的配置和使用

    使用对评论点赞和取消点赞功能开发 一 评论点赞功能开发 1.1 先根据评论的id查询,再对点赞数加一 1.1.1 在CommentController添加方法 1.1.2 在CommentServic ...

  2. 十次方项目开发系列【10】:接口加密Eureka微服务和网关服务开发

    学习目标 了解接口加密业务需求 掌握常用加密算法和密钥格式 实现十次方的接口加密微服务 文章目录 一 业务场景介绍 二 加密方式 2.1 摘要算法 2.2 对称加密 2.3 非对称加密 2.4 数字签 ...

  3. 视频教程-C语言项目开发系列视频课程-C/C++

    C语言项目开发系列视频课程 从事编程数年,曾留学日本深造,擅长C++.后端.尤其是逆向 执教多年,顺应互联网的发展,从线下转为线上 用激情点燃代码,帮助大家实现编程梦想 杨波 ¥500.00 立即订阅 ...

  4. vs2019中如何创建qt项目_在VS2015中创建Qt项目【VS+Qt项目开发系列】(二)

    在VS2015中创建Qt项目[VS+Qt项目开发系列](二) 发布时间:2018-04-20 22:44, 浏览次数:1269 , 标签: VS Qt 在上一篇[VS+Qt项目开发](一)在VS201 ...

  5. 头条项目---01项目介绍和工程搭建

    第一章 项目介绍和工程搭建 学习目标 熟悉移动端应用系统的架构设计 熟悉大型软件系统设计中的各种图形结构 熟悉数据库分库分表设计技巧 熟悉Spring boot2.0+JavaConfig项目封装配置 ...

  6. Java在线教育项目 第一天项目介绍和工程搭建

    第一章 项目介绍和工程搭建 学习目标 熟悉移动端应用系统的架构设计 熟悉大型软件系统设计中的各种图形结构 熟悉数据库分库分表设计技巧 熟悉Spring boot2.0+JavaConfig项目封装配置 ...

  7. 火云开发课堂 - 《Shader从入门到精通》系列 第一节:Shader介绍与工程搭建

    <Shader从入门到精通>系列在线课程 第一节:Shader介绍与工程搭建 视频地址:http://edu.csdn.net/course/detail/1441/22665?auto_ ...

  8. 蓝牙芯片nRF51822开发系列(一):环境搭建和GPIO使用(点亮LED)

    蓝牙芯片nRF51822开发系列(一):环境搭建和GPIO使用(点亮LED) 前言(文章末尾获取工程源码) 一.开发必备 二.开发环境搭建 1.创建文件 2.新建工程 三.编写代码 GPIO详解 使用 ...

  9. 安卓系统的日历开发(项目报告1)【项目开发需求及功能介绍】

    一.项目概述 1.1编写目的 本文档的编写主要为了介绍本项目的开发目的,项目需求,以及开发的情况,将本系统的结构进行大概的介绍,以便用户更熟悉的了解本软件,让用户在使用该软件前,对本软件的使用有一定的 ...

  10. java学习笔记(二十八)——开发一个小项目(VMeeting3.0)

    上篇文章按照较规范的产品需求文档梳理了项目的逻辑,感觉开发起来明晰了很多:挂上一篇文章java学习笔记(二十七)--开发一个小项目(VMeeting2.0)_Biangbangbing的博客-CSDN ...

最新文章

  1. esxi vsphere的端口_vSphere Client 6.0 更改 ESXESXi 主机的端口
  2. c语言easy,C语言easy….doc
  3. 连你的免疫系统都拒绝996:半夜吃东西更容易拉肚子 | Cell
  4. kafka--storm--mongodb
  5. 【赠书】金融领域可解释机器学习模型与实践
  6. hive表指定分区字段搜索_Spark SQL解析查询parquet格式Hive表获取分区字段和查询条件...
  7. OpenSSL 之 RSA 相关命令学习笔记
  8. 计算机领域中,增量是什么意思?
  9. RTX3090深度学习环境配置(PyTorch1.8)
  10. python copy 文件,图片等..
  11. eShopOnContainers 看微服务 ①:总体概览
  12. 探测与响应是各企业机构在2017年的首要安全事务
  13. bool类型数组转换成一个整数_Go 学习笔记 02 | 基本数据类型以及 byte 和 rune 类型...
  14. java局部变量简述
  15. 【Git】Git处理新Repository无法push的问题
  16. Go Web编程--深入学习解析HTTP请求
  17. 网络拓扑发现原理研究
  18. ubuntu服务器长时间不连接显示器后,连上显示器没反应
  19. 从 Microsoft SQL Server 迁移到 Oracle
  20. Mycat分库分表的简单实践 / 用Mycat,学会数据库读写分离、分表分库

热门文章

  1. php ddos 防御,PHP DDos的几个防御方法
  2. 计算机如何制作U盘启动盘,如何制作u盘启动盘三种方式教你
  3. 即刻app暂停服务?趁现在教你一步一步实现即刻点赞效果
  4. # 二极管的种类(1)-稳压二极管的参数与应用
  5. 博弈论(取石子专题)
  6. selnium 判断页面加载完成_Selenium_等待页面加载完毕
  7. talib python文档_TALib中文文档代码实现
  8. 第七章 与Web集成——《跟我学Shiro》[张开涛]
  9. PDF中批量数据的提取与处理
  10. 惠普HP LaserJet 1160 驱动