如何通过 Spring MVC 测试避免“Circular view path”异常

新手上路,请多包涵

我的一个控制器中有以下代码:

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

我收到以下异常:

循环视图路径 [preference]:将再次分派回当前处理程序 URL [/preference]。检查您的 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 测试来测试我的应用程序呢?

原文由 balteo 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

这与 Spring MVC 测试无关。

When you don’t declare a ViewResolver , Spring registers a default InternalResourceViewResolver which creates instances of JstlView for rendering the View .

JstlView 类扩展 InternalResourceView 这是

同一 Web 应用程序中 JSP 或其他资源的包装器。将模型对象公开为请求属性,并使用 javax.servlet.RequestDispatcher 将请求转发到指定的资源 URL。

此视图的 URL 应该指定 Web 应用程序中的资源,适用于 RequestDispatcher 的转发或包含方法。

强调我的。换句话说,在渲染之前,视图将尝试获取 RequestDispatcherforward() 。在执行此操作之前,它会检查以下内容

if (path.startsWith("/") ? uri.equals(path) : uri.equals(StringUtils.applyRelativePath(uri, path))) {
    throw new ServletException("Circular view path [" + path + "]: would dispatch back " +
                        "to the current handler URL [" + uri + "] again. Check your ViewResolver setup! " +
                        "(Hint: This may be the result of an unspecified view, due to default view name generation.)");
}

其中 path 是视图名称,您从 @Controller 返回的内容。在此示例中,即 preference 。变量 uri 保存正在处理的请求的 uri,即 /context/preference

上面的代码意识到,如果您转发到 /context/preference ,同一个 servlet(因为前一个处理的是同一个 servlet)将处理该请求,您将进入无限循环。


When you declare a ThymeleafViewResolver and a ServletContextTemplateResolver with a specific prefix and suffix , it builds the View differently ,给它一条像

WEB-INF/web-templates/preference.html

ThymeleafView 实例通过使用—找到相对于 ServletContext 路径的文件 ServletContextResourceResolver

 templateInputStream = resourceResolver.getResourceAsStream(templateProcessingParameters, resourceName);`

最终

return servletContext.getResourceAsStream(resourceName);

这将获取与 ServletContext 路径相关的资源。然后它可以使用 TemplateEngine 生成 HTML。这里不可能发生无限循环。

原文由 Sotirios Delimanolis 发布,翻译遵循 CC BY-SA 4.0 许可协议

@Controller@RestController

我有同样的问题,我注意到我的控制器也用 @Controller 注释。将其替换为 @RestController 解决了问题。这是 Spring Web MVC 的解释:

@RestController 是一个组合注解,它本身用@Controller 和@ResponseBody 进行元注解,表示一个控制器,其每个方法都继承了类型级别的@ResponseBody 注解,因此直接写入响应主体与视图解析和使用HTML 模板呈现。

原文由 Boris 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