Inhalt:
- Einführung
- Ein Projekt erstellen
- Spring MVC-Verbindung
- Seiten und Controller erstellen
- Aufbau
- Modell
- Model View Controller
Einführung
Ich begann, mich mit für mich neuen Technologien und Frameworks vertraut zu machen, indem ich verschiedene Beispiele studierte, in denen sie verwendet wurden, denn normalerweise verstehe ich etwas am besten, wenn ich es am Beispiel einer vollwertigen Anwendung in Aktion sehe. Typischerweise handelt es sich bei solchen Beispielen um CRUD- Anwendungen ( Erstellen , Lesen , Aktualisieren , Löschen ). Das Internet ist voll von solchen Beispielen unterschiedlicher Komplexität. Das Problem ist, dass sie normalerweise nicht im Detail erklären, wie, was und warum dort gemacht wurde, warum diese oder jene Abhängigkeit hinzugefügt wurde, warum diese oder jene Klasse benötigt wird usw. In den meisten Fällen nehmen sie eine vollständig fertige Bewerbung mit einer endgültigen POM-Datei und endgültigen Klassenversionen und gehen einfach jede einzelne durch, ohne sich auf die kleinen Dinge zu konzentrieren, die für eine erfahrene Person wahrscheinlich offensichtlich erscheinen. Ich habe mir viele solcher Beispiele angesehen und es ist normalerweise klar, wie alles funktioniert, aber wie es dazu kam, ist nicht ganz klar. Daher habe ich entschieden, dass ein solches Beispiel nicht aus der Sicht eines erfahrenen Entwicklers nützlich sein würde, sondern aus der Sicht eines Anfängers, der sich noch nie mit Spring, Hibernate und anderen Dingen beschäftigt hat.Ein Projekt erstellen
Da ich also ein Neuling bin, werden wir keine obskuren Archetypen verwenden. Spring initializr klingt immer noch zu gruselig. Daher werden wir das gewöhnlichste einfache Maven-Projekt erstellen. Ich habe keinen Domainnamen, also schreibe ich in „groupid“ einfachtestgroup
und in „artifactid“ schreibe ich zum Beispiel den Namen filmography
(das wird eine Liste von Filmen sein). Wir erstellen ein Projekt und wählen aus Enable auto-import
, wann die Idee dies nahelegt. Dadurch wird jedes Mal, wenn wir Änderungen an der POM-Datei (Project Object Model, diese Datei beschreibt die gesamte Struktur des Maven-Projekts) vornehmen, alles sofort automatisch auf das Projekt angewendet. Die Bibliotheken werden aus unserem lokalen Repository übernommen, wenn wir sie bereits haben, oder wenn wir einige neue Abhängigkeiten verwenden, mit denen wir uns vorher noch nicht befasst haben, lädt Maven sie einfach über das Internet aus dem zentralen Repository herunter. Maven verfügt außerdem über eine Funktion zum Herunterladen von Quellen und Dokumentation (Download Sources and/or Documentation). Es ist auch sehr praktisch: Wenn bei einer Klasse oder Methode etwas nicht klar ist, können Sie zum Quellcode gehen und sehen, wie alles darin funktioniert. Lassen Sie uns ein paar Details hinzufügen. Dies wird eine Webanwendung sein und wir werden Tomcat verwenden . Um eine Anwendung auf Tomcat bereitzustellen, müssen Sie sie in Form eines War-Archivs (Web Application Resource, ein spezielles Format für Webanwendungen) dorthin übertragen. Fügen Sie dazu der POM-Datei die folgende Zeile hinzu, damit die Anwendung in ein War-Archiv kompiliert wird:
<packaging>war</packaging>
Nun, Sie benötigen auch ein spezielles Verzeichnis für Webquellen, in unserem Fall gibt es JSP- Seiten und einige Webressourcen. main
Lassen Sie uns ein Verzeichnis erstellen webapp
. main
Es sollte genau so heißen und sich genauso befinden wie java
, resources
da dies die Standard-Maven-Verzeichnisstruktur ist. Sobald wir das Paket installiert war
und somit festgestellt haben, dass es sich um ein Webprojekt handelt, webapp
wird das Verzeichnis automatisch als Webanwendungsquellen markiert (es wird ein blauer Punkt darauf angezeigt) und alles, was mit dem Web zu tun hat, wird in diesem Ordner durchsucht. Und einen Moment. Standardmäßig verwendet Maven die Sprachversion 1.5, aber ich möchte beispielsweise Version 1.8 verwenden – Java 8 (Sie können 10 oder 11 nehmen, aber es gibt immer noch keine Pläne, irgendwelche Funktionen von dort zu verwenden, also lassen Sie es 8 sein ). Das lässt sich ganz einfach lösen, wir schreiben in Google so etwas wie „Maven Java 8“ und schauen, was zur POM-Datei hinzugefügt werden muss, damit Maven unsere Klassen für die benötigte Version kompiliert. Als Ergebnis haben wir Folgendes:
Spring MVC-Verbindung
Irgendwo muss man anfangen. Laut Plan werden wir die Datenbank verbinden und den Ruhezustand nutzen, aber das klingt im Moment alles etwas zu beängstigend. Wir müssen zuerst etwas Einfacheres tun. Spring MVC, das ist schon besser, das MVC-Muster kennen wir schon lange, es wurde in der Hälfte der großen Aufgaben des Kurses verwendet. Von hier aus beginnen wir zu tanzen. Um eine Webanwendung mit Spring MVC zu erstellen, benötigen wir außerdem eine Servlet-API, d.h. das Ding, mit dessen Hilfe die Anfrage-Antwort-Interaktion stattfindet. Versuchen wir, dies zu verbinden. Wir gehen zu Google, suchen im Maven-Repository nach den notwendigen Abhängigkeiten und fügen sie dem hinzupom.xml
. Im Abschnitt „Externe Bibliotheken“ können Sie sehen, dass nicht nur spring-webmvc geladen wurde , sondern auch eine Reihe anderer Dinge. Diese. Wir müssen keine zusätzlichen Abhängigkeiten für Spring Core , Context , Beans usw. einschließen. Was wir brauchen, alles, was wir brauchten, wurde zusammen mit spring-webmvc abgerufen .
Wir müssen einen kleinen Haftungsausschluss machen. Normalerweise wird empfohlen, für jede verwendete Bibliothek eine separate Abhängigkeit hinzuzufügen, auch wenn diese bereits mit den bereits hinzugefügten Bibliotheken gebündelt ist, weil Dies kann helfen, einige Probleme und Störungen zu vermeiden. Ein einfaches Beispiel. Nehmen wir an, wir haben eine Abhängigkeit hinzugefügt, die eine API verwendet, und gleichzeitig wird eine Art Implementierung für diese API aufgerufen. Und dann haben wir eine weitere Abhängigkeit hinzugefügt, die dieselbe API verwendet und dafür auch einen Teil ihrer Implementierung abruft, aber dieses Mal ist es anders. Somit werden wir zwei verschiedene Implementierungen derselben API haben. Und wenn wir selbst irgendwo einige Methoden dieser API verwenden möchten, entsteht ein Problem, da das System nicht weiß, welche Implementierung es verwenden soll, sondern eine zufällige Auswahl trifft, möglicherweise nicht die, die wir erwartet haben. Und wenn Sie explizit eine Abhängigkeit für eine der Implementierungen angeben, wird dieser Priorität eingeräumt. Dies ist jedoch keine so strenge Empfehlung, sondern gilt hauptsächlich für große Projekte, bei denen viele verschiedene Bibliotheken verschiedener Unternehmen verwendet werden. Darauf verzichten wir hier, um die POM-Datei nicht zu stark zu belasten; es sind keine Probleme zu erwarten. Dennoch lohnt es sich, dies im Hinterkopf zu behalten. |
provided
abhängig javax.servlet-api
? Der Bereich ist der Umfang der Abhängigkeit, provided
was bedeutet, dass die Abhängigkeit in der Phase des Kompilierens und Testens der Anwendung verfügbar ist, aber nicht archiviert wird. Tatsache ist, dass wir zum Bereitstellen der Anwendung einen Servlet-Container, Tomcat, verwenden werden, der bereits über solche Bibliotheken verfügt, sodass keine Notwendigkeit besteht, sie dorthin zu übertragen und das Archiv mit unnötiger Last zu belasten. Aus dem gleichen Grund werden wir in Zukunft auf die übliche Methode verzichten main
, da diese bereits in Tomcat vorhanden ist.
Seiten und Controller erstellen
Versuchen wir jetzt, etwas Einfaches zu kochen. Erstellen wir zunächstwebapp
beispielsweise ein zusätzliches Verzeichnis, pages
in dem unsere Ansichten gespeichert werden, d. h. JSP-Seiten und erstellen Sie ein paar Seiten. Wir benötigen eine Seite, auf der in Zukunft beispielsweise eine Liste mit Filmen angezeigt wird, films.jsp
und vielleicht können wir eine separate Seite für die Bearbeitung erstellen, sei es so editPage.jsp
. Wir werden sie vorerst nicht mit ernsthaften Informationen füllen; nur zum Testen werden wir auf einer Seite einen Link zu einer anderen erstellen. Jetzt brauchen wir eine Klasse, die Anfragen verarbeitet, d.h. Regler. Fügen wir ein neues Paket hinzu controller
und erstellen darin eine Klasse FilmController
(im Allgemeinen ist es nicht notwendig, alles in verschiedene Pakete zu packen, diese Anwendung wird sehr klein und einfach sein, aber in einem normalen Projekt kann es viele Controller, Konfigurationsklassen und Modelle geben usw., also ist es besser, sich auch bei kleinen Projekten sofort daran zu gewöhnen, alles geordnet und strukturiert zu erledigen, damit kein Durcheinander entsteht. In dieser Klasse erstellen wir Methoden, die unsere Ansichten als Antwort auf Anfragen zurückgeben.
package testgroup.filmography.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class FilmController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView allFilms() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("films");
return modelAndView;
}
@RequestMapping(value = "/edit", method = RequestMethod.GET)
public ModelAndView editPage() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("editPage");
return modelAndView;
}
}
Was ist der Punkt? Spring MVC hat eine Sache namens DispatcherServlet
. Dies ist wie der Hauptcontroller, alle eingehenden Anfragen werden durch ihn geleitet und dann an einen bestimmten Controller weitergeleitet. Die Annotation @Controller
teilt Spring MVC lediglich mit, dass es sich bei dieser Klasse um einen Controller handelt (also im Allgemeinen logisch). Der Dispatcher überprüft die Annotationen, @RequestMapping
um die entsprechende Methode aufzurufen. Mit der Annotation @RequestMapping
können Sie Adressen für Controller-Methoden festlegen, über die diese im Client (Browser) verfügbar sind. Es kann auch auf die Controller-Klasse angewendet werden, um sozusagen die Root-Adresse für alle Methoden festzulegen. allFilms()
Der Parameter für die Methode value
ist auf „ “ gesetzt /
, sodass sie sofort aufgerufen wird, wenn die Kombination http://host:port/ im Browser eingegeben wird (d. h. standardmäßig http ://localhost:8080/ oder http ://127.0 .0.1:8080/ ). Der Parameter method
gibt an, welche Art von Anfrage unterstützt wird (GET, POST, PUT usw.). Da wir hier nur Daten empfangen, kommt GET zum Einsatz. Wenn später Methoden zum Hinzufügen und Bearbeiten erscheinen, wird es bereits POST-Anfragen geben. (Übrigens können Sie anstelle einer Annotation , die eine Methode angibt, annotations usw. äquivalent @RequestMapping
verwenden .)) In unseren Methoden erstellen wir ein Objekt und legen den Namen der Ansicht fest, die zurückgegeben werden muss. @GetMapping
@PostMapping
@GetMapping
@RequestMapping(method = RequestMethod.GET
ModelAndView
Aufbau
Fahren wir mit dem Einrichten der Konfiguration fort.config
Lassen Sie uns eine Klasse im Paket erstellen WebConfig
. Es gibt nur eine Methode, die ein Objekt vom Typ zurückgibt ViewResolver
. Dies ist die Schnittstelle, die erforderlich ist, um eine Darstellung anhand des Namens zu finden.
package testgroup.filmography.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "testgroup.filmography")
public class WebConfig {
@Bean
ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
@Configuration
teilt Spring mit, dass diese Klasse eine Konfigurationsklasse ist und die Definitionen und Abhängigkeiten bean
der Komponenten enthält. Beans sind Objekte, die von Spring verwaltet werden. Die Annotation wird zum Definieren einer Bean verwendet @Bean
. @EnableWebMvc
ermöglicht Ihnen den Import der Spring MVC-Konfiguration aus der WebMvcConfigurationSupport
. Sie können beispielsweise auch eine Schnittstelle implementieren, WebMvcConfigurer
die über eine ganze Reihe von Methoden verfügt, und alles nach Ihren Wünschen anpassen, aber darauf müssen wir noch nicht eingehen, die Standardeinstellungen reichen aus. @ComponentScan
teilt Spring mit, wo es nach den Komponenten suchen soll, die es verwalten soll, d. h. Klassen, die mit einer Annotation @Component
oder deren Ableitungen wie @Controller
, @Repository
, markiert sind @Service
. Diese Annotationen definieren automatisch die Klassen-Bean. In der Methode viewResolver()
erstellen wir ihre Implementierung und bestimmen, wo genau nach Darstellungen gesucht werden soll webapp
. Wenn wir also in der Controller-Methode den Namen „ films
“ festlegen, wird die Ansicht als „ /pages/films.jsp
“ gefunden. Wir haben also eine Konfigurationsklasse, aber im Moment ist es nur eine Art separate Klasse, sie hat keinerlei Auswirkungen auf unsere Anwendung . Wir müssen diese Konfiguration im Spring-Kontext registrieren. Dafür benötigen Sie eine Klasse AbstractAnnotationConfigDispatcherServletInitializer
. Im Paket config
erstellen wir seinen Nachfolger, beispielsweise AppInitializer , und implementieren seine Methoden.
package testgroup.filmography.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
Die letzte Methode registriert Adressen und es gibt zwei weitere Methoden zum Registrieren von Konfigurationsklassen. Webkonfigurationen, in denen ViewResolver
's und dergleichen definiert sind, werden in platziert getServletConfigClasses()
. Es ist besser, all dies in der Dokumentation und in verschiedenen Handbüchern nachzulesen, aber in unserem Fall ist es noch nicht notwendig, sich damit zu befassen. Bei uns können Sie WebConfig
im Prinzip RootClasses
beides definieren, Sie können sogar beide gleichzeitig definieren, es wird trotzdem funktionieren . Eine Sache noch. Es kann zu Problemen bei der Kodierung kommen, wenn beim Senden von Werten mit russischen Zeichen aus dem Formular Kritzeleien entstehen. Um dieses Problem zu lösen, werden wir einen Filter hinzufügen, der Anfragen vorverarbeitet. Wir gehen zur AppInitializer- Klasse und überschreiben die Methode getServletFilters
, in der wir die gewünschte Kodierung angeben, sie sollte natürlich die gleiche sein wie überall sonst, wie auf den Seiten und in der Datenbank:
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return new Filter[] {characterEncodingFilter};
}
Nun, alles scheint eingerichtet zu sein. Sie können versuchen, es auszuführen und zu sehen, was passiert. Ausführen -> Ausführen -> Konfigurationen bearbeiten -> Neue Konfiguration hinzufügen -> Tomcat-Server -> Lokal Als nächstes müssen Sie ein Artefakt zum Bereitstellen auswählen. Die Idee selbst gibt einen Hinweis : Warnung: Keine Artefakte zur Bereitstellung markiert . Klicken Sie auf die Schaltfläche „Reparieren“ und wählen Sie ...: Krieg explodiert . Oder Sie können zu Bereitstellung -> Hinzufügen -> Artefakt -> ...: war explodiert gehen . Außerdem müssen Sie zu „Bereitstellung“ gehen und das Applecation-Kontextfeld (dies ist Teil der URL-Adresse, unter der die Anwendung im Browser verfügbar ist) auf „ /
“ setzen. Dann ist unsere Anwendung sofort unter http://localhost:8080/ verfügbar (Sie können dort aber auch etwas angeben, z. B. „ “, und dann müssen Sie dies nur noch zu allen Adressen hinzufügen, d. h. es wird z. B. Nr „http://localhost:8080/edit“ , aber es wird „http://localhost:8080/filmography/edit“ sein . Klicken Sie auf „Ausführen“ und warten Sie, bis es startet. Folgendes habe ich erhalten: Alles scheint in Ordnung zu sein, aber es gibt eine Einschränkung. Fakt ist, dass unsere Seiten nun öffentlich zugänglich sind und durch Eingabe des Pfades in die Adressleiste direkt aufgerufen werden können. Wir geben http://localhost:8080/pages/films.jsp ein und haben nun unsere Seite ohne Wissen des Verantwortlichen erhalten. Irgendwie ist das nicht ganz korrekt, deshalb erstellen wir ein spezielles Verzeichnis . Der Inhalt bleibt der Öffentlichkeit verborgen und kann nur über einen Controller abgerufen werden. Wir platzieren das Verzeichnis mit unseren Ansichten ( ) in und fügen es entsprechend dem Präfix hinzu: /filmography
webapp
WEB-INF
pages
WEB-INF
ViewResolver
viewResolver.setPrefix("/WEB-INF/pages/");
Jetzt erhalten wir unsere Seite unter http://localhost:8080 , aber wenn wir direkt versuchen , http://localhost:8080/WEB-INF/pages/films.jsp aufzurufen, erhalten wir einen 404-Fehler. Na gut, wir haben das einfachste Webanwendung, Hello World, wie sie sagen. Die Projektstruktur sieht derzeit so aus:
Modell
Wir haben bereits Ansichten und einen Controller, aber in MVC gibt es auch einen dritten Buchstaben, daher werden wir zur Vervollständigung des Bildes auch ein Modell hinzufügen.model
Erstellen wir im Paket Film
beispielsweise eine Klasse mit den folgenden Feldern: int id
, String title
(Titel), int year
(Erscheinungsjahr), String genre
(Genre) und boolean watched
(d. h. haben Sie diesen Film bereits gesehen oder nicht).
package testgroup.filmography.model;
public class Film {
private int id;
private String title;
private int year;
private String genre;
private boolean watched;
// + Getters and setters
}
Nichts Besonderes, nur eine gewöhnliche Klasse, private Felder, Getter und Setter. Objekte solcher Klassen werden auch POJO
(Plain Old Java Object) genannt, also d.h. „einfaches Java-Objekt“. Versuchen wir nun, ein solches Objekt zu erstellen und auf der Seite anzuzeigen. Im Moment machen wir uns keine allzu großen Gedanken darüber, wie man es erstellt und initialisiert. Um es auszuprobieren, erstellen wir es einfach dummerweise direkt im Controller, zum Beispiel so:
public class FilmController {
private static Film film;
static {
film = new Film();
film.setTitle("Inception");
film.setYear(2010);
film.setGenre("sci-fi");
film.setWatched(true);
}
ModelAndView
Und fügen Sie dieses Objekt mit der Methode zu unserem hinzu addObject
:
@RequestMapping(method = RequestMethod.GET)
public ModelAndView allFilms() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("films");
modelAndView.addObject("film", film);
return modelAndView;
}
Jetzt können wir dieses Objekt auf unserer Seite anzeigen. Anstelle films.jsp
von Hello World schreiben wir ${film}
und das Objekt, das dem Attributnamen „ film
“ entspricht, wird hier ersetzt. Versuchen wir, es auszuführen und zu sehen, was passiert ist (für eine klare Ausgabe des Objekts Film
wurde die Klasse neu definiert toString()
):
Model View Controller
Zu diesem Zeitpunkt scheinen wir bereits über eine vollwertige Spring MVC-Anwendung zu verfügen. Bevor wir fortfahren, wäre es gut, sich alles noch einmal anzusehen und herauszufinden, wie alles funktioniert. Im Internet findet man viele Bilder und Diagramme dazu, mir gefällt dieses hier:Dispatcher Servlet
und dann wird ein geeigneter Controller gefunden, mit dem diese Anfrage verarbeitet werden kann HandlerMapping
(dies ist eine Schnittstelle zur Auswahl eines Controllers, prüft, welcher der verfügbaren Controller über eine Methode verfügt, die eine solche Adresse akzeptiert). , ruft eine geeignete Methode auf und Controller
gibt Informationen über die Ansicht zurück, dann findet der Dispatcher mit ViewResolver
'a die gewünschte Ansicht anhand des Namens, woraufhin die Modelldaten in diese Ansicht übertragen werden und wir unsere Seite als Ausgabe erhalten. Irgendwie so. Fortsetzung folgt... Einführung in Maven, Spring, MySQL, Hibernate und die erste CRUD-Anwendung (Teil 1) Einführung in Maven, Spring, MySQL, Hibernate und die erste CRUD-Anwendung (Teil 2) Einführung in Maven, Spring, MySQL, Hibernate und die erste CRUD-Anwendung (Teil 3) Einführung in Maven, Spring, MySQL, Hibernate und die erste CRUD-Anwendung (Teil 4)
GO TO FULL VERSION