首先感谢开涛的博客专栏,很多内容都是拾他牙慧,下面是开涛的SpringMVC的专栏:放心,点了不怀孕
1.SpringMVC是什么?
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。
SpringMVC核心执行流程
如下图:
具体执行流程如下,不考虑拦截器,各种解析等:
1.用户发送请求——>DispatcherServlet,前端控制器收到请求不处理,而是委托给其他解析器处理,作为统一访问点,进行全局流程控制;
2.DispatcherServlet——>HandlerMapping,HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象,多个HandlerInterceptor拦截器对象),通过这种策略,很容易添加新的映射策略;
3..DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装成适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4.HandlerAdapter——>处理器功能方法的调用(调用Controller),HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理,并返回一个ModelAndView对象(包含模型数据,逻辑视图名);
5.ModelAndView的逻辑视图名——>ViewResolver,ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换成其他视图技术;
6.View——>渲染,View会根据传来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7.返回控制权给DispatcherServlet,有DispacherServlet返回响应给用户,一个流程到此结束。
SpringMVC开发流程
首先,指定SpringMVC的入口(在web.xml中)
以一个Servlet作为入口程序是绝大多数MVC框架都遵循的基本设计方案。这里的DispatcherServlet被我们称之为核心分发器,是SpringMVC最重要的类之一。在SpringMVC中,核心分发器就是org.springframework.web.servlet.DispatcherServlet。
核心分发器:提炼一个核心的Servlet覆盖对所有Http请求的处理。
DispatcherServlet还需要完成不同协议之间的转化工作(从Http协议到Java世界的转化)。
然后编写SpringMVC的核心配置文件(在[servlet-name]-servlet.xml中,我一般命名习惯是spring-web.xml或者spring-mvc.xml)
再然后,编写控制(Controller)层的代码
控制(Controller)层的代码编写在一个Java文件中。我们可以看到这个Java文件是一个普通的Java类并不依赖于任何接口。只是在响应类和响应方法上使用了Annotation的语法将它与Http请求对应起来。
之后就是业务逻辑的实现了。
总结下来,构成基于SpringMVC应用程序的最基本要素。它们分别是:
入口程序 —— DispatcherServlet
核心配置 ——[servlet-name]-servlet.xml
控制逻辑 —— UserController
我们在web.xml文件中对servlet进行定义和一系列配置
在Servlet模型中,请求-响应的实现依赖于两大元素的共同配合:
1.配置Servlet及其映射关系(在web.xml中)
<url-pattern>
定义了整个请求-响应的映射载体:URL;而<servlet-name>
则将<servlet>
节点和<servlet-mapping>
节点联系在一起形成请求-响应的映射关系;<servlet-class>
则定义了具体进行响应的Servlet实现类。
2. 在Servlet实现类中完成响应逻辑
Servlet实现类本质上是一个Java类。通过Servlet接口定义中的HttpServletRequest对象,我们可以处理整个请求生命周期中的数据;通过HttpServletResponse对象,我们可以处理Http响应行为。
Servlet中的两大核心方法init方法和service方法,它们的运行时间和触发条件都截然不同:
1. init方法
在整个系统启动时运行,且只运行一次。因此,在init方法中我们往往会对整个应用程序进行初始化操作。这些初始化操作可能包括对容器(WebApplicationContext)的初始化、组件和外部资源的初始化等等。
2. service方法
在整个系统运行的过程中处于侦听模式,侦听并处理所有的Web请求。因此,在service及其相关方法中,我们看到的则是对Http请求的处理流程。
Servlet的这一特性就被SpringMVC用于对不同的逻辑职责加以划分,从而形成两条互不相关的逻辑运行主线:
初始化主线 —— 负责对SpringMVC的运行要素进行初始化
Http请求处理主线 —— 负责对SpringMVC中的组件进行逻辑调度完成对Http请求的处理
而web.xml文件中有两个常用的部分:
<context:component-scan/>
扫描指定的包中的类上的注解,常用的注解有:(这个是一定要用到的,定义Controller时就必须有它作为先决条件)
@Controller 声明Action组件
@Service 声明Service组件 @Service(“myMovieLister”)
@Repository 声明Dao组件
@Component 泛指组件, 当不好归类时.
@RequestMapping(“/menu”) 请求映射
@Resource 用于注入,( j2ee提供的 ) 默认按名称装配,@Resource(name=”beanName”)
@Autowired 用于注入,(srping提供的) 默认按类型装配
@Transactional( rollbackFor={Exception.class}) 事务管理
@Scope(“prototype”) 设定bean的作用域
另一个是<mvc:annotation-driven />
是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。<mvc:annotation-driven />
会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。并提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)。
再加上常用的对静态资源进行配置的标签<mvc:default-servlet-handler/>
所以一般的SpringMVC配置文件中一般包含如下四个标签,分别是:
<context:annotation-config/>
<context:component-scan base-package="Controller"/>
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
最后我们总结一下。
处理流程规范化的首要内容就是考虑一个通用的Servlet响应程序大致应该包含的逻辑步骤: (这个逻辑便于理解springMVC的工作流程)
步骤1 —— 对Http请求进行初步处理,查找与之对应的Controller处理类(方法)
步骤2 —— 调用相应的Controller处理类(方法)完成业务逻辑
步骤3 —— 对Controller处理类(方法)调用时可能发生的异常进行处理
步骤4 —— 根据Controller处理类(方法)的调用结果,进行Http响应处理述的四个流程也就被定义为了四个不同接口,它们分别是:
步骤1 —— HandlerMapping
步骤2 —— HandlerAdapter
步骤3 —— HandlerExceptionResolver
步骤4 —— ViewResolver
通过这里看到,和我们之前所描述的SpringMVC的核心流程对应上了。
注解
既然之前提到了注解,这里顺便就把一些相关的注解提一下。
@RequestMapping
用来处理请求地址映射的注解,用于类或方法上;
有如下六个属性:
1.value:指定请求实际地址,url
2.method:指定请求方法,GET,PUT,POST,DELETE等
3.consumes:指定处理请求的提交内容类型,如application/json, text/html
4.produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
5.params:指定request中必须包含某些参数值时,才让该方法处理
6.headers:指定request中必须包含某些特定的header值,才能让该方法处理请求
@PathVariable 处理request uri部分的注解
如@RequestMapping(”/{booId}”)中的booId就需要使用@PathVariable绑定传过来的值到方法参数上
@ModelAttribute用于方法上时,通常用来处理@RequestMapping之前,为请求绑定一个需要从后台查询的model
这里顺便提一下model.addAttribute(“sss”,sss)——渲染
这个方法就是向前台视图传递参数
@Responsebody表示该方法的返回结果直接写入HTTP response body中,一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@Responsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@Responsebody后,会直接返回json数据。