Erstellen Sie eine Echtzeit-Chat-Anwendung mit Modulus und Spring Boot

In diesem Lernprogramm verwenden wir Spring Boot für die Webentwicklungsumgebung, Websockets für Echtzeitkommunikation, Tomcat für den Java-Anwendungscontainer, Gradle für das Erstellen und Verwalten der Abhängigkeiten, Thymeleaf für das Rendern von Vorlagen, MongoDBfür die Datenspeicherung und schließlich gibt es kein XML für Bean-Konfigurationen. Am Ende dieses Artikels sehen Sie eine vollständig funktionierende Anwendung wie die unten abgebildete.

1. Szenario

  1. Doe öffnet die Chat-Seite, um mit seinen Freunden zu kommunizieren.
  2. Er wird aufgefordert, einen Spitznamen zu wählen.
  3. Er betritt die Chat-Seite und sendet eine Nachricht. Die Nachricht wird an den Spring MVC-Endpunkt gesendet, um in der Datenbank gespeichert und gesendet zu werden.
  4. Der angegebene Endpunkt verarbeitet die Nachricht und sendet diese Nachricht an alle mit dem Chat-System verbundenen Clients.

2. Erstellen Sie Abhängigkeiten und Gradle-Konfiguration

Bevor Sie mit der internen Struktur des Projekts fortfahren, lassen Sie mich erklären, welche Bibliotheken wir für die oben aufgelisteten Projektfeatures verwenden werden, und sie mit Gradle verwalten. Wenn Sie das Projekt aus GitHub klonen, wird eine Datei mit dem Namen angezeigt build.gradle im Projektstammverzeichnis wie folgt.

buildscript Repositorys mavenCentral () Abhängigkeiten classpath ("org.springframework.boot: spring-boot-gradle-plugin: 1.2.4.RELEASE") plugin anwenden: 'java' plugin anwenden: 'eclipse' plugin anwenden : 'idea' plugin anwenden: 'spring-boot' plugin anwenden: 'war' jar baseName = 'Echtzeit-Chat' version = '0.1.0' war baseName = 'ROOT' sourceCompatibility = 1.7 targetCompatibility = 1.7 Repositorys mavenCentral () sourceCompatibility = 1.7 targetCompatibility = 1.7 Abhängigkeiten providedRuntime 'org.springframework.boot: spring-boot-starter-tomcat' kompilieren ("org.springframework.boot: spring-boot-starter-web") kompilieren (" org.springframework.boot: spring-boot-starter-thymeleaf ") kompilieren (" org.springframework.boot: spring-boot-starter-data-mongodb ") kompilieren (" org.springframework.boot: spring-boot-starter- websocket ") compile (" org.springframework: spring-messaging ") testCompile (" junit: junit ") Task-Wrapper (Typ: Wrapper) gradleVersion = '2.3'

Ich werde nicht in die Interna von Gradle eintauchen, sondern ich möchte Ihnen die Teile erklären, die wir für unser Projekt benötigen. Spring Boot wurde hauptsächlich für die Entwicklung von eigenständigen Anwendungen in entwickelt Krug Format. In unserem Projekt werden wir eine generieren Krieg Projekt statt Krug. Das liegt daran, dass Modulus eine Kriegsdatei benötigt, um das Projekt automatisch in der Cloud bereitzustellen. 

Um eine Kriegsakte zu erzeugen, haben wir verwendet Plugin anwenden: 'Krieg'. Modul erwartet auch den Kriegsnamen ROOT.war standardmäßig, und deshalb haben wir verwendet:

war baseName: 'ROOT.war'

Wenn Sie die Gradle ausführen bauen Aufgabe wird eine Kriegsdatei generiert, die im Tomcat-Container bereitgestellt werden kann. Und wie Sie sich vorstellen können, sind im Abschnitt Abhängigkeiten Bibliotheken von Drittanbietern für bestimmte Aktionen enthalten. 

Das ist alles für den Abschnitt Projektabhängigkeiten. Weitere Informationen zu Gradle finden Sie im Gradle-Benutzerhandbuch.

3. Software-Design

Wenn Sie eine gute Anwendung entwickeln möchten, sollten Sie Ihre Projektstruktur in kleinen Teilen definieren. Sie können die Teile der gesamten Architektur unserer Anwendung sehen.

3.1. Modell

Wir entwickeln eine Chat-Anwendung, also können wir sagen, dass wir eine ChatMessageModel Modell (d. h. Domänenobjekt). Während wir die Chatnachrichtendetails speichern oder anzeigen, können wir das Chatobjekt von oder zu diesem umwandeln ChatMessageModel Modell. Wir können auch die verwenden Nutzer Modell für Chat-Benutzer, aber um die Anwendung zu vereinfachen, werden wir nur verwenden Spitzname als Text. Das ChatMessageModel Modell hat die folgenden Felder: Text, Autor, und Erstellungsdatum. Die Klassendarstellung dieses Modells sieht wie folgt aus:

Paket Echtzeit.Domäne; import org.springframework.data.annotation.Id; import java.util.Date; / ** * @author huseyinbabal * / public class ChatMessageModel @Id private String-ID; privater String-Text; privater String-Autor; privates Datum createDate; public ChatMessageModel ()  public ChatMessageModel (Zeichenfolgentext, Zeichenfolgenautor, Datum createDate) this.text = text; this.author = Autor; this.createDate = createDate;  public String getText () return text;  public void setText (String text) this.text = text;  public String getAuthor () return author;  public void setAuthor (Zeichenfolgenautor) this.author = author;  public Date getCreateDate () return createDate;  public void setCreateDate (Datum createDate) this.createDate = createDate;  @Override public String toString () return "" + "\" id \ ": \" "+ id + '\"' + ", \" "\" ": \" "+ text + '\"' + ", \" Autor \ ": \" "+ Autor + '\"' + ", \" "createDate \" ": \" "+ createDate +" \ "" + '';  

Dieses Domänenobjekt hilft uns, die Chat-Nachricht bei Bedarf als JSON darzustellen. Unser Modell ist in Ordnung, also fahren wir mit den Steuerungen fort.

3.2. Regler

Der Controller ist das Verhalten Ihrer Anwendung. Dies bedeutet, dass Sie Ihren Controller einfach halten und mit Domänenmodellen und anderen Diensten problemlos interagieren können. Wir erwarten von unseren Controllern:

  1. Anfragen zum Speichern von Chat-Nachrichten
  2. Auflisten der neuesten Chatnachrichten
  3. Bereitstellen der Chatanwendungsseite
  4. Bereitstellen der Anmeldeseite
  5. Senden von Chatnachrichten an Kunden

Hier können Sie die allgemeinen Endpunkte sehen:

Paket Echtzeit.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.http.HttpEntity; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import realtime.domain.ChatMessageModel; import realtime.message.ChatMessage; import realtime.repository.ChatMessageRepository; import java.util.Date; import java.util.List; / ** * @author huseyinbabal * / @Controller öffentliche Klasse ChatMessageController @Autowired private ChatMessageRepository chatMessageRepository; @RequestMapping ("/ login") public String login () return "login";  @RequestMapping ("/ chat") public String chat () return "chat";  @RequestMapping (value = "/ messages", method = RequestMethod.POST) @MessageMapping ("/ newMessage") @SendTo ("/ topic / newMessage") public ChatMessageMessage save (ChatMessageModel ChatMessageModel) ChatMessageModel ChatMessage = neue ChatMessageModel ChatMessage = neue ChatMessageModel ChatMessage = neue ChatMessageModel ChatMessage = neue ChatMessageModel ChatMessage = neue ChatMessageMeldeMessage .getText (), chatMessageModel.getAuthor (), neues Datum ()); ChatMessageModel message = chatMessageRepository.save (chatMessage); Liste chatMessageModelList = chatMessageRepository.findAll (new PageRequest (0, 5, Sort.Direction.DESC, "createDate")). getContent (); return new ChatMessage (chatMessageModelList.toString ());  @RequestMapping (value = "/ messages", method = RequestMethod.GET) public HttpEntity list () List chatMessageModelList = chatMessageRepository.findAll (new PageRequest (0, 5, Sort.Direction.DESC, "createDate")). getContent (); Rückgabe neuer ResponseEntity (chatMessageModelList, HttpStatus.OK);  

Der erste und der zweite Endpunkt dienen nur zum Bereitstellen der Login- und Haupt-Chat-Seite. Die dritte Aktion betrifft das Speichern und Senden neuer Chatnachrichten. Nachdem die Nachricht gespeichert wurde, wird sie den Clients über die E-Mail benachrichtigt / thema / nachrichtKanal. Um Nachrichtendaten in MongoDB zu speichern, verwenden wir ein MongoDB-Repository.  

Wie Sie sehen, gibt es zwei Arten von Endpunkten /Mitteilungen: GET und POST. Wenn Sie eine POST-Anforderung an den Endpunkt stellen /Mitteilungen Mit der richtigen Nachrichtennutzlast wird sie automatisch in die ChatMessageModel-Klasse umgewandelt und die Nachricht wird in MongoDB gespeichert. Nach dem erfolgreichen Speichern wird es automatisch an die Clients weitergeleitet. Aber wie? In dieser Aktion gibt es eine Anmerkung @SendTo ("/ topic / newMessage"). Dadurch wird der von der Funktion zurückgegebene Inhalt an die Clients gesendet. Und der zurückgegebene Inhalt ist wie folgt:

… Neue ChatMessage zurückgeben (chatMessageModelList.toString ());… 

Dies ist die neueste Nachricht aus der Datenbank:

Die obige Nachricht wird in ein Format für die WebSocket-Kommunikation konvertiert. Diese Kanalnachricht wird auf der Clientseite mit einer JavaScript-Bibliothek eines Drittanbieters behandelt und in den folgenden Abschnitten behandelt. 

Für Message-DB-Operationen, spring-boot-starter-data-mongodb wird eingesetzt. Diese Bibliothek hilft uns bei Repository-Operationen, und das Erstellen eines Repository-Objekts für MongoDB ist sehr einfach. Sie können das Beispiel sehen ChatMessageRepository unten:

Paket realtime.repository; import org.springframework.data.mongodb.repository.MongoRepository; import realtime.domain.ChatMessageModel; import java.util.List; / ** * @author huseyinbabal * / public interface ChatMessageRepository erweitert MongoRepository  Liste findAllByOrderByCreateDateAsc ();  

Wenn Sie eine Schnittstelle erstellen und erweitern MongoRepository, Sie können CRUD-Operationen wie finden(), finde alle(), sparen(), usw. 

Wie du siehst, MongoRepository erwartet ein Domänenobjekt. Dieses Modell haben wir bereits im Tutorial-Abschnitt "Modell" definiert. In diesem Repository haben wir eine benutzerdefinierte Funktion definiert findAllByOrderByCreateDateAsc ()

Wenn Sie JPA schon einmal verwendet haben, können Sie dies leicht verstehen, aber lassen Sie mich das kurz erklären. Wenn Sie einen Funktionsnamen in einer sich erweiternden Schnittstelle definieren MongoRepository, Dieser Funktionsname wird von Spring automatisch in eine Abfrage im Back-End analysiert. Es wird ungefähr so ​​sein:

SELECT * FROM ChatMessageModel WO 1 ORDER BY createDate ASC

Im ChatMessageController, Wir haben diese Funktion verwendet und auch die Standardfunktionen von MongoRepository:

chatMessageRepository.findAll (new PageRequest (0, 5, Sort.Direction.DESC, "createDate")). getContent ()

finde alle wird ein Parameter zum Sortieren und Seitenumbruch verwendet. In der Anleitung auf der Spring-Website finden Sie weitere Informationen zu Spring JPA.

3.3. Aussicht

Im Ansichtsteil haben wir nur zwei Seiten. Eine davon ist die Anmeldeseite, um den Spitznamen des Benutzers abzurufen, und die zweite ist die Haupt-Chat-Seite, über die Nachrichten an Chat-Benutzer gesendet werden. 

Wie Sie im Controller-Abschnitt oben sehen können, werden sie mit zwei Endpunkten gerendert, /Anmeldungund /PlaudernUm interaktive Seiten zu erstellen, verwenden wir JavaScript-Bibliotheken von Drittanbietern. Wir werden sie von CDN-Seiten verwenden. Sie können die Anmeldeseite unten sehen:

             

Wählen Sie einen Spitznamen, um den Chat zu betreten

Auf der Anmeldeseite haben wir ein Beispiel für ein Textfeld mit einem Spitznamen. Wenn Sie auf klicken Chat eingeben, Ihr Nickname wird in einem Cookie gespeichert. Dieser Kurzname wird verwendet, um das Autorenfeld für Chat-Nachrichten festzulegen. Wenn Sie auf klicken Chat eingeben, Die Chat-Seite wird geöffnet. Wenn Sie bereits angemeldet sind und zur Anmeldeseite gehen, werden Sie zur Chat-Seite weitergeleitet. 

Hier ist die Chat-Seite:

                 

Echtzeit-Chat-Anwendung mit Spring Boot, Websockets und MongoDB



Chatverlauf

Diese Seite dient zum einfachen Anzeigen und Senden von Nachrichten. Nachrichten werden über WebSockets an diese Seite gesendet. Auf dieser Seite können Sie sehen sockjs und Stompjs. Dies sind für die Bearbeitung von Benachrichtigungen. Immer wenn eine neue Nachricht eingeht, wird der Bereich für die neuesten Nachrichten neu gefüllt. 

