为了账号安全,请及时绑定邮箱和手机立即绑定

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

/ 猿问

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

MMTTMM 2019-11-13 09:47:59

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


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


查看完整描述

3 回答

?
倚天杖

这与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 ThymeleafViewResolver和a ServletContextTemplateResolver时,它会以不同的方式构建,并为其提供类似的路径prefixsuffixView


WEB-INF/web-templates/preference.html

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


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

最终


return servletContext.getResourceAsStream(resourceName);

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


查看完整回答
反对 回复 2019-11-13
?
宝慕林4294392

我通过使用@ResponseBody解决了这个问题,如下所示:


@RequestMapping(value = "/resturl", method = RequestMethod.GET, produces = {"application/json"})

    @ResponseStatus(HttpStatus.OK)

    @Transactional(value = "jpaTransactionManager")

    public @ResponseBody List<DomainObject> findByResourceID(@PathParam("resourceID") String resourceID) {


查看完整回答
反对 回复 2019-11-13
?
一只甜甜圈

这就是我解决此问题的方法:


@Before

    public void setup() {

        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setPrefix("/WEB-INF/jsp/view/");

        viewResolver.setSuffix(".jsp");


        mockMvc = MockMvcBuilders.standaloneSetup(new HelpController())

                                 .setViewResolvers(viewResolver)

                                 .build();

    }


查看完整回答
反对 回复 2019-11-13
  • 3 回答
  • 0 关注
  • 71 浏览
我要回答

相关问题推荐

慕课专栏
更多

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信