SpringMVC框架是Spring整体组件中的一个,使用SpringMVC框架的前提就是我需要知道Spring整体框架的两个核心:IoC容器和AOP编程,然后才能去使用SpringMVC。这个时候我们也就能回答学完JSP之后的那个问题,这个对应的框架就是SpringMVC。
一、核心API 前端控制器 处理器适配器 处理器映射器 视图解析器
1、DispatcherServlet ,前置(前端)控制器,作用是接受请求,响应结果,相当于转发器
2、HandlerMapping接口 ,处理器映射器:处理请求的映射,准确的说就是找到Handler,其实现类SimpleUrlHandlerMapping 通过配置文件,把一个URL映射到Controller;DefaultAnnotationHandlerMapping 通过注解,把一个URL映射到Controller类上。其作用是根据请求的URL查找Handler(Controller),通过注解或者xml配置找到相应的Controller。
3、HandlerAdapter接口,处理器适配器:处理请求的映射,准确的说是执行Handler,其实现类AnnotationMethodHandlerAdapter类,通过注解,把一个URL映射到Controller类的方法上;实现类SimpleControllerHandlerAdapter通过xml将URL映射到Handler。这里需要注意的是HandlerAdapter并不能执行所有Handler,这个Handler必须按照处理器适配器要求的规则配置,才能被执行。
4、Controller接口,我们常说的控制器,如果我们使用注解开发,那么添加了@Controller注解注解的类就可以担任控制器(Action)的职责,这个接口就用不上了。
5、HandlerInterceptor 接口,拦截器,这个接口需要我们自己实现。
6、ViewResolver接口,视图解析器,其实现类UrlBasedViewResolver类,通过配置文件,把一个逻辑视图名解析为一个View对象;InternalResourceViewResolver类,比上面的类,加入了JSTL的支持,使用较多。
7、View接口,实现类JstlView类,不同的view类型使用不同的实现类。视图对象。
8、LocalResolver接口,区域解析器,SpringMVC国际化中解析用户区域的。
9、HandlerExceptionResolver接口,用来异常处理,其实现类SimpleMappingExceptionResolver,
10、ModelAndView类,Controller执行结果类。
二、SpringMVC执行流程
1、B/S架构MVC模式
MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。
其中,控制器Controller本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据。所以它的代码理论上是最简洁,方便后期维护。模型Model拥有最多的处理任务,也是最复杂的,业务逻辑全部都在这一层,是我们项目开发的重点。需要注意的是,在C/S架构中,比如最常见的APP,Controller选定view视图之后,Model返回的数据是直接给到View,然后由View展现出来,但是在B/S架构中,因为浏览器本身的局限性,需要将返回数据存到Servlet的request域中,然后和view综合起来一块返回给浏览器展示出来。
2、SpringMVC的运行流程
(1)浏览器将请求发送至前端控制器DispatcherServlet,这个控制器是SpringMVC提供的,它相当于中央处理器,负责整个流程管控,就有点想指挥,每一步调用谁由它来控制,浏览器发送的请求信息里面包括了URL,准确的说是URI,DispatcherServlet通过调用处理器映射器HandlerMapping,然后将URI的值给到HandlerMapping,HandlerMapping通过映射就找到了Handler,也就是我们开发的Controller,而且在这个过程中执行了拦截器Interceptor,并将这个结果返回,这个返回包括Handler的位置和Interceptor的结果;DispatcherServlet根据结果看是否调用处理器适配器HandlerAdaper,并且将Handler的位置交给它,它来执行我们写的Controller,Controller执行完将结果(一般是ModelAndView也就是后台传过来的包装数据和视图路径的综合体)返回给HandlerAdaper,然后HandlerAdaper再讲结果返回给DispatcherServlet,DispatcherServlet再调用视图解析器ViewResolver,并将视图路径交给它解析,从而得到视图并将视图返回给DispatcherServlet,这时DispatcherServlet用视图渲染刚才HandlerAdapter提供的数据,从而响应浏览器得到页面。
(2)流程图:
三、SpringMVC开发流程:此处使用xml配置开发,没有用注解。首先需要导入jar包,包括Spring所需要的5个jar包,
1、前端控制器配置,在web.xml中配置,dispatcherservlet作为中央处理器,一直在分发协调各个接口调用,因此在其中还要配置映射器和适配器等等,一般情况下这里面内容较多,我们会只在里面配置一个文件名和路径,同时单独写一个xml文件来配置适配器映射器等等内容(取名一般都是ApplicationContext-mvc.xml); 然后就是配置servlet-mapping,其配置方式有两种:
a、servlet-mapping中配*.action,
b、servlet-mapping中配 / ,这种方式最常用,可以实现RESTful风格的URL,RESTful可以理解为就是一种简洁的URL规范。
我们发现其和servlet的配置是一样的,除了多了加载ApplicationContext-mvc文件。
2、配置处理器适配器,在ApplicationContext-mvc中,指定Handler要遵循的规则,选择配置实现类SimpleControllerHandlerAdapter。配置如下:
3、Handler(Controller)写Handler一定要继承接口Controller,编写Handler需要在该Java文件中指定需要渲染视图的jsp文件,也就是该文件的全限定路径名,同时也需要在ApplicationContext-mvc文件中配置,这个配置关键就是给Handler的全限定类名指定一个id。
(1)因为我们主要测试是SpringMVC,因此就不存在数据库方面的问题,首先需要先创建POJO
(2)因为我们主要测试SpringMVC,不牵涉数据库,因此我们在Controller中直接创建一个有两个POJO对象的List集合,作为从后台传过来的数据:
(3)然后就是创建ModelAndView,这个就是存储数据和逻辑视图的对象,紧接着就可以分别将数据List集合存入,将即将要编写的jsp文件的路径存入,存入的方法分别是addObject(),这个方法相对于servlet中的request对象,addObject(“id名称”,集合名称);setViewName()方法就是存入jsp文件的路径名,返回逻辑视图。最后返回这个ModelAndView对象。
4、视图,这里采用Jsp文件,该文件中的EL表达式中的键名.属性名就是Handler中指定的键名以及value中存放的对象的属性值。编写jsp的时候注意request域也就是这里面的mv对象中已经存了List对象,其别名是articleList。
5、配置处理器映射器,在ApplicationContext-mvc中选择实现类SimpleUrlHandlerMapping来配置,在这里通过步骤3中的id和URL映射起来,后面项目部署完成,就是通过这个url访问到页面的。注意这里面有两步:先要加载映射器,其次将Controller和URL映射起来:
6、视图解析器配置,在ApplicationContext-mvc中选择实现类InternalResourceViewResolver来配置,在这里配置前缀和后缀,可以简化写第三步中的jsp文件的全限定路径名。
四、SpringMVC注解开发,SpringMVC的注解开发因为简便且功能强大而更得认可,它和Xml配置开发最大的不同就是在处理器适配器和处理器映射器的配置上,上面介绍核心API的时候我们提到了两个注解的适配器和映射器的实现类,AnnotationMethodHandlerAdapter和DefaultAnnotationHandlerMapping,这是SpringMVC3.1版本前的,在这之后又增加了新的实现效果更好的实现类,RequestMappingHandlerAdapter和RequestMappingHandlerMapping。
1、但是在项目的实际开发中,我们也不用它们,而是采用功能更强大的方式:
还有组件扫描,取代映射,也就是controller和URL的绑定:
context:component-scan base-package="包含controller的包" >
这一段代码就是扫描controller包里面所有java文件,和文件中的注解一起配合使用,这个注解就是@RequestMapping(“URL”)。
同时,我们编写的controller不仅加了注解,里面代码也发生了变化,不需要在继承实现接口Controller了。
2、上面的注解开发就可以运行了,但是我们还可以在两个地方做一些简化处理:
(1)还在针对Controller,在其方法中返回值是ModelAndView,因此要把model数据和视图的URL都放入ModelAndView,然后再返回这个对象;如果我们返回值是String,那就是这个返回值就直接是视图的URL,但是少了一个model数据,所以直接在方法中定义一个形参Model,通过他的方法addAttribute()直接以键值对形式存入
(2)另外的简化就是,我们发现返回的URL有点长,在同一个项目中一定有很多公共部分,因此可以在视图解析器中定义:
那么上面(1)中的URL返回值就可以直接写成: return “article” ,将首尾都省略了。
3、更复杂的参数绑定:SpringMVC接受页面提交的数据是通过方法的形参,在SpringMVC中默认支持的形参类型有:
(1)特定类型:HttpServletRequest ,通过request对象获取信息, HttpServletResponse ,通过response处理响应信息, HttpSession,通过session获得session中存放的对象, Model/ModelMap,Model是接口,ModelMap是实现类,其作用是将模型数据填充到request域。
(2)普通数据类型:比如integer类型,这些类型是通过@RequestParam进行绑定的,如果不使用该注解就要求类的形参和方法的形参名要一致。
(3)POJO类型及集合类型绑定:这里面需要注意POST乱码和GET乱码,分别需要在web.xml里面配置filter和在tomcat配置文件中配置uft-8。这一部分内容就不在这里面说了。
4、另外SpringMVC中还有一些很重要的注解,也不在这里细说,比如和服务端验证相关的注解,比如和JSON数据相关的注解@ResponseBody,@RequestBody等。
五、拦截器Interceptor,我们在web开发中首先会用到拦截器的地方就是如果网站有后台,需要进行在后台更新资料等,后台肯定不能让人随便访问到,因此就会开发拦截器,拦截器使用了AOP编程的思想。而且这个拦截器一定会继承接口HandlerInterceptor,其中有三个方法一定要重写。
1、编写拦截器:三个方法的作用,第一个方法preHandle,进入Handler之前执行,用于登录认证,身份认证,权限认证,需要此方法拦截,其返回值false表示拦截,true表示放行;第二个方法,postHandle,进入Handler之后,返回modelAndView之前执行,页面的公用模型数据在这个方法中指定;第三个方法afterCompletion,执行完Handler执行此方法,统一的日志、异常处理。
2:在ApplicationContext-mvc中配置,一般采用全局拦截器配置。