Wenn Sie die Chat-Seite zum ersten Mal öffnen, werden die neuesten Nachrichten im Nachrichtenbereich abgerufen. Wie Sie auf der JavaScript-Seite sehen können, ist dies unser Nachrichtenkanal neue Nachricht. Wir hören also diesen Kanal und wenn Sie auf klicken Senden Wenn die Schaltfläche gedrückt wird, wird die Nachricht im Textfeld an den Endpunkt gesendet und diese Nachricht wird nach erfolgreicher Speicherung an die verbundenen Clients gesendet.

Wie Sie sehen, ist die Softwarearchitektur hier sehr einfach und leicht zu entwickeln. Wir haben produktionsreifen Code und lassen ihn in Modulus implementieren.

Modulus ist einer der besten PaaS-Systeme für die Bereitstellung, Skalierung und Überwachung Ihrer Anwendung in der Sprache Ihrer Wahl.

4. Bereitstellung 

4.1. Voraussetzungen

Bevor Sie die Anwendung bereitstellen, erstellen Sie eine Datenbank mithilfe des Modulus-Verwaltungsbereichs. Sie benötigen ein Modulus-Konto für die Erstellung von DBA und die Anwendungsbereitstellung. Erstellen Sie daher ein Konto, falls Sie noch kein Konto haben. 

Gehen Sie zum Modulus-Dashboard und erstellen Sie eine Datenbank:

Geben Sie auf dem Bildschirm zum Erstellen der Datenbank bitte einen Datenbanknamen an, wählen Sie die MongoDB-Version aus (ich habe 2.6.3 verwendet, daher ist es besser, wenn Sie auch 2.6.3 wählen), und definieren Sie schließlich einen Benutzer, der Lese- / Schreibvorgänge für Datenbanken ausführt. 

Sie können eine MongoDB-URL erhalten, nachdem Sie die Datenbank erfolgreich erstellt haben. Wir verwenden die MongoDB-URL in den Umgebungsvariablen, die von der Spring Boot-Anwendung verwendet werden.

Um die Umgebungsvariablen für MongoDB festzulegen, benötigen Sie eine Anwendung. Gehe zu Instrumententafel und klicken Sie auf Projekte. Klicken Sie auf dieser Seite auf Neues Projekt erstellen.

Um mit der Konfiguration der Umgebungsvariablen fortzufahren, gehen Sie bitte zu Instrumententafel und klicken Sie auf Projekte. Wählen Sie Ihr Projekt aus und klicken Sie auf Verwaltung. Blättern Sie auf der Seite nach unten und legen Sie mit der Taste die Umgebungsvariablen fest SPRING_DATA_MONGODB_URI und Wert Ihrer Datenbank-URI:

Wenn Sie Ihre Anwendung bereitstellen, verwendet Spring diesen Wert für die Umgebungsvariable. Wir haben die Anforderungen erfüllt und fahren mit dem Bereitstellungsteil fort.

4.2. Bereitstellung mit CLI

Führen Sie eine Gradle-Build-Aufgabe aus, um das Projekt bereitzustellen:

gradle build

Diese Aufgabe generiert eine Kriegsdatei mit dem Namen ROOT.war. Kopieren Sie diese Datei in einen neuen Ordner und installieren Sie modulus CLI, falls dies nicht der Fall ist.

npm install -g modulus

Melden Sie sich beim System an.

modul login

Führen Sie nun den folgenden Befehl aus, um zu implementieren ROOT.war zu Modul.

Modul bereitstellen

Dadurch wird die War-Datei bereitgestellt, und Sie können die Projektprotokolle mit dem folgenden Befehl abschließen, um den Status Ihrer Bereitstellung anzuzeigen:

Modul-Protokoll protokolliert das Ende

Das ist alles mit der Bereitstellung!

5. Schlussfolgerung

Der Hauptzweck dieses Lernprogramms besteht darin, Ihnen zu zeigen, wie Sie eine Echtzeit-Chat-Anwendung mit Spring Boot, WebSockets und MongoDB erstellen. 

Um das Projekt in der Produktion auszuführen, wird Modulus als PaaS-Anbieter verwendet. Modulus hat sehr einfache Schritte für die Bereitstellung und verfügt auch über eine interne Datenbank (MongoDB) für unsere Projekte. Darüber hinaus können Sie im Modulus-Dashboard sehr hilfreiche Tools wie Protokolle, Benachrichtigungen, Auto-Skalierung, Datenbankverwaltung usw. verwenden.