Eine Anleitung zu Spring-Weiterleitungen

Ein Leitfaden für Spring Redirects

1. Überblick

Dieser Artikel konzentriert sich aufimplementing a Redirect in Spring und erläutert die Gründe für jede Strategie.

Weitere Lektüre:

Nach der Anmeldung mit Spring Security auf andere Seiten umleiten

Beispiel für die Weiterleitung zu verschiedenen Seiten nach der Anmeldung mit Spring Security.

Read more

Spring Security - Nach der Anmeldung zur vorherigen URL umleiten

Ein kurzes Beispiel für die Umleitung nach der Anmeldung in Spring Security

Read more

Steuern Sie die Sitzung mit Spring Security

Sitzungen mit Spring Security konfigurieren - Richten Sie gleichzeitige Sitzungen ein, aktivieren Sie den Sitzungsfixierungsschutz und verhindern Sie, dass URLs Sitzungsinformationen enthalten.

Read more

2. Warum eine Weiterleitung durchführen?

Betrachten wir zunächstthe reasons why you may need to do a redirect in einer Spring-Anwendung.

Es gibt natürlich viele mögliche Beispiele und Gründe. Eine einfache Möglichkeit ist das POSTEN von Formulardaten, das Umgehen des Problems der doppelten Übermittlung oder das Delegieren des Ausführungsflusses an eine andere Controllermethode.

Eine kurze Randnotiz hier ist, dass das typische Post / Redirect / Get-Muster Probleme mit doppelter Übermittlung nicht angemessen behebt. Probleme wie das Aktualisieren der Seite vor Abschluss der ersten Übermittlung können dennoch zu einer doppelten Übermittlung führen.

3. Leiten Sie mitRedirectView um

Beginnen wir mit diesem einfachen Ansatz - undgo straight to an example:

@Controller
@RequestMapping("/")
public class RedirectController {

    @GetMapping("/redirectWithRedirectView")
    public RedirectView redirectWithUsingRedirectView(
      RedirectAttributes attributes) {
        attributes.addFlashAttribute("flashAttribute", "redirectWithRedirectView");
        attributes.addAttribute("attribute", "redirectWithRedirectView");
        return new RedirectView("redirectedUrl");
    }
}

Hinter den Kulissen löstRedirectView einHttpServletResponse.sendRedirect() aus, das die eigentliche Umleitung ausführt.

Beachten Sie hier, wiewe’re injecting the redirect attributes into the method - das Framework hier das schwere Heben übernimmt und es uns ermöglicht, mit diesen Attributen zu interagieren.

Wir fügen das Modellattributattribute – hinzu, das als HTTP-Abfrageparameter verfügbar gemacht wird. Das Modell darf nur Objekte enthalten - im Allgemeinen Zeichenfolgen oder Objekte, die in Zeichenfolgen konvertiert werden können.

Testen wir nun unsere Umleitung - mit Hilfe eines einfachencurl-Befehls:

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

Das Ergebnis wird sein:

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location:
  http://localhost:8080/spring-rest/redirectedUrl?attribute=redirectWithRedirectView

4. Mit dem Präfixredirect: umleiten

Der vorherige Ansatz - die Verwendung vonRedirectView – ist aus mehreren Gründen nicht optimal.

Erstens sind wir jetzt mit der Spring-API verbunden, da wir dieRedirectView direkt in unserem Code verwenden.

Zweitens - wir müssen jetzt von Anfang an wissen, dass das Ergebnis bei der Implementierung dieser Steuerungsoperation immer eine Umleitung ist - was möglicherweise nicht immer der Fall ist.

Eine bessere Option ist die Verwendung des Präfixesredirect: - der Name der Umleitungsansicht wird wie jeder andere Name der logischen Ansicht in den Controller eingefügt. The controller is not even aware that redirection is happening.

So sieht das aus:

@Controller
@RequestMapping("/")
public class RedirectController {

