• SpringMVC||IQ


    Here's question about springmvc

    1.Springmvc

      spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。

      另外还有一种基于组件的、事件驱动的Web框架在此就不介绍了,如Tapestry、JSF等。

      Spring Web MVC也是服务到工作者模式的实现,但进行可优化。前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。

    2.springmvc 作用

    √让我们能非常简单的设计出干净的Web层和薄薄的Web层;

    √进行更简洁的Web层的开发;

    √天生与Spring框架集成(如IoC容器、AOP等);

    √提供强大的约定大于配置的契约式编程支持;

    √能简单的进行Web层的单元测试;

    √支持灵活的URL到页面控制器的映射;

    √非常容易与其他视图技术集成,如Velocity、FreeMarker等等,因为模型数据不放在特定的API里,而是放在一个Model里(Map数据结构实现,因此很容易被其他框架使用);

    √非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API;

    √提供一套强大的JSP标签库,简化JSP开发;

    √支持灵活的本地化、主题等解析;

    √更加简单的异常处理;

    √对静态资源的支持;

    √支持Restful风格。

    3.springmvc原理

      

    过程:

    ①当浏览器的请求Request到达DispatcherServlet。(因为DispatcherServlet也是一个Servlet,所有的Request能够被它拦截到)
    ②然后DispatcherServlet会搜索寻找到一个Mapping,也就是HandlerMaping,并将其功能代理给了HandlerMaping。
    ③然后HandlerMaping根据本身的配置,找到需要用到的Controller和HandlerInterceptor。
    ④然后把Controller和HandlerInterceptor制成一个可执行的链条,也就是Handler/HandlerAdapter的适配器。
    ⑤Handler/HandlerAdapter的适配器将信息返回给了DispatcherServlet,DispatcherServlet便开始调用这个一般化的处理器Handler/HandlerAdapter。
    ⑥Controller的目的就是生成ModelAndView模型,并且返还给DispatcherServlet。
    ⑦DispatcherServlet是不会管理视图显示的,所以它就调用ViewResolver视图解析器并通过该方法返回到View对象。(ViewResolver的作用是告诉DispatcherServlet哪个视图是用来解析当前这种场景的)
    ⑧然后ModelAndView将模型数据传递到View,完成了页面呈现。

    //前端控制器分派方法
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
            HttpServletRequest processedRequest = request;
            HandlerExecutionChain mappedHandler = null;
            int interceptorIndex = -1;
     
            try {
                ModelAndView mv;
                boolean errorView = false;
     
                try {
                       //检查是否是请求是否是multipart(如文件上传),如果是将通过MultipartResolver解析
                    processedRequest = checkMultipart(request);
                       //步骤2、请求到处理器(页面控制器)的映射,通过HandlerMapping进行映射
                    mappedHandler = getHandler(processedRequest, false);
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        noHandlerFound(processedRequest, response);
                        return;
                    }
                       //步骤3、处理器适配,即将我们的处理器包装成相应的适配器(从而支持多种类型的处理器)
                    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
     
                      // 304 Not Modified缓存支持
                    //此处省略具体代码
     
                    // 执行处理器相关的拦截器的预处理(HandlerInterceptor.preHandle)
                    //此处省略具体代码
     
                    // 步骤4、由适配器执行处理器(调用处理器相应功能处理方法)
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
     
                    // Do we need view name translation?
                    if (mv != null && !mv.hasView()) {
                        mv.setViewName(getDefaultViewName(request));
                    }
     
                    // 执行处理器相关的拦截器的后处理(HandlerInterceptor.postHandle)
                    //此处省略具体代码
                }
                catch (ModelAndViewDefiningException ex) {
                    logger.debug("ModelAndViewDefiningException encountered", ex);
                    mv = ex.getModelAndView();
                }
                catch (Exception ex) {
                    Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
                    mv = processHandlerException(processedRequest, response, handler, ex);
                    errorView = (mv != null);
                }
     
                //步骤5 步骤6、解析视图并进行视图的渲染
    //步骤5 由ViewResolver解析View(viewResolver.resolveViewName(viewName, locale))
    //步骤6 视图在渲染时会把Model传入(view.render(mv.getModelInternal(), request, response);)
                if (mv != null && !mv.wasCleared()) {
                    render(mv, processedRequest, 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");
                    }
                }
     
                // 执行处理器相关的拦截器的完成后处理(HandlerInterceptor.afterCompletion)
                //此处省略具体代码
     
            catch (Exception ex) {
                // Trigger after-completion for thrown exception.
                triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
                throw ex;
            }
            catch (Error err) {
                ServletException ex = new NestedServletException("Handler processing failed", err);
                // Trigger after-completion for thrown exception.
                triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
                throw ex;
            }
     
            finally {
                // Clean up any resources used by a multipart request.
                if (processedRequest != request) {
                    cleanupMultipart(processedRequest);
                }
            }
        }

    4.配置

      在web.xml配置

      (1)监听器

      (2)拦截器

    父类接口

    5.拦截器工作流程

      

    实现

    preHandle预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如我们上一章的Controller实现);

       返回值:true表示继续流程(如调用下一个拦截器或处理器);

    false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;

    postHandle后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。

    afterCompletion整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion

    6.other springmvc bean

      

    DispatcherServlet默认使用WebApplicationContext作为上下文,因此我们来看一下该上下文中有哪些特殊的Bean:

    1、Controller处理器/页面控制器,做的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;

    2、HandlerMapping请 求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个 HandlerInterceptor拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的 Bean就是此处的处理器;

    3、HandlerAdapterHandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;如 SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行适配,并且掉处理器的 handleRequest方法进行功能处理;

    4、ViewResolverViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图;

    5、LocalResover本地化解析,因为Spring支持国际化,因此LocalResover解析客户端的Locale信息从而方便进行国际化;

    6、ThemeResovler主题解析,通过它来实现一个页面多套风格,即常见的类似于软件皮肤效果;

    7、MultipartResolver文件上传解析,用于支持文件上传;

    8HandlerExceptionResolver处理器异常解析,可以将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);

    9RequestToViewNameTranslator当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;

    10FlashMapManager用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另一个请求时作为该请求的输入,通常用于重定向场景,

  • 相关阅读:
    记录一下周末作业
    超链接的 使用和按钮添加
    学习了网页设置上传视频
    Java-JDK安装及环境变量配置
    java-库存管理案例
    java-DateFormat
    java-正则表达式练习
    java-StringBuffer类
    java面对对象-匿名对象
    java static和final关键字
  • 原文地址:https://www.cnblogs.com/EraserHead/p/6650245.html
Copyright © 2020-2023  润新知