github项目学习

Posted by Liber Sun on June 18, 2019

清点我看过的所有的给了我进步的Github项目,Tks for all of you!👊👊👊👊。 集百家之所长,融百家之所思,扬孙菱志之所名💩💩💩💩。

developer-roadmap

The purpose of these roadmaps is to give you an idea about the landscape and to guide you if you are confused about what to learn next and not to encourage you to pick what is hip and trendy. You should grow some understanding of why one tool would better suited for some cases than the other and remember hip and trendy never means best suited for the job

成为程序员的第一步,选好自己的Road,通常分为前端和后端,而后端可以引申出DevOps,包括开发、测试和运维。 在任意的道路上我们都需要了解的东西包括:

  • Git-version control
  • Basic Terminal Usage(windows and Lunix)
  • Data Structures & Algorithms
  • Rules
    • SOLID
      • SRP(The Single Responsibility Principle,单一责任原则)
      • OCP(The Open Closed Priciple,开放封闭原则)
      • LSP(The Liskov Substitution Principle,里氏替换原则)
      • DIP(The Dependency Inversion Principle,依赖倒置原则)
      • ISP(The Interface Segregation Principle,接口分离原则)
    • DRY(Don’t repeat yourself)
    • KISS(keep it simple and stupid)
    • YAGNI(you ai’nt gonna need it)
  • GitHub
  • Licenses
  • Semantic Versioning(语义版本号)
  • SSH
  • HTTP/HTTPS
  • Design Patterns
  • Character Encodings
  • Further more

Back-end Roadmap

选择了Back-end,当然不是说就对Front-end DevOps便是置若罔闻。因为你不可避免得会用到它们。

选择一门语言

编程世界中有太多语言选择了,无论是脚本语言(python,Ruby,PHP,Node.js,R),还是函数式语言(Scala,Elixir,Haskell),或者是常见的java,流行的Golang。 我们需要记住没有Best的,只有最适合自己的。

我在这里选择JAVA语言,虽然他有很多的缺点,但是不可否认其茁壮的生态圈,你总是能在其中找到你需要的解决方案。

学习如何管理你的项目

1.版本管理

git与github就不用过多介绍了。

2.依赖管理

PHP有composer,Nodejs有npm和yarn,Python有pip,.Net有nuget,Ruby有gems 等。 而对于java 我们可以使用Maven,Gradle

语言规范特性

不同的语言有着其特点和独特的编码标准。通过练习去熟悉它们。

这里强烈建议了解你选择的代码在应对OWASP时,所能采取的措施。

OWASP(Open Web Application Security Project)涉及到的安全问题包括:

1.注入,指应用程序缺少对输入的安全检查,攻击者可以将一些包含指令的数据传输给服务器。 2.失效的身份认证与会话管理,导致了攻击者可以破坏密码,密钥,会话令牌或实施漏洞冒充其他用户身份 3.跨站脚本攻击(Cross-site Scripting,XSS是为了与CSS混淆),在目标网站注入恶意脚本,使之在用户的浏览器中运行,从而获取用户的敏感信息,比如Cookie、SessionID。 举例:A网站用iframe嵌套了用户的目标网站B,然后就可以获取用户的敏感信息。 4.不安全对象的直接引用,意指一个已经授权的用户通过更改访问时的一个参数,从而访问到原本其并没有得到授权的对象 5.伪造跨站请求(Cross-site request forgery,CSRF),利用了网站允许攻击者预测特定操作所有细节这一特点。由于浏览器自动发送会话cookie等认证凭证,导致攻击者可以创建恶意的web页面来产生伪造请求。这些伪造的请求很难和合法的请求区分开。 举例:用户在目标网站A登陆成功,攻击者在B页面中挟制用户在当前已登录的A应用程序上执行非本意的操作的攻击方法。 6.安全误配置,可以发生在一个应用程序堆栈的任何层面,包括平台,web服务器,应用服务器,数据库,架构和自定义的代码。攻击者通过访问默认账户,未使用的网页,未安装的补丁的漏洞,未被保护的文件和目录等,以获得对系统为授权的访问 7.限制URL访问失败(缺少功能级别的访问控制),攻击者很容易就能把网址改成享有特权的网页,这样就可以使用匿名或普通用户访问未授保护的私人页面,从而提升未授权功能和相关数据信息。 8.未验证的重定向和转发 9.应用已知脆弱性的组件 10.敏感信息暴露

