Spring+MyBatis企业应用实战(1)

第一章 Java EE 应用

JavaEE应用的分层模型

(1)Domain Object(领域对象)层:POJO(Plain Old Java Object)组成,包含了各自所需实现的业务逻辑方法。

(2)DAO(Data Access Object,数据访问对象)层:DAO组件组成,这些DAO实现了对数据库的创建、查询、更新和删除(CRUD)等原子操作。

(3)Service(业务逻辑)层:业务逻辑对象组成,这些对象实现了系统所需要的业务逻辑方法。

(4)Controller(控制器)层:控制器组成,这些控制器用于拦截用户请求,并调用业务逻辑组件的方法,处理请求,根据结果向不同的表现层组件转发。

(5)View(表现)层:Jsp页面、Velocity页面、pdf文档视图组件组成,负责搜集用户请求,并显示处理结果。

Spring+MyBatis企业应用实战(1)

为了应用以后的扩展性,各层的JavaEE组件之间以松耦合的方式耦合,不以硬编码方式耦合。上面组件的实现依赖下面组件的功能,下面组件支持上面组件的实现。

第二章 SpringMVC简介

1、传统 Model1 和 Model2

Model1模式:1)整个 Web 应用几乎全部由 JSP 页面组成。JSP页面接收处理客户请求,对请求处理后直接做出响应。少量的 JavaBean 来处理数据库连接、数据库访问等操作。2)实现简单,适用于快速开发小规模项目。3)局限性明显:JSP 页面身兼 View 和 Controller两种角色,将控制逻辑和表现逻辑混杂在一起,导致代码的重用性非常低,应用难以扩展和维护。

Model2模式:1)基于MVC架构的设计模式。Servlet作为前端控制器,接收客户请求。Servlet中只包含控制逻辑和简单的前端处理;然后调用 JavaBean 来完成实际的逻辑处理;最后,将其转发到响应的 JSP 页面来显示处理逻辑。具体实现方式如下图:

Spring+MyBatis企业应用实战(1)

在Model2模型下,Model由JavaBean充当,View由JSP页面充当,Controller由Servlet充当。Model2具有组件化的特点,适用于大规模应用的开发,但增加了应用开发的复杂程度。

2、MVC思想及其优势

MVC是所有面向对象程序设计语言都应该遵守的规范,并非Java语言所特有的设计思想,也不是Web应用所特有的思想。MVC思想将一个应用分成三个基本部分:Model(模型)、View(视图)、和Controller(控制器),这三个部分以最少的耦合协同工作,提高应用的扩展性和维护性。MVC思想类似于观察者模式,但其与观察者模式存在少许差别:观察者模式下,观察者和被观察者可以是两个互相对等的对象;但在MVC中,被观察者往往只是单纯的数据体,而观察者则是单纯的视图页面。(引起差别的主要原因是:Web应用是一种 请求/响应模式下的应用,如果用户不对应用发出请求,视图将无法主动更新自己。)

MVC有如下特点:1)多个视图可以定义一个模型。按MVC设计模式,一个模型对应多个视图,可以减少代码的复制及代码的维护量,易于维护。2)模型返回的数据与显示逻辑分离。模型数据可以应用任何的显示技术,JSP页面/Velocity模板/直接产生Excel...。3)应用被分隔为三层,降低各层之间的耦合,提供了应用的可扩展性。4)控制层的概念也很有效,由于它把不同的模型和不同的视图组合在一起,完成不同的请求。因此,控制层可以说包含了用户请求权限的概念。5)MVC更符合软件工程化管理的精神。不同的层各司其职,每一层的组件具有相同的特征,有利于通过工程化和工具化的方法产生管理程序代码。

Web模式下的MVC:对于一个普通的应用程序,可以将视图注册给模型,当模型数据发生改变时,及时通知视图页面发送改变;而对于Web应用,即使使多个JSP页面注册给一个模型,但当模型发生变化时,模型也无法主动给JSP页面发送消息(因为Web应用都是基于 请求/响应 模式的),只有当用户请求浏览该页面时,控制器才负责调用模型数据来更新JSP页面。遵循了MVC模式的JavaWeb的运行流程图:

Spring+MyBatis企业应用实战(1)

