在Springboot整合dubbo构建maven多模块项目(三) - 把server分为api(服务接口定义)和server(服务实现)两个子module中,我们配置了一个dubbo项目,包含三个模块springboot-dubbo-api、springboot-dubbo-server和springboot-dubbo-client,并且在springboot-dubbo-server和springboot-dubbo-client的pom中都添加了对dubbo、zk及springboot-dubbo-api的依赖。
下面我们一起来实践下dubbo服务端及客户端的简单设置,以及在dubbo admin中查看服务的注册及消费情况。
1 环境搭建
dubbo环境的搭建可参考文章环境搭建(一):Dubbo环境搭建,包括基于docker的zookeeper安装及dubbo admin的安装。
2 dubbo服务提供方配置
数据库创建表:
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_name` varchar(20) DEFAULT '' COMMENT '登录名',
`real_name` varchar(10) DEFAULT '' COMMENT '真实姓名',
`park_code` char(8) DEFAULT '' COMMENT '园区编号',
`park_name` varchar(20) DEFAULT '' COMMENT '园区',
`pwd` varchar(20) DEFAULT '' COMMENT '密码',
`state` tinyint(4) DEFAULT '0' COMMENT '状态,0-无效,1-有效',
`role` tinyint(4) DEFAULT '0' COMMENT '角色,0-园区管理员,1-系统管理员',
`last_date` timestamp NULL DEFAULT NULL COMMENT '最近一次访问时间',
`last_ip` int(10) unsigned DEFAULT '0' COMMENT '最后一次登录的IP',
`login_count` int(6) DEFAULT '0' COMMENT '登录次数',
`date_add` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '添加时间',
`date_upd` timestamp NULL DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `fk_user_park` (`park_code`),
CONSTRAINT `fk_user_park` FOREIGN KEY (`park_code`) REFERENCES `park` (`code`) ON DELETE NO ACTION ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
2.1 在springboot-dubbo-api中创建实体类及服务接口
BaseEntity.java:
package com.example.demo.model;
import java.io.Serializable;
import java.util.Date;
/**
* @author liyanlei
* @Description:实体公共属性
* @date 2018-01-15 16:15
*/
public class BaseEntity implements Serializable {
/**
* 删除标记(0:正常;1:删除;2:审核;)
*/
// public static final String DEL_FLAG_NORMAL = "0";
// public static final String DEL_FLAG_DELETE = "1";
// public static final String DEL_FLAG_AUDIT = "2";
/** 添加时间 */
private Date dateAdd;
/** 修改时间 */
private Date dateUpd;
// private String delFlag; //0 有效 1 删除
public BaseEntity() {
}
public BaseEntity(Date dateAdd, Date dateUpd) {
this.dateAdd = dateAdd;
this.dateUpd = dateUpd;
}
public Date getDateAdd() {
return dateAdd;
}
public void setDateAdd(Date dateAdd) {
this.dateAdd = dateAdd;
}
public Date getDateUpd() {
return dateUpd;
}
public void setDateUpd(Date dateUpd) {
this.dateUpd = dateUpd;
}
}
User.java
package com.example.demo.model;
import java.util.Date;
public class User extends BaseEntity {
/** 主键ID,自增 */
private Integer id;
/** 登录名 */
private String userName;
/** 真实姓名 */
private String realName;
/** 园区编号 */
private String parkCode;
/** 园区 */
private String parkName;
/** 密码 */
private String pwd;
/** 状态,0-无效,1-有效 */
private Byte state;
/** 角色,0-园区管理员,1-系统管理员 */
private Byte role;
/** 最近一次访问时间 */
private Date lastDate;
/** 最后一次登录的IP */
private String lastIp;
/** 登录次数 */
private Integer loginCount;
public User() {
}
public User(Integer id, String userName, String realName, String parkCode, String parkName, String pwd, Byte state, Byte role, Date lastDate, String lastIp, Integer loginCount, Date dateAdd, Date dateUpd) {
super(dateAdd, dateUpd);
this.id = id;
this.userName = userName;
this.realName = realName;
this.parkCode = parkCode;
this.parkName = parkName;
this.pwd = pwd;
this.state = state;
this.role = role;
this.lastDate = lastDate;
this.lastIp = lastIp;
this.loginCount = loginCount;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public String getParkCode() {
return parkCode;
}
public void setParkCode(String parkCode) {
this.parkCode = parkCode;
}
public String getParkName() {
return parkName;
}
public void setParkName(String parkName) {
this.parkName = parkName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Byte getState() {
return state;
}
public void setState(Byte state) {
this.state = state;
}
public Byte getRole() {
return role;
}
public void setRole(Byte role) {
this.role = role;
}
public Date getLastDate() {
return lastDate;
}
public void setLastDate(Date lastDate) {
this.lastDate = lastDate;
}
public String getLastIp() {
return lastIp;
}
public void setLastIp(String lastIp) {
this.lastIp = lastIp;
}
public Integer getLoginCount() {
return loginCount;
}
public void setLoginCount(Integer loginCount) {
this.loginCount = loginCount;
}
}
Pagination.java
package com.example.demo.vo.queryVo;
/**
* 分页实体类
*/
public class Pagination {
//第几页 从0开始
private int pageNo = 0;
//每页多少条数据
private int pageSize = 10;
private int totalCount = 0;
private int skip = 0;
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getSkip() {
return this.pageNo * this.pageSize;
}
public void setSkip(int skip) {
this.skip = skip;
}
}
UserQuery.java
package com.example.demo.vo.queryVo;
import java.io.Serializable;
/**
* 查询条件
*/
public class UserQuery extends Pagination implements Serializable {
private static final long serialVersionUID = 1609252883937908952L;
//查询条件
private int notId = -1;
/** 园区编号 */
private String parkCode;
/** 登录名 or 真实姓名 */
private String name;
/** 登录名 or 真实姓名 模糊查询 */
private String nameLike;
//查询条件
public int groupId = -1; //组ID
public int getNotId() {
return notId;
}
public void setNotId(int notId) {
this.notId = notId;
}
public int getGroupId() {
return groupId;
}
public void setGroupId(int groupId) {
this.groupId = groupId;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getParkCode() {
return parkCode;
}
public void setParkCode(String parkCode) {
this.parkCode = parkCode;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNameLike() {
return nameLike;
}
public void setNameLike(String nameLike) {
this.nameLike = nameLike;
}
}
PageModel.java
package com.example.demo.vo.resultVo;
import java.io.Serializable;
import java.util.List;
/**
* 分页,返回数据
*/
public class PageModel<T> implements Serializable{
//结果集
private List<T> datas;
//每页多少条数据
private int pageSize = 10;
//第几页 从0开始
private int pageNo = 0;
//总条数
private long totalCount = 0;
//总页数
private int totalPages = 0;
private int last_index = 0;
public List<T> getDatas() {
return datas;
}
public void setDatas(List<T> datas) {
this.datas = datas;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public long getTotalCount() {
return totalCount;
}
public void setTotalCount(long totalCount) {
this.totalCount = totalCount;
}
public int getTotalPages() {
return (int) (totalCount % pageSize >0 ? (totalCount/pageSize+1) :(totalCount / pageSize));
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public int getLast_index() {
return last_index;
}
public void setLast_index(int last_index) {
this.last_index = last_index;
}
}
UserService.java
package com.example.demo.api;
import com.example.demo.model.User;
import com.example.demo.vo.queryVo.UserQuery;
import com.example.demo.vo.resultVo.PageModel;
import java.util.List;
/**
* @author liyanlei
* @Description: 用户Service
* @date 2018-01-15 16:15
*/
public interface UserService {
/**
* 根据id查询
* @param id 用户ID
* @return 商户订单
*/
User findOneById(Integer id);
/**
* 根据用户名密码查询
* @param userName
* @param pwd
* @return
*/
User findOneByNameAndPwd(String userName, String pwd);
/**
* 根据用户名称查询
* @param userName
* @return
*/
User findOneByUserName(String userName);
/**
* 根据组ID查询
* @param groupId
* @return
*/
List<User> findListByGroupId(int groupId);
/**
* 根据角色列表查询
* @param roleTypes
* @return
*/
List<User> findListByRoles(String roleTypes);
/**
* 根据条件分页查询
* @param query 查询条件
* @return 分页信息
*/
PageModel<User> findPageByQuery(UserQuery query);
/**
* 根据条件查询记录总条数
* @param query 查询条件
* @return 符合条件的记录数
*/
int findCountByQuery(UserQuery query);
/**
* 查询账号是否存在
* @param userName 账号
* @param notId != ID
* @return 0:不存在,其他:存在。
*/
int findCountByUserName(String userName, Integer notId);
/**
* 添加一个用户
* @param user
* @return
*/
int insertOne(User user);
/**
* 插入(插入属性不为空的值)
* @param user
* @return
*/
int insertSelective(User user);
/**
* 根据ID修改用户信息
* @param user
* @return
*/
int updateById(User user);
/**
* 根据ID修改组信息
* @param user
* @return
*/
int updateByIdSelective(User user);
int delById(Integer id);
// PageModel<User> getCarrierPage(Integer pageIndex, Integer pageSize, CarrierVo carrierVo);
}
2.2 springboot-dubbo-server中实现springboot-dubbo-api接口
目录结构:
2.2.1 集成mybatis - pom.xml中引入jar包
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
2.2.2 集成mybatis - application.properties 数据库连接配置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/XXX?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=xxx
spring.datasource.password=xxx
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.max-active=10
spring.datasource.max-idle=5
spring.datasource.min-idle=0
xxx需要修改为自己数据库的配置
2.2.3 集成mybatis - UserMapper.java
package com.example.demo.dao;
import com.example.demo.model.User;
import com.example.demo.vo.queryVo.UserQuery;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserMapper {
/**
* 根据条件分页查询
* @param query 查询条件
* @return 分页数据
*/
List<User> selectListByQuery(UserQuery query);
/**
* 根据条件查询记录总条数
* @param query 查询条件
* @return 符合条件的记录数
*/
int selectCountByQuery(UserQuery query);
@Delete({
"delete from user",
"where id = #{id,jdbcType=INTEGER}"
})
int deleteByPrimaryKey(Integer id);
@Insert({
"insert into user (user_name, real_name, ",
"park_code, park_name, ",
"pwd, state, role, ",
"last_date, last_ip, ",
"login_count, date_add, ",
"date_upd)",
"values (#{userName,jdbcType=VARCHAR}, #{realName,jdbcType=VARCHAR}, ",
"#{parkCode,jdbcType=CHAR}, #{parkName,jdbcType=VARCHAR}, ",
"#{pwd,jdbcType=VARCHAR}, #{state,jdbcType=TINYINT}, #{role,jdbcType=TINYINT}, ",
"#{lastDate,jdbcType=TIMESTAMP}, INET_ATON(#{lastIp,jdbcType=INTEGER}), ",
"#{loginCount,jdbcType=INTEGER}, #{dateAdd,jdbcType=TIMESTAMP}, ",
"#{dateUpd,jdbcType=TIMESTAMP})"
})
// @SelectKey(statement="VALUES IDENTITY_VAL_LOCAL()", keyProperty="id", before=false, resultType=Integer.class)
int insert(User record);
int insertSelective(User record);
@Select({
"select",
"id, user_name, real_name, park_code, park_name, pwd, state, role, last_date, ",
"INET_NTOA(last_ip) last_ip, login_count, date_add, date_upd",
"from user",
"where id = #{id,jdbcType=INTEGER}"
})
@ResultMap("BaseResultMap")
User selectByPrimaryKey(Integer id);
@Select({
"select",
"id, user_name, real_name, park_code, park_name, pwd, state, role, last_date, ",
"INET_NTOA(last_ip) last_ip, login_count, date_add, date_upd",
"from user",
"where user_name = #{userName,jdbcType=VARCHAR} and pwd = #{pwd,jdbcType=VARCHAR}"
})
@ResultMap("BaseResultMap")
User selectOneByNameAndPwd(String userName, String pwd);
@Select({
"select",
"id, user_name, real_name, park_code, park_name, pwd, state, role, last_date, ",
"INET_NTOA(last_ip) last_ip, login_count, date_add, date_upd",
"from user",
"where user_name = #{userName,jdbcType=VARCHAR}"
})
@ResultMap("BaseResultMap")
User selectOneByUserName(String userName);
/**
* 查询账号是否存在
* @param userName 账号
* @param notId != ID
* @return 0:不存在,其他:存在。
*/
@Select({
"select count(*) from `user` ",
"where user_name = #{userName,jdbcType=VARCHAR} and id != #{notId,jdbcType=INTEGER}"
})
// @ResultType("java.lang.Integer")
int selectCountByUserName(@Param("userName") String userName, @Param("notId") Integer notId);
int updateByPrimaryKeySelective(User record);
@Update({
"update user",
"set user_name = #{userName,jdbcType=VARCHAR},",
"real_name = #{realName,jdbcType=VARCHAR},",
"park_code = #{parkCode,jdbcType=CHAR},",
"park_name = #{parkName,jdbcType=VARCHAR},",
"pwd = #{pwd,jdbcType=VARCHAR},",
"state = #{state,jdbcType=TINYINT},",
"role = #{role,jdbcType=TINYINT},",
"last_date = #{lastDate,jdbcType=TIMESTAMP},",
"last_ip = INET_ATON(#{lastIp,jdbcType=INTEGER}),",
"login_count = #{loginCount,jdbcType=INTEGER},",
"date_add = #{dateAdd,jdbcType=TIMESTAMP},",
"date_upd = #{dateUpd,jdbcType=TIMESTAMP}",
"where id = #{id,jdbcType=INTEGER}"
})
int updateByPrimaryKey(User record);
}
2.2.4 集成mybatis - UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.demo.dao.UserMapper" >
<resultMap id="BaseResultMap" type="com.example.demo.model.User" >
<constructor >
<idArg column="id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="user_name" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="real_name" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="park_code" jdbcType="CHAR" javaType="java.lang.String" />
<arg column="park_name" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="pwd" jdbcType="VARCHAR" javaType="java.lang.String" />
<arg column="state" jdbcType="TINYINT" javaType="java.lang.Byte" />
<arg column="role" jdbcType="TINYINT" javaType="java.lang.Byte" />
<arg column="last_date" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="last_ip" jdbcType="INTEGER" javaType="java.lang.String" />
<arg column="login_count" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="date_add" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="date_upd" jdbcType="TIMESTAMP" javaType="java.util.Date" />
</constructor>
</resultMap>
<sql id="Base_Column_List" >
id, user_name, real_name, park_code, park_name, pwd, state, role, last_date, INET_NTOA(last_ip) last_ip,
login_count, date_add, date_upd
</sql>
<!-- 根据条件分页查询数据 开始 -->
<select id="selectListByQuery" resultMap="BaseResultMap" parameterType="com.example.demo.vo.queryVo.UserQuery">
select <include refid="Base_Column_List"/> from `user`
<where>
<if test="name != null and name != ''">
and (user_name = #{name} or real_name = #{name})
</if>
<if test="parkCode != null and parkCode != ''">
and park_code = #{parkCode}
</if>
<if test="nameLike != null and nameLike != ''">
and (user_name like CONCAT('%', #{nameLike}, '%') or real_name like CONCAT('%', #{nameLike}, '%'))
</if>
<if test="notId != -1">
and id != #{notId}
</if>
</where>
order by id desc
<if test="pageSize > 0">
limit #{skip}, #{pageSize}
</if>
</select>
<!-- 根据条件分页查询数据 结束 -->
<!-- 根据条件查询记录数 开始 -->
<select id="selectCountByQuery" parameterType="com.example.demo.vo.queryVo.UserQuery" resultType="java.lang.Integer">
SELECT count(*) FROM `user`
<where>
<if test="name != null and name != ''">
and (user_name = #{nameLike} or real_name = #{nameLike})
</if>
<if test="parkCode != null and parkCode != ''">
and park_code = #{parkCode}
</if>
<if test="nameLike != null and nameLike != ''">
and (user_name like CONCAT('%', #{nameLike}, '%') or real_name like CONCAT('%', #{nameLike}, '%'))
</if>
<if test="notId != -1">
and id != #{notId}
</if>
</where>
</select>
<!-- 根据条件查询记录数 结束 -->
<insert id="insertSelective" parameterType="com.example.demo.model.User" >
<!--<selectKey resultType="java.lang.Integer" keyProperty="id" order="AFTER" >
VALUES IDENTITY_VAL_LOCAL()
</selectKey>-->
insert into user
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="userName != null" >
user_name,
</if>
<if test="realName != null" >
real_name,
</if>
<if test="parkCode != null" >
park_code,
</if>
<if test="parkName != null" >
park_name,
</if>
<if test="pwd != null" >
pwd,
</if>
<if test="state != null" >
state,
</if>
<if test="role != null" >
role,
</if>
<if test="lastDate != null" >
last_date,
</if>
<if test="lastIp != null" >
last_ip,
</if>
<if test="loginCount != null" >
login_count,
</if>
<if test="dateAdd != null" >
date_add,
</if>
<if test="dateUpd != null" >
date_upd,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="userName != null" >
#{userName,jdbcType=VARCHAR},
</if>
<if test="realName != null" >
#{realName,jdbcType=VARCHAR},
</if>
<if test="parkCode != null" >
#{parkCode,jdbcType=CHAR},
</if>
<if test="parkName != null" >
#{parkName,jdbcType=VARCHAR},
</if>
<if test="pwd != null" >
#{pwd,jdbcType=VARCHAR},
</if>
<if test="state != null" >
#{state,jdbcType=TINYINT},
</if>
<if test="role != null" >
#{role,jdbcType=TINYINT},
</if>
<if test="lastDate != null" >
#{lastDate,jdbcType=TIMESTAMP},
</if>
<if test="lastIp != null" >
INET_ATON(#{lastIp,jdbcType=INTEGER}),
</if>
<if test="loginCount != null" >
#{loginCount,jdbcType=INTEGER},
</if>
<if test="dateAdd != null" >
#{dateAdd,jdbcType=TIMESTAMP},
</if>
<if test="dateUpd != null" >
#{dateUpd,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.example.demo.model.User" >
update user
<set >
<if test="userName != null" >
user_name = #{userName,jdbcType=VARCHAR},
</if>
<if test="realName != null" >
real_name = #{realName,jdbcType=VARCHAR},
</if>
<if test="parkCode != null" >
park_code = #{parkCode,jdbcType=CHAR},
</if>
<if test="parkName != null" >
park_name = #{parkName,jdbcType=VARCHAR},
</if>
<if test="pwd != null" >
pwd = #{pwd,jdbcType=VARCHAR},
</if>
<if test="state != null" >
state = #{state,jdbcType=TINYINT},
</if>
<if test="role != null" >
role = #{role,jdbcType=TINYINT},
</if>
<if test="lastDate != null" >
last_date = #{lastDate,jdbcType=TIMESTAMP},
</if>
<if test="lastIp != null" >
last_ip = INET_ATON(#{lastIp,jdbcType=INTEGER}),
</if>
<if test="loginCount != null" >
login_count = #{loginCount,jdbcType=INTEGER},
</if>
<if test="dateAdd != null" >
date_add = #{dateAdd,jdbcType=TIMESTAMP},
</if>
<if test="dateUpd != null" >
date_upd = #{dateUpd,jdbcType=TIMESTAMP},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
2.2.5 集成mybatis - UserServiceImpl.java
package com.example.demo.api.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.example.demo.api.UserService;
import com.example.demo.dao.UserMapper;
import com.example.demo.model.User;
import com.example.demo.vo.queryVo.UserQuery;
import com.example.demo.vo.resultVo.PageModel;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
/**
* @author liyanlei
* @Description: userService 实现
* @date 2018-01-15 16:15
*/
//该Service注解是dubbo的注解,不是spring的。若使用xml配置方式暴露接口,则不需要该注解。
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User findOneById(Integer id) {
return this.userMapper.selectByPrimaryKey(id);
}
@Override
public User findOneByNameAndPwd(String userName, String pwd) {
return this.userMapper.selectOneByNameAndPwd(userName, pwd);
}
@Override
public User findOneByUserName(String userName) {
return this.userMapper.selectOneByUserName(userName);
}
@Override
public PageModel<User> findPageByQuery(UserQuery query) {
PageModel<User> pageModel = new PageModel<User>();
pageModel.setDatas(this.userMapper.selectListByQuery(query));//列表数据
pageModel.setTotalCount(this.userMapper.selectCountByQuery(query));//总条数
return pageModel;
}
@Override
public int findCountByQuery(UserQuery query) {
return this.userMapper.selectCountByQuery(query);
}
@Override
public List<User> findListByGroupId(int groupId) {
return null;
}
@Override
public List<User> findListByRoles(String roleTypes) {
return null;
}
@Override
public int findCountByUserName(String userName, Integer notId) {
if(notId == null){
notId = 0;
}
return this.userMapper.selectCountByUserName(userName, notId);
}
@Override
public int insertOne(User user) {
return this.userMapper.insert(user);
}
@Override
public int insertSelective(User user) {
return this.userMapper.insertSelective(user);
}
@Override
public int updateById(User user) {
return this.userMapper.updateByPrimaryKey(user);
}
@Override
public int updateByIdSelective(User user) {
return this.userMapper.updateByPrimaryKeySelective(user);
}
@Override
public int delById(Integer id) {
return this.userMapper.deleteByPrimaryKey(id);
}
}
2.3 dubbo 配置 provider.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="demo-provider" />
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry protocol="zookeeper" address="localhost:2181" timeout="60000"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 暴露dubbo服务的方式一-->
<!-- 使用注解方式暴露接口,会自动扫描package下所有包中dubbo相关的注解,这样就不用在xml中再针对每个服务接口配置dubbo:service interface-->
<dubbo:annotation package="com.example.demo.api.impl"/>
<!-- 暴露dubbo服务的方式二 -->
<!-- 使用xml配置方式申明暴露一个接口服务,在程序启动的时候会自动注册到zookeeper。
等同于在类上打@service注解,打了注解就必须要用annotation指定启动扫描路径,使用这种方式,就不需要指定annotation了-->
<!--<dubbo:service interface="com.example.demo.api.UserService" ref="userService"/>-->
<!-- 具体的实现bean,id与上面的ref要一致-->
<!--<bean id="userService" class="com.example.demo.api.impl.UserServiceImpl" />-->
</beans>
2.4 启动类SpringbootDubboServerApplication.java
package com.example.demo;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
@SpringBootApplication
@MapperScan("com.example.demo.dao")
@ImportResource("classpath:provider.xml") //加载xml文件
public class SpringbootDubboServerApplication {
@Bean
@ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource() {
return new org.apache.tomcat.jdbc.pool.DataSource();
}
@Bean
public SqlSessionFactory sqlSessionFactoryBean() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource());
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mappers/*.xml"));
return sqlSessionFactoryBean.getObject();
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(SpringbootDubboServerApplication.class, args);
Thread.sleep(Long.MAX_VALUE); //pom中没有加spring-boot-starter-web依赖,启动时没有tomcat容器,会自动退出,所以加了一个sleep防止自动退出
}
}
运行springboot-dubbo-server项目
3 dubbo服务消费方配置
项目结构:
3.1 创建xml配置文件
创建远程服务代理和暴露dubbo服务一样,也有两种方式,一是使用注解方式,二是使用xml配置方式。下面的consumer.xml中使用的是第一种方式。如果使用xml配置方式创建远程服务代理,将dubbo:annotation一行替换成如下配置即可。
consumer.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="demo-consumer"/>
<!--zookeeper注册中心 -->
<dubbo:registry protocol="zookeeper" address="localhost:2181" timeout="60000"/>
<!--关闭服务消费方所有服务的启动检查。dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止Spring初始化完成。-->
<dubbo:consumer check="false" />
<!-- 使用注解方式创建远程服务代理-->
<dubbo:annotation package="com.example.demo.controller"/>
<!-- 使用xml配置方式创建远程服务代理,id即为provider.xml中暴露的服务的id-->
<!-- 等同于dubbo:annotation 加上代码里的@Reference注解-->
<!--<dubbo:reference id="userService" interface="com.example.demo.api.UserService"/>-->
</beans>
3.2 创建Controller
UserController.java
package com.example.demo.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.example.demo.api.UserService;
import com.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.Date;
@RestController
@RequestMapping("/user")
public class UserController {
//注入服务提供方暴露的接口,通过@Reference注解,dubbo会在扫描的时候自动代理接口,然后通过rpc调用远程服务。
//如果用xml配置方式,需要将@Reference换成@Autowired。
// @Autowired
@Reference
UserService userService;
@RequestMapping("/findOne")
@ResponseBody
public User findOneById(Integer id){
if(id == null){
id = 18;
}
System.out.println(id);
User user = userService.findOneById(id);
if(user == null){
user = new User();
}
return user;
}
@RequestMapping("/saveOne")
@ResponseBody
public int saveOne(){
User user = new User(1, "lisi", "李四", "010101", "北海公园", "pwd123456", (byte) 1, (byte)1, new Date(), "127.0.0.1", 12, new Date(), new Date());
return userService.insertOne(user);
}
@RequestMapping("/delOne")
@ResponseBody
public int delOne(Integer id){
return userService.delById(id);
}
}
3.3 编写启动类
SpringbootDubboClientApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
//必须在controller包中,在这里报错(这个启动类无法启动)
@SpringBootApplication
@ImportResource("classpath:consumer.xml") //加载xml配置文件
//@RestController
public class SpringbootDubboClientApplication {
public static void main(String[] args) throws Exception{
SpringApplication.run(SpringbootDubboClientApplication.class, args);
}
}
右键-->debug(run)运行启动类:
4 测试
在浏览器中调用canbuy接口,正常返回结果,说明我们的配置都生效啦~~~
http://localhost:8080/user/saveOne
http://localhost:8080/user/findOne?id=12
http://localhost:8080/user/delOne?id=16
到这里,Spring Boot集成Dubbo,整合mybatis的内容都讲完啦