基于Netty自定义RPC 服务端模块rpc-provider(四)

首先是接口的实现,这一点和普通接口实现是一样的

package com.lwl.service;

import com.lwl.common.JSONSerializer;
import com.lwl.common.RpcDecoder;
import com.lwl.common.RpcRequest;
import com.lwl.handler.UserServiceHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements IUserService {

    //客户端需要调用的防范
    @Override
    public String sayHello(String msg) {

        System.out.println("sayHello() -->{}"+msg);
        return "success";
    }

    //创建一个方法启动服务器
    public static void startServer(String ip,int port) throws InterruptedException {
        //创建两个线程池对象
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workGroup = new NioEventLoopGroup();

        //创建服务器启动引导对象
        ServerBootstrap serverBootstrap = new ServerBootstrap();


        //配置启动引导对象
        serverBootstrap.group(bossGroup,workGroup)
                //设置通道为nio
                .channel(NioServerSocketChannel.class)
                //创建监听器
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                        //获取管道对象
                        ChannelPipeline pipeline = nioSocketChannel.pipeline();
                        //设置编码
                        pipeline.addLast(new StringEncoder());
                        pipeline.addLast( new RpcDecoder(RpcRequest.class, new JSONSerializer()));
                        //将自定义的 channelHandler 添加到通道中
                        pipeline.addLast(new UserServiceHandler());

                    }
                });


        //绑定端口号
        ChannelFuture sync = serverBootstrap.bind(8999).sync();
    }

}

在实现中加入了netty的服务器启动程序,上面的代码中添加了 String类型的编解码 handler,添加了一个自定义handler
自定义 handler 逻辑如下:

package com.lwl.handler;

import com.lwl.common.RpcRequest;
import com.lwl.service.UserServiceImpl;
import com.lwl.util.SpringContextUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.lang.reflect.Method;

/**
 * 自定义业务处理器
 */
public class UserServiceHandler extends ChannelInboundHandlerAdapter {

    /**
     * 当客户端读取数据时,该方法被调用
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//        //客户端发送请求时的一个参数 约定    UserService#sayHello#are you ok
//        //   判断当前的请求是否符合规则
//        if (msg.toString().startsWith("UserService")){
//            //符合规则 调用实现类 到一个result
//            UserServiceImpl userService = new UserServiceImpl();
//            String result = userService.sayHello(msg.toString().substring(msg.toString().lastIndexOf("#") + 1));
//            //将结果写到客户端
//            ctx.writeAndFlush(result);
//        }


        /**
         *   1、从RpcRequest对象中获取属性 (调用类名,方法,参数等)
         */
        RpcRequest rpcRequest =(RpcRequest)msg;
        String className = rpcRequest.getClassName();
        String methodName = rpcRequest.getMethodName();
        Object[] parameters = rpcRequest.getParameters();
        Class<?>[] parameterTypes = rpcRequest.getParameterTypes();

        Class<?> aClass = Class.forName(className);
        //从spring容器获取对象
        UserServiceImpl o = (UserServiceImpl) SpringContextUtil.getBean(aClass);
        Method method = aClass.getMethod(methodName, parameterTypes);
        //反射调用
        String result = (String) method.invoke(o, parameters);

        ctx.writeAndFlush(result);
    }
}

SpringContextUtil

package com.lwl.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContextUtil implements ApplicationContextAware {


    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    /**
     * 获取applicationContext
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通过name获取 Bean.
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 通过class获取Bean.
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     *     通过name,以及Clazz返回指定的Bean
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }


}

还需要一个启动类:

package com.lwl;

import com.lwl.service.UserServiceImpl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ServerBoot {

    public static void main(String[] args) throws InterruptedException {

        SpringApplication.run(ServerBoot.class, args);

        //启动服务器
        UserServiceImpl.startServer("127.0.0.1",8999);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时小浅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值