Dubbo

什么是Dubbo

Dubbo是阿里巴巴公司开源的一个高性能、轻量级的 Java RPC 框架

致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。

Dubbo主要特性

  • 面向接口代理的高性能RPC调用:提供高性能的基于代理的远程调用能力,服务以接口为粒度,屏蔽了远程调用底层细节。
  • 智能负载均衡:内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。
  • 服务自动注册与发现:支持多种注册中心服务,服务实例上下线实时感知。
  • 高度可扩展能力:遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现。
  • 运行期流量调度:内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。
  • 可视化的服务治理与运维:提供丰富服务治理、运维工具:随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。

image-20240815035808856

Spring Cloud 团队

Spring Cloud Alibaba

HTTP 短连接 重新建立TCP连接

RPC Dubbo Spring Cloud

Dubbo的基本使用

先来个例子体验一下:这个例子中没有使用注册中心

创建两个maven工程一个当server一个当client,利用quickstart模板,然后在server端起一个api模块去专门的存放接口,然后再创建另一个模块存放服务端应该有的服务

那么这时候在api里面编写接口,在server里面写具体的业务实现类实现api里面的接口,那么在同个工程不同模块里面如何在server端导入api的接口呢?利用pom里面的依赖可以导入api依赖从而实现。

image-20240815184427043

api里面定义接口

1
2
3
public interface IloginService {
String login(String username, String password);
}

然后在服务端写实现类,并且在服务端写好配置类,配置dubbo以及定义对外的服务名以及服务对应的实现类

image-20240815185629543

服务端的实现类

1
2
3
4
5
6
7
8
9
10
11
public class IloginServiceImpl implements IloginService{

@Override
public String login(String username, String password) {
//实现业务逻辑
if(username.equals("admin") && password.equals("admin")){
return "success";
}
return "failed";
}
}

server的配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<dubbo:application name="dubbo-server"/>
<!--配置注册中心-->
<dubbo:registry address="N/A" />
<dubbo:protocol name="dubbo" port="20880"/>
<!--定义服务-->
<dubbo:service interface="com.bitzh.dubbo.server.IloginService" ref="loginService" />
<!--找到实现-->
<bean id="loginService" class="com.bitzh.dubbo.server.IloginServiceImpl"/>

</beans>

然后再server的启动类启动dobbo的服务,启动服务端记住duboo的url以供客户端访问

1
2
3
4
5
6
7
8
public class App 
{
public static void main( String[] args )
{

Main.main(args);
}
}

这个是server的pom依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bitzh.server</groupId>
<artifactId>dubbo-server-demo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>dubbo-server</artifactId>
<packaging>jar</packaging>

<name>dubbo-server</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.8</version>
</dependency>
<dependency>
<groupId>com.bitzh.server</groupId>
<artifactId>dubbo-server-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

现在问题是不同工程如何进行通信呢?他是跨进程的

那么很显然第一件事情要在client端引入整个server端的依赖,把server工程打包然后再client中导入api依赖

执行install将项目的构建结果安装到本地 Maven 仓库中,以供其他项目使用

image-20240815190003381

然后在client端里面导入模块的api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.bitzh.dubbo.client</groupId>
<artifactId>dubbo-client-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>dubbo-client-demo</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.8</version>
</dependency>
<dependency>
<groupId>com.bitzh.server</groupId>
<artifactId>dubbo-server-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

然后再客户端中实现逻辑

然后我们要将两个工程进行通信利用Dubbo,那么两个客户端和服务端都要引入Dubbo的依赖(注意不是两个工程)

然后client端写dubbo配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<dubbo:application name="dubbo-client"/>
<dubbo:registry address="N/A" />
<dubbo:reference id="loginService"
interface="com.bitzh.dubbo.server.IloginService"
url="dubbo://192.168.10.1:20880/com.bitzh.dubbo.server.IloginService"/>


</beans>

client启动类