开发你个人的Lirary

积极参与Github中的开源项目

学会测试代码

write Unit and Integration tests

关系数据库

选择一个关系数据库,mysql是一个不错的选择

Pratical Time

将你学习的到知识应用到一个项目中,它应该拥有注册、登陆和CURD这些功能,创建blog是一个挺好的选择。

构建项目的时候,注意写 测试、遵循Standards、数据库存储,索引、合理的query。

Learn a Framework

SpringBoot SpringClouds当仁不让! 尽快熟悉框架的特性,然后将你的项目应用框架实现。

非关系数据库

了解非关系数据库与关系数据库的区别,以及它的存在意义。

推荐MongoDB,在学习的同时,注意和关系数据库的比较,注意和别的非关系数据库的比较。

缓存

在你的项目中,引入缓存的。

Redis

RESTful APIs

理解REST理念(Roy Fielding),为你的项目提供RESTful 的API

权限认证模块

Oauth,Basic Authentication,Token Authentication,JWT,OpenID,选择其中一个实现它们。

Message Brokers

认识到Message Brokers的作用。

RabbitMQ

Search Engine

随着项目逐渐发展,简单的数据库查询已经无法应付了。你可以尝试着使用搜索引擎来解决这样的问题。

ElasticSearch、Solr

Docker

Docker容器

Web Serves

Web服务器的差异, 这里推荐 Apache Nginx

WebSocket and Socket

GraphQL(Optional)

Graph Dataabases(Optional)

Others

  • Profiling
  • Static Analysis
  • DDD
  • SOAP

Order Backend

@PostConstruct注解

Servelt中影响Servlet声明周期的注解,@PostConstruct修饰于非静态的void方法,在构造函数之后执行。 注意 构造函数 > @Autowired > @PostConstruct。

RabbitMQ

消息队列中间件,

测试

测试不应该是笼统的测试,应该具有测试策略

测试类型 代码目录 测试内容
单元测试 src/unitTest 包含核心领域模型(包含领域对象和Factory类)的测试
组件测试 src/componentTest 用于测试一些核心的组件级对象,比如Repository、Service
API测试 src/apiTest 模拟客户端调用API

多环境,多配置文件

根据项目的不同的工作周期,我们要为项目配置不同的配置文件,

application.yml       //默认配置,配置通用设置,然后在其中指定`spring.profiles.active=**`
application-ci.yml
application-dev.yml   //开发环境
application-local.yml  //本地开发环境
application-prod.yml  //生产环境
application-qa.yml   // 测试环境,一般是生产环境的克隆
application-uat.yml //User Acceptance Test,终端用户进行测试

注意配置之间会进行覆盖,不是说spring.profiles.active=dev

iCloudDisk

简单的云盘系统涉及到了文件的搜索上传、下载、共享、删除等简单操作。

学习的知识点主要包括以下:

MutipartResolver.setResolveLazily

resolveLazily属性启用是可以推迟文件解析。 其默认设置为false,所有我们在controller层可以直接获取文件,但是如果我们想在controller层获取request中的文件流,就必须将其设置为true,以避免默认解析,并清空文件流中的信息。

MD5实现

服务器需要在后台维护一个 线程安全的容器,存储服务器目前已经有了的文件。

public class MD5Mapper {
    public static  final ConcurrentHashMap<String, FileItem> MAP = new ConcurrentHashMap<>();//String对应MD5值
}
public class FileItem{
    private String fileName;
    private String filePath;
    private String md5;
}

大致包含两个请求 对于传递过来的文件,首先我们要通过查询map中是否存在对应的MD5key值(MD5值可以有spark-md.js在前端生成),来确定是否可以进行MD5快速传输。(传输md5值,不传输文件) 根据是否可以进行md5分为两种处理

  • 支持md5,完成文件信息完成存储,将服务器已存在的文件拷贝以及即可。(只传输md5值)
  • 不支持md5,完成文件信息的存储,将传输过来的文件存储在服务器,并在集合容器中添加新的md5记录(传递文件和md5值)

断点续传

即前端需要指定下载的起点和终点,后端根据起始点,利用RandomAccessFile(file,"r").seek(from),然后读取到to位置,然后返回给前端。