3、SpringMVC的特点

  • 1)SpringMVC强大的灵活性、非侵入性、可配置性
  • 2)SpringMVC提供前端控制器DispatcherServlet,开发者无需额外开发控制器对象。
  • 3)SpringMVC分工明确,包括控制器、验证器、命令对象、模型对象、处理程序映射、视图解析器...,每一个功能实现由一个专门的对象负责完成。
  • 4)SpringMVC自动绑定用户输入,正确转换数据类型。例如,SpringMVC能自动解析字符串,并将其设置为模型的int或float类型的属性。
  • 5)SpringMVC使用一个名称/值的Map对象实现更加灵活的模型数据传输
  • 6)SpringMVC内置了常见的校验器,可以校验用户的输入,如果校验不通过,则重定向回输入表单。输入校验是可选的,并且支持编程方式及声明方式。
  • 7)SpringMVC支持国际化,支持根据用户区域显示多国语言,并且国际化的配置非常简单。
  • 8)SpringMVC支持多种视图技术,最常见的有JSP技术以及其他技术,包括Velocity和FreeMarker。
  • 9)Spring提供了一个简单而强大的JSP标签库,支持数据绑定功能,使得编写JSP页面更加容易。

4、详解DispatcherServlet

org.springframework.web.servlet.DispatcherServlet

protected void initStrategies(ApplicationContext context) {
    //初始化文件上传解析器
    this.initMultipartResolver(context);
    //初始化本地化解析器
    this.initLocaleResolver(context);
    //初始化主题解析器
    this.initThemeResolver(context);
    //初始化处理器映射器,,将请求映射到处理器
    this.initHandlerMappings(context);
    //初始化处理器适配器
    this.initHandlerAdapters(context);
    //初始化处理器异常解析器,如果执行过程中遇到异常,将交给HandlerExceptionResolver来解析
    this.initHandlerExceptionResolvers(context);
    //初始化请求到视图名称解析器
    this.initRequestToViewNameTranslator(context);
    //初始化视图解析器,通过 ViewResolver 解析逻辑视图名到具体视图实现
    this.initViewResolvers(context);
    //初始化 flash 映射管理器
    this.initFlashMapManager(context);
}

initStrategies 方法在WebApplicationContext初始化后自动执行,自动扫描上下文的Bean,根据名称或类型匹配的机制查找自定义的组件,如果没有找到则会装配一套Spring的默认组件。在org.springframework.web.servlet路径下有一个DispatcherServlet.properties配置文件,该文件指定了DispatcherServlet所使用的默认组件。

5、SpringMVC执行的流程

问:Controller并未接收到用户请求,它怎么能够处理用户的请求呢?这要看MVC框架的底层机制:前端Servlet接收到请求后,通常会对用户请求进行简单预处理,例如解析、封装参数等,然后通过反射来创建Controller实例,并调用Controller的指定方法(实现Controller接口的是handleRequest方法,而使用基于注解的控制器可以是任意方法)来处理用户请求。

问:当Servlet拦截用户请求后,它如何知道创建哪个Controller接口的实例呢?有两种解决方案:一是利用xml配置文件,例如在xml配置文件中描述hello请求对应使用HelloController类。这就可以让MVC框架知道创建哪个Controller接口的实例。二是利用注解,例如使用注解Controller描述一个类,并使用注解@RequestMapping(value="/hello")描述hello请求对应的方法。这样也可以让MVC框架知道创建哪个Controller接口的实例并调用哪个方法处理请求。

所以说,在SpringMVC框架中,控制器实际上由两部分组成:DispatcherServlet(拦截所有用户请求和处理请求)和Controller(处理实际的业务控制)。

完整流程

①用户向服务器发送请求,请求被Spring的前端控制器DispatcherServlet截获。

②DispatcherServlet对请求URL(统一资源定位符)进行解析,得到URI(请求资源标识符)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关对象,包括Handler对象以及Handler对象对应的拦截器,这些对象会被封装到一个HandlerExecutionChain对象当中返回。

③DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter。HandlerAdapter的设计符合面向对象中的单一职责原则,代码架构清晰,便于维护,最重要的是,代码可复用性高。HandlerAdapter会被用于处理多种Handler,调用Handler实际处理请求的方法,例如hello方法。

④根据请求中的模型数据,开始执行Handler(Controller)。在填充Handler的入参过程中,根据配置,Spring将帮你做一些额外的工作(消息转换、数据转换、数据格式化、数据验证)。

⑤Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象,ModelAndView对象中应该包含视图名或视图名和模型。

⑥根据返回的ModelAndView对象,选择一个合适的ViewResolver(视图解析器)返回给DispatcherServlet。

⑦ViewResolver结合Model和View来渲染视图。

⑧将视图渲染结果返回给客户端。

Spring+MyBatis企业应用实战(1)