上次手写了一个简单的RPC框架,这次对其进行优化升级,添加了版本号,利用Spring进行管理,详细修改过程请看代码。
首先在rpc-server-provider模块下pom文件导入Spring依赖。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.24.RELEASE</version>
</dependency>
自定义一个注解,用于接收类与版本号。
@Target(ElementType.TYPE)//修饰的是类或者接口 对象范围
@Retention(RetentionPolicy.RUNTIME)//保留到运行时
@Component//被Spring进行扫描
public @interface RpcService {
Class<?> value();//服务的类与接口
String version() default "";
}
为HelloServiceImpl加上注解
@RpcService(value = IHelloService.class,version = "v1.0")
public class HelloServiceImpl implements IHelloService {
@Override
public String sayHello(String content) {
System.out.println("{v1.0}request in sayHello:"+content);
return "Say Hellp: "+content;
}
@Override
public String saveUser(User user) {
System.out.println("{v1.0}request in SaveUser:"+user.toString());
return "SUCCESS";
}
}
新建YbRpcServer实现ApplicationContextAware、InitializingBean 接口用来处理接口传递的信息与bean的初始化过程。
@Component
public class YbRpcServer implements ApplicationContextAware, InitializingBean {
ExecutorService executorService= Executors.newCachedThreadPool();
private int port;
private Map<String,Object> handlerMap=new HashMap<>();//用来存储对应Bean
public YbRpcServer(int port) {
this.port = port;
}
@Override
public void afterPropertiesSet() {
ServerSocket serverSocket=null;
try {
serverSocket = new ServerSocket(port);
while (true){
Socket socket= serverSocket.accept();
//每个Socker 交给一个ProcessorHandler来处理
executorService.execute(new ProcessorHandler(socket,handlerMap));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String,Object> serviceBeanMap=applicationContext.getBeansWithAnnotation(RpcService.class);
if(!serviceBeanMap.isEmpty()){
for (Object serviceBean:serviceBeanMap.values()){
//拿到注解
RpcService rpcService= serviceBean.getClass().getAnnotation(RpcService.class);
String serviceName = rpcService.value().getName();//拿到接口类
String version =rpcService.version();//拿到版本号
if(!StringUtils.isEmpty(version)){
serviceName+="-"+version;
}
handlerMap.put(serviceName,serviceBean);
}
}
}
}
新建类SpringConfig用于将类交予Spring管理
@Configuration
@ComponentScan(basePackages ="com.rpc" )
public class SpringConfig {
@Bean(name = "ybRpcServer")
public YbRpcServer ybRpcServer(){
return new YbRpcServer(8080);
}
}
修改RpcRequest中传递版本号。
public class RpcRequest implements Serializable {
private String className;
private String methodName;
private Object[] parameters;
private String version;
接下来改一下服务器启动方式,大功告成。记得在客户端传递版本号。
public class App {
public static void main(String[] args) {
// IHelloService helloService=new HelloServiceImpl();
// RpcProxyServer proxyServer=new RpcProxyServer();
// proxyServer.publisher(helloService,8080);
ApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);
((AnnotationConfigApplicationContext)context).start();
}
}
后续如果有空可以利用NIO优化下IO问题目前还是BIO的模型。