nodeGdal

gdal的node.js的实现,能让在node.js的环境下对地理空间数据VectorRaster进行操作。

var gdal = require("gdal");

var dataset_tif = gdal.open("sample.tif");
var bands=dataset.bands;

var dataset_shp = gdal.open("sample.shp");
var layer = dataset.layers.get(0);

photomosaic

python真的是个好东西啊,你总是在里面能找到奇奇怪怪的东西。

根据你提供的一张指定图片以及你的图片集,可以以马赛克的形式,将图集中最匹配的照片拼到指定图片的某个像素中。

指定图片

不晓得我女朋友会不会👊👊👊我,还不是怪他给我的照片不够多。😆😆😆😆 ps:女人p图真可怕

马塞克图片

coordtransform

该库提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换的工具模块。

当前互联网坐标系的现状

  • 地球坐标 (WGS84)
    • 国际标准,从 GPS 设备中取出的数据的坐标系
    • 国际地图提供商使用的坐标系
    • 使用单位:google国外地图、osm地图、BingMap
  • 火星坐标 (GCJ-02)也叫国测局坐标系
    • 中国标准,从国行移动设备中定位获取的坐标数据使用这个坐标系
    • 国家规定: 国内出版的各种地图系统(包括电子形式),必须至少采用GCJ-02对地理位置进行首次加密。
    • 使用单位:高德地图,google的国内地图,搜搜、腾讯、阿里云等
  • 百度坐标 BD-09,(本来就乱了,百度又在火星坐标上来个二次加密)
    • 百度标准,百度 SDK,百度地图,Geocoding 使用
    • 使用单位:百度地图

使用意义

手里的WGS84的坐标,放置到国内的地图上面时,存在位置的偏移。

halo

Halo 是一款现代化的个人独立博客系统,给习惯写博客的同学一个更好的选择。

除了其后端系统以外,它的周边系统包括:

结构化数据库

以前的项目一直都是使用的MongoDB,这次尝试着使用mysql数据库。

Entity层

我们可以设置BaseEntity,然后利用 JPA 为我们提供的注解@PrePersist,@PreUpdate,@PreRemove在持久化到数据库时做一些额外的操作,比如createTime、updateTime、visitCount等,这本质上是一种AOP操作。

另外Mongodb是不支持@PrePersist,@PreUpdate,@PreRemove,在自己的项目中通过接口+泛型+反射,对实体持久化到数据库进行了实现@BeforeInsert、@BeforeUpdate

同时在JPS的理论中,提供了关于继承的相关处理策略,包括:

  • 单表继承策略,父类和子类公用一张数据表,在表中利用每个字段表明即可。在父类中指明字段,@DiscriminatorColumn(name=”辨别字段列名”),在子类中指明value,@DiscriminatorValue(子类实体辨别字段列值)
  • Joined策略:父类和子类存储在不同的表中,子类只存储其扩展的特殊属性,父类的公共数据保存在父类实体表中。

DTO的处理策略

由于前端页面传输的DTO对象始终与数据库中存储的Entity对象存在着差异,这其中的转换可以通过BeanUtil.copyProperties来实现,但是在以往我的代码中都是在service层中代码进行处理,其实这种转换能力应该是每个DTO对象及拥有的能力,因此参考该项目,为每个DTO创建一个转换器。

public class LinkDTO implements OutputConverter<LinkDTO, Link>InputConverter<LinkDTO>{
  //....
}
public interface OutputConverter<DTO extends OutputConverter<DTO, DOMAIN>, DOMAIN> {
    default <T extends DTO> T convertFromDomain(@NonNull DOMAIN domain) {
        BeanUtils.copyProperties(domain, this);
        return (T) this;
    }
}
public interface InputConverter<DOMAIN> {
    default DOMAIN convertToDomain() {
        // Get parameterized type
        ParameterizedType currentType = parameterizedType();
        // Assert not equal
        Objects.requireNonNull(currentType, "Cannot fetch actual type because parameterized type is null");
        Class<DOMAIN> domainClass = (Class<DOMAIN>) currentType.getActualTypeArguments()[0];
        return CopyUtils.transformFrom(this,domainClass);
    }
    default ParameterizedType parameterizedType() {
        return ReflectionUtils.getParameterizedType(InputConverter.class, this.getClass());
    }
}

