SpringMVC的视图解析器
2021-04-09 01:26
标签:hello exe 不同 不同的 报错 free which sde read 请求处理方法执行完成后,最终返回一个 ModelAndView 对象。对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个 ModelAndView 对象,它包含了逻辑名和模型对象的视图 Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP ,也可能是 Excel、JFreeChart等各种表现形式的视图 对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦 视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。为了实现视图模型和具体实现技术的解耦,Spring 在 org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口: 视图对象由视图解析器负责实例化。由于视图是无状态的,所以他们不会有线程安全的问题 常用的视图实现类 SpringMVC 为逻辑视图名的解析提供了不同的策略,可以在 Spring WEB 上下文中配置一种或多种解析策略,并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。 视图解析器的作用比较单一:将逻辑视图解析为一个具体的视图对象。 所有的视图解析器都必须实现 ViewResolver 接口: 程序员可以选择一种视图解析器或混用多种视图解析器。每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性,可以通过 order 属性指定解析器的优先顺序,order 越小优先级越高。 SpringMVC 会按视图解析器顺序的优先顺序对逻辑视图名进行解析,直到解析成功并返回视图对象,否则将抛出 ServletException 异常。 JSP 是最常见的视图技术,可以使用 InternalResourceViewResolve作为视图解析器: 请求转发 都可以跳到index.jsp 1.任何的方法都会进入到doDispatch(request, response);中 2.在它的方法中mv = ha.handle(processedRequest, response, mappedHandler.getHandler());,有处理器适配器调用生成ModelAndView 3.调用handle方法,是由子类AnnotationMethodHandlerAdapter实现的,里面会调用invokeHandlerMethod(request, response, handler)方法。 最终会返回ModelAndView对象,view就是要跳转的页面,model里面就是数据。 4.方法继续放下走到processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); 5.render(mv, request, response); 其中有一个重要的方法resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);,解析试图名,点进去看看。 试图解析器根据方法的返回值,得到一个view对象。要是不为空,说明能解析。 ? view = createView(viewName, locale);这个方法,是真正的创建试图。 创建完成,会有一个view 视图解析器得到View对象的流程就是,所有配置的视图解析器都来尝试根据视图名(返回值)得到View(试图)对象;如果能得到就返回,得不到就换下一个试图解析器。 6.view进行渲染。 视图解析器只是为了得到试图对象;视图对象才能真正的转发(将模型数据全部放在请求域中)或者重定向到页面,视图对象才能渲染试图。 但是请求别的接口的时候,都报错404。 配置mvc:view-controller会导致其他请求路径失效 解决办法: SpringMVC的视图解析器 标签:hello exe 不同 不同的 报错 free which sde read 原文地址:https://www.cnblogs.com/dalianpai/p/14630333.html视图和视图解析器
视图
视图解析器
实验代码
@RequestMapping("/hello1")
public String hello1(){
return "../../hello";
}
@RequestMapping("/hello2")
public String hello2(){
return "forward:/hello.jsp";
}
@RequestMapping("/hello3")
public String hello3(){
return "forward:/hello2";
}
@RequestMapping("/hello4")
public String hello4(){
return "redirect:/index.jsp";
}
源码断点
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
// Did the handler return a view to render?
if (mv != null && !mv.wasCleared()) {
//要进行渲染
render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name ‘" + getServletName() +
"‘: assuming HandlerAdapter completed request handling");
}
}
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
// Concurrent handling started during a forward
return;
}
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
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() + "‘");
}
}
else {
// No need to lookup: the ModelAndView object contains the actual View object.
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name ‘" + getServletName() + "‘");
}
}
// Delegate to the View object for rendering.
if (logger.isDebugEnabled()) {
logger.debug("Rendering view [" + view + "] in DispatcherServlet with name ‘" + getServletName() + "‘");
}
try {
view.render(mv.getModelInternal(), request, response);
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name ‘"
+ getServletName() + "‘", ex);
}
throw ex;
}
}
@Override
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) {
synchronized (this.viewCreationCache) {
view = this.viewCreationCache.get(cacheKey);
if (view == null) {
// Ask the subclass to create the View object.
//根据方法的返回值创建view对象
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);
}
}
@Override
protected void renderMergedOutputModel(
Map
拓展
自定义视图和视图解析器
/**
* @author WGR
* @create 2021/4/8 -- 0:06
*/
@Component
public class HelloView implements View {
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map