Een gids voor Spring-omleidingen

1. Overzicht

Dit artikel zal zich concentreren op het implementeren van een omleiding in het voorjaar en bespreekt de redenering achter elke strategie.

2. Waarom een ​​omleiding?

Laten we eerst eens kijken de redenen waarom u mogelijk een omleiding moet uitvoeren in een voorjaarstoepassing.

Er zijn natuurlijk veel mogelijke voorbeelden en redenen. Een simpele kan zijn: het plaatsen van formuliergegevens, het omzeilen van het probleem van dubbele indiening of het delegeren van de uitvoeringsstroom naar een andere controllermethode.

Een snelle kanttekening hier is dat het typische Post / Redirect / Get-patroon problemen met dubbele indiening niet adequaat aanpakt - problemen zoals het vernieuwen van de pagina voordat de eerste indiening is voltooid, kunnen nog steeds resulteren in een dubbele indiening.

3. Omleiden met de RedirectView

Laten we beginnen met deze eenvoudige benadering - en ga direct naar een voorbeeld:

@Controller @RequestMapping ("/") openbare klasse RedirectController {@GetMapping ("/ redirectWithRedirectView") openbare RedirectView redirectWithUsingRedirectView (RedirectAttributes-attributen) {attributes.addFlashAttribute ("flashAttribute", "redirectWithRedirectView"); attributes.addAttribute ("attribuut", "redirectWithRedirectView"); retourneer nieuwe RedirectView ("redirectedUrl"); }}

Achter de schermen, RedirectView zal een HttpServletResponse.sendRedirect () - die de daadwerkelijke omleiding zal uitvoeren.

Merk hier op hoe we injecteren de omleidingsattributen in de methode - het raamwerk zal hier het zware werk doen en ons in staat stellen om met deze attributen te communiceren.

We voegen het modelattribuut toe attribuut - die wordt weergegeven als HTTP-queryparameter. Het model mag alleen objecten bevatten - meestal strings of objecten die naar strings kunnen worden geconverteerd.

Laten we nu onze omleiding testen - met behulp van een simple krullen opdracht:

curl -i // localhost: 8080 / spring-rest / redirectWithRedirectView

Het resultaat zal zijn:

HTTP / 1.1 302 Gevonden server: Apache-Coyote / 1.1 Locatie: // localhost: 8080 / spring-rest / redirectedUrl? Attribute = redirectWithRedirectView

4. Omleiden met het voorvoegsel omleiding:

De vorige benadering - gebruiken RedirectView - is om een ​​aantal redenen niet optimaal.

Ten eerste: we zijn nu gekoppeld aan de Spring API omdat we de RedirectView rechtstreeks in onze code.

Ten tweede - we moeten nu vanaf het begin, bij het implementeren van die controllerbewerking - weten dat het resultaat altijd een omleiding zal zijn - wat misschien niet altijd het geval is.

Een betere optie is het gebruik van het voorvoegsel omleiding: - de omleidingsweergavenaam wordt in de controller geïnjecteerd zoals elke andere logische weergavenaam. De controller is zich er niet eens van bewust dat er wordt omgeleid.

Hier is hoe dat eruit ziet:

@Controller @RequestMapping ("/") openbare klasse RedirectController {@GetMapping ("/ redirectWithRedirectPrefix") openbare ModelAndView redirectWithUsingRedirectPrefix (ModelMap-model) {model.addAttribute ("attribute", "redirectWithRedirectPrefix"); retourneer nieuw ModelAndView ("redirect: / redirectedUrl", model); }} 

Wanneer een weergavenaam wordt geretourneerd met het voorvoegsel omleiding:de UrlBasedViewResolver (en al zijn subklassen) zullen dit herkennen als een speciale indicatie dat er een omleiding moet plaatsvinden. De rest van de weergavenaam wordt gebruikt als de omleidings-URL.

Een snelle maar belangrijke opmerking hier is dat - wanneer we deze logische weergavenaam hier gebruiken - omleiding: / redirectedUrl - we zijn bezig met een omleiding ten opzichte van de huidige Servlet-context.