    @GetMapping("/redirectWithRedirectPrefix")
    public ModelAndView redirectWithUsingRedirectPrefix(ModelMap model) {
        model.addAttribute("attribute", "redirectWithRedirectPrefix");
        return new ModelAndView("redirect:/redirectedUrl", model);
    }
}

Wenn ein Ansichtsname mit dem Präfixredirect: zurückgegeben wird, erkennen dieUrlBasedViewResolver (und alle seine Unterklassen) dies als besonderen Hinweis darauf, dass eine Umleitung erfolgen muss. Der Rest des Ansichtsnamens wird als Umleitungs-URL verwendet.

Ein kurzer, aber wichtiger Hinweis ist, dass wir - wenn wir diesen logischen Ansichtsnamen hier verwenden -redirect:/redirectedUrl - eine Umleitungrelative to the current Servlet context durchführen.

Wir können einen Namen wiea redirect: http://localhost:8080/spring-redirect-and-forward/redirectedUrl verwenden, wenn wir zu einer absoluten URL umleiten müssen.

Wenn wir nun den Befehlcurl ausführen:

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

Wir werden sofort umgeleitet:

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location:
  http://localhost:8080/spring-rest/redirectedUrl?attribute=redirectWithRedirectPrefix

5. Weiterleiten mit dem Präfixforward:

Lassen Sie uns nun sehen, wie Sie etwas anderes machen - einen Stürmer.

Gehen wir vor dem Code übera quick, high-level overview of the semantics of forward vs. redirect:

  • redirect antwortet mit einer 302 und der neuen URL im Header vonLocation; Der Browser / Client stellt dann eine weitere Anfrage an die neue URL

  • forward geschieht vollständig auf einer Serverseite; Der Servlet-Container leitet dieselbe Anforderung an die Ziel-URL weiter. Die URL ändert sich im Browser nicht

Schauen wir uns nun den Code an:

@Controller
@RequestMapping("/")
public class RedirectController {

    @GetMapping("/forwardWithForwardPrefix")
    public ModelAndView redirectWithUsingForwardPrefix(ModelMap model) {
        model.addAttribute("attribute", "forwardWithForwardPrefix");
        return new ModelAndView("forward:/redirectedUrl", model);
    }
}

Wieredirect: wird das Präfixforward: durchUrlBasedViewResolver und seine Unterklassen aufgelöst. Intern wird dadurch einInternalResourceView erstellt, das einRequestDispatcher.forward() für die neue Ansicht ausführt.

Wenn wir den Befehl mitcurl: ausführen

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

Wir erhalten HTTP 405 (Methode nicht erlaubt):

HTTP/1.1 405 Method Not Allowed
Server: Apache-Coyote/1.1
Allow: GET
Content-Type: text/html;charset=utf-8

Zum Abschluss haben wir im Vergleich zu den beiden Anforderungen, die wir im Fall der Umleitungslösung hatten, in diesem Fall nur eine einzige Anforderung, die vom Browser / Client zur Serverseite ausgeht. Das Attribut, das zuvor durch die Umleitung hinzugefügt wurde, fehlt natürlich ebenfalls.

6. Attribute Mit denRedirectAttributes

Als nächstes - schauen wir unspassing attributes in a redirect genauer an - nutzen Sie das Framework mitRedirectAttribures vollständig:

@GetMapping("/redirectWithRedirectAttributes")
public RedirectView redirectWithRedirectAttributes(RedirectAttributes attributes) {

    attributes.addFlashAttribute("flashAttribute", "redirectWithRedirectAttributes");
    attributes.addAttribute("attribute", "redirectWithRedirectAttributes");
    return new RedirectView("redirectedUrl");
}

Wie wir bereits gesehen haben, können wir das Attribut-Objekt direkt in die Methode einfügen, wodurch dieser Mechanismus sehr einfach zu verwenden ist.

Beachten Sie auch, dasswe are adding a flash attribute as well - dies ist ein Attribut, das es nicht in die URL schafft. Was wir mit dieser Art von Attribut erreichen können, ist - wir können später mit@ModelAttribute(“flashAttribute”)only in the method that is the final target of the redirect auf das Flash-Attribut zugreifen:

