继上文 :spring整合各种RPC框架(netty、dubbo、dubbox、gRPC、Motan)-续(gRPC)
Motan相关介绍?
Motan是新浪微博开源的一套基于java开发的RPC框架,除了常规的点对点调用外,Motan还提供服务治理功能,包括服务节点的自动发现、摘除、高可用和负载均衡等。Motan具有良好的扩展性,主要模块都提供了多种不同的实现,例如支持多种注册中心,支持多种rpc协议等。
参考网站:
github地址:https://github.com/weibocom/motan
文档地址:https://github.com/weibocom/motan/wiki/zh_quickstart
用户指南;https://github.com/weibocom/motan/wiki/zh_userguide
源码实现
无注册中心测试
pom.xml
<?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">
<parent>
<artifactId>spring_rpc</artifactId>
<groupId>com.hong</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.hong.spring</groupId>
<artifactId>spring_motan_server</artifactId>
<dependencies>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-core</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-transport-netty</artifactId>
<version>RELEASE</version>
</dependency>
<!-- only needed for spring-based features -->
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-springsupport</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-registry-zookeeper</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
</project>
com.hong.service.FooService
package com.hong.service;
/**
*
* 功能描述: 测试服务接口
*
* @param:
* @return:
* @auther: csh
* @date: 2021/2/1 10:40
*/
public interface FooService {
String hello(String name);
}
com.hong.service.impl.FooServiceImpl
package com.hong.service.impl;
import com.hong.service.FooService;
/**
* @author: csh
* @Date: 2021/2/1 10:22
* @Description:测试服务接口实现
*/
public class FooServiceImpl implements FooService {
public String hello(String name) {
System.out.println(name + " invoked rpc service");
return "hello " + name;
}
}
Client
import com.hong.service.FooService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
*
* 功能描述: 客户端
*
* @param:
* @return:
* @auther: csh
* @date: 2021/2/1 10:57
*/
public class Client {
public static void main(String[] args) throws InterruptedException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:motan_client.xml");
FooService service = (FooService) ctx.getBean("remoteService");
System.out.println(service.hello("hong"));
}
}
Server
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
*
* 功能描述: 服务端
*
* @param:
* @return:
* @auther: csh
* @date: 2021/2/1 10:57
*/
public class Server {
public static void main(String[] args) throws InterruptedException {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:motan_server.xml");
System.out.println("server start...");
}
}
motan_client.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:motan="http://api.weibo.com/schema/motan"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd">
<!-- reference to the remote service -->
<motan:referer id="remoteService" interface="com.hong.service.FooService" directUrl="localhost:8002"/>
</beans>
motan_server.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:motan="http://api.weibo.com/schema/motan"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd">
<!-- service implemention bean -->
<bean id="serviceImpl" class="com.hong.service.impl.FooServiceImpl" />
<!-- exporting service by Motan -->
<motan:service interface="com.hong.service.FooService" ref="serviceImpl" export="8002" />
</beans>
运行:先跑server,再跑client 结果如下:
.FooService?group=default_rpc]
10:39:09.954 [main] INFO info - cluster init cost 120, refer size:1, cluster:motan://10.3.6.59:0/com.hong.service.FooService?group=default_rpc
10:39:10.556 [New I/O client worker #1-2] INFO info - NettyChannelHandler channelConnected: remote=localhost/127.0.0.1:8002 local=/127.0.0.1:54848 event=UpstreamChannelStateEvent
10:39:10.557 [New I/O client worker #1-1] INFO info - NettyChannelHandler channelConnected: remote=localhost/127.0.0.1:8002 local=/127.0.0.1:54847 event=UpstreamChannelStateEvent
10:39:10.559 [New I/O client worker #1-3] INFO info - NettyChannelHandler channelConnected: remote=localhost/127.0.0.1:8002 local=/127.0.0.1:54861 event=UpstreamChannelStateEvent
10:39:10.559 [AbstractPoolClient-initPool--1-thread-1] INFO info - async initPool success!motan://localhost:8002/com.hong.service.FooService
hello hong
springmvc版整合
启动zk(参考:注册中心:spring整合各种服务注册中心(zk、eureka、nacos、consul))
配置管理台
下载:https://github.com/weibocom/motan.git
配置数据库、运行sql,然后启动,这边配置的端口号是:8888
登陆:http://localhost:8888/账号密码:gust/gust 或 admin/admin
spring_dubbo_api 跟其他文章一样,略过~
springmvc+motan+zk 服务端
引入zkjar包
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-registry-zookeeper</artifactId>
<version>RELEASE</version>
</dependency>
项目结构
│ pom.xml
│ spring_motan_server.iml
│
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─hong
│ │ │ └─spring
│ │ │ ├─config
│ │ │ │ AnnotationRpcServerDemo.java
│ │ │ │
│ │ │ ├─dao
│ │ │ │ UserMapper.java
│ │ │ │
│ │ │ ├─mapper
│ │ │ │ UserMapper.xml
│ │ │ │
│ │ │ ├─provider
│ │ │ │ UserServiceImpl.java
│ │ │ │
│ │ │ └─utils
│ │ │ MotanServletContextListener.java
│ │ │
│ │ └─resources
│ │ application.properties
│ │ applicationContext-mybatis.xml
│ │ jdbc.properties
│ │ log4j2.xml
│ │ logging.properties
│ │ motan.properties
│ │ motan_server.xml
│ │ mybatis.xml
│ │ user.sql
│ │
│ └─test
│ ├─java
│ │ │ Client.java
│ │ │ Server.java
│ │ │
│ │ └─com
│ │ └─hong
│ │ └─service
│ │ │ FooService.java
│ │ │
│ │ └─impl
│ │ FooServiceImpl.java
│ │
│ └─resources
│ motan_client.xml
│ motan_server.xml
│
└─web
└─WEB-INF
web.xml
com.hong.spring.utils.MotanServletContextListener
package com.hong.spring.utils;
import com.weibo.api.motan.common.MotanConstants;
import com.weibo.api.motan.util.MotanSwitcherUtil;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
*
* 功能描述: motan的配置
*
* @param:
* @return:
* @auther: csh
* @date: 2021/2/1 11:58
*/
public class MotanServletContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
}
@Override
public void contextInitialized(ServletContextEvent event) {
//这个时候spring已经初始化完成,调用以下的类来调整motan状态
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);
}
}
com.hong.spring.config.AnnotationRpcServerDemo
package com.hong.spring.config;
import com.weibo.api.motan.config.springsupport.BasicServiceConfigBean;
import com.weibo.api.motan.config.springsupport.ProtocolConfigBean;
import com.weibo.api.motan.config.springsupport.RegistryConfigBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class AnnotationRpcServerDemo {
@Bean(name="demoMotan")
public ProtocolConfigBean protocolConfig1() {
ProtocolConfigBean config = new ProtocolConfigBean();
config.setDefault(true);
config.setName("motan");
config.setMaxContentLength(1048576);
return config;
}
// @Bean(name = "motan")
// public ProtocolConfigBean protocolConfig2() {
// ProtocolConfigBean config = new ProtocolConfigBean();
//// config.setId("demoMotan2");
// config.setName("motan");
// config.setMaxContentLength(1048576);
// return config;
// }
@Bean(name="registryConfig1")
public RegistryConfigBean registryConfig() {
RegistryConfigBean config = new RegistryConfigBean();
config.setRegProtocol("zookeeper");
config.setAddress("127.0.0.1:2181");
// config.setRegProtocol("local");
return config;
}
@Bean
public BasicServiceConfigBean baseServiceConfig() {
BasicServiceConfigBean config = new BasicServiceConfigBean();
config.setExport("demoMotan:8081");
config.setGroup("motan-demo-rpc");
config.setAccessLog(false);
config.setShareChannel(true);
config.setModule("motan-demo-rpc");
config.setApplication("myMotanDemo");
config.setRegistry("registryConfig1");
return config;
}
}
com.hong.spring.dao.UserMapper
package com.hong.spring.dao;
import com.hong.spring.entity.User;
import com.hong.spring.entity.ao.UserAO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @Auther: csh
* @Date: 2020/8/18 15:04
* @Description:用户dao层
*/
public interface UserMapper {
/**
*
* 功能描述:查询总条数
*
* @param:
* @return:
* @auther: csh
* @date: 2020/8/18 15:31
*/
List<User> findAllUserList();
/**
*
* 功能描述:获取总数
*
* @param:
* @return:
* @auther: csh
* @date: 2020/8/18 15:30
*/
int findAllTotal();
/**
*
* 功能描述:更新
*
* @param:
* @return:
* @auther: csh
* @date: 2020/8/18 15:30
*/
int update(User user);
/**
*
* 功能描述:添加
*
* @param:
* @return:
* @auther: csh
* @date: 2020/8/19 18:39
*/
int save(User user);
/**
*
* 功能描述:批量添加
*
* @param:
* @return:
* @auther: csh
* @date: 2020/8/21 15:46
*/
int insertBatch(@Param("list") List <User> list);
/**
*
* 功能描述:通过id查询
*
* @param:
* @return:
* @auther: csh
* @date: 2020/8/19 18:39
*/
User findById(int id);
/**
*
* 功能描述:通过分页查询
*
* @param:
* @return:
* @auther: csh
* @date: 2020/8/21 16:05
*/
List<User> findByPage(UserAO ao);
}
com/hong/spring/mapper/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.hong.spring.dao.UserMapper">
<resultMap type="com.hong.spring.entity.User" id="user">
<id column="id" property="id" />
<result column="user_name" property="username" />
<result column="age" property="age" />
</resultMap>
<select id="findById" resultType="com.hong.spring.entity.User">
SELECT * FROM user WHERE id = #{id,jdbcType=INTEGER}
</select>
<select id="findByPage" resultMap="user" parameterType="com.hong.spring.entity.ao.UserAO">
select * from user where 1=1 limit #{page},#{pageSize}
</select>
<select id="findAllUserList" resultMap="user">
SELECT * FROM user
</select>
<select id="findAllTotal" resultType="int">
SELECT count(*) FROM user
</select>
<insert id="save" >
INSERT INTO user ( user_name, age)
VALUES (#{username,jdbcType=VARCHAR},
#{age,jdbcType=INTEGER})
</insert>
<insert id="insertBatch">
insert into user
( user_name, age)
values
<foreach collection="list" item="user" index="index"
separator=",">
(#{user.username,jdbcType=VARCHAR},#{user.age,jdbcType=INTEGER})
</foreach>
</insert>
<update id="update" >
update user
<set>
<if test="username !=null">
user_name=#{username,jdbcType=VARCHAR},
</if>
<if test="age !=null">
age =#{age,jdbcType=INTEGER}
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
com.hong.spring.provider.UserServiceImpl
package com.hong.spring.provider;
import com.hong.spring.api.IUserService;
import com.hong.spring.dao.UserMapper;
import com.hong.spring.entity.User;
import com.hong.spring.entity.ao.UserAO;
import com.hong.spring.utils.DataResponse;
import com.weibo.api.motan.config.springsupport.annotation.MotanService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @Auther: csh
* @Date: 2020/8/18 15:16
* @Description:用户实现
*/
@MotanService
public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper userDao;
@Override
public DataResponse<List<User>> findByAll() {
List <User> allUserList = userDao.findAllUserList();
int allTotal = userDao.findAllTotal();
return DataResponse.BuildSuccessResponse(allUserList,allTotal);
}
@Override
@Transactional
public DataResponse <Boolean> save(User user) {
if(null==user){
return DataResponse.BuildFailResponse("必传参数不能为空!");
}
int save = userDao.save(user);
return DataResponse.BuildSuccessResponse(save>0?true:false);
}
@Override
public DataResponse <Boolean> insertBatch(List <User> list) {
if(null==list){
return DataResponse.BuildFailResponse("参数不能为空!");
}
int batchSave = userDao.insertBatch(list);
return DataResponse.BuildSuccessResponse(batchSave>0?true:false);
}
@Override
@Transactional
public DataResponse <Boolean> update(User user) {
if(null==user || user.getId()==null){
return DataResponse.BuildFailResponse("必传参数不能为空!");
}
int update = userDao.update(user);
return DataResponse.BuildSuccessResponse(update>0?true:false);
}
@Override
public DataResponse <User> findById(int i) {
User byId = userDao.findById(i);
return DataResponse.BuildSuccessResponse(byId);
}
@Override
public DataResponse <List <User>> findByPage(UserAO ao) {
if(ao==null){
ao.setPage(0);
ao.setPageSize(10);
}else{
ao.setPage(ao.getPageSize() * ao.getPage());
}
int allTotal = userDao.findAllTotal();
List <User> byPage = userDao.findByPage(ao);
return DataResponse.BuildSuccessResponse(byPage,allTotal);
}
}
相关配置
application.properties
logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
applicationContext-mybatis.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:motan="http://api.weibo.com/schema/motan"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd">
<!-- 配置组件扫描 -->
<context:component-scan base-package="com.hong.spring"></context:component-scan>
<!--启用motan的注解-->
<motan:annotation />
<!--加载配置文件-->
<context:property-placeholder location="classpath:jdbc.properties,classpath:motan.properties"/>
<!-- 开启注解 -->
<context:annotation-config />
<!--开启注解事务-->
<tx:annotation-driven transaction-manager="transactionManager" />
<!--放行静态资源-->
<mvc:default-servlet-handler />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/pages/" />
<!-- 后缀 -->
<property name="suffix" value=".html" />
<property name="contentType" value="text/html"/>
</bean>
<!--开启mvc注解事务-->
<!-- 定义注解驱动 -->
<mvc:annotation-driven>
<mvc:message-converters>
<!-- 设置支持中文 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!-- 基础配置 -->
<property name="url" value="${jdbc.url}"></property>
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="username" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<!-- 关键配置 -->
<!-- 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 -->
<property name="initialSize" value="3" />
<!-- 最小连接池数量 -->
<property name="minIdle" value="2" />
<!-- 最大连接池数量 -->
<property name="maxActive" value="15" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="10000" />
<!-- 性能配置 -->
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
<!-- 其他配置 -->
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<!-- 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,
执行validationQuery检测连接是否有效。-->
<property name="testWhileIdle" value="true" />
<!-- 这里建议配置为TRUE,防止取到的连接不可用 ,申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。-->
<property name="testOnBorrow" value="true" />
<!-- 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 -->
<property name="testOnReturn" value="false" />
</bean>
<!--事务管理器-->
<!-- sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 加载 MyBatis 的配置文件 -->
<property name="configLocation" value="classpath:mybatis.xml"/>
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 所有配置的mapper文件 -->
<property name="mapperLocations" value="classpath*:com/hong/spring/mapper/*.xml" />
</bean>
<!-- Mapper 扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描 包下的组件 -->
<property name="basePackage" value="com.hong.spring.dao" />
<!-- 关联mapper扫描器 与 sqlsession管理器 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<!--事务配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
jdbc.properties
config.properties:
#数据库驱动
jdbc.driver=com.mysql.jdbc.Driver
#数据库连接url
jdbc.url=jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8
#数据库用户名
jdbc.user=root
#数据库密码
jdbc.password=123456
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="INFO">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
<SizeBasedTriggeringPolicy size="5 MB"/>
</RollingFile>
</appenders>
<loggers>
<root level="DEBUG">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFile"/>
</root>
</loggers>
</configuration>
logging.properties
org.apache.catalina.core.ContainerBase.[Catalina].level=INFO
org.apache.catalina.core.ContainerBase.[Catalina].handlers=java.util.logging.ConsoleHandler
handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
org.apache.juli.FileHandler.level = FINE
org.apache.juli.FileHandler.directory = ../logs
org.apache.juli.FileHandler.prefix = error-debug.
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
motan.properties
server.port=8083
#地址。我写的就是自己虚拟机的地址。端口号都是一样的。
motan.registry.address=127.0.0.1:2181
motan.server.port=20272
mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- settings -->
<settings>
<!-- 打开延迟加载的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载(即按需加载) -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 打开全局缓存开关(二级缓存)默认值就是 true -->
<setting name="cacheEnabled" value="true"/>
<!-- 开启驼峰命名转换 Table(create_time) -> Entity(createtime) -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 使用列别名代替列名 默认:true seslect name as title from table -->
<setting name="useColumnLabel" value="true"/>
<!--使用jdbc的getGeneratedKeys获取数据库自增主键值-->
<setting name="useGeneratedKeys" value="true"/>
</settings>
<!-- 别名定义 -->
<typeAliases>
<package name="com.hong.spring.entity"/>
</typeAliases>
</configuration>
user.sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键 ',
`user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名称',
`age` int(11) NULL DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
web.xml
<?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_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>motan_server</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext-mybatis.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>motan_server</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- motan优雅起停功能 -->
<listener>
<listener-class>com.hong.spring.utils.MotanServletContextListener</listener-class>
</listener>
</web-app>
pom.xml
<?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">
<parent>
<artifactId>spring_rpc</artifactId>
<groupId>com.hong</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.hong.spring</groupId>
<artifactId>spring_motan_server</artifactId>
<properties>
<!--<log4j-slf4j-impl>2.8</log4j-slf4j-impl>-->
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.25</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!--<dependency>-->
<!--<groupId>org.apache.logging.log4j</groupId>-->
<!--<artifactId>log4j-api</artifactId>-->
<!--<version>2.10.0</version>-->
<!--</dependency>-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.hong</groupId>
<artifactId>spring_dubbo_api</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>log4j-slf4j-impl</artifactId>
<groupId>org.apache.logging.log4j</groupId>
</exclusion>
<exclusion>
<artifactId>mybatis-spring</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-core</artifactId>
<version>RELEASE</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-transport-netty</artifactId>
<version>RELEASE</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- only needed for spring-based features -->
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-springsupport</artifactId>
<version>RELEASE</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-registry-zookeeper</artifactId>
<version>RELEASE</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
启动结果
.IUserService?group=motan-demo-rpc
[2021-02-01 05:47:14,372] Artifact spring_motan_client:war exploded: Artifact is deployed successfully
[2021-02-01 05:47:14,373] Artifact spring_motan_client:war exploded: Deploy took 11,307 milliseconds
springmvc+motan+zk 客户端
D:.
│ pom.xml
│ spring_motan_client.iml
│
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─hong
│ │ │ └─spring
│ │ │ ├─config
│ │ │ │ MotanConfig.java
│ │ │ │
│ │ │ └─controller
│ │ │ UserController.java
│ │ │
│ │ └─resources
│ │ application.properties
│ │ applicationContext.xml
│ │ log4j2.xml
│ │ logging.properties
│ │ motan.properties
│ │ motan_client.xml
│ │
│ └─test
│ └─java
└─web
└─WEB-INF
web.xml
com.hong.spring.controller.UserController
package com.hong.spring.controller;
import com.hong.spring.api.IUserService;
import com.hong.spring.entity.User;
import com.hong.spring.utils.DataResponse;
import com.weibo.api.motan.config.springsupport.annotation.MotanReferer;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Auther: csh
* @Date: 2020/8/18 16:11
* @Description:
*/
@RestController
@RequestMapping("/")
@Log4j2
public class UserController {
//注意这个directUrl必须写,因为这个是getHost的地址可能获取出错,就导致不是127.0.0.1。。。坑!
@MotanReferer(basicReferer = "motantestClientBasicConfig", directUrl = "127.0.0.1:8081")
private IUserService userService;
@RequestMapping(value = "/user",method = RequestMethod.GET)
@ResponseBody
public DataResponse<User> user(Integer id){
try {
return userService.findById(id);
}catch (Exception e){
log.error("获取出错!{}",e);
}
return DataResponse.BuildFailResponse("获取出错!");
}
@RequestMapping(value = "/findAll",method = RequestMethod.GET)
@ResponseBody
public DataResponse<List<User>> findAll(){
try {
return userService.findByAll();
}catch (Exception e){
log.error("获取出错!{}",e);
}
return DataResponse.BuildFailResponse("获取出错!");
}
}
com.hong.spring.config.MotanConfig
package com.hong.spring.config;
import com.weibo.api.motan.config.springsupport.BasicRefererConfigBean;
import com.weibo.api.motan.config.springsupport.ProtocolConfigBean;
import com.weibo.api.motan.config.springsupport.RegistryConfigBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author: csh
* @Date: 2021/2/1 16:08
* @Description:
*/
@Configuration
public class MotanConfig {
@Bean(name = "demoMotan")
public ProtocolConfigBean demoMotanProtocolConfig() {
ProtocolConfigBean config = new ProtocolConfigBean();
//Id无需设置
// config.setId("demoMotan");
config.setName("motan");
config.setDefault(true);
config.setMaxContentLength(1048576);
config.setHaStrategy("failover");
config.setLoadbalance("roundrobin");
return config;
}
// @Bean(name = "demoMotan2")
// public ProtocolConfigBean protocolConfig2() {
// ProtocolConfigBean config = new ProtocolConfigBean();
// config.setName("motan");
// config.setMaxContentLength(1048576);
// config.setHaStrategy("failover");
// config.setLoadbalance("roundrobin");
// return config;
// }
@Bean(name = "registry")
public RegistryConfigBean registryConfig() {
RegistryConfigBean config = new RegistryConfigBean();
config.setRegProtocol("zookeeper");
config.setAddress("127.0.0.1:2181");
return config;
}
@Bean(name = "motantestClientBasicConfig")
public BasicRefererConfigBean baseRefererConfig() {
BasicRefererConfigBean config = new BasicRefererConfigBean();
config.setProtocol("demoMotan");
config.setGroup("motan-demo-rpc");
config.setModule("motan-demo-rpc");
config.setApplication("hongMotanClient");
config.setRegistry("registry");
config.setCheck(false);
config.setAccessLog(true);
config.setRetries(2);
config.setThrowException(true);
return config;
}
}
配置文件
application.properties
logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
applicationContext.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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置组件扫描 -->
<context:component-scan base-package="com.hong.spring"></context:component-scan>
<!--加载配置文件-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<property name="locations">
<list>
<value>classpath:motan.properties</value>
</list>
</property>
</bean>
<!-- 开启注解 -->
<context:annotation-config />
<mvc:default-servlet-handler />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/pages/" />
<!-- 后缀 -->
<property name="suffix" value=".html" />
<property name="contentType" value="text/html"/>
</bean>
<!--开启mvc注解事务-->
<!-- 定义注解驱动 -->
<mvc:annotation-driven>
<mvc:message-converters>
<!-- 设置支持中文 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
</beans>
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="INFO">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
<SizeBasedTriggeringPolicy size="5 MB"/>
</RollingFile>
</appenders>
<loggers>
<root level="DEBUG">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFile"/>
</root>
</loggers>
</configuration>
logging.properties
org.apache.catalina.core.ContainerBase.[Catalina].level=INFO
org.apache.catalina.core.ContainerBase.[Catalina].handlers=java.util.logging.ConsoleHandler
handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
org.apache.juli.FileHandler.level = FINE
org.apache.juli.FileHandler.directory = ../logs
org.apache.juli.FileHandler.prefix = error-debug.
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
motan.properties
#地址。我写的就是自己虚拟机的地址。端口号都是一样的。
motan.registry.address=127.0.0.1:2181
motan.client.port=20271
motan_client.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:motan="http://api.weibo.com/schema/motan"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd">
<motan:annotation package="com.hong.spring.controller"/>
</beans>
web.xml
<?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_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>motan_client</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml,
classpath:motan_client.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>motan_client</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
pom.xml
<?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">
<parent>
<artifactId>spring_rpc</artifactId>
<groupId>com.hong</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.hong.spring</groupId>
<artifactId>spring_motan_client</artifactId>
<dependencies>
<dependency>
<groupId>com.hong</groupId>
<artifactId>spring_dubbo_api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-core</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-transport-netty</artifactId>
<version>RELEASE</version>
</dependency>
<!-- only needed for spring-based features -->
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-springsupport</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-registry-zookeeper</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
</project>
springboot整合
服务端
项目结构
│ pom.xml
│ springboot_motan_server.iml
│
└─src
└─main
├─java
│ └─com
│ └─hong
│ └─springboot
│ │ Application.java
│ │
│ ├─config
│ │ DruidConfig.java
│ │ MotanConfig.java
│ │
│ ├─dao
│ │ UserMapper.java
│ │
│ └─provider
│ UserServiceImpl.java
│
└─resources
application.properties
代码实现
springboot_all/springboot_motan_server/pom.xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.hong.springboot</groupId>
<artifactId>springboot_all</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>1.0.0-SNAPASHOT</version>
<groupId>com.hong.springboot</groupId>
<artifactId>springboot_motan_server</artifactId>
<properties>
<java.version>1.8</java.version>
<motan.version>1.1.8</motan.version>
</properties>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.hong.springboot</groupId>
<artifactId>springboot_dubbo_api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-registry-zookeeper</artifactId>
<version>RELEASE</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-core</artifactId>
<version>${motan.version}</version>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-transport-netty</artifactId>
<version>${motan.version}</version>
</dependency>
<!-- only needed for spring-based features -->
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-springsupport</artifactId>
<version>${motan.version}</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
com.hong.springboot.provider.UserServiceImpl
package com.hong.springboot.provider;
import com.hong.springboot.api.IUserService;
import com.hong.springboot.dao.UserMapper;
import com.hong.springboot.entity.User;
import com.hong.springboot.utils.DataResponse;
import com.weibo.api.motan.config.springsupport.annotation.MotanService;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
/**
* @Auther: csh
* @Date: 2020/8/18 15:16
* @Description:用户实现
*/
@MotanService
public class UserServiceImpl implements IUserService {
@Autowired
private UserMapper userDao;
@Override
public DataResponse <List <User>> findByAll() {
List <User> allUserList = userDao.findAllUser();
return DataResponse.BuildSuccessResponse(allUserList, allUserList.size());
}
}
com.hong.springboot.dao.UserMapper
package com.hong.springboot.dao;
import com.hong.springboot.entity.User;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @Auther: csh
* @Date: 2020/8/18 15:04
* @Description:用户dao层
*/
public interface UserMapper {
@Select("select id,user_name,age from user")
List <User> findAllUser();
}
com.hong.springboot.config.MotanConfig
package com.hong.springboot.config;
import com.weibo.api.motan.config.springsupport.AnnotationBean;
import com.weibo.api.motan.config.springsupport.BasicServiceConfigBean;
import com.weibo.api.motan.config.springsupport.ProtocolConfigBean;
import com.weibo.api.motan.config.springsupport.RegistryConfigBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author: csh
* @Date: 2021/2/2 10:36
* @Description:
*/
@Configuration
public class MotanConfig {
/**
*
* 功能描述: 声明Annotation用来指定需要解析的包名
*
* @param:
* @return:
* @auther: csh
* @date: 2021/2/2 9:48
*/
@Bean
@ConfigurationProperties(prefix = "motan.annotation")
public AnnotationBean motanAnnotationBean() {
AnnotationBean motanAnnotationBean = new AnnotationBean();
return motanAnnotationBean;
}
/**
*
* 功能描述: 配置ProtocolConfig、RegistryConfig、BasicServiceConfig的bean对象,功能与xml配置中的protocol、registry、basicService标签一致。
*
* @param:
* @return:
* @auther: csh
* @date: 2021/2/2 9:48
*/
@Bean(name = "demoMotan")
@ConfigurationProperties(prefix = "motan.protocol")
public ProtocolConfigBean protocolConfig1() {
ProtocolConfigBean config = new ProtocolConfigBean();
return config;
}
@Bean(name = "registryConfig")
@ConfigurationProperties(prefix = "motan.registry")
public RegistryConfigBean registryConfig() {
RegistryConfigBean config = new RegistryConfigBean();
return config;
}
@Bean
@ConfigurationProperties(prefix = "motan.server")
public BasicServiceConfigBean baseServiceConfig() {
BasicServiceConfigBean config = new BasicServiceConfigBean();
config.setExport("demoMotan:8086");
config.setAccessLog(false);
config.setShareChannel(true);
return config;
}
}
application.properties
#避免端口冲突
server.port=8087
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
#mybatis配置
mybatis.typeAliasesPackage=com.hong.springboot.entity
##注册中心配置
#注册中心协议
motan.registry.regProtocol=zookeeper
#注册中心地址
motan.registry.address=localhost:2181
#注册中心连接超时时间(毫秒)
motan.registry.requestTimeout=3000
#注册中心请求超时时间(毫秒)
motan.registry.connectTimeout=3000
##协议配置
#协议名称
motan.protocol.name=motan
#最小工作pool线程数
motan.protocol.minWorkerThread=20
#最大工作pool线程数
motan.protocol.maxWorkerThread=50
motan.protocol.filter=statistic
#指定需要解析的包名
motan.annotation.package=com.hong.springboot
##客户端配置
motan.server.group=hongGroup
motan.server.check=false
#请求超时时间(毫秒)
motan.server.requestTimeout.3000
#连接超时时间(毫秒)
motan.server.connectTimeout=5000
motan.server.registry=registryConfig
#应用名称
motan.server.application=hongMotanServer
motan.server.module=motan-hong-rpc
com.hong.springboot.Application
package com.hong.springboot;
import com.weibo.api.motan.common.MotanConstants;
import com.weibo.api.motan.util.MotanSwitcherUtil;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @author: csh
* @Date: 2020/11/21 11:37
* @Description:
*/
@SpringBootApplication(scanBasePackages = "com.hong.springboot")
@MapperScan("com.hong.springboot.dao")
public class Application {
public static void main(String[] args) {
//这一行代码是必须的,否则无法启动spring,然后再将motan放到spring中
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);
}
}
com.hong.springboot.config.DruidConfig
package com.hong.springboot.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
/**
* @author: csh
* @Date: 2021/1/8 18:08
* @Description:数据源配置
*/
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return new DruidDataSource();
}
}
结果
客户端
项目结构
│ pom.xml
│ springboot_motan_client.iml
│
└─src
└─main
├─java
│ └─com
│ └─hong
│ └─springboot
│ │ Application.java
│ │
│ ├─config
│ │ MotanClientConfig.java
│ │
│ └─controller
│ IndexController.java
│ UserController.java
│
└─resources
application.properties
com.hong.springboot.config.MotanClientConfig
package com.hong.springboot.config;
import com.weibo.api.motan.config.springsupport.AnnotationBean;
import com.weibo.api.motan.config.springsupport.BasicRefererConfigBean;
import com.weibo.api.motan.config.springsupport.ProtocolConfigBean;
import com.weibo.api.motan.config.springsupport.RegistryConfigBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*
* 功能描述: motan的配置
*
* @param:
* @return:
* @auther: csh
* @date: 2021/2/2 11:47
*/
@Configuration
public class MotanClientConfig {
/**
* 客户端配置
*
* @return BasicRefererConfigBean
*/
@Bean(name = "clientBasicConfig")
@ConfigurationProperties(prefix = "motan.client")
public BasicRefererConfigBean baseRefererConfig() {
BasicRefererConfigBean config = new BasicRefererConfigBean();
return config;
}
/**
* 声明Annotation用来指定需要解析的包名
*
* @return AnnotationBean
*/
@Bean
@ConfigurationProperties(prefix = "motan.annotation")
public static AnnotationBean motanAnnotationBean() {
AnnotationBean motanAnnotationBean = new AnnotationBean();
return motanAnnotationBean;
}
/**
* Motan协议配置
*
* @return ProtocolConfigBean
*/
@Bean(name = "motan")
@ConfigurationProperties(prefix = "motan.protocol")
public ProtocolConfigBean protocolConfig() {
ProtocolConfigBean config = new ProtocolConfigBean();
return config;
}
/**
* Motan注册中心配置
*
* @return RegistryConfigBean
*/
@Bean(name = "registryConfig")
@ConfigurationProperties(prefix = "motan.registry")
public RegistryConfigBean registryConfig() {
RegistryConfigBean config = new RegistryConfigBean();
return config;
}
}
com.hong.springboot.Application
package com.hong.springboot;
import com.weibo.api.motan.common.MotanConstants;
import com.weibo.api.motan.util.MotanSwitcherUtil;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
/**
* @author: csh
* @Date: 2020/11/21 11:37
* @Description:springboot motan消费
*/
@SpringBootApplication(scanBasePackages = "com.hong.springboot")
public class Application {
public static void main(String[] args) {
//先启动spring 再加载motan
SpringApplication.run(Application.class, args);
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);
}
}
springboot_all/springboot_motan_client/pom.xml
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.hong.springboot</groupId>
<artifactId>springboot_all</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.hong.springboot</groupId>
<artifactId>springboot_motan_client</artifactId>
<properties>
<java.version>1.8</java.version>
<motan.version>1.1.8</motan.version>
</properties>
<dependencies>
<dependency>
<groupId>com.hong.springboot</groupId>
<artifactId>springboot_dubbo_api</artifactId>
<version>1.0.0-SNAPSHOT</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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-registry-zookeeper</artifactId>
<version>RELEASE</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-core</artifactId>
<version>${motan.version}</version>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-transport-netty</artifactId>
<version>${motan.version}</version>
</dependency>
<!-- only needed for spring-based features -->
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-springsupport</artifactId>
<version>${motan.version}</version>
</dependency>
</dependencies>
<!--静态资源导出问题-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
application.properties
#避免端口冲突
server.port=8088
##注册中心配置
#注册中心协议
motan.registry.regProtocol=zookeeper
#注册中心地址
motan.registry.address=localhost:2181
#注册中心连接超时时间(毫秒)
motan.registry.requestTimeout=3000
#注册中心请求超时时间(毫秒)
motan.registry.connectTimeout=3000
##协议配置
#协议名称
motan.protocol.name=motan
#最小工作pool线程数
motan.protocol.minWorkerThread=20
#最大工作pool线程数
motan.protocol.maxWorkerThread=50
motan.protocol.filter=statistic
#指定需要解析的包名
motan.annotation.package=com.hong.springboot
##客户端配置
motan.client.protocol=motan
motan.client.group=hongGroup
motan.client.check=false
#请求超时时间(毫秒)
motan.client.requestTimeout.3000
#连接超时时间(毫秒)
motan.client.connectTimeout=5000
motan.client.registry=registryConfig
com.hong.springboot.controller.UserController
package com.hong.springboot.controller;
import com.hong.springboot.api.IUserService;
import com.hong.springboot.entity.User;
import com.hong.springboot.utils.DataResponse;
import com.weibo.api.motan.config.springsupport.annotation.MotanReferer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Auther: csh
* @Date: 2020/8/18 16:11
* @Description:
*/
@RestController
@Slf4j
public class UserController {
@MotanReferer(basicReferer = "clientBasicConfig",requestTimeout =3000 )
private IUserService userService;
@GetMapping("/findByAll")
public DataResponse <List <User>> findByAll() {
try {
return userService.findByAll();
} catch (Exception e) {
log.error("查询出错{}", e);
}
return DataResponse.BuildFailResponse("查询出错!");
}
}
com.hong.springboot.controller.IndexController
package com.hong.springboot.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author: csh
* @Date: 2021/1/12 10:16
* @Description:
*/
@RestController
public class IndexController {
@RequestMapping("/")
public String index() {
return "成功!";
}
}
启动成功:
调用发生错误
查看相关的说明发现是请求超时:https://www.bookstack.cn/read/Motan/spilt.2.d6ce09276872b11f.md 将客户端请求超时改为3秒
@MotanReferer(basicReferer = "clientBasicConfig",requestTimeout =3000 )
结果
请求:http://localhost:8088/findByAll
最后
rpc的框架非常多,目前以上是流程的种类,当然还有非常非常多的未知名的框架,但是其实最终实现的目的就是跨服务间互相调用,当然为了高可用加上注册中心可以实现动态横向增缩,使必要的时候可以一键式增缩子节点,实现高可用,相对来说非常靠谱,但是好归好,话说回来,因为拆分了所以系统结构更加复杂,维护成本、开发成本投入也更多,所以利弊取决于企业及项目用户规模和阶段。
看完啦觉得不错给个"一键三联"呗,日后方便阅读接下来的文章~
以下是之前的文章可以参考:
spring整合各种RPC框架(netty、dubbo、dubbox、gRPC、Motan)-续(gRPC)
spring整合各种RPC框架(netty、dubbo、dubbox、RPC、Motan)-续netty
spring整合各种RPC框架(netty、dubbo、dubbox、RPC、Motan)