We kunnen een naam gebruiken zoals een redirect: // localhost: 8080 / spring-redirect-and-forward / redirectedUrl als we moeten omleiden naar een absolute URL.

Dus nu, wanneer we het krullen opdracht:

curl -i // localhost: 8080 / spring-rest / redirectWithRedirectPrefix

We worden onmiddellijk omgeleid:

HTTP / 1.1 302 Gevonden server: Apache-Coyote / 1.1 Locatie: // localhost: 8080 / spring-rest / redirectedUrl? Attribute = redirectWithRedirectPrefix

5. Doorsturen met het voorvoegsel vooruit:

Laten we nu eens kijken hoe we iets anders kunnen doen - een forward.

Laten we voordat we de code doornemen een snel overzicht op hoog niveau van de semantiek van forward vs. redirect:

  • omleiding zal reageren met een 302 en de nieuwe URL in het Plaats koptekst; de browser / client zal dan een ander verzoek doen naar de nieuwe URL
  • vooruit gebeurt volledig aan de serverkant; de Servlet-container stuurt hetzelfde verzoek door naar de doel-URL; de URL verandert niet in de browser

Laten we nu eens kijken naar de code:

@Controller @RequestMapping ("/") openbare klasse RedirectController {@GetMapping ("/ forwardWithForwardPrefix") openbare ModelAndView redirectWithUsingForwardPrefix (ModelMap-model) {model.addAttribute ("attribute", "forwardWithForwardPrefix"); retourneer nieuw ModelAndView ("forward: / redirectedUrl", model); }} 

Hetzelfde als omleiding:, de vooruit: prefix zal worden omgezet door UrlBasedViewResolver en zijn subklassen. Intern wordt hierdoor een InternalResourceView wat doet een RequestDispatcher.forward () naar de nieuwe weergave.

Wanneer we het commando uitvoeren met krullen:

curl -I // localhost: 8080 / spring-rest / forwardWithForwardPrefix 

We krijgen HTTP 405 (methode niet toegestaan):

HTTP / 1.1 405-methode niet toegestaan ​​Server: Apache-Coyote / 1.1 Allow: GET Content-Type: text / html; charset = utf-8

Om af te ronden, vergeleken met de twee verzoeken die we hadden in het geval van de omleidingsoplossing, in dit geval, hebben we in dit geval slechts één verzoek dat van de browser / client naar de server gaat. Het attribuut dat eerder door de omleiding werd toegevoegd, ontbreekt natuurlijk ook.

6. Kenmerken met de RedirectAttributes

Volgende - laten we eens nader kijken het doorgeven van attributen in een omleiding - volledig gebruik maken van het framework met RedirectAttribures:

@GetMapping ("/ redirectWithRedirectAttributes") openbare RedirectView redirectWithRedirectAttributes (RedirectAttributes-attributen) {attributes.addFlashAttribute ("flashAttribute", "redirectWithRedirectAttributes"); attributes.addAttribute ("attribuut", "redirectWithRedirectAttributes"); retourneer nieuwe RedirectView ("redirectedUrl"); } 

Zoals we eerder zagen, kunnen we het attributes-object rechtstreeks in de methode injecteren - waardoor dit mechanisme erg gemakkelijk te gebruiken is.

Merk ook dat op we voegen ook een flash-attribuut toe - dit is een attribuut dat de URL niet haalt. Wat we kunnen bereiken met dit soort attribuut is - we hebben later toegang tot het flash-attribuut met @ModelAttribute ("flashAttribute")alleen in de methode die het uiteindelijke doel van de omleiding is:

@GetMapping ("/ redirectedUrl") openbare ModelAndView-omleiding (ModelMap-model, @ModelAttribute ("flashAttribute") Object flashAttribute) {model.addAttribute ("redirectionAttribute", flashAttribute); retourneer nieuw ModelAndView ("redirection", model); } 

Dus, om af te ronden - als we de functionaliteit testen met krullen:

curl -i // localhost: 8080 / spring-rest / redirectWithRedirectAttributes

We worden doorgestuurd naar de nieuwe locatie:

HTTP / 1.1 302 Server gevonden: Apache-Coyote / 1.1 Set-Cookie: JSESSIONID = 4B70D8FADA2FD6C22E73312C2B57E381; Pad = / spring-rust /; HttpOnly Locatie: // localhost: 8080 / spring-rest / redirectedUrl; jsessionid = 4B70D8FADA2FD6C22E73312C2B57E381? attribute = redirectWithRedirectAttributes

Op die manier gebruiken RedirectAttribures inplaats van een ModelMap geeft ons de mogelijkheid om alleen te delen enkele attributen tussen de twee methoden die betrokken zijn bij de omleidingsoperatie.

7. Een alternatieve configuratie zonder het voorvoegsel

Laten we nu een alternatieve configuratie onderzoeken - een omleiding zonder het voorvoegsel te gebruiken.

Om dit te bereiken, moeten we een org.springframework.web.servlet.view.XmlViewResolver:

  /WEB-INF/spring-views.xml 

In plaats van org.springframework.web.servlet.view.InternalResourceViewResolver we gebruikten in de vorige configuratie:

We moeten ook een RedirectView bean in de configuratie:

Nu kunnen we activeer de omleiding door op id naar deze nieuwe bean te verwijzen:

@Controller @RequestMapping ("/") openbare klasse RedirectController {@GetMapping ("/ redirectWithXMLConfig") openbaar ModelAndView redirectWithUsingXMLConfig (ModelMap-model) {model.addAttribute ("attribute", "redirectWithXMLConfig"); retourneer nieuw ModelAndView ("RedirectedUrl", model); }} 

En om het te testen, zullen we opnieuw de krullen opdracht:

curl -i // localhost: 8080 / spring-rest / redirectWithRedirectView

Het resultaat zal zijn:

HTTP / 1.1 302 Gevonden server: Apache-Coyote / 1.1 Locatie: // localhost: 8080 / spring-rest / redirectedUrl? Attribute = redirectWithRedirectView

8. Omleiden van een HTTP POST-verzoek

Voor gebruikssituaties zoals bankbetalingen, moeten we mogelijk een HTTP POST-verzoek omleiden. Afhankelijk van de geretourneerde HTTP-statuscode, kan het POST-verzoek worden omgeleid naar een HTTP GET of POST.

Volgens de HTTP 1.1-protocolreferentie maken statuscodes 301 (permanent verplaatst) en 302 (gevonden) het mogelijk de verzoekmethode te wijzigen van POST in GET. De specificatie definieert ook de corresponderende statuscodes 307 (tijdelijke omleiding) en 308 (permanente omleiding) die niet toestaan ​​dat de verzoekmethode wordt gewijzigd van POST naar GET.

Laten we nu eens kijken naar de code voor het omleiden van een postverzoek naar een ander postverzoek:

@PostMapping ("/ redirectPostToPost") openbaar ModelAndView redirectPostToPost (verzoek HttpServletRequest) {request.setAttribute (View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.TEMPORARY_REDIRECT); retourneer nieuw ModelAndView ("redirect: / redirectedPostToPost"); }
@PostMapping ("/ redirectedPostToPost") openbaar ModelAndView redirectedPostToPost () {retourneer nieuw ModelAndView ("redirection"); }

Laten we nu de omleiding van POST testen met behulp van de krullen opdracht:

curl -L --verbose -X POST // localhost: 8080 / spring-rest / redirectPostToPost

We worden omgeleid naar de bestemde locatie:

> POST / redirectedPostToPost HTTP / 1.1> Host: localhost: 8080> User-Agent: curl / 7.49.0> Accepteren: * / *> <HTTP / 1.1 200 <Content-Type: application / json; charset = UTF-8 < Overdrachtcodering: chunked <Datum: di, 08 aug. 2017 07:33:00 GMT {"id": 1, "content": "redirect voltooid"}

9. Conclusie

Dit artikel is geïllustreerd drie verschillende benaderingen voor het implementeren van een omleiding in het voorjaar, hoe attributen behandeld / doorgegeven moeten worden bij het uitvoeren van deze redirects en hoe redirects van HTTP POST-verzoeken verwerkt moeten worden.