[TOC]
preface
The last article talked about a beginner’s demo of Netty; On the project, I have finished the data processing and will start to save the database. I use mybatis framework, if used alone or feel more troublesome, so I use SpringBoot + Mybatis +netty; This article mainly talks about netty and Springboot integration, and I encountered problems in this process, and how to solve;
The body of the
When I was integrating Springboot with Netty, I found numerous articles in Google and Baidu, but none of them was what I wanted, nor could THEY reach the purpose I wanted.
code
1. Create a SpringBoot project and add netty dependencies to the POM file:
Ty < dependency > < groupId > io.net < / groupId > < artifactId > netty -all < / artifactId > < version > 5.0.0. 1 < / version > </dependency>Copy the code
2. Create a Netty service
You can actually copy the three Netty service classes from the previous article with some minor modifications. Here in order to facilitate the demonstration, and repair are changed, directly posted out;
- DiscardServer class:
@Component
public class DiscardServer {
@Resource
private ChildChannelHandler childChannelHandler;
public void run(int port) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
System.out.println("Ready to run port:" + port);
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128)
.childHandler(childChannelHandler);
// Bind the port and wait for synchronization successfully
ChannelFuture f = bootstrap.bind(port).sync();
// Wait for the service listening port to close
f.channel().closeFuture().sync();
} finally {
// Exit to release thread resourcesworkerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); }}}Copy the code
- ChildChannelHandler class
@Component
public class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
@Resource
private DiscardServerHandler discardServerHandler;
public void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(discardServerHandler); }}Copy the code
3. The DiscardServerHandler class
Note that the @sharable annotation is required on the DiscardServerHandler class, otherwise an error will be reported;
@Component
@Sharable
public class DiscardServerHandler extends ChannelHandlerAdapter {
@Resource
private BaseService baseService;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
try {
ByteBuf in = (ByteBuf) msg;
System.out.println("What is transmitted?");
System.out.println(in.toString(CharsetUtil.UTF_8));
// Call the service service here
baseService.test();
} finally{ ReferenceCountUtil.release(msg); }}@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// If there is an exception, close itcause.printStackTrace(); ctx.close(); }}Copy the code
3.NET TY Calls required service classes
1. BaseService interface
public interface BaseService {
/**
* 测试接口
*/
void test(a);
}
Copy the code
2. BaseServiceImpl:
@Service
public class BaseServiceImpl implements BaseService {
@Override
public void test(a) {
System.out.println("Call the service"); }}Copy the code
4 Springboot Starts the class
- Since main is a static method, netty service startup class is not a static class, in the main method needs to use a new way to start;
- You can also change the Netty service startup class to a static class, and then use the new method to construct other classes when calling non-static classes.
I also read several articles about implementing the CommandLineRunner interface, so I used the SpringBoot boot boot class to implement the CommandLineRunner interface’s Run method and then start the Netty service in the Run method
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@Resource
private DiscardServer discardServer;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
discardServer.run(8080); }}Copy the code
5. Test
Write a socket that can send data.
The data sent is:
public static void main(String[] args){
try {
Socket socket=new Socket("localhost".8080);
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter=new PrintWriter(outputStream);
printWriter.write("$08/22 11:58 tmb00035ET3318/04029.94, 027.25, 20.00, 20.00 $");
printWriter.flush();
socket.shutdownOutput();
socket.close();
} catch(IOException e) { e.printStackTrace(); }}Copy the code
My test results:
The transfer content is $tmb00035ET3318/08/22 11:5804029.94.027.25.20.00.20.00$
aaaaa
Copy the code
At this point, netty’s integration with SpringBoot is complete;
The problems I encountered in the integration process
I use SpringBoot in conjunction with netty’s process
Springboot starts the Netty startup class (DiscardServer), and the Netty startup class (DiscardServer) calls the initialization channel class (ChildChannelHandler). Then initialize the Channel class and call the (DiscardServerHandler) class; The DiscardServerHandler class then calls the Service service; Here’s an example:
Question:
- Instead of implementing the CommandLineRunner interface, I directly start the Netty service using a new method in the main method
- I implement the CommandLineRunner interface, but I start the Netty service using new in the run method or I start netty using injection in the run method, but call another class somewhere else using new;
- The DiscardServerHandler class is marked @sharable, and an error is reported;
The problem is that there is a point in springBoot’s integration of Netty that calls other classes in a new way, so that although SpringBoot can start, Netty can also start, but the netty service in the new construction of the class cannot rely on injection. A null pointer exception is reported;
For example, in this example, I call DiscardServerHandler from ChildChannelHandler with a new method. Other procedures are called with an injection method, which causes this problem.
When I encountered a null pointer, I printed out the spring-hosted bean. All the classes were hosted by Spring, but I couldn’t inject them, and I never understood what was going on. I ended up using the extreme method of fetching the spring context when calling the service and then fetching the bean by name. You Google or Baidu: unmanaged class call spring hosted class, can find a lot of articles; Although this way can solve the above problems, but it is always not good;
Final solution: Use Spring’s dependency injection for all calls between classes, not new or static
conclusion
Since the project uses Spring, class to class calls should use dependency injection, otherwise null Pointers will be reported (unmanaged objects call Spring-managed objects); This is also a common sense of the problem, but now they just encounter such a problem, or to step on the pit to encounter memory ah; These problems troubled me for two or three days, or to have the experience of the people with, if the experience of the people with words, said not a few minutes to fix;
This is the end of netty’s article, the next is to catch up on the project; Ha ha,
GitHub Project address: