目录
一、Dubbo 概述
Apache Dubbo |ˈdʌbəʊ | 提供了六大核心能力:面向接口代理的高性能RPC调用,智能容错和负载均衡,服务自动注册和发现,高度可扩展能力,运行期流量调度,可视化的服务治理与运维。
Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案、服务治理方案。
官网 :https://dubbo.apache.org/zh/
特性 :
面向接口代理:
调用接口的方法,在 A 服务器调用 B 服务器的方法,由 dubbo 实现对 B 的调用,无需关心实现的细节,就像 MyBatis 访问 Dao 的接口,可以操作数据库一样。不用关心 Dao 接口方法的实现。
二、基本架构
服务提供者(Provider) :暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者(Consumer) : 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
注册中心 (Registry) :注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
监控中心 (Monitor) :服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
调用关系说明:
● 服务容器负责启动,加载,运行服务提供者。
● 服务提供者在启动时,向注册中心注册自己提供的服务。
● 服务消费者在启动时,向注册中心订阅自己所需的服务。
● 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
● 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
● 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
三、Dubbo 支持的协议
支持多种协议:
dubbo 、hessian 、 rmi 、 http 、webservice 、thrift 、 memcached 、 redis等
dubbo 官方推荐使用 dubbo 协议,dubbo 协议默认端口 20880。
使用 dubbo 协议,需要在 spring 配置文件加入:
<dubbo:protocol name="dubbo" port="20880" />
四、第一个 Dubbo 项目
某电商平台系统需求:
- 用户浏览商品
- 选择商品下订单,订单系统需要获取用户信息中的送货地址
- 向支付系统请求完成付款
服务 | 功能 |
---|---|
网站系统 | 展示商品 |
订单系统 | 生成订单,获取用户地址 |
用户系统 | 用户信息 (地址,收件,联系方式等) |
直连方式
点对点的直连项目 :
- 消费者直接访问服务提供者,没有注册中心
- 消费者必须指定服务提供者的访问地址(url)
- 消费者直接通过 url 地址访问固定的服务提供者,这个 url 地址是不变的
实现目标:
实现方式 :
以 JavaSE 为例,服务提供者,服务消费者都是 JavaSE 项目。
1) 创建服务提供者 :订单服务
A、新建 java project
项目名称 : order-provider
设置 version 为 1.0.0
B、 maven pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
C、创建订单实体类 : Order
package com.fancy.pojo;
import java.io.Serializable;
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
// 订单id
private String id;
// 商品名称
private String goodName;
// 商品单价
private float price;
// 购买数量
private Integer amount;
public Order() {
}
public Order(String id, String goodName, float price, Integer amount) {
this.id = id;
this.goodName = goodName;
this.price = price;
this.amount = amount;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getGoodName() {
return goodName;
}
public void setGoodName(String goodName) {
this.goodName = goodName;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
}
D、新建订单服务接口 : OrderService
package com.fancy.service;
import com.fancy.pojo.Order;
public interface OrderService {
public Order create(Integer userId, String goodName, float price, Integer amount);
}
E、新建接口的实现类 OrderServiceImpl
package com.fancy.service;
import com.fancy.pojo.Order;
import java.util.UUID;
public class OrderServiceImpl implements OrderService{
@Override
public Order create(Integer userId, String goodName, float price, Integer amount) {
Order order = new Order();
String orderId = UUID.randomUUID().toString().replaceAll("-", "");
order.setId(orderId);
order.setGoodName(goodName);
order.setPrice(price);
order.setAmount(amount);
return order;
}
}
F、创建 Dubbo 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 服务的名称, 使用唯一值, 服务名称是Dubbo内部使用标识服务的 -->
<dubbo:application name="order-provider"></dubbo:application>
<!-- 访问服务的协议名称, 端口 -->
<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
<!--
interface : 接口的全限定名称
ref : 接口的实现bean的id
registry : 直连方式, 不使用注册中心。 N/A: 不使用注册中心
-->
<dubbo:service interface="com.fancy.service.OrderService" ref="orderService" registry="N/A"></dubbo:service>
<!-- 声明订单实现bean -->
<bean id="orderService" class="com.fancy.service.OrderServiceImpl"></bean>
</beans>
G、测试配置文件
package com.fancy.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
public class OrderApplication {
public static void main(String[] args) throws IOException {
String configLocation = "order-provider.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
((ClassPathXmlApplicationContext)ctx).start();
// 阻塞操作
System.in.read();
}
}
H、安装本地 jar 到 maven 仓库
服务接口中的方法要给消费者使用,消费者项目需要知道接口名称和接口中的方法名称、参数等。这些信息服务提供者才知道。需要把接口的 class 文件打包为 jar 。服务接口项目的类文件打包为 jar, 安装到 maven 仓库,仓库中的提供者 jar 可以被消费者使用。
使用 idea 的 maven 窗口执行 install 即可,可以将当前项目打包并部署到本地仓库
2) 创建服务消费者 :商品网站
A、新建 java project
B、maven pom.xml
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fancy</groupId>
<artifactId>order-provider</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
其中,order-provider 项目依赖 在reload之后仍报错的话,可以手动导入其 jar 包
之后再reload即可
C、创建购买商品接口
package com.fancy;
import com.fancy.pojo.Order;
public interface ShopService {
public Order buyGoods(Integer userId, String goodName, float price, Integer amount);
}
D、创建购买接口的实现类
package com.fancy;
import com.fancy.pojo.Order;
import com.fancy.service.OrderService;
public class ShopServiceImpl implements ShopService{
private OrderService orderService;
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
@Override
public Order buyGoods(Integer userId, String goodName, float price, Integer amount) {
Order order = orderService.create(userId, goodName, price, amount);
return order;
}
}
E、创建 dubbo 配置文件
shop-consume.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="product-web"></dubbo:application>
<dubbo:reference id="remoteOrderService" interface="com.fancy.service.OrderService" url="dubbo://localhost:20880" registry="N/A"></dubbo:reference>
<bean id="shopService" class="com.fancy.service.ShopServiceImpl">
<property name="orderService" ref="remoteOrderService"></property>
</bean>
</beans>
F、执行消费者
package com.fancy.main;
import com.fancy.pojo.Order;
import com.fancy.service.ShopService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ConsumeApplication {
public static void main(String[] args) {
String configLocation = "shop-consume.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocation);
((ClassPathXmlApplicationContext)ctx).start();
ShopService service = (ShopService) ctx.getBean("shopService");
Order order = service.buyGoods(1, "手机", 2000, 2);
System.out.println("order : " + order);
}
}
五、dubbo 服务化最佳实践
1、分包
建议将服务接口、服务模型、服务异常等均放在公共包中
2、粒度
服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,否则将面临分布式事务问题,Dubbo 暂未提供分布式事务支持。
服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。
不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便。
3、版本
每个接口都应定义版本号,为后续不兼容升级提供可能
如: <dubbo:service interface="com.xxx.XxxService" version="1.0" />。
建议使用两位版本号,要变更服务版本。
先升级一半提供者为新版本,再将消费者全部升为新版本,然后将剩下的一半提供者升为新版本。
六、改造 dubbo 项目
抽象分散在多个项目中的公共接口,实体类,异常,工具类到一个项目中,在其他项目如服务提供者,消费者共用公共的资源。
1、实现目标
用户访问电商网站浏览商品—选择商品购买
用户访问电商网站—查看用户信息(收件人地址)
项目是 web 应用,需要加入 spring web 开发 jar:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
2、创建公共资源
服务提供者、消费者、网站等多个服务中共用,重复使用的类单独定义在一个项目中。
A、创建公共的 maven java project
项目名称 : node-shop-interface
修改 version
B、复制之前 order-provider 项目的接口文件,实体类文件
C、新建 Address 实体类
package com.fancy.pojo;
import java.io.Serializable;
public class Address implements Serializable {
private static final long serialVersionUID = 1L;
// 收件人姓名
private String name;
// 城市
private String city;
// 街道
private String street;
// 邮编
private String zipcode;
// 手机号
private String mobile;
// 是否使用此地址
private Boolean use;
public Address() {}
public Address(String name, String city, String street, String zipcode, String mobile, Boolean use) {
this.name = name;
this.city = city;
this.street = street;
this.zipcode = zipcode;
this.mobile = mobile;
this.use = use;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public Boolean getUse() {
return use;
}
public void setUse(Boolean use) {
this.use = use;
}
}
D、新建 UserInfoService 接口
package com.fancy.service;
import com.fancy.pojo.Address;
import java.util.List;
public interface UserInfoService {
List<Address> queryAddress(Integer userId);
}
E、安装 jar 到 maven 仓库
使用 idea 的 maven 窗口执行 install
3、创建用户信息服务
A、新建 web project
项目名称 :shop-userservice
B、maven pom.xml
<dependency>
<groupId>com.fancy</groupId>
<artifactId>node-shop-interface</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
C、创建 UserInfoService 实现类
package com.fancy.service;
import com.fancy.pojo.Address;
import java.util.ArrayList;
import java.util.List;
public class UserInfoServiceImpl implements UserInfoService{
@Override
public List<Address> queryAddress(Integer userId) {
List<Address> adds = new ArrayList<>();
if (userId == 1) {
Address address = new Address();
address.setName("张三");
address.setCity("北京");
address.setStreet("海淀区");
address.setUse(true);
adds.add(address);
} else if(userId == 2) {
Address address = new Address();
address.setName("李四");
address.setCity("北京");
address.setStreet("大兴区");
address.setUse(true);
adds.add(address);
}
return adds;
}
}
D、dubbo 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
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">
<dubbo:application name="node-shop-userservice"></dubbo:application>
<dubbo:protocol name="dubbo" port="20881"></dubbo:protocol>
<dubbo:service interface="com.fancy.service.UserInfoService" ref="userService" registry="N/A"></dubbo:service>
<bean id="userService" class="com.fancy.service.UserInfoServiceImpl"></bean>
</beans>
E、web.xml 注册 spring 监听器
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:userservice-provider.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
4、创建订单服务
A、新建 web project
项目名称:node-shop-orderservice
B、 maven pom.xml
<dependency>
<groupId>com.fancy</groupId>
<artifactId>node-shop-interface</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
C、创建 OrderService 接口实现类
拷贝 order-provider 的实现类
D、dubbo 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
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">
<dubbo:application name="node-shop-orderservice"></dubbo:application>
<dubbo:protocol name="dubbo" port="20882"></dubbo:protocol>
<dubbo:service interface="com.fancy.service.UserInfoService" ref="orderService" registry="N/A"></dubbo:service>
<bean id="orderService" class="com.fancy.service.OrderServiceImpl"></bean>
</beans>
E、web.xml 注册 spring 监听器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dubbo-orderservice.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
5、创建商品网站
A、新建 web project
项目名称:node-shop-web
B、创建首页 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script>
var URL_PREFIX="${pageContext.request.contextPath}";
function buyGoods(userId,name,price,amount){
window.location.href= URL_PREFIX +"/shop/buy?userId="+userId +"&name="+name +"&price="+price +"&amount="+amount;
}
function showAddress(userId){
window.location.href= URL_PREFIX +"/shop/addresses?userId="+userId;
}
</script>
</head>
<body>
<div style="margin-left:400px">
<table border="1" cellpadding="1" cellspacing="1" width="60%">
<p>商品列表</p>
<tr>
<td>iphone</td><td>5000</td> <td>20</td> <td><a href="javascript:void(0)" onClick="buyGoods(1,'iphone','5000','1')">购买</a></td>
</tr>
</table>
<div style="margin-left:700px">
<a href="javascript:void(0)" onClick="showAddress(2)" >我的收件地址</a>
</div>
</div>
</body>
</html>
C、maven pom.xml
<dependency>
<groupId>com.fancy</groupId>
<artifactId>node-shop-interface</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
D、项目结构
E、创建商品信息实体类 Goods
package com.fancy.beans;
public class Goods {
private String name;
private Float price;
private Integer amount;
public Goods() {
}
public Goods(String name, Float price, Integer amount) {
this.name = name;
this.price = price;
this.amount = amount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getPrice() {
return price;
}
public void setPrice(Float price) {
this.price = price;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
}
F、创建接口 ShopService
package com.fancy.service;
import com.fancy.beans.Goods;
import com.fancy.pojo.Address;
import com.fancy.pojo.Order;
import java.util.List;
public interface ShopService {
public Order createOrder(Integer userId, Goods goods);
public List<Address> showAddress(Integer userId);
}
G、创建接口实现类 ShopServiceImpl
package com.fancy.service;
import com.fancy.beans.Goods;
import com.fancy.pojo.Address;
import com.fancy.pojo.Order;
import java.util.List;
public class ShopServiceImpl implements ShopService{
// 远程接口作为属性
private OrderService orderService;
private UserInfoService userInfoService;
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
public void setUserInfoService(UserInfoService userInfoService) {
this.userInfoService = userInfoService;
}
@Override
public Order createOrder(Integer userId, Goods goods){
Order order = orderService.create(userId, goods.getName(), goods.getPrice().floatValue(), goods.getAmount());
return order;
}
@Override
public List<Address> showAddress(Integer userId) {
List<Address> addresses = userInfoService.queryAddress(userId);
return addresses;
}
}
H、创建类 ShopController
接收来自页面的请求,处理订单,查询地址信息
package com.fancy.controllers;
import com.fancy.beans.Goods;
import com.fancy.pojo.Address;
import com.fancy.pojo.Order;
import com.fancy.service.ShopService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@Controller
@RequestMapping("/shop")
public class ShopController {
@Autowired
private ShopService shopService;
@RequestMapping("/buy")
public ModelAndView buyGoods(Integer userId, Goods goods) {
ModelAndView mv = new ModelAndView();
Order order = shopService.createOrder(userId, goods);
mv.addObject("order", order);
mv.setViewName("view-order");
return mv;
}
@RequestMapping("/addresses")
public ModelAndView showListAddress(Integer userId) {
ModelAndView mv = new ModelAndView();
List<Address> addresses = shopService.showAddress(userId);
mv.addObject("addresses", addresses);
mv.setViewName("view-address");
return mv;
}
}
I、view-order.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<br>
<div align="align" style="margin-left: 400px"></div>
view-order.jsp<br>
<h5>您的订单已经生成</h5>
<h5>订单号 : ${order.id}</h5>
<h5>商品 : ${order.goodName}</h5>
</body>
</html>
J、view-address.jsp
显示收件人地址信息
页面加入 JSTL :<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<div style="margin-left: 400px">
view-address.jsp<br>
<c:forEach items="${addresses}" var="address">
<h5>收件人 : ${address.name}</h5>
<h5>收件地址 : ${address.city} ${address.street}</h5>
<h5>联系电话 : ${address.mobile}</h5>
<h5>邮编 : ${address.zipcode}</h5>
<h5>默认地址 : ${address.use}</h5>
<br>
</c:forEach>
</div>
</body>
</html>
K、新建 SpringMVC 配置文件
文件名称:dispatcherServlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.fancy.controllers"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
L、新建 dubbo 配置文件
文件名称:dubbo-consume.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
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">
<dubbo:application name="node-shop-web"></dubbo:application>
<dubbo:reference id="remoteUserService" interface="com.fancy.service.UserInfoService" url="dubbo://localhost:20881" registry="N/A" check="false"></dubbo:reference>
<dubbo:reference id="remoteOrderService" interface="com.fancy.service.OrderService" url="dubbo://localhost:20882" registry="N/A" check="false"></dubbo:reference>
<bean id="shopService" class="com.fancy.service.ShopServiceImpl">
<property name="orderService" ref="remoteOrderService"></property>
<property name="userInfoService" ref="remoteUserService"></property>
</bean>
</beans>
M、web.xml 注册 DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dispatcherServlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
测试运行的话,同时启动3个tomcat服务器配置不同端口号,在index.jsp发送请求进行测试
七、Dubbo 常用标签
Dubbo 中常用标签,分为三个类别:公用标签,服务提供者标签,服务消费者标签。
公用标签 :<dubbo:application/>
和 <dubbo:registry/>
A、配置应用信息
<dubbo:application name=”服务的名称”/>
B、配置注册中心
<dubbo:registry address=”ip:port” protocol=”协议”/>
服务提供者标签
配置暴露的服务
<dubbo:service interface="服务接口名" ref="服务实现对象bean">
服务消费者
配置服务消费者引用远程服务
<dubbo:reference id="服务引用 bean 的 id" interface="服务接口名"/>