SpringBoot操作数据库(5)

8.富文本编辑器

1.简介

思考:我们平时在博客园,或者CSDN等平台进行写作的时候,有同学思考过他们的编辑器是怎么实现的吗?

  • 在博客园后台的选项设置中,可以看到一个文本编辑器的选项:

  • 其实这个就是富文本编辑器,市面上有许多非常成熟的富文本编辑器,比如:

  • Editor.md——功能非常丰富的编辑器,左端编辑,右端预览,非常方便,完全免费

    • 官网:https://pandao.github.io/editor.md/
  • wangEditor——基于javascript和css开发的 Web富文本编辑器, 轻量、简洁、界面美观、易用、开源免费。

    • 官网:http://www.wangeditor.com/
  • TinyMCE——TinyMCE是一个轻量级的基于浏览器的所见即所得编辑器,由JavaScript写成。它对IE6+和Firefox1.5+都有着非常良好的支持。功能齐全,界面美观,就是文档是英文的,对开发人员英文水平有一定要求。

    • 官网:https://www.tiny.cloud/docs/demo/full-featured/
    • 博客园
  • 百度ueditor——UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,功能齐全,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码,缺点是已经没有更新了

    • 官网:https://ueditor.baidu.com/website/onlinedemo.html
  • kindeditor——界面经典。

    • 官网:http://kindeditor.net/demo.php
  • Textbox——Textbox是一款极简但功能强大的在线文本编辑器,支持桌面设备和移动设备。主要功能包含内置的图像处理和存储、文件拖放、拼写检查和自动更正。此外,该工具还实现了屏幕阅读器等辅助技术,并符合WAI-ARIA可访问性标准。

    • 官网:https://textbox.io/
  • CKEditor——国外的,界面美观。

    • 官网:https://ckeditor.com/ckeditor-5/demo/
  • quill——功能强大,还可以编辑公式等

    • 官网:https://quilljs.com/
  • simditor——界面美观,功能较全。

    • 官网:https://simditor.tower.im/
  • summernote——UI好看,精美

    • 官网:https://summernote.org/
  • jodit——功能齐全

    • 官网:https://xdsoft.net/jodit/
  • froala Editor——界面非常好看,功能非常强大,非常好用(非免费)

    • 官网:https://www.froala.com/wysiwyg-editor

总之,目前可用的富文本编辑器有很多…这只是其中的一部分。

2.Editor.md

  • 这里使用的就是Editor.md,作为一个资深码农,Mardown必然是我们程序猿最喜欢的格式,看下面,就爱上了!

  • 可以在官网下载它:https://pandao.github.io/editor.md/ , 得到它的压缩包!

  • 解压以后,在examples目录下面,可以看到他的很多案例使用!学习,其实就是看人家怎么写的,然后进行模仿就好了!

  • 可以将整个解压的文件导入至我们的项目,将一些无用的测试和案例删掉即可!

3.基础工程搭建

数据库设计

article:文章表

字段 备注
id int 文章的唯一ID
author varchar 作者
title varchar 标题
content longtext 文章的内容

建表SQL:

use springboot;
CREATE TABLE `article` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'int文章的唯一ID',
`author` varchar(50) NOT NULL COMMENT '作者',
`title` varchar(100) NOT NULL COMMENT '标题',
`content` longtext NOT NULL COMMENT '文章的内容',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

基础项目搭建

  1. 建一个SpringBoot项目配置。
spring:datasource:username: rootpassword: root# ?serverTimezone=UTC解决时区的报错url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8driver-class-name: com.mysql.cj.jdbc.Driver
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.1</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><filtering>true</filtering></resource>
</resources>
  1. 实体类:
// 文章类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Article implements Serializable {private int id; // 文章的唯一IDprivate String author; // 作者名private String title; // 标题private String content; // 文章的内容}

3、mapper接口:

