一Dubbo的简易介绍
1.Dubbo是什么?
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东西,说白了就是个远程服务调用的分布式框架(告别Web Service模式中的WSdl,以服务者与消费者的方式在dubbo上注册)。
其核心部分包含:
1. 远程通讯:
提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
2. 集群容错:
提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
3. 自动发现
基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
2.Dubbo能做什么?
1.透明化的远程方法调用
就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
2.软负载均衡及容错机制
可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
 3. 服务自动注册与发现
不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
Dubbo采用全spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。
3.Dubbo核心组件

1)注册中心(registry)
生产者在此注册并发布内容,消费者在此订阅并接收发布的内容。
2)消费者(consumer)
客户端,从注册中心获取到方法,可以调用生产者中的方法。
3)生产者(provider)
服务端,生产内容,生产前需要依赖容器(先启动容器)。
4)容器(container)
生产者在启动执行的时候,必须依赖容器才能正常启动(默认依赖的是spring容器),
5)监控(Monitor)
统计服务的调用次数与时间等。
二.springboot+dubbo+zookeeper整合使用
1.在Linux中安装zookeeper实现服务注册

进入到镜像中
[root ~]# docker exec -it 46c8d188683b bash
查看zookeeper中的,服务情况
 
 查看已经注册存在的服务

2.服务层中service,使用dubbo中的@Service注解

3.Providor服务提供者

 3.0.application.yml
dubbo:
  provider:
    application: dubbo-provider
  registry:
    address: zookeeper://192.168.58.128:2181
  scan:
    base-packages:
      - com.tjetc.service
  protocol:
    name: dubbo #使用dubbo协议
    port: 20880 #协议端口为20880
server:
  port: 8081
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.58.128:3306/springboot?serverTimezone=GMT%2B8
    username: root
    password: root
mybatis:
  type-aliases-package: com.tjetc.domain
logging:
  level:
    com.tjetc.mapper: debug
3.1.ProvidorApplication
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//开启dubbo服务注册
("com.tjetc.mapper")
public class ProvidorApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProvidorApplication.class, args);
    }
}
3.2.ProductServiceImpl,@Service使用dubbo中的注解
import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tjetc.domain.Product;
import com.tjetc.mapper.ProductMapper;
import com.tjetc.service.ProductService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
public class ProductServiceImpl implements ProductService {
    
    private ProductMapper productMapper;
    
    public void add(Product product) {
        productMapper.add(product);
    }
    
    public PageInfo<Product> list(String name, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<Product> list=productMapper.list(name);
        PageInfo<Product> pageInfo = new PageInfo<>(list);
        System.out.println("pageInfo.getList() = " + pageInfo.getList());
        return pageInfo;
    }
    
    public List<Product> listByName(String name) {
        return productMapper.listByName(name);
    }
    
    public Product findById(Integer id) {
        return productMapper.findById(id);
    }
    
    public void update(Product product) {
        productMapper.update(product);
    }
    
    public int del(Integer id) {
        return productMapper.del(id);
    }
}
4.mapper模块,代码省略

 5.实体类对象模块domain,代码省略

6.Service服务接口,代码省略
 
7.consumer,服务消费者

7.0.ComsumerApplication
 
7.1.ProductController
import com.alibaba.dubbo.config.annotation.Reference;
import com.github.pagehelper.PageInfo;
import com.tjetc.domain.Product;
import com.tjetc.service.ProductService;
import com.tjetc.utils.FastDfsClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
("/product")
public class ProductController {
    ("${fastdfs}")
    private String fastdfs;
    
