В одном из моих контроллеров есть следующий код:
@Controller
@RequestMapping("/preference")
public class PreferenceController {
@RequestMapping(method = RequestMethod.GET, produces = "text/html")
public String preference() {
return "preference";
}
}
Я просто пытаюсь протестировать его с помощью теста Spring MVC следующим образом:
@ContextConfiguration
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class PreferenceControllerTest {
@Autowired
private WebApplicationContext ctx;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = webAppContextSetup(ctx).build();
}
@Test
public void circularViewPathIssue() throws Exception {
mockMvc.perform(get("/preference"))
.andDo(print());
}
}
Я получаю следующее исключение:
Путь кругового просмотра [предпочтение]: снова будет направлено обратно на текущий URL-адрес обработчика [/ предпочтение]. Проверьте настройки ViewResolver! (Подсказка: это может быть результатом неуказанного представления из-за генерации имени представления по умолчанию.)
Что мне показалось странным, так это то, что он отлично работает, когда я загружаю «полную» конфигурацию контекста, которая включает в себя преобразователи шаблона и представления, как показано ниже:
<bean class="org.thymeleaf.templateresolver.ServletContextTemplateResolver" id="webTemplateResolver">
<property name="prefix" value="WEB-INF/web-templates/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="characterEncoding" value="UTF-8" />
<property name="order" value="2" />
<property name="cacheable" value="false" />
</bean>
Мне хорошо известно, что префикс, добавленный преобразователем шаблонов, гарантирует отсутствие "кругового пути просмотра", когда приложение использует этот преобразователь шаблонов.
Но как тогда я должен тестировать свое приложение с помощью теста Spring MVC?
ViewResolver
что используете, когда это не удается?@RestController
вместо@Controller
Ответы:
Это не имеет ничего общего с тестированием Spring MVC.
Если вы не объявляете a
ViewResolver
, Spring регистрирует значение по умолчанию,InternalResourceViewResolver
которое создает экземплярыJstlView
для рендерингаView
.JstlView
Класс расширяетInternalResourceView
которыйСмелый мой. Другими словами, представление перед рендерингом будет пытаться получить объект,
RequestDispatcher
к которому нужноforward()
. Перед этим он проверяет следующиегде
path
имя представления, которое вы вернули из@Controller
. В этом примере это такpreference
. Переменнаяuri
содержит uri обрабатываемого запроса, то есть/context/preference
.В приведенном выше коде понимается, что если бы вы перешли на
/context/preference
тот же сервлет (поскольку он обрабатывал предыдущий), он обработал бы запрос, и вы вошли бы в бесконечный цикл.Когда вы объявляете a
ThymeleafViewResolver
и aServletContextTemplateResolver
с конкретнымprefix
andsuffix
, он строит по-View
разному, давая ему путь вродеThymeleafView
экземпляры находят файл относительноServletContext
пути, используяServletContextResourceResolver
что в конечном итоге
Это получает ресурс, относящийся к
ServletContext
пути. Затем он может использоватьTemplateEngine
для создания HTML. Здесь не может быть бесконечного цикла.источник
ThymleafViewResolver
View
prefix
suffix
InternalResourceViewResolver
RequestDispatcher
Servlet
/preference
DispatcherServlet
ViewResolver
. Либо,ThymeleafViewResolver
как в вашем вопросе, вы сами настроилиInternalResourceViewResolver
или измените имя представления, которое вы возвращаете в своем контроллере.@RequestMapping
Аннотированный метод обработчика сString
типом возврата (и no@ResponseBody
) имеет возвращаемое значение, обрабатываемое a,ViewNameMethodReturnValueHandler
которое интерпретирует String как имя представления и использует его для выполнения процесса, который я объясняю в своем ответе. С@ResponseBody
, Spring MVC будет использовать вместо этого ,RequestResponseBodyMethodProcessor
который вместо записывает строку непосредственно в ответ HTTP, то есть. нет разрешения просмотра.Я решил эту проблему, используя @ResponseBody, как показано ниже:
источник
List<DomainObject>
.@Controller
→@RestController
У меня была такая же проблема, и я заметил, что мой контроллер также был помечен
@Controller
. Замена на@RestController
решила проблему. Вот объяснение из Spring Web MVC :источник
@ControllerAdvice
сhandleXyException
методом, который возвращал мой собственный объект вместо ResponseEntity. Добавление@RestController
поверх@ControllerAdvice
аннотации сработало, и проблема исчезла.Вот как я решил эту проблему:
источник
Я использую Spring Boot, чтобы попытаться загрузить веб-страницу, а не тестировать, и у меня возникла эта проблема. Мое решение немного отличалось от приведенного выше, учитывая несколько иные обстоятельства. (хотя эти ответы помогли мне понять.)
Мне просто пришлось изменить свою стартовую зависимость Spring Boot в Maven с:
кому:
Простая замена «паутины» на «тимелист» устранила для меня проблему.
источник
Вот простое исправление, если вы на самом деле не заботитесь о рендеринге представления.
Создайте подкласс InternalResourceViewResolver, который не проверяет круговые пути просмотра:
Затем настройте свой тест с его помощью:
источник
Если вы используете Spring Boot, добавьте зависимость тимелеафа в свой pom.xml:
источник
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
Добавление
/
после/preference
решения проблемы для меня:источник
В моем случае я пробовал загрузку Kotlin + Spring и столкнулся с проблемой Circular View Path. Все предложения, которые я получил в Интернете, не помогли, пока я не попробовал следующее:
Изначально я аннотировал свой контроллер, используя
@Controller
import org.springframework.stereotype.Controller
Затем я заменил
@Controller
на@RestController
import org.springframework.web.bind.annotation.RestController
И это сработало.
источник
если вы не использовали @RequestBody и используете только
@Controller
, самый простой способ исправить это - использовать@RestController
вместо@Controller
источник
Добавьте аннотацию
@ResponseBody
к вашему методу return.источник
Я использую Spring Boot с Thymeleaf. Это то, что у меня сработало. Есть аналогичные ответы с JSP, но обратите внимание, что я использую HTML, а не JSP, и они находятся в папке,
src/main/resources/templates
как в стандартном проекте Spring Boot, как описано здесь . Это также может быть вашим случаем.Надеюсь это поможет.
источник
При запуске Spring Boot + Freemarker, если страница появляется:
Страница ошибки Whitelabel Это приложение не имеет явного сопоставления для / error, поэтому вы рассматриваете это как запасной вариант.
В версии spring-boot-starter-parent 2.2.1.RELEASE freemarker не работает:
spring.freemarker.suffix = .ftl
источник
Для тимелеафа:
Я только начал использовать Spring 4 и тимелеаф, когда я столкнулся с этой ошибкой, она была устранена добавлением:
источник
При использовании
@Controller
аннотации нужны@RequestMapping
и@ResponseBody
аннотации. Повторите попытку после добавления аннотации@ResponseBody
источник
Я использую аннотацию для настройки веб-приложения Spring, проблема решена путем добавления
InternalResourceViewResolver
bean-компонента в конфигурацию. Надеюсь, это будет полезно.источник
Это происходит потому, что Spring удаляет «предпочтение» и снова добавляет «предпочтение», используя тот же путь, что и Uri запроса.
Происходит так: запрос Uri: "/ preference"
удалить "предпочтение": "/"
добавить путь: "/" + "предпочтение"
конец строки: "/ предпочтение"
Это входит в цикл, о котором Spring уведомляет вас, выбрасывая исключение.
Лучше всего в ваших интересах дать другое имя представления, например "preferenceView" или что угодно.
источник
попробуйте добавить зависимость compile ("org.springframework.boot: spring-boot-starter-thymeleaf") к вашему файлу gradle. Tymeleaf помогает отображать представления.
источник
В моем случае эта проблема возникла при попытке обслуживать страницы JSP с помощью загрузочного приложения Spring.
Вот что у меня сработало:
application.properties
pom.xml
Чтобы включить поддержку JSP, нам нужно добавить зависимость от tomcat-embed-jasper.
источник
Еще один простой подход:
источник