@GetMapping("/redirectedUrl")
public ModelAndView redirection(
  ModelMap model,
  @ModelAttribute("flashAttribute") Object flashAttribute) {

     model.addAttribute("redirectionAttribute", flashAttribute);
     return new ModelAndView("redirection", model);
 }

Zum Abschluss: Wenn wir die Funktionalität mitcurl testen:

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

Wir werden an den neuen Ort weitergeleitet:

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=4B70D8FADA2FD6C22E73312C2B57E381; Path=/spring-rest/; HttpOnly
Location: http://localhost:8080/spring-rest/redirectedUrl;
  jsessionid=4B70D8FADA2FD6C22E73312C2B57E381?attribute=redirectWithRedirectAttributes

Auf diese Weise können wir durch die Verwendung vonRedirectAttribures anstelle vonModelMap nursome attributes between the two methods teilen, die an der Umleitungsoperation beteiligt sind.

7. Eine alternative Konfiguration ohne Präfix

Lassen Sie uns nun eine alternative Konfiguration untersuchen - eine Umleitung ohne Verwendung des Präfixes.

Um dies zu erreichen, müssen wir einorg.springframework.web.servlet.view.XmlViewResolver: verwenden


    
        /WEB-INF/spring-views.xml
    
    

Anstelle vonorg.springframework.web.servlet.view.InternalResourceViewResolver haben wir in der vorherigen Konfiguration Folgendes verwendet:


Wir müssen auch eineRedirectView Bean in der Konfiguration definieren:


    

Jetzt können wirtrigger the redirect by referencing this new bean by id:

@Controller
@RequestMapping("/")
public class RedirectController {

    @GetMapping("/redirectWithXMLConfig")
    public ModelAndView redirectWithUsingXMLConfig(ModelMap model) {
        model.addAttribute("attribute", "redirectWithXMLConfig");
        return new ModelAndView("RedirectedUrl", model);
    }
}

Zum Testen verwenden wir erneut den Befehlcurl:

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

Das Ergebnis wird sein:

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location:
  http://localhost:8080/spring-rest/redirectedUrl?attribute=redirectWithRedirectView

8. Umleiten einer HTTP-POST-Anforderung

Für Anwendungsfälle wie Bankzahlungen müssen wir möglicherweise eine HTTP-POST-Anforderung umleiten. Abhängig vom zurückgegebenen HTTP-Statuscode kann die POST-Anforderung an ein HTTP-GET oder -POST umgeleitet werden.

Gemäß dem HTTP 1.1-Protokollreference ermöglichen die Statuscodes 301 (dauerhaft verschoben) und 302 (gefunden), dass die Anforderungsmethode von POST zu GET geändert wird. In der Spezifikation werden auch die entsprechenden Statuscodes 307 (temporäre Umleitung) und 308 (permanente Umleitung) definiert, mit denen die Anforderungsmethode nicht von POST auf GET geändert werden kann.

Schauen wir uns nun den Code zum Umleiten einer Post-Anfrage zu einer anderen Post-Anfrage an:

@PostMapping("/redirectPostToPost")
public ModelAndView redirectPostToPost(HttpServletRequest request) {
    request.setAttribute(
      View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.TEMPORARY_REDIRECT);
    return new ModelAndView("redirect:/redirectedPostToPost");
}
@PostMapping("/redirectedPostToPost")
public ModelAndView redirectedPostToPost() {
    return new ModelAndView("redirection");
}

Now, let’s test the redirect of POST using the curl command:

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

Wir werden zum Bestimmungsort weitergeleitet:

> POST /redirectedPostToPost HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.49.0
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 08 Aug 2017 07:33:00 GMT

{"id":1,"content":"redirect completed"}

9. Fazit

In diesem Artikel wurdethree different approaches to implementing a redirect in Spring erläutert, wie Attribute bei diesen Weiterleitungen behandelt / übergeben werden und wie Weiterleitungen von HTTP-POST-Anforderungen behandelt werden.