springmvc支持直接在返回字符串上申明該視圖是轉發或者是重定向
@RequestMapping(value="/taoge")
public String taogetest(HttpServletRequest request,Model model){
return "forward:toregister";
# return "redirect:toregister";
}
這兩種方式都能完成control之間的跳轉,它們具體是怎麼實現的呢
主要是在DispatcherServlet.render(ModelAndView, HttpServletRequest, HttpServletResponse) line: 1234 上
/**
* Render the given ModelAndView.
* <p>This is the last stage in handling a request. It may involve resolving the view by name.
* @param mv the ModelAndView to render
* @param request current HTTP servlet request
* @param response current HTTP servlet response
* @throws ServletException if view is missing or cannot be resolved
* @throws Exception if there's a problem rendering the view
*/
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()) { #判斷當前view名是否是可用的,如果不能直接用,那麼需要解析該視圖名
// 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() + "'");
}
}
DispatcherServlet.resolveViewName(String, Map<String,Object>, Locale, HttpServletRequest) line: 1296
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;
}
InternalResourceViewResolver(AbstractCachingViewResolver).resolveViewName(String, Locale) line: 145
public View resolveViewName(String viewName, Locale locale) throws Exception {
if (!isCache()) { 是否存在緩存
return createView(viewName, locale);
}
else {
Object cacheKey = getCacheKey(viewName, locale); 從緩存中取出對應的鍵
View view = this.viewAccessCache.get(cacheKey);
if (view == null) { 如果在緩存map還是找不到該視圖,那麼就重新生成一個
synchronized (this.viewCreationCache) {
view = this.viewCreationCache.get(cacheKey);
if (view == null) {
// Ask the subclass to create the View object.
view = createView(viewName, locale); 重新生成一個視圖
if (view == null && this.cacheUnresolved) {
view = UNRESOLVED_VIEW;
}
if (view != null) {
this.viewAccessCache.put(cacheKey, view);
this.viewCreationCache.put(cacheKey, view);
if (logger.isTraceEnabled()) {
logger.trace("Cached view [" + cacheKey + "]");
}
}
}
}
}
return (view != UNRESOLVED_VIEW ? view : null);
}
}
UrlBasedViewResolver類中453行
@Override
protected View createView(String viewName, Locale locale) throws Exception {
// If this resolver is not supposed to handle the given view,
// return null to pass on to the next resolver in the chain.
if (!canHandle(viewName, locale)) {
return null;
}
// Check for special "redirect:" prefix. 判斷是否存在前置字符串redirect:
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
view.setHosts(getRedirectHosts());
return applyLifecycleMethods(viewName, view);
}
// Check for special "forward:" prefix.
if (viewName.startsWith(FORWARD_URL_PREFIX)) { 判斷是否存在前置字符串forward:
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
return new InternalResourceView(forwardUrl);
}
// Else fall back to superclass implementation: calling loadView.
return super.createView(viewName, locale);
}