clustereventmulticaster: Custom Applicationeventmulticaster
The bean set to the root context
In the configuration file in the root context:
@Bean public
Applicationeventmulticaster Applicationeventmulticaster () {
Simpleapplicationeventmulticaster eventmulticaster = new clustereventmulticaster ();
Clustermanager is also in the listening event, if we do not set the background run Settaskexecutor (), then Clustermanager onapplicationevent () must be marked with @async, Otherwise, this will take 1 minutes, during which time, because the web context can not be continued to initialize the initialization (need to complete the first onapplicationevent ()), that is,/ping not normal response, resulting in failure. For security reasons, we can still add @async to the Clustermanager onapplicationevent (), which is a thread in the thread.
Eventmulticaster.settaskexecutor (New Simpleasynctaskexecutor ());
return eventmulticaster;
}
Clustereventmulticaster Code
public class Clustereventmulticaster extends simpleapplicationeventmulticaster{private static final Logger log = Logm
Anager.getlogger (); Private final set<clustermessagingendpoint> endpoints = new hashset<> (); Manage and maintain each WebSocket connection @Inject ApplicationContext context;
is set as a bean in the root context, so this will get the root context//"1" custom message release, which, if it belongs to the Clusterevent event, will be published to the cluster via WebSocket (excluding the received cluster event, of course) @Override public void Multicastevent (Applicationevent event, Resolvabletype eventtype) {try{super.multicast
Event (event, EventType); }finally{try{if (event instanceof clusterevent &&! (
(clusterevent) event). isrebroadcasted ()) publishclusteredevent ((clusterevent) event);
}catch (Exception e) {log.error ("Failed to broadcast distributable event to cluster.", e); }}//"2" cluster event send and receive related methods//"2.1" broadcast events to the cluster via websocket private void PublishclusTeredevent (Clusterevent event) {synchronized (endpoints) {for (Clustermessagingendpoint endpoint:this.
Endpoints) {endpoint.send (event); An event was received from the WebSocket in the}///"2.2" to be published locally in order to trigger a response applicationeventlistener.
The rebroadcasted tag in the message is also set, indicating that the word message is not required to be broadcast to the cluster protected final void Handlereceivedclusteredevent (Clusterevent event) {
Event.setrebroadcasted (); This.multicastevent (Event,null); Equivalent to local publish}//"3" admin socket Connection (clustermessagingendpoint)//"3.1" Registered WebSocket connection protected void Regist Erendpoint (Clustermessagingendpoint Endpoint) {synchronized (endpoints) {This.endpoints.add (endpoint)
;
}//"3.2" Logoff websocket connection protected void Deregisterendpoint (Clustermessagingendpoint endpoint) {
Synchronized (endpoints) {this.endpoints.remove (endpoint); Turn off all websocket connections @PreDestroy public void when the "3.3" program exits Shutdown () {synchronized (this.endpoints) {for (Clustermessagingendpoint endpoint:this.endpoints) {
Endpoint.close (); The more appropriate name is CreateNode, which is based on the listener to the WebSocket URL, creating the connection (creating the Clustermessagingendpoint object) and needing attention websocketend Point is not part of the spring framework, and you will not be able to support @inject in Websocketendpoint by manually incorporating it.
This has been learned before, relive.
protected void Registernode (String endpoint) {log.info ("Connecting to cluster Node {}.", endpoint); /* A websocketcontainer is a implementation provided object, provides applications a view * on the Containe R running it. The Websocketcontainer container various configuration parameters * Control default session and buffer prop Erties of the endpoints it contains.
It also allows * the developer to deploy WebSocket client endpoints by initiating a Web sockets handshake from
* The provided endpoint to a supplied URI where the peer endpoint was presumed to reside. * A Websocketcontainer May is accessed by concurrent threads, so implementations must ensure the
* integrity of its mutable attributes in such circumstances.
* * URI uri = new uri ("ws", "localhost:8080", path,null,null);
* Session sessions = Containerprovider.getwebsocketcontainer (). Connecttoserver (this, URI);
* */Websocketcontainer container = Containerprovider.getwebsocketcontainer (); /* Clustermessagingendpoint is a websocket cilent+server,websocket is not a spring framework. If you want to inject an automatic injection into the bean, we need to use the org.springframework.beans.factory.annotation.Configurable annotation for non-spring-managed beans. */Clustermessagingendpoint Bean = This.context.getAutowireCapableBeanFactory (). Createbean (Cl
Ustermessagingendpoint.class);
try {log.info ("Connect to server {}", endpoint);
Container.connecttoserver (Bean, new URI (endpoint)); catch (Deploymentexception | IOException | UrisyntaxexcEption e) {log.error ("Failed to connect to cluster node {}", endpoint, E); }
}
}
Clustermessagingendpoint:websocket Endpoint
"1" We are concerned with the event of the cluster received from the WebSocket connection, which is handled with the server and client of WebSocket. After serializing the event object, it is passed directly in the WebSocket connection, so codec is the serialization and deserialization, implemented by the internal static class codec @ServerEndpoint (value = "/services/messaging/{ Securitycode} ", encoders = {ClusterMessagingEndpoint.Codec.class}, decoders = {CLUSTERMESSAGINGENDPOINT.CODEC.C Lass}, configurator = Springconfigurator.class) @ClientEndpoint (encoders = {ClusterMessagingEndpoint.Codec.clas s}, decoders = {ClusterMessagingEndpoint.Codec.class}) public class Clustermessagingendpoint {private static F
inal Logger log = Logmanager.getlogger ();
Private session session; Support @inject, for server, set Configurator to Springconfigurator.class, each new connection will create @serviceendpoint Bean.
For the client needs to be created as a spring bean, see the code previously in Clustereventmulticaster.
@Inject Clustereventmulticaster Multicaster;
@OnOpen public void Open (session session) {map<string, string> parameters = Session.getpathparameters (); if (Parameters.containskey ("Securitycode")&&! " A83teo83hou9883hha9 ". Equals (Parameters.get (" Securitycode "))) {try {log.error (" Received Connec
tion with illegal code {}. ", Parameters.get (" Securitycode "));
Session.close (New Closereason (CloseReason.CloseCodes.VIOLATED_POLICY, "illegal Code"));
catch (IOException e) {Log.warn ("Failed to close illegal connection.", e);
}}else{Log.info ("Successful connection OnOpen.");
This.session = session; This.multicaster.registerEndpoint (this); WebSocket connection successfully established} @OnMessage public void receive (Clusterevent message) {This.multicaster. Handlereceivedclusteredevent (message);
The message in the cluster was received} @OnClose public void Close () {Log.info ("Cluster node Connection closed."); This.multicaster.deregisterEndpoint (this); The other closes the connection if (This.session.isOpen ()) {try {this.session.close ();
catch (IOException e) {Log.warn ("Error while closing cluster node connection.", e); }} public void Send (Clusterevent message) {try {session.getbasicremote (). s EndObject (message); To publish an event (message) through a websocket connection} catch (IOException |
Encodeexception e) {log.error ("Failed to send message to adjacent node.", E); The event object is serialized directly in the WebSocket connection, and the Codec is implemented for serialization and deserialization by the internal static class Codec to implement the public static classes Codec implements encoder.binarystream<clusterevent>,decoder.binarystream<clusterevent> {@Override public void
Init (endpointconfig config) {} @Override public void Destroy () {} @Override public clusterevent decode (InputStream is) throws Decodeexception, IOException {try (Ob Jectinputstream ois = new ObjectInputStream (IS);) {try {REturn (clusterevent) ois.readobject ();
The catch (ClassNotFoundException e) {throw new Decodeexception ((String) NULL, "Failed to decode.", e); @Override public void Encode (Clusterevent object, O Utputstream os) throws Encodeexception, IOException {try (objectoutputstream Oos = new ObjectOutputStream (OS);
) {Oos.writeobject (object); }
}
}
}
RELATED links: My professional Java for WEB applications related articles