Spring MVC
Doku: http://docs.spring.io/spring-framework/docs/4.1.2.RELEASE/spring-framework-reference/html/mvc.html#mvc
Spring MVC ist Request-Driven, d. h. ein Controller erhält Http-Requests (GET, POST), die er verarbeitet und zu guter Letzt eine Antwort in Form eines Views (= UI) sendet.
http://docs.spring.io/spring-framework/docs/4.1.2.RELEASE/spring-framework-reference/html/mvc.html#mvc
Spring MVC Rest
Ein @RestController und ein @Controller (für UIs) sehen fast identisch aus. Während der RestController allerdings HttpResponses zurückliefert, liefert der Controller View-Identifier, über die dann eine HTML-Response gebaut und zum Client (= Browser) geliefert wird.
Die Grenzen zwischen UI-Client und Rest-Client verschwimmen ... und das ist auch gut so.
Spring MVC - View-Technologie
Spring MVC ist zunächst mal unabhängig von der konkret eingesetzten View-Technologie. Es bietet Adapter, um beispielsweise JSP oder Thymeleaf zu verwenden. Hier findet man weitere Informationen:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-viewresolver
i18n - Internationalization
https://justinrodenbostel.com/2014/05/13/part-4-internationalization-in-spring-boot/
Gedanken von Mkkyong: https://www.mkyong.com/spring-mvc/spring-mvc-internationalization-example/
Locale-Resolver
Per Default verwendet Spring MVC den org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver, so daß die Sprache aus dem Accept-Header gewählt wird. Diese Sprache ist die Sprache, die im Browser eingestellt ist. Da dort mehrere Sprachen eingestellt sein können, wird die erste genommen (= man unterstellt, daß das die bevorzugte Sprache ist).
Will man seine eigene Logik verwenden, so muß man nur einen eigenen MyLocaleResolver schreiben und als Bean konfigurieren:
Dadurch wird dieser MyLocaleResolver automatisch eingebunden, wenn ich beispielsweise in einem Controller die Locale injecten lasse:
LocaleContextHolder
Über
LocaleContextHolder.getLocale()LocaleContextHolder.getTimezone()
lassen sich Informationen zum aktuellen Thread ermitteln. Dort steckt beispielsweise die Locale drin, die der konfigurierte LocaleResolver ermittelt hat.
LocaleChangeInterceptor
Hat man diesen Interceptor konfiguriert (
so läßt sich über http://localhost:8081/persondetails?language=de die Sprache auf deutsch umschalten.
Message-Resolver
Spring MVC kommt mit der in Spring Boot üblichen AutoConiguration (org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration) daher. Diese Klasse offenbart, was man tun muß, um Texte/Labels/Messages zu internationalisieren ... Dateien der Art:
src/main/resources/messages.propertiessrc/main/resources/messages_de.properties...
anlegen. Gemeinsam mit dem LocaleResolver (s. o.) wird zur Laufzeit der richtige Wert ausgelesen.
Sollen die Dateien in einem anderen Verzeichnis liegen, sollen es mehrere sein oder sollen sie einen anderen Namen haben, dann müssen die application.properties angepaßt werden:
So läßt sich beispielsweise auch das Caching konfigurieren:
Caching
Die vom Server bereitgestellten Ressourcen (JavaScript, Images, ...) sollten clientseitig gecached werden. Hierzu bietet Spring die org.springframework.boot.autoconfigure.web.ResourceProperties an, in der sich viele interessante Schalter befinden
Spring MVC - Controller und Model
Der Controller übernimmt die Seitensteuerung, d. h. die Controller-Methode liefert einen String als Rückgabewert, der die nachfolgende View-Page repräsentiert, z. B.
Je nach gewählter View-Technologie (z. B. Thymeleaf) und deren Konfiguration wird dann beispielsweise eine Seite login.html gebaut (aus einem Template) und zum Client geschickt.
Hier kann aber beispielsweise auch ein Redirect-Request auf eine externe Seite getriggert werden:
Configuration
Wie üblich verwendet Spring einen annotationsbasierten Ansatz. Die Annotationen werden bei Anwendungsstart gescannt und dadurch die Applikation initialisiert. Handelt es sich um eine Spring Boot Applikation mit @EnableAutoConfiguration so sollte alles automatisch initialisiert werden. Ansonsten muß
eingesetzt werden, um die Annotationen in den Initialisierungsfokus zu rücken.
@Controller
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-controller
Kennzeichnet eine Klasse in der Rolle eines Controllers. Ein Controller erhält HTTP-Requests, z. B. aus Http-Post-Form-Requests. Spring MVC versucht, den Lücke zwischen textbasiertem HTTP und der Arbeit mit Java-Objekten im Controller so klein wie möglich erscheinen zu lassen. Hier muß sich niemand mehr um das Marshalling/Unmarshalling (aus HTTP-Stringwerten Java-Objekte machen) kümmern.
Ein Controller ist zudem für den Web-Flow zuständig und liefert deshalb den zu rendernden View im Return-Value. Diese Information wird vom konfigurierten ViewResolver (hier ist die Brücke zur UI-technologie) verwendet, um die HTML-Seite zu erzeugen. Siehe unten Typkonvertierung.
Einige der in diesem Kontext verwendeten Annotationen (z. B. @RequestMapping) kommen auch beim @RestController zur Anwendung.
ACHTUNG: im Gegensatz zu JSF ist Spring MVC ein Controller-First-Ansatz (ähnlich wie JSP). JSF ist ein View-First-Ansatz, d. h. der Einstiegspunkt der View.
@RequestMapping
Hierüber werden die Controller-Actions deklariert:
Hierüber wird ein HTTP-Endpunkt, der dann über http://.../user auf ALLE HTTP-Methoden (GET, POST, PUT, ...) reagiert. Über method = RequestMethod.GET läßt sich das auf GET-Requests einschränken.
Solche Request-Mappings können relativ komplex werden, wenn beispielsweise @PathVariable verwendet werden (ein Beispsiel von hier):
Man kann auch Headerwerte zur Selektion der richtigen Controllermethode aufzunehmen.
@GetMapping
Ein typischer HTTP-GET @Controller:
Mittlerweile gibt es auch spezialisierte RequestMappings: @GetMapping, ...
@PostMapping
Ein typischer HTTP-POST-Controller:
@RequestMapping ... Parameter der Java-Methode
Spring Doku: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-typeconversion
Default-Methoden-Parameter:
Man kann in eine Controller-Methode die folgenden Parameter aufnehmen und bekommt sie richtig injeziert:
BindingResultModelLocale- die im Browser eingestellte Sprache (kommt über den HTTP Accept-Language Header)
Methoden-Parameter:
Dieser Link beschreibt die Regeln für die Java-Methode, die an einem @RequestMapping hängt:
http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-methods
Typ-Konvertierung:
Im HTTP-Request sind nun Strings enthalten, in den Controller-Methoden arbeitet man häufig aber mit komplexeren Java-Klassen. Hierfür gibt es bereits häufig automatische Konvertierungen, häufig wird aber auch JAXB verwendet.
Ist keine automatische Konvertierung möglich, so könnte es zu einer org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException kommen. In solchen Fällen muß man im worst-case entsprechende Converter schreiben (weitere Details).
Tritt beim Unmarshalling ein Fehler auf, so wird das in BindingResult hinterlegt. Dieser Parameter sollte in keiner HTTP-POST, so daß der Hier finden sich weitere Informationen zur Typ-Konvertierung:
http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-typeconversion
Mit JAXB kann die Typ-Konvertierung unterstützt werden.
Semantische Prüfungen:
Neben diesen syntaktischen Typ-Prüfungen (ein String muß in ein java.util.Date konvertierbar sein) können weitere semantische Prüfungen sinnvoll sein. Diese können über Java Bean Validation mit @Valid sehr schön integriert werden:
Die Fehlermeldungen können über den üblichen i18n-Mechanismus (e. g. messages.properties) konfiguriert werden. Allerdings muß dann folgende Konfiguration durchgeführt werden:
HttpServletRequest
Wie kommt man an den HttpServletRequest im Controller?
Option 3:
Hierzu braucht es aber noch einen
AOP-Proxying
Will man im Controller Transaktionen deklarieren (@Transactional), so kann man Class-Based Proxying verwenden. Das wird im Spring-Context beispielweise über
konfiguriert.
@RequestBody
Mit dieser Annotation kann man den HTTP-Body (z. B. eines HTTP-POST) in einen Parameter injecten lassen:
Der gelieferte String kann über HTTP Message Conversion verarbeitet werden. Bei folgender Schnittstelle geschieht das automatisch ... das entsprechende Marshalling vorausgesetzt (z. B. über JSON-Jackson oder JAXB):
@ResponseBody
Mit dieser Annotation wird das Ergebnis einer Controller-Methode an den HTTP-Response-Body gebunden:
Spring (Boot) Security
Zur Absicherung der HTTP-Schnittstellen stellt Spring bereits eine Auto-Configuration bereit, sofern man die Abhängigkeit
in der pom.xml eingetragen hat. Die Auto-Konfiguration sichert ALLE Http-Endpunkte per Default über HTTP-Basic-Authentication ab (hier zeigt der Browser ein Popup) - über einen WebSecurityConfigurerAdapter läßt sich die Konfiguration entsprechend anpassen, so daß einige Endpunkte auch public sind (keiner Authentifizierung bedürfen) oder beispielsweise auch Form-Authentication (mit entsprechendem Layout) ermöglicht wird.
Last updated
Was this helpful?