Руководство по перенаправлению Spring

Java Spring Curl модульный тест

1 Обзор

В этой статье мы сосредоточимся на реализации Redirect в Spring и обсудим причины, лежащие в основе каждой стратегии.

2. Зачем перенаправлять?

Давайте сначала рассмотрим причины, по которым вам может понадобиться перенаправление в приложении Spring.

Конечно, есть много возможных примеров и причин. Простым может быть отправка данных формы POST, проблема двойной отправки или просто делегирование потока выполнения другому методу контроллера.

В качестве примечания: типичный шаблон Post/Redirect/Get не решает проблему двойной отправки адекватно — проблема обновления страницы до завершения первоначальной отправки может по-прежнему приводить к двойной отправке.

3.использовать RedirectView перенаправление

Давайте начнем с этого простого метода - сразу к примеру:

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

За кулисами RedirectView запускает HttpServletResponse.sendRedirect() — это выполнит фактическое перенаправление.

Обратите внимание, как здесь мы вводим свойства перенаправления в метод — фреймворк делает всю тяжелую работу, чтобы позволить нам взаимодействовать с этими свойствами.

мы добавляемattribute к модели RedirectAttributes — выставьте ее как параметр HTTP-запроса. Эта модель содержит объекты — обычно строки или объекты, которые можно преобразовать в строки.

Теперь давайте проверим нашу функциональность перенаправления с помощью простой команды curl:

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

Результат будет:

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

4. Используйтеredirect:префикс для перенаправления

Предыдущий метод использует RedirectView, что не является оптимальным по нескольким причинам.

Во-первых, теперь мы связаны с Spring API, потому что используем его непосредственно в нашем коде.RedirectView.

Во-вторых, нам нужно с самого начала знать, что при реализации действия контроллера его результат всегда будет перенаправлен, что не всегда так.

Лучшим вариантом является использованиеredirect:Префикс — имена представлений перенаправления вводятся в контроллер, как и другие имена логических представлений.Контроллер даже не знает, что происходит перенаправление.

Это выглядит так:

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

Когда имя представления возвращается с перенаправлением:,UrlBasedViewResolverКласс (и все его подклассы) распознает это как особое указание на то, что требуется перенаправление. Остальная часть имени представления используется в качестве URL-адреса перенаправления.

Здесь есть одна оговорка — когда мы используемredirect:/redirectedUrlВ логическом представлении мы делаем перенаправление относительно текущего контекста сервлета.

Если нам нужно перенаправить на абсолютный URL-адрес, мы можем использовать такое имя:redirect: http://localhost:8080/spring-redirect/redirectedUrl.

Итак, теперь, когда мы выполняем команду curl:

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

Сразу получаем редирект:

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

5. Используйтеforwardпереадресация префикса:

Давайте теперь посмотрим, как сделать что-то немного другое — ретвит.
Прежде чем смотреть код, давайте посмотримКраткое обобщенное описание семантики переадресации и перенаправления.:

  • Перенаправление ответит новым URL-адресом, содержащим код ответа 302 и заголовок Location; затем браузер/клиент снова отправит запрос на новый URL-адрес.

  • Переадресация происходит полностью на стороне сервера, контейнер сервлетов перенаправляет тот же запрос на целевой URL-адрес, URL-адрес в браузере менять не нужно.

Теперь давайте посмотрим на код:

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

а такжеredirect:Такой же,forward:Префикс будет разрешен с помощью UrlBasedViewResolver и его подклассов. Внутри это создает InternalResourceView, который выполняет операцию RequestDispatcher.forward() для нового представления.
Когда мы выполняем эту команду с помощью curl:

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

Мы получим HTTP 405 (метод не разрешен):

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

По сравнению с нашими двумя запросами в решении перенаправления, в этом случае у нас есть только один запрос, отправленный из браузера/клиента на сторону сервера. Конечно, атрибуты, ранее добавленные редиректами, тоже не нужны.

6. СодержитRedirectAttributesсвойства

Далее - посмотримПередать атрибуты в перенаправлении- Воспользуйтесь преимуществами RedirectAttribures в рамках:

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

Как уже упоминалось, мы можем вставлять объекты свойств прямо в метод — это делает механизм очень простым в использовании.
Отметим также, что мы такжеДобавить свойство Flash- Это атрибут, который не будет добавлен к URL-адресу. Мы можем сделать это с помощью этого атрибута — мы можем получить доступ к атрибуту flash позже, используя @ModelAttribute("flashAttribute") в методе конечной цели перенаправления:

@GetMapping("/redirectedUrl")
public ModelAndView redirection(
  ModelMap model, 
  @ModelAttribute("flashAttribute") Object flashAttribute) {
      
     model.addAttribute("redirectionAttribute", flashAttribute);
     return new ModelAndView("redirection", model);
 }

Итак, молодцы — если вам нужно протестировать функциональность с помощью curl:

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

Мы будем перенаправлены на новое место:

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

Таким образом, использование RedirectAttribures вместо ModelMap дает намНекоторые свойства являются общими для двух методов.Способность.

7. Другая конфигурация без префикса

Теперь рассмотрим другую конфигурацию — перенаправление без префикса.

Чтобы добиться этого, нам нужно использоватьorg.springframework.web.servlet.view.XmlViewResolver:

<bean class="org.springframework.web.servlet.view.XmlViewResolver">
    <property name="location">
        <value>/WEB-INF/spring-views.xml</value>
    </property>
    <property name="order" value="0" />
</bean>

вместо того, который мы использовали в предыдущей конфигурацииorg.springframework.web.servlet.view.InternalResourceViewResolver:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
</bean>

Нам также необходимо определитьRedirectView фасоль:

<bean id="RedirectedUrl" class="org.springframework.web.servlet.view.RedirectView">
    <property name="url" value="redirectedUrl" />
</bean>

Теперь мы можем сослаться на этот новый компонент по идентификатору, чтобы вызвать перенаправление:

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

Чтобы проверить это, мы снова используемcurlЗаказ:

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

Результат будет:

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

8. Перенаправление HTTP-запроса POST Запрос

Для таких случаев использования, как банковские платежи, нам может потребоваться перенаправить HTTP-запросы POST. В зависимости от возвращенного кода состояния HTTP запросы POST могут быть перенаправлены на HTTP GET или POST.
По протоколу HTTP 1.1Ссылаться на, коды состояния 301 (удален навсегда) и 302 (найден) позволяют изменить метод запроса с POST на GET. Спецификация также определяет соответствующие коды состояния 307 (временное перенаправление) и 308 (постоянное перенаправление), которые не позволяют изменить метод запроса с POST на GET.
Теперь давайте посмотрим на код, который перенаправляет почтовый запрос на другой почтовый запрос:

@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");
}

Теперь давайте проверим перенаправленный POST с помощью команды curl:

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

Нас перенаправляют на целевой адрес:

> 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. Заключение

В этой статье описываетсяТри разных способа реализовать перенаправление в Spring, как обрабатывать/передавать атрибуты при выполнении этих перенаправлений и как обрабатывать перенаправления для HTTP-запросов POST.