一、Spring Boot中使用Dubbo
1 定义commons工程11-dubboCommons
(1) 创建工程
这里就创建一个普通的Maven的Java工程,并命名为dubboCommons。
(2) 定义pom文件
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
(3) 定义实体类
@Data
public class Employee implements Serializable{
private Integer id;
private String name;
private int age;
}
(4) 定义业务接口
public interface EmployeeService {
void addEmployee(Employee employee);
Employee findEmployeeById(int id);
Integer findEmployeecount();
}
(5) 将工程安装到本地库
运行Maven的install命令,将工程安装到本地版本库,以备其它工程使用。
2 定义提供者
(1) 创建工程
创建一个Spring Boot工程provider-springboot;
(2) 定义pom文件
A、添加dubbo与spring boot整合依赖
B、添加zkClient依赖
C、其它依赖
-
dubboCommons依赖
-
spring boot与redis整合依赖
-
mybatis与spring boot整合依赖
-
数据源Druid依赖
-
mysql驱动依赖
-
slf4j-log4j12依赖
-
spring-boot-starter-web依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--dubbo与spring boot整合依赖-->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!-- zk客户端依赖:zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<dependency>
<groupId>com.zxy</groupId>
<artifactId>dubboCommons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--Spring Boot与Redis整合依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--mybatis与Spring Boot整合依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--数据源Druid依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--MySQL驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<!--注册dao包下mybatis映射文件为资源目录-->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
(3) 定义Service实现类
@Service //阿里dubbo的注解
@Component
public class EmployeeServiceImpl implements EmployeeService{
@Autowired
private EmployeeDao dao;
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
//插入操作会清空realTimeCache区域缓存
@CacheEvict(value="tralTimeCache",allEntries=true)
//指定发生受查异常回滚
@Transactional(rollbackFor = Exception.class)
@Override
public void addEmployee(Employee employee) {
dao.insertEmployee(employee);
}
//将从DB中查询的数据存放到realTimeCache缓存区域,并为其指定key为employee_id值
@Cacheable(value="realTimeCache",key="'employee_'+#id")
@Override
public Employee findEmployeeById(int id) {
// TODO Auto-generated method stub
return dao.selectEmployeeById(id);
}
//使用双重检测锁解决热点缓存问题
@Override
public Integer findEmployeecount() {
//获取Redis操作对象
BoundValueOperations<Object,Object> ops =
redisTemplate.boundValueOps("count");
//从缓存中读取数据
Object count = ops.get();
if(count == null) {
synchronized(this) {
count = ops.get();
if(count == null) {
//从DB中查询
count = dao.selectEmployeeCount();
//将查询的数据写入到Redis缓存,并设置到期时限
ops.set(count,10,TimeUnit.SECONDS);
}
}
}
return (Integer)count;
}
}
(4) 定义Dao接口
@Mapper
public interface EmployeeDao {
void insertEmployee(Employee employee);
Integer selectEmployeeCount();
Employee selectEmployeeById(int id);
}
(5) 定义映射文件
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zxy.dao.EmployeeDao">
<insert id="insertEmployee">
insert into employee(name, age) values(#{name}, #{age})
</insert>
<select id="selectEmployeeCount" resultType="int">
select count(id) from employee
</select>
<select id="selectEmployeeById" resultType="Employee">
select id, name, age from employee where id=#{xxx}
</select>
</mapper>
(6) 修改启动类
在启动类上必须要添加@EnableDubboConfiguration注解,开启Dubbo的自动配置功能;
@EnableTransactionManagement //开启事务
@SpringBootApplication
@EnableCaching //开启缓存
@EnableDubboConfiguration //开启Dubbo自动配置
public class ProviderSpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderSpringbootApplication.class, args);
}
}
(7) 主配置文件
配置文件中划分了realTimeCache实时数据缓存区,redis缓存区域划分,根据业务需求划分为非实时数据与实时数据缓存区;
-
非实时数据:某些不需要实时更新,并且不影响业务的数据,例,统计型数据,平台用户数量、浏览量等,可以设置为30分钟更新一次DB;
-
实时数据:数据一旦变更必须实时同步的缓存数据,例,新产品发布信息、广告信息;
server.port=8001
# 该名称是由服务治理平台使用
spring.application.name=provider-springboot
#注册mybatis中实体类别名
mybatis.type-aliases-package=com.zxy.entity
#注册映射文件
mybatis.mapper-locations=classpath:com/zxy/dao/*.xml
#注册数据源,类型为Druid
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql:///test?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
#配置缓存为redis
spring.cache.type=redis
#指定实时数据缓存区域
spring.cache.cache-names=realTimeCache
#连接Redis服务器
spring.redis.host=192.168.85.130
spring.redis.port=6379
#配置dubbo治理
spring.dubbo.registry=zookeeper://192.168.85.129:2181
#spring.dubbo.registry=zookeeper://192.168.85.129:2181?backup=192.168.85.136:2181,192.168.85.137:2181
3 定义消费者
(1) 创建工程
创建一个Spring Boot工程,命名为11-consumer-springboot;
(2) 定义pom文件
-
dubbo与spring boot整合依赖
-
zkClient依赖
-
dubboCommons依赖
-
JSP引擎jasper依赖
-
slf4j-log4j12依赖
-
spring-boot-starter-web依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--dubbo与spring boot整合依赖-->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!-- zk客户端依赖:zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
<dependency>
<groupId>com.zxy</groupId>
<artifactId>15-dubboCommons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--Tomcat内置JSP引擎jasper-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<!--注册webapp目录为资源目录-->
<resource>
<directory>src/main/webapp</directory>
<targetPath>META-INF/resources</targetPath>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
</build>
</project>
(3) 修改主配置文件
server.port=8002
spring.application.name= consumer-springboot
spring.dubbo.registry=zookeeper://192.168.85.129:2181
(4) 创建index.jsp页面
在src/main/webapp目录下定义index.jsp文件;
<body>
<form action="/consumer/employee/register" method="post">
姓名:<input type="text" name="name"/><br>
年龄:<input type="text" name="age"/>
<input type="submit" value="注册">
</form>
</body>
(5) 定义处理器
@Controller
@RequestMapping("/consumer/employee")
public class SomeController {
//@Autowired
@Reference
private EmployeeService employeeService;
@PostMapping("/register")
public String someHandle(Employee employee,Model model) {
employeeService.addEmployee(employee);
model.addAttribute("employee",employee);
return "/welcome.jsp";
}
@RequestMapping("/find/{id}")
@ResponseBody
public Employee findHandle(@PathVariable("id") int id) {
return employeeService.findEmployeeById(id);
}
@RequestMapping("/count")
@ResponseBody
public Integer countHandle() {
return employeeService.findEmployeecount();
}
}
(6) 定义welcome.jsp页面
在src/main/webapp目录下定义welcome.jsp文件;
<body>
welcome you 【${employee}】<br>
</body>
(7) 修改入口类
@SpringBootApplication
@EnableDubboConfiguration
public class ConsumerSpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerSpringbootApplication.class, args);
}
}