All Projects → kgusarov → spring-boot-netty

kgusarov / spring-boot-netty

Licence: MIT license
Spring Boot integration with Netty

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to spring-boot-netty

websocket-scala-client
WebSocket client based on Netty
Stars: ✭ 37 (-27.45%)
Mutual labels:  netty
rpc-spring-boot-starter
自定义rpc框架,支持Java序列化和protobuf序列化协议,多种负载均衡算法
Stars: ✭ 75 (+47.06%)
Mutual labels:  netty
smartacus-mqtt-broker
smartacus-mqtt-broker is a Java-based open source MQTT broker that fully supports MQTT 3.x .Using Netty 4.1.37
Stars: ✭ 25 (-50.98%)
Mutual labels:  netty
xmutca-rpc
Xmutca-rpc是一个基于netty开发的分布式服务框架,提供稳定高性能的RPC远程服务调用功能,支持注册中心,服务治理,负载均衡等特性,开箱即用。
Stars: ✭ 18 (-64.71%)
Mutual labels:  netty
hrpc
A simple Java RPC framework based on Spring, Netty, Protobuf and Consul
Stars: ✭ 34 (-33.33%)
Mutual labels:  netty
JavaHub
Java程序员学习之路,持续更新原创内容,欢迎Star
Stars: ✭ 27 (-47.06%)
Mutual labels:  netty
CampusForum
校园论坛
Stars: ✭ 62 (+21.57%)
Mutual labels:  netty
xpllyn
个人网站项目。使用spring-boot搭建,集合了博客、书籍下载、留言、github page查询、Netty+WebSocket搭建的Web网页聊天室等功能。其中github page查询工具使用了github的api,Web聊天室使用Netty+Websocket+Redis+MySQL搭建服务,使用Shiro安全框架实现身份验证/登录,采用MySql作为网站的数据库,使用Redis用于聊天记录缓存,实现了群聊、单聊、查询用户、添加好友、聊天记录等功能。
Stars: ✭ 21 (-58.82%)
Mutual labels:  netty
toy-rpc
Java基于Netty,Protostuff和Zookeeper实现分布式RPC框架
Stars: ✭ 55 (+7.84%)
Mutual labels:  netty
NioSmtpClient
Smtp Client based on Netty
Stars: ✭ 25 (-50.98%)
Mutual labels:  netty
styx
Programmable, asynchronous, event-based reverse proxy for JVM.
Stars: ✭ 250 (+390.2%)
Mutual labels:  netty
spring-boot-learn-box
spring boot集成其他组件
Stars: ✭ 21 (-58.82%)
Mutual labels:  netty
rulegin
基于JavaScript Engine的轻量级规则引擎系统,重构于开源IOT项目thingboard
Stars: ✭ 100 (+96.08%)
Mutual labels:  netty
freeswitch-esl-all
freeswitch event socket base on netty 4 and has some new features.
Stars: ✭ 110 (+115.69%)
Mutual labels:  netty
thinglinks
开源ThingLinks物联网一体化平台,高性能、高吞吐量、高扩展性的物联网平台!单机可以支持百万链接,同时支持自定义扩展功能,功能非常强大,采用netty作为通信层组件,支持插件化开发集成!
Stars: ✭ 338 (+562.75%)
Mutual labels:  netty
small-rpc
🔥基于netty和hessian的一个轻量级RPC调用框架
Stars: ✭ 21 (-58.82%)
Mutual labels:  netty
dsip
通过netty网络框架,编解码sip消息。 以及国标gb28181的部分功能, 不依赖spring,方便集成
Stars: ✭ 19 (-62.75%)
Mutual labels:  netty
packetevents
PacketEvents is a powerful packet library. Our packet wrappers are efficient and easy to use. We support many protocol versions. (1.8+)
Stars: ✭ 235 (+360.78%)
Mutual labels:  netty
netty-tcnative-alpine
Build netty-tcnative native binaries for Alpine Linux.
Stars: ✭ 20 (-60.78%)
Mutual labels:  netty
codes-scratch-zookeeper-netty
zk + netty 实现集群节点文件同步服务
Stars: ✭ 29 (-43.14%)
Mutual labels:  netty

spring-boot-netty

Build Status Coverage Maven Central

Latest Release Highlights

Motivation

Both Spring Boot and Netty are awesome projects! So, why not use them together? Imagine, how cool it would be, if you were able to use something similar to Spring WebMvc when working with Netty!

So, this is what this little project is aimed for. Initially, I've developed this for myself in order to be able to use Netty in several projects along with Spring Boot.