@Mapper
@Repository
public interface ArticleMapper {// 查询所有的文章List<Article> queryArticles();// 新增一个文章int addArticle(Article article);// 根据文章id查询文章Article getArticleById(int id);// 根据文章id删除文章int deleteArticleById(int id);}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.github.mapper.ArticleMapper"><select id="queryArticles" resultType="Article">select * from article</select><select id="getArticleById" resultType="Article">select * from article where id = #{id}</select><insert id="addArticle" parameterType="Article">insert into article (author,title,content) values (#{author},#{title},#{content});</insert><delete id="deleteArticleById" parameterType="int">delete from article where id = #{id}</delete></mapper>
  • 既然已经提供了 myBatis 的映射配置文件,自然要告诉 spring boot 这些文件的位置
# 指定myBatis的核心配置文件与Mapper映射文件
mybatis.mapper-locations=classpath:com/github/mapper/*.xml
# 注意:对应实体类的路径
mybatis.type-aliases-package=com.github.pojo
  • 编写一个Controller测试下,是否ok;
@RestController
public class ArticleController {// DI注入数据源@AutowiredArticleMapper articleMapper;// 查询全部内容@GetMapping("/queryArticles")public List<Article> queryArticles(){return articleMapper.queryArticles();}}

4.文章编辑整合

  1. 导入 editor.md 资源 ,删除多余文件。

  2. 编辑文章页面 editor.html、需要引入jQuery;

<!DOCTYPE html>
<html class="x-admin-sm" lang="zh" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>哇哈哈'Blog</title><meta name="renderer" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi" /><!--Editor.md--><link rel="stylesheet" th:href="@{/css/editormd.css}"/><link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon" />
</head><body><div class="layui-fluid"><div class="layui-row layui-col-space15"><div class="layui-col-md12"><!--博客表单--><form name="mdEditorForm"><div>标题:<input type="text" name="title"></div><div>作者:<input type="text" name="author"></div><div id="article-content"><textarea name="content" id="content" style="display:none;"> </textarea></div></form></div></div>
</div>
</body><!--editormd-->
<script th:src="@{/lib/jquery.min.js}"></script>
<script th:src="@{/editormd.js}"></script><script type="text/javascript">var testEditor;//window.onload = function(){ }$(function() {testEditor = editormd("article-content", {width : "95%",height : 400,syncScrolling : "single",path : "../lib/",saveHTMLToTextarea : true,    // 保存 HTML 到 Textareaemoji: true,theme: "dark",//工具栏主题previewTheme: "dark",//预览主题editorTheme: "pastel-on-dark",//编辑主题tex : true,                   // 开启科学公式TeX语言支持,默认关闭flowChart : true,             // 开启流程图支持,默认关闭sequenceDiagram : true,       // 开启时序/序列图支持,默认关闭,//图片上传imageUpload : true,imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],imageUploadURL : "/article/file/upload",onload : function() {console.log('onload', this);},/*指定需要显示的功能按钮*/toolbarIcons : function() {return ["undo","redo","|","bold","del","italic","quote","ucwords","uppercase","lowercase","|","h1","h2","h3","h4","h5","h6","|","list-ul","list-ol","hr","|","link","reference-link","image","code","preformatted-text","code-block","table","datetime","emoji","html-entities","pagebreak","|","goto-line","watch","preview","fullscreen","clear","search","|","help","info","releaseIcon", "index"]},/*自定义功能按钮,下面我自定义了2个,一个是发布,一个是返回首页*/toolbarIconTexts : {releaseIcon : "<span bgcolor=\"gray\">发布</span>",index : "<span bgcolor=\"red\">返回首页</span>",},/*给自定义按钮指定回调函数*/toolbarHandlers:{releaseIcon : function(cm, icon, cursor, selection) {//表单提交mdEditorForm.method = "post";mdEditorForm.action = "/article/addArticle";//提交至服务器的路径mdEditorForm.submit();},index : function(){window.location.href = '/';},}});});</script></html>
  1. 编写Controller,进行跳转,以及保存文章
@RestController
@RequestMapping("/article")
public class ArticleController {// DI注入数据源@AutowiredArticleMapper articleMapper;// 查询全部内容@GetMapping("/queryArticles")public List<Article> queryArticles(){return articleMapper.queryArticles();}// 测试@GetMapping("/toEditor")public String toEditor(){return "editor";}// 添加文章@PostMapping("/addArticle")public String addArticle(Article article){articleMapper.addArticle(article);return "editor";}}

图片上传问题

  1. 前端js中添加配置
// 图片上传
imageUpload : true,
imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
imageUploadURL : "/article/file/upload",  // 这个是上传图片时的访问地址
  1. 后端请求,接收保存这个图片, 需要导入 FastJson 的依赖!
// 博客图片上传问题
@RequestMapping("/file/upload")
@ResponseBody
public JSONObject fileUpload(@RequestParam(value = "editormd-image-file", required = true) MultipartFile file, HttpServletRequest request) throws IOException {// 上传路径保存设置// 获得SpringBoot当前项目的路径:System.getProperty("user.dir")String path = System.getProperty("user.dir")+"/upload/";// 按照月份进行分类:Calendar instance = Calendar.getInstance();String month = (instance.get(Calendar.MONTH) + 1)+"月";path = path+month;File realPath = new File(path);if (!realPath.exists()){realPath.mkdir();}// 上传文件地址System.out.println("上传文件保存地址:"+realPath);// 解决文件名字问题:我们使用uuid;String filename = "ks-"+UUID.randomUUID().toString().replaceAll("-", "");// 通过CommonsMultipartFile的方法直接写文件(注意这个时候)file.transferTo(new File(realPath +"/"+ filename));// 给editormd进行回调JSONObject res = new JSONObject();res.put("url","/upload/"+month+"/"+ filename);res.put("success", 1);res.put("message", "upload success!");return res;
}

3、解决文件回显显示的问题,设置虚拟目录映射!在我们自己拓展的MvcConfig中进行配置即可!

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {// 文件保存在真实目录/upload/下,// 访问的时候使用虚路径/upload,比如文件名为1.png,就直接/upload/1.png就ok了。@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/upload/**").addResourceLocations("file:"+System.getProperty("user.dir")+"/upload/");}}

表情包问题

  • 自己手动下载,emoji 表情包,放到图片路径下:

  • 修改editormd.js文件
// Emoji graphics files url path
editormd.emoji     = {path : "../editormd/plugins/emoji-dialog/emoji/",ext   : ".png"
};

5.文章展示

  1. Controller 中增加方法
@GetMapping("/{id}")
public String show(@PathVariable("id") int id,Model model){Article article = articleMapper.getArticleById(id);model.addAttribute("article",article);return "article";
}
  1. 编写页面 article.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><title th:text="${article.title}"></title>
</head>
<body><div><!--文章头部信息:标题,作者,最后更新日期,导航--><h2 style="margin: auto 0" th:text="${article.title}"></h2>作者:<span style="float: left" th:text="${article.author}"></span><!--文章主体内容--><div id="doc-content"><textarea style="display:none;" placeholder="markdown" th:text="${article.content}"></textarea></div></div><link rel="stylesheet" th:href="@{/editormd/css/editormd.preview.css}" />
<script th:src="@{/lib/jquery.min.js}"></script>
<script th:src="@{/lib/marked.min.js}"></script>
<script th:src="@{/lib/prettify.min.js}"></script>
<script th:src="@{/lib/raphael.min.js}"></script>
<script th:src="@{/lib/underscore.min.js}"></script>
<script th:src="@{/lib/sequence-diagram.min.js}"></script>
<script th:src="@{/lib/flowchart.min.js}"></script>
<script th:src="@{/lib/jquery.flowchart.min.js}"></script>
<script th:src="@{/editormd.js}"></script><script type="text/javascript">var testEditor;$(function () {testEditor = editormd.markdownToHTML("doc-content", {//注意:这里是上面DIV的idhtmlDecode: "style,script,iframe",emoji: true,taskList: true,tocm: true,tex: true, // 默认不解析flowChart: true, // 默认不解析sequenceDiagram: true, // 默认不解析codeFold: true});});</script>
</body>
</html>
  • 重启项目,访问进行测试!大功告成!

9.整合Dubbo+Zookeeper

1.分布式理论

什么是分布式系统?

  • 在《分布式系统原理与范型》一书中有如下定义:“分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统”;
  • 分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据

分布式系统(distributed system)是建立在网络之上的软件系统。

  • 首先需要明确的是,只有当单个节点的处理能力无法满足日益增长的计算、存储任务的时候,且硬件的提升(加内存、加磁盘、使用更好的CPU)高昂到得不偿失的时候,应用程序也不能进一步优化的时候,我们才需要考虑分布式系统。
  • 因为,分布式系统要解决的问题本身就是和单机系统一样的,而由于分布式系统多节点、通过网络通信的拓扑结构,会引入很多单机系统没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题。

Dubbo文档

  • DUBBO官网:https://dubbo.apache.org/zh/

  • 随着互联网的飞速发展,Web应用的规模不断扩大,最终我们发现传统的垂直架构(单体)已经无法应对。分布式服务架构和流计算架构势在必行,迫切需要一个治理体系来保证架构的有序演进。

单体架构

  • 当流量很低时,只有一个应用,所有的特性都部署在一起,减少部署节点和成本。此时,数据访问框架(ORM)是简化 CRUD 工作量的关键。

  • 适用于小型网站,小型管理系统,将所有功能都部署到一个功能里,简单易用。
  • 缺点:
    • 1、性能扩展比较难
    • 2、协同开发问题
    • 3、不利于升级维护

垂直架构

  • 当流量变大时,添加单体应用实例并不能很好地加速访问,提高效率的一种方法是将单体应用拆分成离散的应用程序。此时,用于加速前端页面开发的Web框架(MVC)是关键。

  • 通过切分业务来实现各个模块独立部署,降低了维护和部署的难度,团队各司其职更易管理,性能扩展
    也更方便,更有针对性。
  • 缺点: 公用模块无法重复利用,开发性的浪费

分布式服务架构

  • 当垂直应用越来越多时,应用之间的交互是不可避免的,一些核心业务被提取出来,作为独立的服务,逐渐形成一个稳定的服务中心,这样前端应用就可以更好地响应多变的市场需求。迅速地。此时,用于业务重用和集成的分布式服务框架(RPC)是关键。

流计算架构

  • 当服务越来越多时,容量评估变得困难,而且小规模的服务也经常造成资源浪费。为了解决这些问题,需要增加调度中心,根据流量对集群容量进行管理,提高集群的利用率。这时,用来提高机器利用率的资源调度和治理中心(SOA)是关键。

2.什么是RPC?

RPC【Remote Procedure Call】是指远程过程调用,像调用本地方法一样调用远程方法,是一种进程间通信方式,他是一种技术的思想,而不是规范。

它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。

  • 也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。
  • 为什么要用RPC呢?
    • 就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如不同的系统间的通讯,甚至不同的组织间的通讯,由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用。RPC就是要像调用本地的函数一样去调远程函数;
RPC基本原理

  • 服务消费方(client)调用以本地调用方式调用服务;
  • client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
  • client stub找到服务地址,并将消息发送到服务端;
  • server stub收到消息后进行解码;
  • server stub根据解码结果调用本地的服务;
  • 本地服务执行并将结果返回给server stub;
  • server stub将返回结果打包成消息并发送至消费方;
  • client stub接收到消息,并进行解码;
  • 服务消费方得到最终结果。

具体参考:简书;官网说法。

时序步骤解析

RPC两个核心模块:通讯,序列化。

3.什么是dubbo?

Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

  • dubbo官网

    1. 了解Dubbo的特性;
    2. 查看官方文档
Dubbo架构

  • 服务提供者**(Provider)**:暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
  • 服务消费者**(Consumer)**: 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  • 注册中心**(Registry)**:注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  • 监控中心**(Monitor)**:服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
  • 调用关系说明
    • 服务容器负责启动,加载,运行服务提供者。
    • 服务提供者在启动时,向注册中心注册自己提供的服务。
    • 服务消费者在启动时,向注册中心订阅自己所需的服务。
    • 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
    • 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
    • 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

Dubbo的基本要求

  • 在大规模服务出现之前,应用程序可能只是通过 RMI 或 Hessian 暴露或引用远程服务,通过配置服务 URL 进行调用,通过 F5 等硬件完成负载均衡。
  • **当服务越来越多,配置服务URL变得非常困难,F5硬件负载均衡器的单点压力也越来越大。**此时,需要一个服务注册中心来动态注册和发现服务,使服务的位置透明化。通过在消费者端获取服务提供者地址列表,可以实现软负载均衡和Failover,减少对F5硬件负载均衡器的依赖和部分成本。
  • 当事情进一步发展时,服务依赖变得如此复杂,以至于它甚至无法告诉之前启动哪些应用程序,甚至架构师也无法完全描述应用程序架构关系。这时就需要自动绘制应用程序的依赖关系图,帮助架构师理清关系。
  • **然后,流量变得更重,服务的容量问题暴露出来,需要多少台机器来支持这个服务?什么时候应该加机器?**要解决这些问题,首先要将每天的服务调用量和响应时间量作为容量规划的参考。二、动态调整权重,增加一台在线机器的权重,并记录响应时间的变化,直到达到阈值,记录此时的访问次数,然后将此访问次数乘以总机器数计算反过来的能力。

更多参考:网页。

4.Dubbo环境搭建

  • 点进dubbo官方文档,推荐我们使用Zookeeper注册中心!
  • 什么是zookeeper呢?可以查看官方文档!

window下安装zookeeper

  • 深入学习请参考教程:菜鸟教程
  1. 下载zookeeper:地址①,地址②,下载3.7.0!解压zookeeper;

  2. 运行/bin/zkServer.cmd ,初次运行会报错,没有zoo.cfg配置文件;

可能遇到问题:闪退!

  • 解决方案:编辑zkServer.cmd文件末尾添加pause。这样运行出错就不会退出,会提示错误信息,方便找到原因。

报错:错误: 找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain

  • 下载编译后的二进制的包,就好了。地址:https://www.apache.org/dyn/closer.lua/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7.0-bin.tar.gz

  1. 将conf目录下的zoo_sample.cfg文件,复制一份,重命名为zoo.cfg:

  1. 在安装目录下面新建一个空的 data 文件夹和 log 文件夹:

  1. 修改 zoo.cfg 配置文件,将 dataDir=/tmp/zookeeper 修改成 zookeeper 安装目录所在的 data 文件夹,再添加一条添加数据日志的配置(需要根据自己的安装路径修改)。

  1. 修改完成后再次双击 zkServer.cmd 启动程序:


Zookeeper启动失败:Unexpected exception, exiting abnormally java.net.BindException: Address alr

  • 这是2181端口被占用导致的,需要结束占用2181端口的进程。
  • 进去命令提示符之后,输入“netstat -aon | findstr 2181”命令,按回车键,如下图所示:

  • 打开任务管理器,显示进程的pid之后,找到pid为19236的进程,点击结束进程。

  • 结束进程之后,再次运行项目,就正常运行了。

  1. 测试,双击zkCli.cmd 启动客户端。

    • ls /:列出zookeeper根下保存的所有节点。
    • create –e /subei 123:创建一个subei节点,值为123。
    • get /subei:获取/subei节点的值。

5.window下安装dubbo-admin

  • dubbo本身并不是一个服务软件。它其实就是一个jar包,能够帮你的java程序连接到zookeeper,并利用zookeeper消费、提供服务。
  • 但是为了让用户更好的管理监控众多的dubbo服务,官方提供了一个可视化的监控程序dubbo-admin,不过这个监控即使不装也不影响使用。
  1. 下载dubbo-admin
  • 地址:https://github.com/apache/dubbo-admin/tree/master-0.2.0
  1. 解压进入目录
  • 修改 dubbo-admin-master-0.2.0\dubbo-admin\src\main\resources\application.properties 指定zookeeper地址
server.port=7001
spring.velocity.cache=false
spring.velocity.charset=UTF-8
spring.velocity.layout-url=/templates/default.vm
spring.messages.fallback-to-system-locale=false
spring.messages.basename=i18n/message
spring.root.password=root
spring.guest.password=guest
# 注册中心的地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
  1. 在项目目录下打包dubbo-admin
mvn clean package -Dmaven.test.skip=true
  • 过程有点慢,需要耐心等待!直到成功!

  1. 执行dubbo-admin\target下的dubbo-admin-0.0.1-SNAPSHOT.jar
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar

  • 注意:zookeeper的服务一定要打开
  • 执行完毕,去访问一下 http://localhost:7001/,这时候需要输入登录账户和密码,都是默认的root-root;登录成功后,查看界面。

安装完成!


新版实现

  1. 下载代码: git clone https://github.com/apache/dubbo-admin.git

  2. dubbo-admin-server/src/main/resources/application.properties中指定注册中心地址

  3. 构建

    • mvn clean package -Dmaven.test.skip=true

  4. 启动

    • mvn --projects dubbo-admin-server spring-boot:run
      或者
    • cd dubbo-admin-distribution/target; java -jar dubbo-admin-0.1.jar
  5. 访问 http://localhost:8080

不太稳定,启动失败!!!

6.框架搭建

  1. 启动zookeeper!
  • 双击 zkServer.cmd 启动程序!
  1. IDEA创建一个空项目;
  2. 创建一个模块,实现服务提供者:provider-server,选择web依赖即可;

  1. 项目创建完毕,写一个服务,比如卖票的服务;

编写接口:

package com.github.service;public interface TicketService {public String getTicket();
}

编写实现类:

package com.github.service;public class TicketServiceImpl implements TicketService {@Overridepublic String getTicket() {return "《subeiLY》";}
}
  1. 创建一个模块,实现服务消费者:consumer-server,选择web依赖即可

  1. 项目创建完毕,写一个服务,比如用户的服务; 编写service
package com.github.service;public class UserService {// 获取去注册中心的服务
}

7.服务提供者

  1. 将服务提供者注册到注册中心,需要整合Dubbo和zookeeper,所以需要导包。

    • 从dubbo官网进入github,看下方的帮助文档,找到dubbo-springboot,找到依赖包。
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.8</version>
</dependency>
  • zookeeper的包我们去maven仓库下载,zkclient;
<!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->
<dependency><groupId>com.github.sgroschupf</groupId><artifactId>zkclient</artifactId><version>0.1</version>
</dependency>
  • zookeeper及其依赖包,解决日志冲突,还需要剔除日志依赖;
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>5.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>5.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.7.0</version><!--排除这个slf4j-log4j12--><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></exclusion></exclusions>
</dependency>
  1. 在springboot配置文件中配置dubbo相关属性!
# 当前应用名字
dubbo.application.name=provider-server
# 注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
# 扫描指定包下服务
dubbo.scan.base-packages=com.github.service
  1. 在service的实现类中配置服务注解,发布服务!注意导包问题。
package com.github.service;import org.apache.dubbo.config.annotation.Service;
import org.springframework.stereotype.Component;@Service //将服务发布出去
@Component //放在容器中
public class TicketServiceImpl implements TicketService {@Overridepublic String getTicket() {return "《subeiLY》";}
}

逻辑理解:应用启动起来,dubbo就会扫描指定的包下带有@component注解的服务,将它发布在指定的注册中心中!

8.消费者

  1. 导入依赖,和之前的依赖一样;
<!--   导入依赖:Dubbo + Zookeeper   -->
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
<dependency><groupId>org.apache.dubbo</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.7.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->
<dependency><groupId>com.github.sgroschupf</groupId><artifactId>zkclient</artifactId><version>0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>5.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>5.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.7.0</version><!--排除这个slf4j-log4j12--><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></exclusion></exclusions>
</dependency>
  1. 配置参数
# 当前应用名字
dubbo.application.name=consumer-server
# 注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
  1. 本来正常步骤是需要将服务提供者的接口打包,然后用pom文件导入,这里使用简单的方式,直接将服务的接口拿过来,路径必须保证正确,即和服务提供者相同;

  1. 完善消费者的服务类
package com.github.provider.seriver;import com.github.consumer.seriver.TicketService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;@Service // 注入到容器中
public class UserService {@Reference // 远程引用指定的服务,他会按照全类名进行匹配,看谁给注册中心注册了这个全类名TicketService ticketService;public void bugTicket(){String ticket = ticketService.getTicket();System.out.println("在注册中心买到:"+ticket);}
}
  1. 测试类
import com.github.provider.seriver.UserService;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest
public class ConsumerServerApplicationTests {@AutowiredUserService userService;@Testpublic void contextLoads() {userService.bugTicket();}
}
  1. 启动测试
  • 开启zookeeper
  • 打开dubbo-admin实现监控【可以不用做】
  • 开启服务者

  • 消费者消费测试

SpingBoot + dubbo + zookeeper实现分布式开发的应用,其实就是一个服务拆分的思想!!!

狂神说笔记——SpringBoot操作数据库22-5相关推荐

  1. SpringBoot操作数据库

    SpringBoot操作数据库 1.SpringData简介 对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),Spring Boot 底层都是采用 Spring D ...

  2. MySQL(狂神说笔记)

    MySQL(狂神说笔记) 1.初始数据库 1.1为什么学习数据库? 1.岗位需求 2.现在的世界,大数据时代,得数据库者得天下. 3.被迫需求: 存数据 4.数据库是所有软件体系中最核心的存在: DB ...

  3. Java系列技术之JDBC操作数据库-钟洪发-专题视频课程

    Java系列技术之JDBC操作数据库-22人已学习 课程介绍         JDBC连接数据库是Java系列技术中数据库知识的核心技术,是学习后续课程JavaWeb入门前需要掌握的基础! 这门课的前 ...

  4. boot spring test 文档_SpringBoot入门建站全系列(五)使用Spring-data-jpa操作数据库

    SpringBoot入门建站全系列(五)使用Spring-data-jpa操作数据库 SpringBoot操作数据库有多种方式,如 JDBC直接操作:太古老了,没人愿意这样玩 Mybatis插件:比较 ...

  5. MySQL学习笔记04【数据库的查询操作、今日内容、表的约束】

    MySQL 文档-黑马程序员(腾讯微云):https://share.weiyun.com/RaCdIwas 1-MySQL基础.pdf.2-MySQL约束与设计.pdf.3-MySQL多表查询与事务 ...

  6. SpringBoot 学习二:操作数据库

    2019独角兽企业重金招聘Python工程师标准>>> 本文将从以下几个方面介绍: 前言 配置数据源 SpringBoot 整合 Mybatis SpringBoot 整合 Jdbc ...

  7. MySQL学习笔记03【数据库表的CRUD操作、数据库表中记录的基本操作、客户端图形化界面工具SQLyog】

    MySQL 文档-黑马程序员(腾讯微云):https://share.weiyun.com/RaCdIwas 1-MySQL基础.pdf.2-MySQL约束与设计.pdf.3-MySQL多表查询与事务 ...

  8. Python学习笔记:使用Python操作数据库

    Python学习笔记:使用Python操作数据库 一.数据库编程接口 为了对数据库进行统一的操作,大多数语言都提供了简单的.标准化的数据库接口(API).在Python Database API 2. ...

  9. SpringBoot的数据库操作

    SpringBoot的数据库操作 1.添加依赖,一个是我们数据库也要用到的data-jpa(简化程序与数据库之间的交互),一个数据库驱动.(文件名:pom.xml),基本的配置在建好项目的时候就有了, ...

最新文章

  1. java使用POI获取sheet、行数、列数
  2. Python获取环境变量值
  3. java工程窗口程序_java工程开发之图形化界面之(第二课)
  4. SSH框架之-hibernate 三种状态的转换
  5. 在控制器控制方式中,异步控制与联合控制有什么区别?
  6. 推荐的开源 PHP CMS 系统
  7. 金融级IT架构-数字银行的云原生架构解析
  8. RHEL 6和RHEL 7管理服务的区别
  9. AtCoder - ABC 160 - DE(贪心)
  10. STM32 与 ST-Link V2仿真器 接线与烧录
  11. Linux(六)NFS(network file system)服务器实验
  12. 记录一次利用pn532进行学校水卡改余额过程
  13. 钉钉视频下载方法地瓜网络钉钉视频下载器
  14. 小米10至尊纪念版和华为mate40的区别 哪个好
  15. Android | 打印堆栈
  16. commons-io工具包的基本使用
  17. 有了Service Mesh,还需要API网关么?
  18. 【转】超星转PDF最佳方法(对打印机重新审视)
  19. 嵌入式软件测试项目管理
  20. 羊皮卷之八:今天我要加倍重视自己的价值

热门文章

  1. 4、欧姆定律和焦耳定律
  2. java中的僵死进程_Java中线程间怎么通讯?什么叫僵死线程?
  3. 打码平台破解验证码+session登陆豆瓣
  4. 某石油化工数字化交付项目
  5. 西班牙专线物流有哪些运输方式 西班牙专线物流有哪些优点和缺点
  6. 25_PyTorch的十九个损失函数(L1Loss、MSELoss、CrossEntropyLoss 、CTCLoss、NLLLoss、PoissonNLLLoss 、KLDivLoss等)
  7. 公司企业如何建立一个网站?
  8. 【《STL源码剖析》提炼总结】 第1节:空间配置器 allocator
  9. 网络地址ABCDE划分记忆,靠谱的回答
  10. python定义二维数组_二维数组的定义、初始化和输出,C语言二维数组详解