//使用
LinkDTO dto=new LinkDTO().convertFromDomain() //由domain创建DTO
Link link=new LinkDTO().convertToDomain()

SpringBoot 的ApplicationEvent&Listner完成业务的解耦

ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是为了发布事件而已。

我们首先要创建一个事件,其继承于ApplicationEvent,继承之后必须重载构造函数,构造函数的参数可以任意指定,其中source是指发生事件的对象,一般我们用this关键字来代替本类对象。而后面的参数是我们自定义的对象,该对象可在监听里面被获取。

@Getter
public class UserRegisterEvent extends ApplicationEvent
{
    //注册用户对象
    private UserBean user;

    /**
     * 重写构造函数
     * @param source 发生事件的对象
     * @param user 注册用户对象
     */
    public UserRegisterEvent(Object source,UserBean user) {
        super(source);
        this.user = user;
    }
}

在Spring中要实现监听有多种方法:

  • @Component + @EventListener注解
  • implements ApplicationListener
  • implements SmartApplicationListener

我们在Service层利用ApplicaitonContext进行事件的发布。

@Service
public class UserService
{
    @Autowired
    ApplicationContext applicationContext;

    /**
     * 用户注册方法
     * @param user
     */
    public void register(UserBean user)
    {
        //发布UserRegisterEvent事件
        applicationContext.publishEvent(new UserRegisterEvent(this,user));
    }
}

@EventListener

@Component
public class RegisterListener {

    /**
     * 注册监听实现方法
     * @param userRegisterEvent 用户注册事件
     */
    @EventListener
    public void register(UserRegisterEvent userRegisterEvent)
    {
        //获取注册用户对象
        UserBean user = userRegisterEvent.getUser();

        //逻辑操作
    }
}

我们只需要在方法上添加@EventListener注解即可。

ApplicationListener

@Component
public class RegisterListener implements ApplicationListener<UserRegisterEvent>
{
    @Override
    public void onApplicationEvent(UserRegisterEvent userRegisterEvent) {
        //获取注册用户对象
        UserBean user = userRegisterEvent.getUser();
        //逻辑操作
    }
}

如果一个事件存在多个监听,这也是被允许的,但是多个监听的执行顺序是完全随机的。

SmartApplicationListener

