首頁 > 軟體

如何在Netty中註解使用Service或者Mapper

2022-02-14 19:00:04

Netty註解使用Service或Mapper

SpringBoot搭配Netty使用,在Handler中註解使用Service/Mapper 一直 為null。起初使用 SpringBoot啟動類繼承ApplicationContextAware,再寫一個靜態方法獲取Bean來解決。

放在伺服器上跑了幾個小時就出現了問題,好像是該方案造成的。

另闢蹊徑,再看網上給出的答案,因為 Handler 是 new出來的,不被Spring管理,所以註解根本就沒有什麼作用。

思前想後,(有BUG,下文修正解決:覺得可以給Handler新增@Component 註解交給Spring 管理,再通過構造方法把 Handler 傳遞給Server。結構程式碼):

Handler

@Component
public class OBDHandler extends ChannelInboundHandlerAdapter {
 
    private final Logger logger = LoggerFactory.getLogger(getClass());
    
    @Autowired
    private OBDMapper mOBDMapper;
}

Server

public class OBDServer { 
    private Logger log = LoggerFactory.getLogger(getClass());
    private OBDHandler obdHandler;
    private int port; 
    public OBDServer(int port,OBDHandler obdHandler) {
        this.port = port;
        this.obdHandler = obdHandler;
    }
 
    private void bind() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(group)//
        .channel(NioServerSocketChannel.class) //
        .childHandler(new ChannelInitializer<SocketChannel>() { //
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024*1024,0,4));
                ch.pipeline().addLast(obdHandler);
            }
        });
    }
}

建立Server

@Configuration
public class NettyConfig {    
    @Autowired
    private OBDHandler obdHandler;
    
    @Bean
    public OBDServer obdServer(){
        OBDServer obdServer = new OBDServer(7788,obdHandler);
        obdServer.startServer();
        return obdServer;
    }
}

二次修訂

並行需要建立多個Handler,而被Spring託管的單例Handler會造成以下錯誤:

is not a @Sharable handler, so can't be added or removed multiple times.

最終通過在Server中注入 Service/Mapper,再通過Handler構造傳遞:

public class OBDServer { 
    @Autowired
    private OBDMapper mOBDMapper;    
    public OBDServer(int port) {
        this.port = port;
    }
 
    private void bind() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(group)//
        .channel(NioServerSocketChannel.class) //
        .childHandler(new ChannelInitializer<SocketChannel>() { //
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024*1024,0,4));
                ch.pipeline().addLast(new OBDHandler(mOBDMapper));
            }
        });
    }
}

Netty handler注入service為空

注入方式

@Slf4j
@Component
public class BootNettyChannelInboundHandlerAdapter extends ChannelInboundHandlerAdapter {
   public static BootNettyChannelInboundHandlerAdapter 
   bootNettyChannelInboundHandlerAdapter;
    //1.正常注入[記得主類也需要使用@Component註解]
    @Autowired
    private DeviceUpService deviceUpService;
    //2.初始化構造方法一定要有
    public BootNettyChannelInboundHandlerAdapter() {
 
    }
    //3.容器初始化的時候進行執行-這裡是重點
    @PostConstruct
    public void init() {
        bootNettyChannelInboundHandlerAdapter = this;
        bootNettyChannelInboundHandlerAdapter.deviceUpService = this.deviceUpService;
    }
}

完成以上步驟後通過

bootNettyChannelInboundHandlerAdapter.deviceUpService

呼叫service類即可

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com