最近,前端nginx的日誌一直在報一些URL的請求後端響應是500狀態碼,於是緩存其結果,可以看到一直是報一個 javax.servlet.ServletException: Could not resolve view with name 'xxxx'in servlet with name 'Spring MVC Dispatcher Servlet ‘的異常。
分析這些報這個異常的的URL,規則都是/xxx/{xxx},報錯的URL都是類似於 /xxx/xxx.jpg之類的跟着後綴的,我們的資源內容中也就是這個路由是對應的是沒有這個jpg的資源的,也就是說自然會是404,但是404竟然也報這個異常和500錯誤碼。
看了springmvc關於這個異常的出處,很明顯的是View爲null,而view是由resolveViewName獲得的。
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine locale for request and apply it to the response.
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view;
if (mv.isReference()) {
// We need to resolve the view name.
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException(
"Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" +
getServletName() + "'");
}
}
......
}
我們接下來繼續看resolveViewName實現。 protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
HttpServletRequest request) throws Exception {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
return null;
}
public View resolveViewName(String viewName, Locale locale) throws Exception {
RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
Assert.isInstanceOf(ServletRequestAttributes.class, attrs);
List<MediaType> requestedMediaTypes = getMediaTypes(((ServletRequestAttributes) attrs).getRequest());
if (requestedMediaTypes != null) {
List<View> candidateViews = getCandidateViews(viewName, locale, requestedMediaTypes);
View bestView = getBestView(candidateViews, requestedMediaTypes);
if (bestView != null) {
return bestView;
}
}
if (this.useNotAcceptableStatusCode) {
if (logger.isDebugEnabled()) {
logger.debug("No acceptable view found; returning 406 (Not Acceptable) status code");
}
return NOT_ACCEPTABLE_VIEW;
}
else {
logger.debug("No acceptable view found; returning null");
return null;
}
}
我們看到了,是requestedMediaTypes爲null引起的view爲空,而requestedMediaTypes 通過getMediaTypes方法生成,看了裏面的代碼,才明白原來是springmvc會去判斷URI的後綴,然後根據後綴去獲取對應的mediatypes。jpg對應的mediatype是jpg/image。
因此找到原因了,我們的項目中,關於springmvc的viewresolve的配置,沒有關於這個media的,所以去解析視圖的時候無法解析。解決辦法也很簡單,直接加一個默認的viewsolve就OK了。
<!--通用視圖解析器-->
<bean id="viewResolverCommon" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"/>
<property name="suffix" value=".jsp"/><!--可爲空,方便實現自已的依據擴展名來選擇視圖解釋類的邏輯 -->
<property name="viewClass">
<value>org.springframework.web.servlet.view.InternalResourceView</value>
</property>
<property name="order" value="1"/>
</bean>