小编典典

Spring MVC测试中如何避免“圆形视图路径”异常

spring

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

@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测试来测试我的应用程序呢?有人知道吗?


阅读 552

收藏
2020-04-11

共1个答案

小编典典

这与Spring MVC测试无关。

当你不声明a时ViewResolver,Spring注册一个默认值InternalResourceViewResolver,该默认值创建的实例JstlView以呈现View。

的JstlView类扩展InternalResourceView其是

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

该视图的URL应该用于指定Web应用程序中的资源,适用于RequestDispatcher的forward或include方法。

大胆是我的。。换句话说,视图渲染之前,将尝试获得RequestDispatcher到其中forward()。在执行此操作之前,它会检查以下内容

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处理了前一个)将处理请求,并且你将陷入无限循环。

当你使用特定的and 声明a ThymeleafViewResolvera ServletContextTemplateResolver时,它会以不同的方式构建,并为它提供如下路径prefixsuffixView

WEB-INF/web-templates/preference.html

ThymeleafView实例使用以下命令相对于ServletContext路径 定位文件ServletContextResourceResolver

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

最终

return servletContext.getResourceAsStream(resourceName);

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

2020-04-11