HOWTO

Basics

As, it is already mentioned, this project aims to be similar to Spring WebMvc, so here we have concepts of controllers and handler methods, as well as filters. So, where should you start? I like to say, that the code is the best documentation! So, we will look into codes, and I am going to refer some tests, you might look at! In order to integrate Spring Boot with Netty, you have to use @EnableNettyServers annotation on your configuration class. This will turn the integration ON. However, in comparison to some other Spring Boot Enable annotations, you WILL have to do some additional work - since we don't have a lot of default values here! First thing to do, is to add the configuration to the Spring Context (for example, via .yaml file):

netty:
  servers:
    - name: server1
      host: localhost
      port: 40000

Take a look at this class for possible configuration properties, however for us it is time to move on! Next thing to do is to create some handlers for your server. If you have defined at least one server in configuration, you must have some handlers for it, otherwise, you will see BeanCreationException here. Below, we will explore various handlers and how they work together.

We are going to start with @NettyOnConnect handler. This one allows to react on connection events. All the handlers should be present in a class annotated with @NettyController annotation. So, in case we want to react on connect event, we should do the following:

@NettyController
public class OnConnectController {   
    @NettyOnConnect(serverName = "server1", priority = 1)
    private void onConnect1() {
        System.out.println("Hello, world!");
    }

    @NettyOnConnect(serverName = "server1", priority = 2)
    ByteBuf onConnect2(final ChanneHandlerContext ctx) {
        ctx.writeAndFlush(Unpooled.copyLong(new Random().nextLong()));
        return Unpooled.copyLong(new Random().nextLong());
    }
}

As a result, when conneting to the server, you should see Hello, world! in server's stdout as well as receive two random long numbers. As you can see, handlers have priority (this applies for all types of them, not only connect ones). Also, if the method returns something, this something will be sent to client. Also it is possible to inject some arguments into the handler method. This is ensured by having method parameter resolvers . By default, it is possible to receive ChanneHandlerContext or Channel as a connection handler parameter.

Now, moving to @NettyOnDisconnect handler. Basic idea here is the same, create controller, mark its appropriate method, consider method parameter resolvers and react on disconnect events. However, one notable difference here is that return value of the method is ignored. So, you can return whatever from disconnect handler, nothing will happen with it... Disconnect handlers can resolve ChannelFuture and Channel as method parameters by default:

@NettyController
public class OnDisconnectController {   
    @NettyOnDisconnect(serverName = "server1", priority = 1)
    private void onDisconnect1() {
        System.out.println("Hello, world!");
    }

    @NettyOnDisconnect(serverName = "server1", priority = 2)
    ByteBuf onDisconnect2() {
        System.out.println("Hello, world!");
        return Unpooled.copyLong(new Random().nextLong());
    }
}

Having server with such a controller and disconnecting from it, you should see Hello, world! in server's stdout twice.

Next type of handlers is message handlers. These handlers rely on @NettyOnMessage annotation. They differ from ones previously described due to the fact, that these handlers are also supporting message body parameter resolution, with a help of @NettyMessageBody annotation. Only one such annotation should be present on given method parameters. Method parameter resolvers here by default support ChannelHandlerContext, Channel and @NettyMessageBody annotated parameter resolution. Again, return value will be sent back to the client. Please, find an example below:

@NettyController
public class SomeController {
    @NettyOnConnect(serverName = "server1")
    private void onConnect() {
        System.out.println("Client connected");
    }
    
    @NettyOnDisconnect(serverName = "server1")
    private void onDisconnect() {
        System.out.println("Client disconnected");
    }

    @NettyOnMessage(serverName = "server1", priority = 1)
    public String onStringMessage(@NettyMessageBody final String msg) {
        return msg;
    }
    
    @NettyOnMessage(serverName = "server1", priority = 2)
    void onLongMessage1(final ChannelHandlerContext ctx, final Channel channel, @NettyMessageBody final Long msg) {
        ctx.writeAndFlush(msg + 1);
        channel.writeAndFlush(msg + 2);
    }   
    
    @NettyOnMessage(serverName = "server1", priority = 3)
    long onLongMessage2(@NettyMessageBody final long msg) {
        return msg;
    } 

    @NettyOnMessage(serverName = "server1", priority = 4)
    private void onLongMessage3() {
    }    
}

Study this example, or also refer to this test to see, which handlers in which order depending on which message are getting called. 👓

Custom Method Parameter Resolvers

