In deze tutorial gebruiken we Spring Boot voor de webontwikkelingsomgeving, WebSockets voor real-time communicatie, Tomcat voor de Java-toepassingscontainer, Gradle voor het bouwen en beheren van de afhankelijkheden, Thymeleaf voor sjabloonweergave, MongoDBvoor gegevensopslag en tot slot is er geen XML voor bonenconfiguraties. Om je geïnspireerd te laten worden, zul je aan het eind van dit artikel een volledig werkende applicatie zien zoals die hieronder wordt getoond.
Alvorens verder te gaan met de interne structuur van het project, wil ik u uitleggen welke bibliotheken we zullen gebruiken voor de hierboven genoemde projectfuncties en deze beheren met behulp van Gradle. Wanneer u het project vanuit GitHub kloont, ziet u een bestand met de naam build.gradle
in de hoofdmap van het project, zoals hieronder.
buildscript repositories mavenCentral () afhankelijkheden classpath ("org.springframework.boot: spring-boot-gradle-plugin: 1.2.4.RELEASE") plug-in toepassen: 'java' apply plugin: 'eclipse' apply plugin : 'idea' apply plugin: 'spring-boot' apply plugin: 'war' jar baseName = 'realtime-chat' versie = '0.1.0' war baseName = 'ROOT' sourceCompatibility = 1.7 targetCompatibility = 1.7 repositories mavenCentral () sourceCompatibility = 1.7 targetCompatibility = 1.7 dependencies providedRuntime 'org.springframework.boot: spring-boot-starter-tomcat' compile ("org.springframework.boot: spring-boot-starter-web") compile (" org.springframework.boot: spring-boot-starter-thymeleaf ") compile (" org.springframework.boot: spring-boot-starter-data-mongodb ") compile (" org.springframework.boot: spring-boot-starter- websocket ") compile (" org.springframework: spring-messaging ") testCompile (" junit: junit ") taakwikkelaar (type: Wrapper) gradleVersion = '2.3'
Ik zal niet in de Gradle-internals duiken, maar laat me de onderdelen uitleggen die we nodig hebben voor ons project. Spring Boot is voornamelijk gebouwd voor het ontwikkelen van stand-alone applicaties in pot
formaat. In ons project zullen we een genereren oorlog
project in plaats van pot
. Dat komt omdat Modulus een war-bestand nodig heeft om het project automatisch in zijn cloud te implementeren.
Om een oorlogsbestand te genereren, hebben we het gebruikt plug-in toepassen: 'oorlog'
. Modulus verwacht ook dat de naam van de oorlog is ROOT.war
standaard, en dat is waarom we hebben gebruikt:
oorlog baseName: 'ROOT.war'
Wanneer je de Gradle uitvoert bouwen
taak, het genereert een war-bestand om in de Tomcat-container te implementeren. En tot slot, zoals u kunt raden, is het gebied afhankelijkheden voor bibliotheken van derden voor specifieke acties.
Dat is alles voor de sectie met projectafhankelijkheden, en u kunt de gebruikershandleiding van Gradle raadplegen voor meer informatie over Gradle.
Als u een goede toepassing wilt ontwikkelen, is het verstandig om uw projectstructuur in kleine stukjes te definiëren. U kunt de onderdelen van de volledige architectuur van onze applicatie bekijken.
We zijn een chattoepassing aan het ontwikkelen, dus we kunnen zeggen dat we een ChatMessageModel
model (d.w.z. domeinobject). Terwijl we het chatbericht opslaan of bekijken, kunnen we het chat-object van of naar dit casten ChatMessageModel
model. We kunnen ook de Gebruiker
model voor chatgebruikers, maar om de applicatie eenvoudiger te maken, zullen we gewoon gebruiken bijnaam
als tekst. De ChatMessageModel
model heeft de volgende velden: tekst
, schrijver
, en CreateDate
. De klassenweergave van dit model is als volgt:
pakket realtime.domain; import org.springframework.data.annotation.Id; importeer java.util.Date; / ** * @author huseyinbabal * / public class ChatMessageModel @Id private String id; private String-tekst; private String auteur; privé Datum createDate; public ChatMessageModel () public ChatMessageModel (String-tekst, String-auteur, Date createDate) this.text = text; this.author = auteur; this.createDate = createDate; public String getText () retour tekst; public void setText (String text) this.text = text; public String getAuthor () return author; public void setAuthor (String author) this.author = auteur; public Datum getCreateDate () return createDate; public void setCreateDate (Date createDate) this.createDate = createDate; @Override public String toString () return "" + "\" id \ ": \" "+ id + '\"' + ", \" text \ ": \" "+ text + '\"' + ", \" auteur \ ": \" "+ author + '\"' + ", \" createDate \ ": \" "+ createDate +" \ "" + '';
Dit domeinobject helpt ons om het chatbericht als JSON te vertegenwoordigen wanneer dat nodig is. Ons model is in orde, dus laten we doorgaan met de controllers.
De controller is het gedrag van uw applicatie. Dit betekent dat u uw controller eenvoudig moet kunnen houden en in staat bent om eenvoudig te communiceren met domeinmodellen en andere services. We verwachten dat onze controllers omgaan met:
Hier kunt u de algemene eindpunten bekijken:
pakket realtime.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; importeer java.util.Date; importeer java.util.List; / ** * @author huseyinbabal * / @Controller public class ChatMessageController @Autowired private ChatMessageRepository chatMessageRepository; @RequestMapping ("/ login") public String login () terug "login"; @RequestMapping ("/ chat") public String chat () terug "chat"; @RequestMapping (value = "/ messages", method = RequestMethod.POST) @MessageMapping ("/ newMessage") @SendTo ("/ topic / newMessage") public ChatMessage save (ChatMessageModel chatMessageModel) ChatMessageModel chatMessage = nieuw ChatMessageModel (chatMessageModel .getText (), chatMessageModel.getAuthor (), nieuwe datum ()); ChatMessageModel-bericht = chatMessageRepository.save (chatMessage); LijstchatMessageModelList = chatMessageRepository.findAll (nieuwe PageRequest (0, 5, Sort.Direction.DESC, "createDate")). getContent (); return nieuwe ChatMessage (chatMessageModelList.toString ()); @RequestMapping (value = "/ messages", method = RequestMethod.GET) public Http Entity list () Lijst chatMessageModelList = chatMessageRepository.findAll (nieuwe PageRequest (0, 5, Sort.Direction.DESC, "createDate")). getContent (); retourneer nieuwe ResponseEntity (chatMessageModelList, HttpStatus.OK);
De eerste en tweede eindpunten zijn alleen voor het weergeven van de inlog- en hoofdchatpagina. De derde actie is voor het verwerken van nieuwe berichtenopslag en het uitzenden van berichten. Nadat het bericht is opgeslagen, wordt het via de / Onderwerp / bericht
kanaal. Voor het opslaan van berichtgegevens in MongoDB gebruiken we een MongoDB-repository.
Zoals u kunt zien, zijn er twee soorten eindpunt / messages
: GET en POST. Wanneer u een POST-aanvraag naar eindpunt doet / messages
met de juiste payload van berichten wordt deze automatisch naar de klasse ChatMessageModel cast en wordt het bericht in MongoDB opgeslagen. Na een succesvolle opslag wordt deze automatisch naar de clients gepusht. Maar hoe? In die actie is er een annotatie @SendTo ( "/ topic / newMessage")
. Hiermee wordt de inhoud verzonden van de functie naar de clients verzonden. En de geretourneerde inhoud is als volgt:
... return new ChatMessage (chatMessageModelList.toString ()); ...
Dit is het laatste bericht uit de database:
Het bovenstaande bericht wordt geconverteerd naar een indeling voor WebSocket-communicatie. Dit kanaalbericht wordt aan de clientzijde afgehandeld met een JavaScript-bibliotheek van derden en wordt in de volgende secties verwerkt.
Voor bericht db-bewerkingen, veer-boot-starter-data-MongoDB
is gebruikt. Deze bibliotheek helpt ons bij repository-bewerkingen en het maken van een repository-object voor MongoDB is heel eenvoudig. Je kunt het voorbeeld zien ChatMessageRepository
hieronder:
pakket realtime.repository; import org.springframework.data.mongodb.repository.MongoRepository; import realtime.domain.ChatMessageModel; importeer java.util.List; / ** * @author huseyinbabal * / public interface ChatMessageRepository verlengt MongoRepositoryLijst findAllByOrderByCreateDateAsc ();
Als u een interface maakt en uitbreidt MongoRepository, String>
, je zult in staat zijn om automatisch CRUD-operaties te gebruiken zoals vind()
, vind alle()
, opslaan()
, enz.
Zoals je kunt zien, MongoRepository
verwacht een domeinobject. We hebben dit model al gedefinieerd in het gedeelte Model van de zelfstudie. In deze repository hebben we een aangepaste functie gedefinieerd met de naam findAllByOrderByCreateDateAsc ()
.
Als je ooit JPA hebt gebruikt voordat je dit gemakkelijk kunt begrijpen, maar laat me dit even uitleggen. Als u een functienaam definieert in een interface die wordt uitgebreid MongoRepository
, deze functienaam wordt automatisch automatisch doorgestuurd naar een vraag aan de achterkant van Spring. Het zal iets zijn als:
SELECT * FROM ChatMessageModel WAAR 1 BESTELLING VAN createDate ASC
In ChatMessageController
, we hebben deze functie gebruikt, en ook hebben we de standaardfuncties van de MongoRepository
:
chatMessageRepository.findAll (nieuwe PageRequest (0, 5, Sort.Direction.DESC, "createDate")). getContent ()
vind alle
wordt een parameter gebruikt voor sorteren en paginering. U kunt de gids op de Spring-website bekijken voor meer informatie over Spring JPA.
In het viewgedeelte hebben we slechts twee pagina's. Een daarvan is de inlogpagina om de bijnaam van de gebruiker te krijgen, en de tweede is de belangrijkste chatpagina om berichten naar chatgebruikers te verzenden.
Zoals je kunt zien in het gedeelte over de controller hierboven, worden ze weergegeven met behulp van twee eindpunten, /Log in
en / chatten
. Om interactieve pagina's te maken, gebruiken we JavaScript-bibliotheken van derden. We zullen ze gebruiken van CDN-pagina's. U kunt de inlogpagina hieronder bekijken:
Kies een bijnaam om naar de chat te gaan
Op de inlogpagina hebben we een voorbeeldtekstvak. Wanneer u klikt Voer Chat in, je bijnaam wordt opgeslagen in een cookie. Deze bijnaam zal worden gebruikt om het veld voor het auteurschap van het chatbericht in te stellen. Wanneer u klikt Voer Chat in, de chatpagina wordt geopend. Als u al bent ingelogd en naar de inlogpagina gaat, wordt u doorgestuurd naar de chatpagina.
Dit is de chatpagina:
Realtime-chatapplicatie met Spring Boot, Websockets en MongoDB
Chatgeschiedenis
Deze pagina is voor het eenvoudig bekijken en verzenden van berichten. Berichten worden via WebSockets op deze pagina afgeleverd. Op deze pagina kunt u zien sockjs
en stompjs
. Die zijn voor het verwerken van meldingen. Wanneer een nieuw bericht wordt ontvangen, wordt het laatste berichtengebied opnieuw bevolkt.
Overigens, wanneer u de chatpagina voor het eerst opent, worden de nieuwste berichten opgehaald in het berichtengebied. Zoals je aan de JavaScript-kant kunt zien, is ons berichtkanaal dat nieuw bericht
. Dus we luisteren naar dit kanaal en wanneer u op de knop klikt Sturen knop, wordt het bericht in het tekstvak naar het eindpunt verzonden en wordt dat bericht na succesvolle opslag naar de verbonden clients verzonden.
Zoals u kunt zien, is de softwarearchitectuur hier heel eenvoudig en gemakkelijk te ontwikkelen. We hebben een productiegereed code en laten we deze toepassen op Modulus.
Modulus is een van de beste PaaS voor het implementeren, schalen en bewaken van uw toepassing in de taal van uw keuze.
Voordat we de applicatie gaan inzetten, kunnen we een database maken met behulp van het Modulus admin-paneel. U hebt een Modulus-account nodig voor het maken en implementeren van dba. Maak daarom een account aan als u er nog geen heeft.
Ga naar het Modulus-dashboard en maak een database aan:
Geef in het scherm voor het maken van de database een databasenaam op, selecteer de MongoDB-versie (ik heb 2.6.3 gebruikt, dus het is beter als u ook 2.6.3 kiest) en definieer uiteindelijk een gebruiker om lees / schrijfbewerkingen voor de database toe te passen.
U kunt een MongoDB-URL krijgen nadat u met succes de database hebt gemaakt. We gebruiken de MongoDB-URL in de omgevingsvariabelen die moeten worden gebruikt door de toepassing Spring Boot.
Als u de omgevingsvariabelen voor MongoDB wilt instellen, moet u een toepassing hebben. Ga naar Dashboard en klik projecten. Klik op deze pagina Maak een nieuw project.
Ga naar om door te gaan met het configureren van de omgevingsvariabelen Dashboard en klik projecten. Selecteer uw project en klik op Toediening. Blader naar beneden op de pagina en stel omgevingsvariabelen in met de toets SPRING_DATA_MONGODB_URI
en waarde van uw database-URI:
Wanneer u uw toepassing implementeert, gebruikt Spring die omgevingsvariabele. We hebben gedaan met de vereisten en laten we doorgaan met het implementatiedeel.
Om het project in te zetten, voert u een taak uit in stappen:
gradle build
Deze taak genereert een war-bestand met de naam ROOT.war
. Kopieer dit bestand naar een nieuwe map en installeer modulus CLI als dat niet het geval is.
npm install-g modulus
Log in op het systeem;
modulus login
Voer nu de volgende opdracht uit om te implementeren ROOT.war
naar Modulus.
modulus deploy
Hiermee wordt het oorlogsbestand geïmplementeerd en kunt u projectlogboeken achterhalen om de status van uw implementatie te bekijken door de volgende opdracht uit te voeren:
modulus project logs staart
Dat is alles met de inzet!
Het belangrijkste doel van deze zelfstudie is om u te laten zien hoe u een real-time chat-applicatie kunt maken met Spring Boot, WebSockets en MongoDB.
Om het project in productie te houden, wordt Modulus gebruikt als een PaaS-provider. Modulus heeft zeer eenvoudige implementatiestappen en heeft ook een interne database (MongoDB) voor onze projecten. Daarnaast kunt u zeer nuttige tools gebruiken in het Modulus-dashboard zoals Logs, Notifications, Auto-Scaling, Db Administration en meer.