搭建一个基于spingboot+dubbo的“用户Rpc服务”
- 环境配置
jdk1.8、maven3.5、zookeeper3.4
- maven模块
user-api : 服务接口, 定义服务接口和方法, 模块会打成jar包被服务实现者和调用者依赖
user-provider : 服务实现者, 实现服务接口和方法, 会被集群部署.
user-consumer : 服务调用者, 不止一个, 比如会员、积分等需要RPC调用用户服务的独立系统
-
user-api
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<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.wx</groupId>
<artifactId>user-api</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
java类
1) Rpc返回错误枚举
package com.wx.rpc;
/**
* PRC返回错误码枚举
*/
public enum RpcResCodeEnum {
SUCCESS("0000", "成功"),
REQUIRED_PARAM_IS_EMPTY("0001", "必要的请求参数为空"),
USER_DISABLED("1001", "用户被冻结"),
//其他返回码...
UNKNOWN_ERROR("9999", "未知异常");
String code;
String message;
RpcResCodeEnum(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
}
2) Rpc返回结果
package com.wx.rpc;
import java.io.Serializable;
/**
* RPC返回结果对象
*
* @param <T>
*/
public class RpcResponse<T> implements Serializable {
private String code;
private String message;
private T data;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
/**
* 返回成功
*
* @return
*/
public static RpcResponse succeed() {
RpcResponse response = new RpcResponse();
response.setCode(RpcResCodeEnum.SUCCESS.getCode());
response.setMessage(RpcResCodeEnum.SUCCESS.getMessage());
return response;
}
/**
* 返回成功,带实体data
*
* @param data
* @return
*/
public static RpcResponse succeed(Object data) {
RpcResponse response = new RpcResponse();
response.setCode(RpcResCodeEnum.SUCCESS.getCode());
response.setMessage(RpcResCodeEnum.SUCCESS.getMessage());
response.setData(data);
return response;
}
/**
* 返回失败
*
* @param rpcCodeEnum 错误枚举
* @return
*/
public static RpcResponse fail(RpcResCodeEnum rpcCodeEnum) {
RpcResponse response = new RpcResponse();
response.setCode(rpcCodeEnum.getCode());
response.setMessage(rpcCodeEnum.getMessage());
return response;
}
}
3) 数据传输对象
package com.wx.rpc;
import java.io.Serializable;
/**
* 用户DTO
*/
public class UserDto implements Serializable{
private String id;
private String username;
private String password;
//略
}
4 ) Rpc接口
package com.wx.rpc;
public interface UserService {
/**
* 保存用户
* @param userDto
* @return
*/
RpcResponse saveUser(UserDto userDto);
/**
* 查询用户
* @param id
* @return
*/
RpcResponse getUser(String id);
}
打包并安装接口jar到本地仓库
mvn clean install -Dmaven.skip.test=true
-
user-provider
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<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.wx</groupId>
<artifactId>user-provider</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.12.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
</exclusions>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<!--服务接口-->
<dependency>
<groupId>com.wx</groupId>
<artifactId>user-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
java类和resource文件
1) 加载dubbo配置
package com.wx.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
/**
* dubbo服务实例化和注册
*/
@Configuration
@ImportResource("classpath:dubbo-provider.xml")
public class DubboProviderConfig {
}
2) 实现服务接口
package com.wx.rpc.impl;
import com.wx.rpc.RpcResCodeEnum;
import com.wx.rpc.RpcResponse;
import com.wx.rpc.UserDto;
import com.wx.rpc.UserService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
* 服务接口实现类
*/
@Service
public class UserServiceImpl implements UserService {
@Override
public RpcResponse saveUser(UserDto userDto) {
//参数为空校验
if (StringUtils.isEmpty(userDto.getUsername())
|| StringUtils.isEmpty(userDto.getPassword())) {
return RpcResponse.fail(RpcResCodeEnum.REQUIRED_PARAM_IS_EMPTY);
}
//@TODO: insert数据库
//返回保存成功
return RpcResponse.succeed();
}
@Override
public RpcResponse getUser(String id) {
//模拟查询
UserDto userDto = new UserDto();
userDto.setId(id);
userDto.setUsername("dubbo");
//返回查询结果
return RpcResponse.succeed(userDto);
}
}
3) 启动类
package com.wx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* boot启动类
*/
@SpringBootApplication
public class StartUserProvider {
public static void main(String[] args) {
SpringApplication.run(StartUserProvider.class, args);
}
}
4) properties文件
#web端口
server.port=8088
#zookeeper地址
zookeeper.address=127.0.0.1:2181
#dubbo服务监听端口
dubbo.port=20880
5) dubbo服务的spring配置
<?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="user-provider"/>
<!--注册协议和注册地址-->
<dubbo:registry protocol="zookeeper" address="${zookeeper.address}"/>
<!--服务监听端口-->
<dubbo:protocol name="dubbo" port="${dubbo.port}"/>
<!--服务接口和实现类-->
<dubbo:service interface="com.wx.rpc.UserService" ref="userServiceImpl"/>
</beans>
打jar包
mvn clean package -Dmaven.skip.test=true
本地集群部署3个服务节点
java -jar ./target/user-provider-1.0-SNAPSHOT.jar --server.port=8088 --dubbo.port=20880
java -jar ./target/user-provider-1.0-SNAPSHOT.jar --server.port=8090 --dubbo.port=20881
java -jar ./target/user-provider-1.0-SNAPSHOT.jar --server.port=8092 --dubbo.port=20882
通过dubbo-admin查看服务注册情况
-
user-consumer
pom文件
<?xml version="1.0" encoding="UTF-8"?> <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.wx</groupId> <artifactId>user-consumer</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.12.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </exclusion> </exclusions> <version>2.5.3</version> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> <!--服务接口--> <dependency> <groupId>com.wx</groupId> <artifactId>user-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
java类型和resource文件
1) 加载dubbo配置
package com.wx.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
/**
* 加载dubbo消费配置
*/
@Configuration
@ImportResource("classpath:dubbo-consumer.xml")
public class DubboConsumerConfig {
}
2) 测试Controller
package com.wx.controller;
import com.wx.rpc.UserDto;
import com.wx.rpc.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 用户Controller
*/
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/save")
@ResponseBody
public Object saveUser(UserDto userDto){
return userService.saveUser(userDto);
}
@RequestMapping("/user")
@ResponseBody
public Object getUser(String id){
return userService.getUser(id);
}
}
3) 启动类
package com.wx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* boot启动类
*/
@SpringBootApplication
public class StartConsumer {
public static void main(String[] args) {
SpringApplication.run(StartConsumer.class, args);
}
}
4) properties文件
#web端口
server.port=8000
#zookeeper地址
zookeeper.address=127.0.0.1:2181
5) dubbo消费的spring配置
<?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="user-consumer"/>
<!--注册协议和注册地址-->
<dubbo:registry protocol="zookeeper" address="${zookeeper.address}"/>
<!--引用服务接口-->
<dubbo:reference interface="com.wx.rpc.UserService" id="userService"/>
</beans>
打包并启动user-consumer, 通过UserController来测试整个RPC
http://127.0.0.1:8000/user/save?username=wx
{
"code": "0001",
"message": "必要的请求参数为空",
"data": null
}
http://127.0.0.1:8000/user/save?username=wx&password=123456
{
"code": "0000",
"message": "成功",
"data": null
}
http://127.0.0.1:8000/user/get?id=1
{
"code": "0000",
"message": "成功",
"data": {
"id": "1",
"username": "dubbo",
"password": null
}
}