In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly introduces how to use Redant in Netty, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let the editor take you to understand it.
Quick start
Redant is a Netty-based Web container, similar to Tomcat and WebLogic containers
You only need to start a Server, and the default implementation class is NettyHttpServer to start a web container quickly, as shown below:
Public final class ServerBootstrap {public static void main (String [] args) {Server nettyServer = new NettyHttpServer (); / / various initialization work nettyServer.preStart (); / / start server nettyServer.start ();}}
We can directly start the ServerBootstrap class in the redant-example module, because there are many sample Controller in redant-example. We directly run ServerBootstrap in example. After startup, you will see the following log information:
The following default routes are built into the redant-example module:
After launching successfully, you can visit http://127.0.0.1:8888/ to view the results, as shown in the following figure:
If you can see "Welcome to redant!" With such news, it means that you have started successfully.
Custom rout
The framework implements a custom route, which can be uniquely identified through the @ Controller @ Mapping annotation. As shown in the following UserController:
In the same way as Spring, visit / user/list to see the effect, as shown in the following figure:
Result rendering
Currently, json, html, xml, text and other types of result rendering are supported. You only need to specify a specific rendering type through renderType on the @ Mapping annotation of the method. If not, the default is json type range.
As shown in the following figure, the home page returns a html page by specifying renderType as html:
IOC container
From the UserController code, we can see that userServerce objects are automatically injected through the @ Autowired annotation, which is a basic capability of any IOC container. Let's take a look at how to implement a simple IOC container.
First, define a BeanContext interface, as shown below:
Public interface BeanContext {/ * get the name of Bean * @ param name Bean * @ return Bean * / Object getBean (String name); / * get the name of Bean * @ param name Bean * @ param clazz Bean class * @ param generics * @ return Bean * / T getBean (String name,Class clazz);}
Then we need to scan out all the classes modified by the @ Bean annotation when the system starts, then instantiate these classes, and then save the instantiated objects in a Map, as shown in the following figure:
The code is very simple, by scanning out all the classes under the specified path, add the instance object to the map, but you can no longer join the bean that you have joined, and it is very easy to get a Bean after joining, just go to map through name to get it.
Now that we have managed all the @ Bean objects, how do we inject the other bean we depend on, in other words, assign our instantiated object to the variable modified by the @ Autowired annotation.
The simpler thing to do is to iterate through the beanMap, and then check each bean to see every setter method and property in the bean. If there is a @ Autowired annotation, find a specific bean instance and stuff the value in.
Setter injection
Field injection
Obtain BeanContext through Aware
BeanContext has been implemented, so how to get an instance of BeanContext? Consider that there are many Aware interfaces in Spring, each of which is responsible for callback of an instance. For example, if we want to get a BeanFactory, we only need to implement our class BeanFactoryAware API. The BeanFactory instance in the setBeanFactory (BeanFactory factory) method parameter in the interface is what we need. We just need to implement the method, and then save the instance in the parameter in our class, and then we can use it directly later.
Now I'll implement this function. First, define an Aware interface, and all other interfaces that need to call back the plug value inherit from this interface, as shown below:
Public interface Aware {
}
Public interface BeanContextAware extends Aware {
/ * *
* set BeanContext
* @ param beanContext BeanContext object
, /
Void setBeanContext (BeanContext beanContext)
}
Next, you need to inject an instance of BeanContext into all the implementation classes of BeanContextAware. The instance of BeanContext is easy to get, and the implementation class of BeanContext is itself an instance of BeanContext, and you can set the instance as a singleton, so that you can get the same instance wherever you need to get BeanContext.
After getting the instance of BeanContext, we need to scan out all the classes that implement the BeanContextAware interface, instantiate these classes, then call the setBeanContext method of these classes, and pass the parameters to the BeanContext instance we got.
Once the logic is clear, it is easy to implement, as shown in the following figure:
Cookie management
Basically all web containers will have the ability to manage cookie, so our redant should not lag behind. First, define an interface for CookieManager. The core methods for operating cookie are as follows:
Public interface CookieManager {
Set getCookies ()
Cookie getCookie (String name)
Void addCookie (String name,String value)
Void setCookie (Cookie cookie)
Boolean deleteCookie (String name)
}
Among them, I only list a few core methods, and there are some overloaded methods with different parameters, which will not be described in detail here. The most important thing is two methods, one is to read Cookie and the other is to write Cookie.
Read Cookie
In Netty, the Cookie carried in the request is saved through the Header of HttpRequest, so if you want to read Cookie, the most important thing is to get HttpRequest. HttpRequest can be found in ChannelHandler, and Netty has helped us convert the requested data into HttpRequest through the HttpServerCodec codec. But this HttpRequest can only be accessed in ChannelHandler, and dealing with Cookie is usually a user-defined operation, and for the user, he does not care about HttpRequest, he only needs to get a Cookie through CookieManager.
In this case, the most suitable thing is to save the HttpRequest object in a ThreadLocal. When you need to get it in CookieManager, you can just go to ThreadLocal and take it out, as shown in the following code:
@ Overridepublic Set getCookies () {HttpRequest request = TemporaryDataHolder.loadHttpRequest (); Set cookies = new HashSet (); if (request! = null) {String value = request.headers () .get (HttpHeaderNames.COOKIE); if (value! = null) {cookies = ServerCookieDecoder.STRICT.decode (value);}} return cookies;}
TemporaryDataHolder is the class that holds the HttpRequest through ThreadLocal.
Write Cookie
Writing Cookie faces the same problem as reading Cookie, that is, when writing, you need to write Cookie into the Header of HttpResponse with the help of HttpResponse, but when the user performs the write Cookie operation, he doesn't care about HttpResponse at all, even when he is writing, he doesn't have HttpResponse.
This is also done by saving the Cookie that needs to be written to HttpResponse in ThreadLocal, and then taking out the Cookie and stuffing it into HttpResponse before finally writing the response through channel, as shown in the following code:
@ Override
Public void setCookie (Cookie cookie) {
TemporaryDataHolder.storeCookie (cookie)
}
/ * *
* response message
, /
Private void writeResponse () {
Boolean close = isClose ()
Response.headers () .add (HttpHeaderNames.CONTENT_LENGTH, String.valueOf (response.content () .readableBytes ()
/ / remove the cookie to be written from the ThreadLocal
Set cookies = TemporaryDataHolder.loadCookies ()
If (! CollectionUtil.isEmpty (cookies)) {
For (Cookie cookie: cookies) {
/ / write cookie to response
Response.headers () .add (HttpHeaderNames.SET_COOKIE, ServerCookieEncoder.STRICT.encode (cookie))
}
}
ChannelFuture future = channel.write (response)
If (close) {
Future.addListener (ChannelFutureListener.CLOSE)
}
}
Interceptor
Interceptor is a very important function of the framework, through the interceptor can achieve some general work, such as login authentication, transaction processing and so on. Remember in the era of Servlet, interceptor is a very important function, basically every system will configure a lot of interceptors in web.xml.
The basic idea of an interceptor is to perform an intercepted operation through a series of classes, and once the intercepting operation in a class returns false, it terminates all subsequent processes and returns directly.
This scenario is very suitable for the implementation of the chain of responsibility pattern, and Netty's pipeline itself is an application of the chain of responsibility pattern, so we can implement our interceptor through pipeline. Here I define two types of interceptors: the front interceptor and the post interceptor.
The pre-interceptor is an intercept operation before processing the user's business logic. If the operation returns false, it will directly return and will not continue to execute the user's business logic.
The post interceptor is a little different, the post interceptor mainly deals with some subsequent operations, because the post interceptor is the same as the front interceptor, when the operation returns false direct return, it is meaningless, because the business logic has already been executed.
After you understand the specific logic, it is easy to implement, as shown in the following code:
Front interceptor
Rear interceptor
Once we have the implementation, we need to add them to the appropriate place in the pipeline to make them take effect in the entire chain of responsibility, as shown in the following figure:
Specify the execution order of the interceptor
At present, the interceptor does not implement the function of specified sequence execution, but it is actually very simple. You can define a @ InterceptorOrder annotation to be applied to all interceptor implementation classes. After scanning the interceptor's results, you can sort them according to the annotations, and then add the results to the pipeline after shooting the sequence.
Cluster mode
So far, I have described the single-node mode, and if one day the performance of the single node can not be satisfied, then you need to use a cluster, so I have also implemented the cluster mode.
The cluster mode consists of one master node and several slave nodes. After receiving the request, the master node forwards the request to the slave node for processing, and the slave node returns the processed result to the master node, and the master node responds to the request.
In order to implement the cluster pattern, we need to have a function of service registration and discovery, which is currently done with the help of Zk.
Prepare a Zk server
Because the master node needs to forward the request to the slave node, so the master node needs to know which slave nodes are currently available. I use ZooKeeper to achieve service registration and discovery.
If you do not have an available Zk server, you can start a ZooKeeper server by running the following Main method:
Public final class ZkBootstrap {
Private static final Logger LOGGER = LoggerFactory.getLogger (ZkBootstrap.class)
Public static void main (String [] args) {
Try {
ZkServer zkServer = new ZkServer ()
ZkServer.startStandalone (ZkConfig.DEFAULT)
} catch (Exception e) {
LOGGER.error ("ZkBootstrap start failed,cause:", e)
System.exit (1)
}
}
}
So you can use this Zk later when you start the master-slave node. But this is not necessary. If you already have a running Zk server, you can use it directly when starting the master-slave node by specifying the address of the Zk in the parameters of the main method.
Start the primary node
You can start a master node simply by running the following code:
Public class MasterServerBootstrap {
Public static void main (String [] args) {
String zkAddress = ZkServer.getZkAddressArgs (args,ZkConfig.DEFAULT)
/ / start MasterServer
Server masterServer = new MasterServer (zkAddress)
MasterServer.preStart ()
MasterServer.start ()
}
}
If the address of Zk is specified in the parameters of the main method, service discovery is made through that address, otherwise the default Zk address is used.
Start the slave node
Just run the following code to start a slave node:
Public class SlaveServerBootstrap {
Public static void main (String [] args) {
String zkAddress = ZkServer.getZkAddressArgs (args,ZkConfig.DEFAULT)
Node node = Node.getNodeWithArgs (args)
/ / start SlaveServer
Server slaveServer = new SlaveServer (zkAddress,node)
SlaveServer.preStart ()
SlaveServer.start ()
}
}
If the address of Zk is specified in the parameters of the main method, the service is registered with that address, otherwise the default Zk address will be used.
In fact, the specific processing logic of the multi-node mode reuses the core function of the single-node mode, only extending the original one instance to multiple instances.
Thank you for reading this article carefully. I hope the article "how to use Redant in Netty" shared by the editor will be helpful to everyone. At the same time, I also hope you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.