[dispatcherServlet] in context with path [/demo] threw exception [Circular view path [users]: would dispatch back to the current handler URL [/demo/users] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)] with root cause
javax.servlet.ServletException: Circular view path [users]: would dispatch back to the current handler URL [/demo/users] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:210)
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:148)
网上都是说什么使用@RestController和@ResponseBody, 然后我本生就是使用的@RestController
各种百度,google,github都没有解决, 最后决定自己调式看看, 于是发现一个异常位置
at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:210)
因为我使用@RestControllerAdvice对返回结果封装, 又使用了@ControllerAdvice进行了全局异常捕获
问题主要出在返回封装的结果抛出了异常, 然后全局异常捕获处理, 就更不容易看到问题, 然而这个异常就影响了Servlet处理的流程, 导致报了这个循环视图的问题, 所以本质不是视图配置问题, 就是要解决最原始的异常即可解决问题
我这里本质问题是一个类转换异常
报错的代码位置
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters
else {
((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);
}
这里的StringHttpMessageConverter有点怪怪的, 为什么是String, 我返回的结果可是Json啊

可以用的信息转换器

经过计算测试发现, 只有第8和9个执行这个代码不会抛出异常

是不是什么地方错误导致这个信息转换器使用错误呢?
最后发现这个value其实不是我们的body, 而是我们封装数据格式中的一个data的数据结果. 所示被识别成了String.class, 也就导致了我们的Result->String出现CastClass的异常

问题就出在285行, 执行这一行之前, 我们的body还是String, 执行之后就变成了Result类型了

最后发现一处错误: 我的全局异常处理使用的注解是@ControllerAdvice但是, 统一封装返回结果使用的是@RestControllerAdvice
应该统一使用@RestControllerAdvice注解, 改正后, 可以正常返回异常信息, 但是应该不返回异常才是, 问题还是没有得到根本解决]
{
"code": 500,
"message": "class len.hgy.response.Result cannot be cast to class java.lang.String (len.hgy.response.Result is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')",
"data": null
}
这里应该返回处理的结果, 而不是返回一个类转换异常
最终发现了问题
String类型不能直接包装成对象类型, 这样就会出现上面的现象, 所以我们需要特殊处理下我们的统一包装类
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
// 提供一定的灵活度,如果body已经被包装了,就不进行包装
if (body instanceof Result) {
return body;
}
// String类型不能直接包装
if (returnType.getGenericParameterType().equals(String.class)) {
try {
// 将数据包装在 ResultVo 里后转换为json串进行返回
return JacksonUtils.mapper.writeValueAsString(Result.success(body));
} catch (JsonProcessingException e) {
throw new MyException(e.getMessage(), e);
}
}
return Result.success(body);
}
至此, 终于解决了一个错误报错提示问题
[dispatcherServlet] in context with path [/demo] threw exception [Circular view path [users]: would dispatch back to the current handler URL [/demo/users] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)] with root cause
javax.servlet.ServletException: Circular view path [users]: would dispatch back to the current handler URL [/demo/users] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
at org.springframework.web.servlet.view.InternalResourceView.prepareForRendering(InternalResourceView.java:210)
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:148)
问题和这个错误异常没有任何毛线的关系
总结:
如果我们遇到一个非常奇怪的问题, 网上可能很常见但是解决不了自己的问题, 或者网上基本没有这样的问题, 那肯定是我们有些细节除了问题, 要知道, 此时我们不管是如何网上找寻答案, 基本都是无用功, 我们不妨做如下两个选择, 一个是先放下这个问题, 后续可能会恍然大悟, 或者深入调式源码, 不然可能就真的是在浪费时间了