1
2
3
4
5
6
7
8
9
10
11
public class App 
{
public static void main( String[] args )
{
IloginService iloginService = null;
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:/META-INF/spring/application.xml");
iloginService = ac.getBean(IloginService.class);

System.out.println( iloginService.login("admin", "admin") );
}
}

Dubbo支持的注册中心

consul

zookeeper

Eureka

Redis

etcd

nacos

nacos做注册中心

从github上拉取nacos的源码方式获取nacos1.1.4版本的压缩包和源码,解压之后打开,然后打开nacos的confgi下面有nacos-mysql.sql然后在数据库中执行脚本就会生成表,

在application.properties中配置

image-20240817091233064

然后在bin里面的startup.cmd里面配置MODE为standalone

image-20240817051116257

配置完成之后,回到nacos然后再bin目录下启动nacos

image-20240817051150268

或者在nacos-server里面启动要先配置vm

image-20240817092103024

然后访问控制台http://localhost:8848/nacos/#/login

账号密码都是nacos

image-20240817051210377

然后回到之前的server项目里面配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<dubbo:application name="dubbo-server"/>
<!--配置注册中心-->
<dubbo:registry address="nacos://localhost:8848" />
<dubbo:protocol name="dubbo" port="20880"/>
<!--定义服务-->
<dubbo:service interface="com.bitzh.dubbo.server.IloginService" ref="loginService" />
<!--找到实现-->
<bean id="loginService" class="com.bitzh.dubbo.server.IloginServiceImpl"/>

</beans>

然后添加依赖,添加一下日志的依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.1.4</version>
</dependency>

然后服务端启动!

image-20240817051301110

然后看控制台发现注册成功

image-20240817050457444

然后我们如果想更改别的注册中心更改一下配置和端口就可以了

拔插式的服务

1
<dubbo:registry address="nacos://localhost:8848" />

配置一下客户端,导入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

<dubbo:application name="dubbo-client"/>
<dubbo:registry address="nacos://localhost:8848" timeout="100000" />
<dubbo:reference id="loginService"
interface="com.bitzh.dubbo.server.IloginService"
url="dubbo://192.168.10.1:20880/com.bitzh.dubbo.server.IloginService"/>


</beans>

然后启动客户端就完成了注册

Dubbo Spring Cloud

功能组件 Spring Cloud Dubbo Spring Cloud
分布式配置(Distributed configuration) Git、Zookeeper、Consul、JDBC Spring Cloud 分布式配置 + Dubbo 配置中心
服务注册与发现(Service registration and discovery) Eureka、Zookeeper、Consul Spring Cloud 原生注册中心 + Dubbo 原生注册中心
负载均衡(Load balancing) Ribbon(随机、轮询等算法) Dubbo 内建实现(随机、轮询等算法 + 权重等特性)
服务熔断(Circuit Breakers) Spring Cloud Hystrix Spring Cloud Hystrix + Alibaba Sentinel 等
服务调用(Service-to-service calls) Open Feign、RestTemplate Spring Cloud 服务调用 + Dubbo @Reference
链路跟踪(Tracing) Spring Cloud Sleuth + Zipkin Zipkin、opentracing 等

以上对比表格摘自Dubbo Spring Cloud官方文档。

本质上 都是为业务而生

Dubbo多注册中心

多注册中心 | Apache Dubbo

Dubbo多协议

多协议 | Apache Dubbo

Dubbo 源码

怎么学?先看整体架构

了解 Dubbo 核心概念和架构 | Apache Dubbo

image-20240817090956204

nacos就完成了服务注册的功能

image-20240817091636138

那么如何实现注册功能呢?

首先逻辑应该是服务提供者会将ip端口号还有serversname 放到服务中心提供给消费者

那么消费者想要拿到数据必须要有对应访问的路径来调用

此时问题来了,假设需要使用注册中心的操作,如何注册到注册呢?

可以用curl的方式以post请求来进行注册,在linux环境下来执行curl(用git也可以)

image-20240817093052920

从这个路径(官方文档中的案例)看出在源码nacos中肯定有个/v1/ns/instance的入口

image-20240817093410952

然后继续看下去