@Component
public class RegisterListener implements SmartApplicationListener
{
    /**
     *  该方法返回true&supportsSourceType同样返回true时,才会调用该监听内的onApplicationEvent方法
     * @param aClass 接收到的监听事件类型
     * @return
     */
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
        //只有UserRegisterEvent监听类型才会执行下面逻辑
        return aClass == UserRegisterEvent.class;
    }

    /**
     *  该方法返回true&supportsEventType同样返回true时,才会调用该监听内的onApplicationEvent方法
     * @param aClass
     * @return
     */
    @Override
    public boolean supportsSourceType(Class<?> aClass) {
        //只有在UserService内发布的UserRegisterEvent事件时才会执行下面逻辑
        return aClass == UserService.class;
    }

    /**
     *  supportsEventType & supportsSourceType 两个方法返回true时调用该方法执行业务逻辑
     * @param applicationEvent 具体监听实例,这里是UserRegisterEvent
     */
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {

        //转换事件类型
        UserRegisterEvent userRegisterEvent = (UserRegisterEvent) applicationEvent;
        //获取注册用户对象信息
        UserBean user = userRegisterEvent.getUser();
        //.../完成注册业务逻辑
        System.out.println("注册信息,用户名:"+user.getName()+",密码:"+user.getPassword());
    }

    /**
     * 同步情况下监听执行的顺序 ,数值越小,越先执行
       异步情况下,不存在顺序
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

可以指定触发的supportsSourceType,以及执行顺序。

@Async

在方法上使用@Async注解,可以实现异步任务。

获取接口的泛型类型

public interface MyInterface<T,V>{
    default Class[] getClassOfGenericType(){
            ParameterizedType currentType = ReflectionUtils.getParameterizedType(ToDomainConverter.class, this.getClass());
            return currentType.getActualTypeArguments();
    }

    default Class getClassOfGenericType(T,V){
          return new Class[]{T.getClass(),V.getClass()};
    }
}

在获取到泛型的类型后,我们可以通过反射获取其方法,注解,feilds去做一些操作。

hutool

中国版的Google guava,为用户提供了开箱即用的一系列Java工具包。 Hutool的目标是使用一个工具方法代替一段复杂代码,从而最大限度的避免“复制粘贴”代码的问题,彻底改变我们写代码的方式。

涉及到的领域有:

  • hutool-aop JDK动态代理封装,提供非IOC下的切面支持
  • hutool-bloomFilter 布隆过滤,提供一些Hash算法的布隆过滤
  • hutool-cache 简单缓存实现
  • hutool-core 核心,包括Bean操作、日期、各种Util等
  • hutool-cron 定时任务模块,提供类Crontab表达式的定时任务
  • hutool-crypto 加密解密模块,提供对称、非对称和摘要算法封装
  • hutool-db JDBC封装后的数据操作,基于ActiveRecord思想
  • hutool-dfa 基于DFA模型的多关键字查找
  • hutool-extra 扩展模块,对第三方封装(模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等)
  • hutool-http 基于HttpUrlConnection的Http客户端封装
  • hutool-log 自动识别日志实现的日志门面
  • hutool-script 脚本执行封装,例如Javascript
  • hutool-setting 功能更强大的Setting配置文件和Properties封装
  • hutool-system 系统参数调用封装(JVM信息等)
  • hutool-json JSON实现
  • hutool-captcha 图片验证码实现
  • hutool-poi 针对POI中Excel的封装
  • hutool-socket 基于Java的NIO和AIO的Socket封装

当然我们在使用的时候,按需使用,因地制宜也是很重要的。

Nativefier

利用Electron,快速将网页打包成桌面程序,支持windows、苹果操作系统。 真的是好用哦,Web端、Desktop端一次全部Okay。

litemall

AnnotationUtils

AnnotationUtils 是Spring提供的开源工具类,可以方便的对Annotation进行一些操作:

  • getAnnotation: 从某个类获取某个annotation
  • findAnnotation: 从类或方法中查找某个annotation。
  • isAnnotationDeclaredLocally: 验证annotation是否直接注释在类上而不是集成来的。
  • isAnnotationInherited: 验证annotation是否继承于另一个class。
  • getAnnotationAttributes: 获取annotation的所有属性。
  • getValue: 获取指定annotation的值.
  • getDefaultValue: 获取指定annotation或annotation 属性的默认值

Shiro实现安全控制

后面再花时间去详细的看吧!!!

缓存

该项目在内存中,对部分不是经常修改的东西,进行了缓存。如首页的信息,分类的信息。

public class HomeCacheManager {
    public static final String INDEX = "index";
    public static final String CATALOG = "catalog";

    private static ConcurrentHashMap<String, Map<String, Object>> cacheDataList = new ConcurrentHashMap<>();
    //cache的存储、删除、查询
    //。。。
}

该项目没有太多的代码层次可以借鉴的东西,但是其中使用到了一些技术,如果系统需要的话可以进行参考。

vue-element-admin

基于Vue和element-ui实现的后台管理的前端解决方案。 内置了i18n、动态路由、权限验证、提炼了典型的业务模型,提供了丰富的功能组件,能够帮助 快速搭建企业级后台产品原型。 涉及到的功能有:

- 登录 / 注销

- 权限验证
  - 页面权限
  - 指令权限
  - 权限配置
  - 二步登录

- 多环境发布
  - dev sit stage prod

- 全局功能
  - 国际化多语言
  - 多种动态换肤
  - 动态侧边栏(支持多级路由嵌套)
  - 动态面包屑
  - 快捷导航(标签页)
  - Svg Sprite 图标
  - 本地/后端 mock 数据
  - Screenfull全屏
  - 自适应收缩侧边栏

- 编辑器
  - 富文本
  - Markdown
  - JSON 等多格式

- Excel
  - 导出excel
  - 导入excel
  - 前端可视化excel
  - 导出zip

- 表格
  - 动态表格
  - 拖拽表格
  - 内联编辑

- 错误页面
  - 401
  - 404

- 組件
  - 头像上传
  - 返回顶部
  - 拖拽Dialog
  - 拖拽Select
  - 拖拽看板
  - 列表拖拽
  - SplitPane
  - Dropzone
  - Sticky
  - CountTo

- 综合实例
- 错误日志
- Dashboard
- 引导页
- ECharts 图表
- Clipboard(剪贴复制)
- Markdown2html

多模块,多个SpringBootApplication

多个模块,多个SpringBootApplication之间如何引用

scanBasePackages

在njnu.opengms.reproduce.core模块中通过scanBasePackages可以引入njnu.opengms.reproduce.db模块中的内容

@SpringBootApplication(scanBasePackages = {"njnu.opengms.reproduce.db", "njnu.opengms.reproduce.core"})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

application.yml

在上述中已经引入了db模块,因此可以使用其对应模块的配置文件。

spring.profiles.active=core,db

MyBatis Generator

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

在myBatis中里可以使用XML或者注解来实现 POJO和数据库表的映射,但是XML或者注解以及POJO、Mapper类的编码过程是繁琐的。 因此我们可以利用MyBatis Generator,根据数据库中的表,自动生成对应的Mapper类文件+mapper.xml(注解)和POJO类。,注意这里的使用情景是 我们已经存在着数据库的表 当然细致的SQL查询,MaBatis Generator就可能不好用了,还是需要自己精心打磨。

ps:😆,Spring Data JPA 真好用!其实还是我不会写SQL的错,HO~HO~

第三方服务

微信、短信、邮箱的消息通知

local、阿里云、腾讯云、七牛等的存储

对于文件的上传可以采取本地和远端两种方式,针对本地上传我们需要考虑的是是:文件存储在本地的什么位置?

SpringBoot 对静态资源提供了默认的配置,涉及:

classpath:/static
classpath:/public
classpath:/resources
classpath:/META-INF/resources

针对这些文件夹下的文件,我们都可以直接通过http://localhost/1.jpg访问。 但是针对用户上传的文件,我们也不能将其上传到其默认的静态存储位置中的, 因为这样会使文件和代码进行一种集强的耦合。

我们在配置文件中添加自定义外部地址

web.upload-path=E:/reproduceStorage
spring.resources.static-locations = classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path}

快鸟的物流查询

二维码

支付功能

Symphony

哇哦,茫然得我不知道从何入手。

Sym功能点

coderiver

Spring全家桶 构建分布式、高并发的, 前后端分离的 JavaWeb项目。

SpringBoot + SpringClouds + Spring data JPA

项目设计

服务网关 微服务代理、路由配置、请求过滤、灰度 服务治理 服务注册,发现,注销,状态监控,负载均衡 统一配置 加载、更新、配置存储,版本管理、加密与解密 服务监控 日志聚合、链路监控、指标度量 服务容错 降级、熔断、超时、回退、限流 服务通信 Rest、MQ、Message Bus 、Event 服务安全 单点登陆、授权、鉴权、网络安全、sql注入、ddos 服务部署 Pipeline、docker、ks、devops tools

技术栈

公共技术栈

JavaEE RESTFul SpringBoot Docker Swagger2.0

API GateWay

Zuul 实现服务网关

安全中心

JWT 分布式校验的基础,避免了分布式情况下session的共享。 Spring OAuth BCrypt密码加密

注册中心

Eureka(zookeeper)

治理中心

Spring Cloud Ribbon 实现负载均衡 Eureka Spring Cloud Hystrix 熔断器 Feign

配置中心

SpringCloudConfig 集中配置 SpringCloudBus 消息总线

监控中心

提供隐藏的经济效应:用户行为、推荐

InfluxDB 时序数据库,记录每一条数据和其时间戳。适合存放log Grafana 实时monitor工具 cAdvisor Rancher 容器部署管理

消息中心

RabbitMQ

数据层

在微服务中都没有Dao层,只有一个数据持久层。 在每个微服务中是没有具体的Dao层的。

Spring Data JPA ,不用SQL很舒服。 SpringCloud Bus SpringCloud Task SpringCloud Stream MongoDB 集群 Redis 集群 Mycat DB分片 Mysql 读写分离

部署集成

Dockerfile 编写构建私人仓库 Gogs Jenkins 持续集成

额外

ElasticSearch 提高搜索效率 Logstash Nginx

代码学习

公共的代码,将其抽象为Common提供,在pom中引入依赖。

 <dependencies>
    <dependency>
        <artifactId>common</artifactId>
        <groupId>njnu.opengms</groupId>
        <version>${njnu.opengms.version}</version>
    </dependency>
 </dependencies>