As it was mentioned, when working with @NettyController annotated classes, it is possible to pass various parameters to the methods. These parameters are resolved with the help of method parameter resolvers, so if you need to introduce additional parameters for your handler methods, just implement appropriate resolver and mark it as a Spring @Component. That should do the trick:

@Component
public class RNG extends Random {
    private final List<Long> generatedNumbers = Lists.newArrayList();

    @Override
    public long nextLong() {
        final long result = super.nextLong();
        generatedNumbers.add(result);
        return result;
    }

    public List<Long> getGeneratedNumbers() {
        return generatedNumbers;
    }
}

@Component
public class RandomLongOnConnectResolver implements NettyOnConnectParameterResolver {
    private final RNG rng;

    @Autowired
    public RandomLongOnConnectResolver(final RNG rng) {
        this.rng = rng;
    }

    @Override
    public Object resolve(final ChannelHandlerContext ctx) {
        return rng.nextLong();
    }

    @Override
    public boolean canResolve(final MethodParameter methodParameter) {
        final Class<?> parameterType = methodParameter.getParameterType();
        return long.class.isAssignableFrom(parameterType) || Long.class.isAssignableFrom(parameterType);
    }
}

@Component
public class RandomLongOnDisconnectResolver implements NettyOnDisconnectParameterResolver {
    private final RNG rng;

    @Autowired
    public RandomLongOnDisconnectResolver(final RNG rng) {
        this.rng = rng;
    }

    @Override
    public boolean canResolve(final MethodParameter methodParameter) {
        final Class<?> parameterType = methodParameter.getParameterType();
        return long.class.isAssignableFrom(parameterType) || Long.class.isAssignableFrom(parameterType);
    }

    @Override
    public Object resolve(final ChannelFuture future) {
        return rng.nextLong();
    }
}

@Component
public class RandomLongOnMessageResolver implements NettyOnMessageParameterResolver {
    private final RNG rng;

    @Autowired
    public RandomLongOnMessageResolver(final RNG rng) {
        this.rng = rng;
    }

    @Override
    public boolean canResolve(final MethodParameter methodParameter) {
        final Class<?> parameterType = methodParameter.getParameterType();
        return long.class.isAssignableFrom(parameterType) || Long.class.isAssignableFrom(parameterType);
    }

    @Override
    public Object resolve(final ChannelHandlerContext ctx, final Object msg) {
        return rng.nextLong();
    }
}

Refer to this test for more information.

Filters

The last part to be discussed, are filters. There is analogy between Netty filters marked with @NettyFilter annotation and servlet filters in Java Servlet Specification. Classes marked with this annotation will be added to Netty handler pipeline before any @NettyController classes will do the processing. Filters should implement @ChannelHanlder interfaces. Also, filters can be stateless and stateful. Netty itself achieves this using @ChannelHandler.Sharable annotation. Same rules apply here with one additional requirement - if handler is not sharable, it should be defined in a ConfigurableBeanFactory.SCOPE_PROTOTYPE scope to ensure Spring will create new instances of this bean when required! So, say, you want your server to speak with client using String messages. Here's an example of appropriate filters and handlers:

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@NettyFilter(serverName = "server1", priority = 1)
public class Decoder extends ReplayingDecoder<Object> {
    @Override
    protected void decode(final ChannelHandlerContext ctx, final ByteBuf in, final List<Object> out) {
        final int size = in.readInt();
        final byte[] bytes = new byte[size];

        in.readBytes(bytes, 0, size);
        out.add(new String(bytes, Charset.forName("UTF-8")));
    }
}

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@NettyFilter(serverName = "server1", priority = 2)
public class Encoder extends MessageToByteEncoder<Object> {   
    @Override
    protected void encode(final ChannelHandlerContext ctx, final Object msg, final ByteBuf out) {        
        final String s = (String) msg;
        final byte[] bytes = s.getBytes(Charset.forName("UTF-8"));

        out.writeByte(1);
        out.writeInt(bytes.length);
        out.writeBytes(bytes);
    }
}


@NettyController
@SuppressWarnings("WeakerAccess")
public class OnMessageController {    
    @NettyOnMessage(serverName = "server1", priority = 1)
    public String onMessage(@NettyMessageBody final String msg) {
        // Do your processing here...
    }
}

NB! Priorities for @NettyController and @NettyFilter are used only with appropriate classes, which means first filters are sorted by their priority, then controllers by their. It is also possible to use only filters to do all the handling! Check this test for more information

License

This project is licensed under my personal favorite - MIT License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].