`
jaesonchen
  • 浏览: 296958 次
  • 来自: ...
社区版块
存档分类
最新评论

Spring MVC 解读——View,ViewResolver

 
阅读更多
摘要: ViewResolver 用来将用户控制器生成的返回结果解析成视图,View定义了不同的视图,并渲染给用户,但是Spring是怎样工作的呢?

    上一篇文章(1)(2)分析了Spring是如何调用和执行控制器方法,以及处理返回结果的,现在我们就分析下Spring如何解析返回的结果生成响应的视图。

一、概念理解

  •     View ---View接口表示一个响应给用户的视图,例如jsp文件,pdf文件,html文件等,它的定义如下

public interface View {
    //HttpServletRequest中的属性名,其值为响应状态码
    String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
    //HttpServletRequest中的属性名,前一篇文章用到了该变量,它的对应值是请求路径中的变量,及@PathVariable
    //注解的变量
    String PATH_VARIABLES = View.class.getName() + ".pathVariables";
    //该视图的ContentType
    String getContentType();
    //渲染该视图
    void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response);
}

 

   该接口只有两个方法定义,分别表明该视图的ContentType和如何被渲染。Spring中提供了丰富的视图支持,几乎包含所有你想得到的,并且Spring的视图拓展性很好,你可以轻松实现自己的视图。下面是View的一些实现类(不是全部)

  • ViewResolver --- ViewResolver接口定义了如何通过view 名称来解析对应View实例的行为,它的定义相当简单:

public interface ViewResolver {

    View resolveViewName(String viewName, Locale locale) throws Exception;
}

 

   该接口只有一个方法,通过view name 解析出View。同样Spring提供了丰富的ViewResolver实现用来解析不同的View:

二、获取ModelAndView

    上一篇文章我们分析了处理器方法如何被调用以及获取了返回值,但是Spring是如何处理返回值并响应给客户呢?这就是这节要分析的,根据返回值解析出对应的视图。

private ModelAndView invokeHandleMethod(HttpServletRequest request,
            HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

        ServletWebRequest webRequest = new ServletWebRequest(request, response);

        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
        ServletInvocableHandlerMethod requestMappingMethod = 
                                    createRequestMappingMethod(handlerMethod, binderFactory);

        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
        modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
        mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

        AsyncExecutionChain chain = AsyncExecutionChain.getForCurrentRequest(request);
        chain.addDelegatingCallable(getAsyncCallable(mavContainer, modelFactory, webRequest));
        chain.setAsyncWebRequest(createAsyncWebRequest(request, response));
        chain.setTaskExecutor(this.taskExecutor);
        //上一篇文章分析到这里,调用了处理器方法并处理了返回值
        requestMappingMethod.invokeAndHandle(webRequest, mavContainer);

        if (chain.isAsyncStarted()) {
            return null;
        }
        //这里是根据返回值返回ModelAndView了
        return getModelAndView(mavContainer, modelFactory, webRequest);
    }

 

   上面的代码在上一篇文章中已经分析到了invokeAndHandle方法,该方法调用了处理器方法,并处理了返回值,剩下的就是如何将返回值呈现给用户了,我们看getModelAndView的实现:

private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
            ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
        //主要是同步model属性,并且将BindingResult添加到model中来
        modelFactory.updateModel(webRequest, mavContainer);
        //是否直接处理请求,如@ResponseBody
        if (mavContainer.isRequestHandled()) {
            return null;
        }
        ModelMap model = mavContainer.getModel();
        ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model);
        if (!mavContainer.isViewReference()) {
            mav.setView((View) mavContainer.getView());
        }//如果model是RedirectAttributes,进行flashAttributes的处理
        //即将flashAttribute属性添加到request的Output FlashMap中,以被重定向后的request获取
        if (model instanceof RedirectAttributes) {
            Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
            HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
            RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
        }
        return mav;
    }

 

   上面的代码是根据方法执行完后生成的model和视图名等信息生成ModelAndView对象,该对象维护了一个View和Model的对应关系,以便在View中可以访问Model的属性。

三、RedirectAttributes    

    上面的代码还有一个对RedirectAttributes的处理,这里我们来分析下是个什么回事?我们知道request中的属性只能在request范围内访问到,一旦执行重定向,重定向后的request并访问不到前面设置的属性了,虽然放到Session中可以在不同的request中共享这些属性,但是有时候放到Session中显得没有必要,毕竟很多属性只需要在“某次操作”中有用(重定向操作对用户来说其实是一次操作,因为重定向是浏览器执行的,对用户透明的。

    因此为了解决这个问题,Spring引入了RedirectAttributes概念,即添加到RedirectAttributes中的属性,在重定向后依旧可以获取到,并且获取到以后,这些属性就会失效,新的request便无法获取了,这样就方便了开发者,同样也节省了内错占用。

    那Spring是怎么实现的呢?这里牵扯到了FlashMap这一概念,Spring会默认为每一个请求添加两个FlashMap属性,一个是InputFlashMap,另一个是OutputFlashMap,其中InputFlashMap便包含了上一个请求在重定向到该请求前设置的属性值,也就是上一个请求的OutputFlashMap,看下面的图方便理解:

    下面是DispatcherServlet中doService中的代码片段,在调用doDispatch前便设置了InputFlashmap和OutputFlashMap:

//尝试获取该request的InputFlashMap
FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
        if (inputFlashMap != null) {
            request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, 
                                                Collections.unmodifiableMap(inputFlashMap));
        }
//设置该请求的OutputFlashMap
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
//设置该请求的FlashMapManager,用来管理InputFlashMap和OutputFlashMap
request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);

 

四、视图解析

    了解了FlashMap的概念我们继续往下看,前面我们已经获取到了请求的ModelAndView对象,这时invokeHandleMethod执行完毕将控制权交给了doDispatch,我们看怎么处理ModelAndView:

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncChain.isAsyncStarted()) {///异步调用,暂不关心
        mappedHandler.applyPostHandleAsyncStarted(processedRequest, response);
        return;
}//如果ModelAndView中没有设置视图名,则设置默认视图(大致是prefix/请求路径/suffix)
applyDefaultViewName(request, mv);
//执行拦截器的后处理器
mappedHandler.applyPostHandle(processedRequest, response, mv);
//处理分派结果,响应用户
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

 

   重点就在最后一行,我们继续追踪:

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
            HandlerExecutionChain mappedHandler, ModelAndView mv, Exception 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);
            }
        }
        // 如果返回View需要渲染?
        if (mv != null && !mv.wasCleared()) {
            //惊醒视图的渲染,我们主题
            render(mv, request, response);
            if (errorView) {
                WebUtils.clearErrorRequestAttributes(request);
            }
        }
        else {
        }
        //调用拦截器的afterComplete
        if (mappedHandler != null) {
            mappedHandler.triggerAfterCompletion(request, response, null);
        }
    }

 

   上面的代码我们着重看render方法是怎样实现的,这是我们今天的主题啊:

protected void render(ModelAndView mv,HttpServletRequest request,HttpServletResponse response){
        // 确定当前请求的Locale,并设置Response
        Locale locale = this.localeResolver.resolveLocale(request);
        response.setLocale(locale);

        View view;//ModelAndView中的View还只是名称,需要解析成View对象
        if (mv.isReference()) {
            view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
            if (view == null) {
                throw new ServletException(
                        "Could not resolve view with name '");
            }
        }
        else {//直接获取视图对象
            view = mv.getView();
            if (view == null) {
                throw new ServletException("ModelAndView [" + mv + "] ");
            }
        }
        //委托视图对象进行渲染
        view.render(mv.getModelInternal(), request, response);
    }

 

   上面的代码涉及了两个重要步骤,视图名的解析和视图的渲染,这一小节我们来讲解视图名的解析,也就是ViewResolver了:

protected View resolveViewName(String viewName, Map<StringObject> 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;
    }

 

    我们查看resolveViewName方法,发现其中有一个viewResolvers实例变量,如果你看过前面的几篇文章,你获取会记得handlerMappings, handlerAdapters等变量,不错他们是一伙的,都是在DispatcherServlet初始化时完成设置的,并且我们可以在配置文件中定义我们自己的HandleMappings, HandlerAdapters,ViewResolvers等(这里不讲解怎样设置了),但是如果我们不设置的话Spring也会为我们设置一些默认值:

org.springframework.web.servlet.HandlerMapping =
                org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
                org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=
                org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
                org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
                org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
    org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
    org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=
                org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=
                            org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=
                    org.springframework.web.servlet.support.SessionFlashMapManager

 

   上面代码片段来自Spring MVC包中的DispatcherServlet.properties属性文件中,这里Spring为我们默认设置了诸多处理器,解析器等,可以看出在我们不进行ViewResolver设置的情况下,默认实现是InternalResourceViewResolver。由第一节的ViewResolver继承层次图我们知道,InternalResourceViewResolver继承自UrlBasedViewResolver, 而UrlBasedViewResolver继承自AbstractCachingViewResolver,其实这就是Spring的聪明之处,为了提高性能,Spring中充斥着缓存策略,这不,在试图解析中也使用了缓存。这样只需在第一次解析时完成整个的视图创建工作,后续的请求只需从缓存中索取即可了。

    这里的InternalResourceViewResolver主要是用来支持Jsp文件的,换句话说,如果你的系统中只用到了jsp文件而没有模板引擎等框架,这个ViewResolver就够你用了,你也就无需在配置文件中多此一举的写上该ViewResolver了。下面我们就来看它的实现吧:

public View resolveViewName(String viewName, Locale locale) throws Exception {
        //如果没有被缓存呢,只能创建了
        if (!isCache()) {
            return createView(viewName, locale);
        }
        else {//检索缓存中的视图对象
            Object cacheKey = getCacheKey(viewName, locale);
            synchronized (this.viewCache) {
                View view = this.viewCache.get(cacheKey);
                if (view == null && (!this.cacheUnresolved 
                                                || !this.viewCache.containsKey(cacheKey))) {
                    // Ask the subclass to create the View object.
                    view = createView(viewName, locale);
                    if (view != null || this.cacheUnresolved) {
                        this.viewCache.put(cacheKey, view);
                    }
                }
                return view;
            }
        }
    }

 

   方法很简单,我们接着看是怎样创建视图的:

protected View createView(String viewName, Locale locale) throws Exception {
        // 当前ViewResolver无法解析该视图名,返回null
        if (!canHandle(viewName, locale)) {
            return null;
        }
        // view名称以redirect:开头,即重定向视图解析
        if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
            String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
            RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative()
                                                               , isRedirectHttp10Compatible());
            return applyLifecycleMethods(viewName, view);
        }
        // view名称以forward:开头,即转发视图解析
        if (viewName.startsWith(FORWARD_URL_PREFIX)) {
            String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
            return new InternalResourceView(forwardUrl);
        }
        // 正常情况下,让父类创建吧
        return super.createView(viewName, locale);
    }

 

   创建视图时,Spring会检查视图名,有三种情况redirect视图,forward视图,普通视图,进行了不同处理。对于redirect视图,spring获取redirectURL并创建了RedirectView对象,然后执行了一下bean实例的生命周期方法,没什么实质性东西,我们不关心。对于转发视图,创建了InternalResourceView对象,上面说的这两种对象的渲染过程我们过会会降到的。这里大家先记住。第三种情况呢,又交给了父类处理,我们继续看看吧:

protected View createView(String viewName, Locale locale) throws Exception {
        return loadView(viewName, locale);
}
@Override
protected View loadView(String viewName, Locale locale) throws Exception {
        AbstractUrlBasedView view = buildView(viewName);
        View result = applyLifecycleMethods(viewName, view);
        return (view.checkResource(locale) ? result : null);
}

 

   父类的createView方法又委托给了loadView,而loadView是抽象的由子类实现,好吧,我只能说这个地方真饶。我们继续看loadView中有一个buildView方法,看着不错哦:

protected AbstractUrlBasedView buildView(String viewName) throws Exception {
        //根据ViewClass实例化该Class
        AbstractUrlBasedView view = (AbstractUrlBasedView) BeanUtils
                                                            .instantiateClass(getViewClass());
        //设置视图的url,prefix/viewName/suffix
        view.setUrl(getPrefix() + viewName + getSuffix());
        String contentType = getContentType();
        if (contentType != null) {//设置ContentType
            view.setContentType(contentType);
        }//设置请求上下文属性
        view.setRequestContextAttribute(getRequestContextAttribute());
        view.setAttributesMap(getAttributesMap());
        if (this.exposePathVariables != null) {//设置是否暴露PathVariable
            view.setExposePathVariables(exposePathVariables);
        }
        return view;
}

 

   上面的代码又出来个ViewClass, prefix,suffix,他们又是个什么东西呢?其实我们知道在配置InternalResourceViewResolver时可以指定一个viewClass,prefix,suffix,没错,就是他们,先说prefix,suffix,我们看到了它会分别添加到viewName的前后,组成视图的URL。那个viewClass呢就是视图的class对象类型了。我们看InternalResourceViewResolver的构造器:

public InternalResourceViewResolver() {
        Class viewClass = requiredViewClass();
        if (viewClass.equals(InternalResourceView.class) && jstlPresent) {
            viewClass = JstlView.class;
        }
        setViewClass(viewClass);
}

 

   会发现在我们没有指定的情况下默认是JstlView哦。根据第一季中的图片我们可以知道它继承自InternalResourceView。到此为止呢我们的视图对象已经创建完毕。

    我们这里只解析了Spring默认情况下的InternalResourceViewResolver的解析过程,默认情况下解析的视图类型是JstlView。如果是Redirect的话则是RedirectView。

五、视图渲染

    视图解析出来了,下面就是要将视图渲染给用户显示了。这里我们依旧只讲解默认的JstlView的渲染过程,当然还有RedirectView的。

public void render(Map<String, ?> model, HttpServletRequest request, 
                                                HttpServletResponse response) throws Exception {
        
        Map<StringObject> mergedModel = createMergedOutputModel(model, request, response);

        prepareResponse(request, response);
        renderMergedOutputModel(mergedModel, request, response);
}
protected Map<StringObject> createMergedOutputModel(Map<String, ?> model, 
                            HttpServletRequest request, HttpServletResponse response) {
        @SuppressWarnings("unchecked")
        //如果需要保留PathVariable
        Map<StringObject> pathVars = this.exposePathVariables ?
            (Map<StringObject>) request.getAttribute(View.PATH_VARIABLES) : null;

        //联合动态和静态属性
        int size = this.staticAttributes.size();
        size += (model != null) ? model.size() : 0;
        size += (pathVars != null) ? pathVars.size() : 0;
        Map<StringObject> mergedModel = new HashMap<StringObject>(size);
        mergedModel.putAll(this.staticAttributes);
        if (pathVars != null) {
            mergedModel.putAll(pathVars);
        }
        if (model != null) {
            mergedModel.putAll(model);
        }
        // Expose RequestContext?
        if (this.requestContextAttribute != null) {
            mergedModel.put(this.requestContextAttribute, 
                                        createRequestContext(request, response, mergedModel));
        }
        
        return mergedModel;
}

 

   上面代码是AbstractView中的方法,也就是所有视图都会执行的操作,就是将静态属性和动态生成的属性合并,我们重点看

renderMergedOutputModel方法,子类会覆盖该方法,实现不同的逻辑。我们来看JstlView和RedirectView的实现,首先JstlView :

protected void renderMergedOutputModel(
            Map<StringObject> model, HttpServletRequest request,HttpServletResponse response){

        //确定执行请求转发的request对象
        HttpServletRequest requestToExpose = getRequestToExpose(request);
        //将model中的属性暴露为请求属性表中
        exposeModelAsRequestAttributes(model, requestToExpose);
        //暴露MessageResource
        exposeHelpers(requestToExpose);
        //确定转发的路径,也就是View的URL,但会检查是否会进入死循环,即跟当前请求同一个路径
        String dispatcherPath = prepareForRendering(requestToExpose, response);
        //生成RequestDispatcher对象
        RequestDispatcher rd = getRequestDispatcher(requestToExpose, dispatcherPath);
        if (rd == null) {
            throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +"]");
        }
        //include操作
        if (useInclude(requestToExpose, response)) {
            response.setContentType(getContentType());
            rd.include(requestToExpose, response);
        }
        else {
            //执行转发,暴露属性到转发请求中
            exposeForwardRequestAttributes(requestToExpose);
            rd.forward(requestToExpose, response);
        }
}

 

  方法看着很长其实思路比较简单,主要就是调用了RequestDispatcher的include 或forward的方法,将请求转发到指定URL。JstlView的视图渲染相对简单,我们来看RedirectView的渲染:

protected void renderMergedOutputModel(
            Map<StringObject> model, HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        //获取重定向的路径,也就是前面生成RedirectView时设置的URL,但会进行相对路径的处理
        String targetUrl = createTargetUrl(model, request);
        //调用用户注册的RequestDataValueProcessor的process方法,通常用不到,不管
        targetUrl = updateTargetUrl(targetUrl, model, request, response);
        //哈哈,这里就是我们上面讲到的FlashMap的处理啦,是怎样实现的呢?
        //我们知道前面将RedirectAttributes的属性都设置到了当前请求的OutputFlashMap中了,这里再取出来。
        //设置flashMap的目标请求路径,用来比对下次请求的路径,如果匹配,将其中的属性设置到请求属性表中
        FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
        if (!CollectionUtils.isEmpty(flashMap)) {
            UriComponents uriComponents = UriComponentsBuilder.fromUriString(targetUrl).build();
            flashMap.setTargetRequestPath(uriComponents.getPath());
            flashMap.addTargetRequestParams(uriComponents.getQueryParams());
        }
        //将flashMap交由FlashMapManager管理。
        FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);
        flashMapManager.saveOutputFlashMap(flashMap, request, response);
        //返回结果,设置响应头304.
        sendRedirect(request, response, targetUrl.toString(), this.http10Compatible);
}

 

   到此为止,我们的试图解析,渲染过程就完全分析完了,获取到目前为止有点晕,其实好好思考下,Spring在视图解析,和渲染这块给了我们足够的拓展空间。

六、总结

    Spring对视图的支持相当完善,默认的JSP不用说,PDF,Excel, 等,还包括主流的模板引擎,像FreeMarker, Tiles等,可以参考第一张图片。当然你完全也可以实现自己的View,以及ViewResolver,来解析自定义的视图。不过应该没多大必要。

分享到:
评论

相关推荐

    Spring MVC 解读——View,ViewResolver.zip

    View,ViewResolver

    Spring MVC 入门实例

    6 &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; 7 8 9 10 11 &lt;bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet....

    spring mvc 3.2 参考文档

    Spring Web model-view-controller (MVC)框架是围绕 DispatcherServlet 设计的,并分发请求到处理程序(handler),Spring MVC支持可配置的处理程序映射(handler mapping),视图解析(view resolution)、 区域设置...

    java spring mvc

    5)Spring MVC处理流程 a.... d.ModelAndView里包含了响应View和数据信息,主控制器调用ViewResolver视图解析器根据ModelAndView的内容寻找View组件,生成响应 e.主控制器将响应内容给客户浏览器输出

    Spring MVC 员工管理系统

    Spring为展现层提供了一个优秀的Web框架——Spring MVC。和众多其它Web框架一样,它基于MVC设计理念,此外,由于它采用了松散耦合可插拔组件结构,具有比其它MVC框架更多的扩展性和灵活性。 Spring MVC框架围绕...

    看透springMvc源代码分析与实践

    8.2.2 创建Spring MVC的xml配置文件85 8.2.3 创建Controller和view86 8.3 关联spring源代码87 8.4 小结89 第9章 创建Spring MVC之器90 9.1 整体结构介绍90 9.2 HttpServletBean93 9.3 FrameworkServlet95 ...

    Spring MVC 学习笔记

    5、 ModelAndView的逻辑视图名交给ViewResolver解析器, ViewResolver解析器把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术; 6、 View会根据传进来的Model模型数据进行渲染,此处的...

    Spring-mvc,例题

    &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;property name="prefix" value="/"&gt;&lt;/property&gt; &lt;property name="suffix" value=".jsp"&gt;&lt;/property&gt; &lt;!-...

    org.springframework.web.servlet-3.1.0.RELEASE

    是源代码,不是jar文件!!!!! /** * Holder for both Model and View in the web MVC framework. * Note that these are entirely ... * @see org.springframework.web.servlet.mvc.Controller#handleRequest */

    Spring-Reference_zh_CN(Spring中文参考手册)

    2.5.1. Spring MVC的表单标签库 2.5.2. Spring MVC合理的默认值 2.5.3. Portlet 框架 2.6. 其他特性 2.6.1. 动态语言支持 2.6.2. JMX 2.6 .3. 任务规划 2.6.4. 对Java 5(Tiger)的支持 2.7. 移植到Spring 2.0 ...

    Spring中文帮助文档

    2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态...

    Spring API

    2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态...

    Spring3中配置DBCP,C3P0,Proxool,Bonecp数据源

    &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt; ...

    helloword.rar

    最近学习java,学习使用Springmvc,作为练习写了一个 通过IDEA新建Spring MVC项目设置运行、调试相关配置导入Spring MVC 相关类库添加 Controller修改 url-attern(web.xml)配置 component-scan(dispatcher-...

    SpringMVC+Hibernate实例

    &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"&gt; &lt;property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/&gt; ...

    microboot:基于netty的高性能HTTP静态服务器,netty http服务器,支持HTTP2.0

    microboot是什么microboot是基于Netty开发的一个HTTP服务框架,本身提供http服务器功能,jar包方式启动,使用方式与架构与Spring MVC极为相似,microboot没有遵循java web规范,非常轻量级,并且高效。微启动能做...

    基于SpringBoot+Java+MySQL的新闻爬取发布管理投稿聊天前后台管理系统.zip

    本系统开发采用SpringBoot框架开发,Spring框架提供了构建 Web 应用程序的全功能MVC模块,主要由DispatcherServlet、处理器映射(HandlerMapping)、处理器(Controller)、视图解析器(ViewResolver)、视图(View)组成。...

    跳板

    관리를로를유지보수와이개발효율DispatcherServle / HandlerMapping용한이용한MVC패턴 DisapatcherServlet处理程序对HandlerMapping处理对策후DispatcherServlet에게pat pat 이과정에서Model이생성되어View에서같이...

Global site tag (gtag.js) - Google Analytics