image-20240817093902059

image-20240817093908237

image-20240817093940066

这样就找到了目标的接口了,此时我们用的是post请求,用到的是post方法,但是在里面没有找到instance的方法而是一个controller,原因是post只是个表单的提交,表单的提交有可能只要找到目标源就ok,不一定要用路径拼接

image-20240817094707873

然后在里面找到了真正的服务,打个断点

也就是说这个服务必然进入register方法,

但是每次访问这个都要写这么长的路径来进入register方法很麻烦,所以就nacos就把路径封装起来

image-20240817095135215

也就是说如果我们只用传入serviceName 和URL给register就可以实现注册。

然后再源码里面已经有了很多工具来实现了,写了很多参数来封装。

那么我们新建了service然后这个service就必然要调用service.registerInstance那么我们如何实现自动注册呢?

类似于springboot的自动注册一样呢?

在配置文件中,拥有nacos服务端的地址的

image-20240817095737273

我们就加了依赖和配置就完成了自动注册

springboot里面的有一个观察者模式,具体实现代码springboot里面已经实现了,写个demo来展现观察者模式

image-20240817105744481

image-20240817105805977

image-20240817165605550

刚才我们的流程

image-20240817171520321

SpringCloud去实现,在nacos我们不能增加规范,那我们就定义规范,所以去定义接口

Admin管理界面搭建

​ 资料中把dubbo-admin-0.2.0.jar\BOOT-INF\classes 中application.properties里面注册中心的ip设置正确

​ 使用java -jar dubbo-admin-0.2.0.jar运行即可。

​ 注意:占用8080端口,不要冲突了。

负载均衡

​ 集群:一个内容,部署多次,形成的整体称为集群。集群中每个个体应该部署到不同的服务器上。

​ 伪集群:集群中内容部署到同一台服务器上,通过不同端口区分不同个体。

​ 负载均衡是在集群前提下,当访问整个集群时,集群中每个节点被访问次数或频率的规则。

​ Dubbo 内置了四个负载均衡策略。默认为Random

1.内置策略

1.1Random

​ 随机。随机访问集群中节点。访问概率和权重有关。

1.2RoundRobin

​ 轮询。访问频率和权重有关。

​ 权重(weight):占有比例。集群中每个项目部署的服务器的性能可能是不同,性能好的服务器权重应该高一些。

1.3LeastActive

​ 活跃数相同的随机,不同的活跃数高的放前面。

1.4ConsistentHash

​ 一致性Hash。相同参数请求总是发到一个提供者。

2.Provider集群

​ 新建四个启动类。

​ 每次启动启动类修改配置文件dubbo.protocal.port

3.设置负载均衡

3.1@Reference

​ 调用的服务采用的负载均衡

1
2
@Reference(loadbalance = "roundrobin")
private DemoDubboService demoDubboService;
3.2 @Service

​ 当前服务采用的负载均衡算法