    private ProductService productService;
    ("/add")
    public String add(){
        return "add";
    }
    ("/add")
    public String add(Product product, MultipartFile photo){
        System.out.println("photo = " + photo);
        System.out.println("product = " + product);
        if (photo!=null && photo.getSize()>0){
            String filename = photo.getOriginalFilename();
            String extName = filename.substring(filename.lastIndexOf(".")+1);
            FastDfsClient fastDfsClient = new FastDfsClient("classpath:client.properties");
            try {
                //7. 显示上传的结果(file_id 也就是文件的路径)
                String path = fastDfsClient.upload(photo.getBytes(), extName);
                System.out.println("path = " + path);
                product.setPhotopath(fastdfs+path);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("product = " + product);
        productService.add(product);
        return "redirect:/product/list";
    }
    ("/list")
    public String list((defaultValue = "") String name,
                       (defaultValue = "1") Integer pageNum,
                       (defaultValue = "3") Integer pageSize, Model model){
        System.out.println(productService);
        PageInfo<Product> pageInfo=productService.list(name,pageNum,pageSize);
        List<Product> list = pageInfo.getList();
        for (Product product : list) {
            System.out.println("product = " + product);
        }
        /*List<Product> list = productService.listByName(name);
        System.out.println("list = " + list);*/
        model.addAttribute("page",pageInfo);
        model.addAttribute("list",list);
        model.addAttribute("name",name);
        return "list";
    }
    ("/findById")
    public String findById(Integer id,Model model){
        Product product=productService.findById(id);
        model.addAttribute("p",product);
        return "update";
    }
    ("/update")
    public String update(Product product,MultipartFile photo){
        if (photo!=null && photo.getSize()>0){
            String fileName=photo.getOriginalFilename();
            String extName=fileName.substring(fileName.lastIndexOf(".")+1);
            FastDfsClient fastDfsClient = new FastDfsClient("classpath:client.properties");
            try {
                String path = fastDfsClient.upload(photo.getBytes(), extName);
                product.setPhotopath(fastdfs+path);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        productService.update(product);
        return "redirect:/product/list";
    }
    ("/del")
    public String del(Integer id){
        int i=productService.del(id);
        return "redirect:/product/list";
    }
}
7.2.FastDfsClient集合文件系统工具类
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
 * FastDFS上传文件的工具类
 */
public class FastDfsClient {
    //声明4个成员变量
    private TrackerClient trackerClient=null;
    private TrackerServer trackerServer=null;
    // 4. 声明存储服务端storage
    private StorageServer storageServer=null;
    private StorageClient1 storageClient=null;
    /*
     * 根据配置文件初始化4个成员变量
     * */
    public FastDfsClient(String config) {
        Properties properties = new Properties();
        if (config.contains("classpath:")) {
            try {
                config=config.replaceAll("classpath:","");
                System.out.println("config = " + config);
                // 使用ClassLoader加载properties配置文件生成对应的输入流
                InputStream in = this.getClass().getClassLoader().getResourceAsStream(config);
                // 使用properties对象加载输入流
                properties.load(in);
                System.out.println("properties = " + properties);
                // 1. 加载配置文件
                ClientGlobal.initByProperties(properties);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (MyException e) {
                e.printStackTrace();
            }
        }else {
            try {
                ClientGlobal.initByProperties(config);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (MyException e) {
                e.printStackTrace();
            }
        }
        // 2. 创建tracker的客户端
        this.trackerClient = new TrackerClient();
        try {
            // 3. 通过客户端得到服务端连接对象
            this.trackerServer = trackerClient.getConnection();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 5. 获取存储服务器的storage客户端对象
        this.storageClient = new StorageClient1(trackerServer, storageServer);
    }
    public FastDfsClient() {
    }
    public String upload(String filename, String extName, NameValuePair[] metas){
        try {
            return storageClient.upload_file1(filename, extName, metas);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
        return null;
    }
    public String upload(String filename,String exName){
        return this.upload(filename, exName,null);
    }
    /**
     * *根据文件的内容上传*
     * @paramcontent文件内容byte[]*
     * @paramextName文件扩展名
     * *@parammetas参数*@return
     */
    public String upload(byte[] content,String extNAme,NameValuePair[] metas){
        try {
            return storageClient.upload_file1(content, extNAme, metas);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
        return null;
    }
    public String upload(byte[] content,String extName){
        return this.upload(content, extName,null);
    }
    public static void main(String[] args) {
        // 外部普通类
        System.out.println("方法名 类名");
        System.out.println("getName " + FastDfsClient.class.getName());
        System.out.println("getCanonicalName " + FastDfsClient.class.getCanonicalName());
        System.out.println("getSimpleName " + FastDfsClient.class.getSimpleName());
        System.out.println();
        //用代码实现:得到类路径的真实路径
        String path = FastDfsClient.class.getClassLoader().getResource("").getPath();
        System.out.println("path = " + path);
    }
}
7.3.client.properties
fastdfs.tracker_servers=192.168.58.128:22122
7.4.application.yml
fastdfs: http://192.168.58.128/
dubbo:
  application:
    name: dubbo-consumer
  registry:
    address: zookeeper://192.168.58.128:2181
  protocol:
    name: dubbo #使用dubbo协议
    port: 20880 #协议端口为20880
server:
  port: 8082
spring:
  servlet:
    multipart:
      # 设置 上传文件的大小
      max-file-size: 20MB
      # 设置 整个请求的大小
      max-request-size: 20MB
7.5.list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        table{
            width: 700px;
            border-collapse: collapse;
            text-align: center;
        }
        th,td{
            border: 1px solid #CCCCCC;
        }
    </style>
    <script type="text/javascript">
        function fenye(pageNum) {
            alert(document.getElementById("pageSize").value)
            location.href="/product/list?pageNum="+pageNum+"&name="+document.getElementById("name").value;
        }
        function findById(id) {
            location.href="/product/findById?id="+id;
        }
        function del(id) {
            location.href="/product/del?id="+id;
        }
    </script>
</head>
<body>
<div>
    <input type="text" id="name" th:value="${name}" placeholder="请输入商品名称">
    <button th:onclick="fenye(1)">查询</button>
</div>
<table>
    <tr>
        <th>编号</th>
        <th>名称</th>
        <th>单价</th>
        <th>时间</th>
        <th>美照</th>
        <th>操作</th>
    </tr>
    <tr th:each="p:${list}">
        <td th:text="${p.id}"></td>
        <td th:text="${p.name}"></td>
        <td th:text="${p.price}"></td>
        <td th:text="${#dates.format(p.time)}"></td>
        <td>
            <img th:src="${p.photopath}" width="100px">
        </td>
        <td>
            <button th:onclick="|findById(${p.id})|">编辑</button>
            <button th:onclick="|del(${p.id})|">删除</button>
        </td>
    </tr>
    <tr>
        <td colspan="10">
            <button th:onclick="|fenye(1)|">首页</button>
            <button th:onclick="|fenye(${page.prePage})|">上一页</button>
            当前页<span th:text="${page.pageNum}"></span>/<span th:text="${page.pages}"></span>
            <button th:onclick="|fenye(${page.nextPage})|">下一页</button>
            <button th:onclick="|fenye(${page.pages})|">尾页</button>
            每页<select id="pageSize" th:onclick="fenye(1)">
                <option value="3">3</option>
                <option value="6">6</option>
                <option value="9">9</option>
            </select>条数据
            总记录数:<span th:text="${page.total}"></span>
        </td>
    </tr>
</table>
</body>
</html>
效果截图

 








![[软件工具]姓氏谐音梗随机生成工具使用教程](https://i0.hdslb.com/bfs/archive/1373a7c71fa54b2707f9b430c59a36d597059301.jpg@100w_100h_1c.png@57w_57h_1c.png)