1
2
@Service(loadbalance = "random")
public class DemoDubboServiceImpl implements DemoDubboService {

​ 设置权重

1
@Service(weight = 4)
3.3配置文件

​ 全局设置所有provider和consumer的负载均衡效果。

1
2
3
4
5
6
7
8
9
10
11
dubbo:
application:
name: dubbo-provider
registry:
address: zookeeper://192.168.32.128:2181
protocol:
port: 20884
provider:
loadbalance: random
consumer:
loadbalance: random

完整Dubbo项目演示

1.原型

1.1部门显示

​ 显示全部部门信息

1.2员工新增

1.3查看部门员工

2.按照分布式架构进行设计项目

​ 设定员工管理和部门管理不在同一个模块中,需要有一个员工管理项目和一个部门管理项目。

​ 为了方便,不去每个项目使用一个窗口,而是使用聚合项目。

3.创建数据库表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
create table dept(
id int(11) primary key auto_increment,
name varchar(20)
);

insert into dept values(default,'开发部');
insert into dept values(default,'产品部');

create table emp(
id int(11) primary key auto_increment,
name varchar(20),
photo varchar(200),
did int(11),
CONSTRAINT fk_emp_dept FOREIGN key (did) REFERENCES dept(id)
);

4.创建父项目

​ 创建项目parent。

编写pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.10.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.1.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</dependencyManagement>

5.创建pojo项目

6.创建mapper项目

6.1编写pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependencies>
<dependency>
<artifactId>pojo</artifactId>
<groupId>com.msb</groupId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
6.2新建配置文件

​ 新建application-mybatis.yml

1
2
3
4
5
6
7
8
9
10
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/maven
username: root
password: root

mybatis:
mapper-locations: classpath:mybatis/*.xml
type-aliases-package: com.msb.pojo

7.新建api项目

7.1编写pom.xml
1
2
3
4
5
6
7
<dependencies>
<dependency>
<artifactId>pojo</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>

8.新建provider

8.1编写pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<dependencies>
<dependency>
<artifactId>mapper</artifactId>
<groupId>com.msb</groupId>
<version>1.0.0</version>
</dependency>
<dependency>
<artifactId>api</artifactId>
<groupId>com.msb</groupId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
</dependencies>
8.2新建配置文件

​ 新建application.yml

1
2
3
4
5
6
7
8
9
10
dubbo:
application:
name: dubbo-provider
registry:
address: zookeeper://192.168.52.128:2181

# 加载其他配置文件,加载其他application-*.yml文件,多个名称之间使用逗号分隔
spring:
profiles:
active: mybatis
8.3新建启动类

​ 新建com.msb.ProviderApplication

1
2
3
4
5
6
7
8
@SpringBootApplication
@EnableDubbo
@MapperScan("com.msb.mapper")
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}

9.完成Dept查询功能

9.1在api中新建接口

​ com.msb.dubbo.service.DeptDubboService

1
2
3
public interface DeptDubboService {
List<Dept> selectAll();
}
9.2在provider中新建实现类

​ com.msb.dubbo.service.impl.DeptDubboServiceImpl

1
2
3
4
5
6
7
8
9
@Service
public class DeptDubboServiceImpl implements DeptDubboService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> selectAll() {
return deptMapper.selectByExample(null);
}
}
9.3新建项目dept
9.3.1添加依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<dependencies>
<dependency>
<artifactId>api</artifactId>
<groupId>com.msb</groupId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
</dependencies>
9.3.2编写配置文件

​ 新建application.yml

1
2
3
4
5
dubbo:
application:
name: dubbo-dept-consumer
registry:
address: zookeeper://192.168.52.128:2181
9.3.3新建启动类

​ com.msb.DeptApplication

1
2
3
4
5
6
7
@SpringBootApplication
@EnableDubbo
public class DeptApplication {
public static void main(String[] args) {
SpringApplication.run(DeptApplication.class,args);
}
}
9.3.4新建接口及实现类

​ 接口:com.msb.service.DeptService

​ 实现类:com.msb.service.impl.DeptServiceImpl

1
2
3
public interface DeptService {
List<Dept> showAll();
}
1
2
3
4
5
6
7
8
9
@Service
public class DeptServiceImpl implements DeptService {
@Reference
private DeptDubboService deptDubboService;
@Override
public List<Dept> showAll() {
return deptDubboService.selectAll();
}
}
9.3.5新建控制器

​ com.msb.controller.DeptController

1
2
3
4
5
6
7
8
9
10
11
12
@Controller
public class DeptController {

@Autowired
private DeptService deptService;

@GetMapping("/dept")
public String shwoDept(Model model){
model.addAttribute("list",deptService.showAll());
return "dept";
}
}
9.3.6 新建页面

​ 在resources /templates新建dept.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1" width="500">
<tr>
<th>编号</th>
<th>部门名称</th>
<th>查看</th>
</tr>
<tr th:each="dept : ${list}">
<td th:text="${dept.id}"></td>
<td th:text="${dept.name}"></td>
<td> <a th:href="@{/showEmp(did=${dept.id})}">查看</a> </td>
</tr>
</table>
</body>
</html>