Spring MVC 4x 学习笔记.docx
《Spring MVC 4x 学习笔记.docx》由会员分享,可在线阅读,更多相关《Spring MVC 4x 学习笔记.docx(33页珍藏版)》请在冰豆网上搜索。
SpringMVC4x学习笔记
SpringMVC学习笔记
1springMVC初接触
1.1springMVC是什么
SpringWebMVC是一种基于Java的实现了WebMVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,SpringWebMVC也是要简化我们日常Web开发的。
另外还有一种基于组件的、事件驱动的Web框架。
SpringWebMVC也是服务到工作者模式的实现,但进行可优化。
前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(HandlerMapping)进行处理器管理和视图解析器(ViewResolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndViewhandleRequest(request,response)方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。
1.2SpringWebMVC能帮我们做什么
●让我们能非常简单的设计出干净的Web层和薄薄的Web层;
●进行更简洁的Web层的开发;
●天生与Spring框架集成(如IoC容器、AOP等);
●提供强大的约定大于配置的契约式编程支持;
●能简单的进行Web层的单元测试;
●支持灵活的URL到页面控制器的映射;
●非常容易与其他视图技术集成,如Velocity、FreeMarker等等,因为模型数据不放在特定的API里,而是放在一个Model里(Map数据结构实现,因此很容易被其他框架使用);
●非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API;
●提供一套强大的JSP标签库,简化JSP开发;
●支持灵活的本地化、主题等解析;
●更加简单的异常处理;
●对静态资源的支持;
●支持Restful风格。
1.3SpringWebMVC架构
SpringWebMVC框架也是一个基于请求驱动的Web框架,并且也使用了前端控制器模式来进行设计,再根据请求映射规则分发给相应的页面控制器(动作/处理器)进行处理。
首先让我们整体看一下SpringWebMVC处理请求的流程:
1.3.1、SpringWebMVC处理请求的流程
具体执行步骤如下:
1、 首先用户发送请求————>前端控制器,前端控制器根据请求信息(如URL)来决定选择哪一个页面控制器进行处理并把请求委托给它,即以前的控制器的控制逻辑部分;图中的1、2步骤;
2、 页面控制器接收到请求后,进行功能处理,首先需要收集和绑定请求参数到一个对象,这个对象在SpringWebMVC中叫命令对象,并进行验证,然后将命令对象委托给业务对象进行处理;处理完毕后返回一个ModelAndView(模型数据和逻辑视图名);图的3、4、5步骤;
3、 前端控制器收回控制权,然后根据返回的逻辑视图名,选择相应的视图进行渲染,并把模型数据传入以便视图渲染;图的步骤6、7;
4、 前端控制器再次收回控制权,将响应返回给用户,图的步骤8;至此整个结束。
问题:
1、 请求如何给前端控制器?
2、 前端控制器如何根据请求信息选择页面控制器进行功能处理?
3、 如何支持多种页面控制器呢?
4、 如何页面控制器如何使用业务对象?
5、 页面控制器如何返回模型数据?
6、 前端控制器如何根据页面控制器返回的逻辑视图名选择具体的视图进行渲染?
7、 不同的视图技术如何使用相应的模型数据?
首先我们知道有如上问题,那这些问题如何解决呢?
请让我们先继续,在后边依次回答。
1.3.2SpringWebMVC架构
SpringWebMVC核心架构图,如图
核心架构的具体流程步骤如下:
1、 首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2、 DispatcherServlet——>HandlerMapping,HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3、 DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4、 HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
5、 ModelAndView的逻辑视图名——>ViewResolver,ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6、 View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
此处我们只是讲了核心流程,没有考虑拦截器、本地解析、文件上传解析等,后边再细述。
到此,再来看我们前边提出的问题:
1、 请求如何给前端控制器?
这个应该在web.xml中进行部署描述,在HelloWorld中详细讲解。
2、 前端控制器如何根据请求信息选择页面控制器进行功能处理?
我们需要配置HandlerMapping进行映射
3、 如何支持多种页面控制器呢?
配置HandlerAdapter从而支持多种类型的页面控制器
4、 如何页面控制器如何使用业务对象?
可以预料到,肯定利用SpringIoC容器的依赖注入功能
5、 页面控制器如何返回模型数据?
使用ModelAndView返回
6、 前端控制器如何根据页面控制器返回的逻辑视图名选择具体的视图进行渲染?
使用ViewResolver进行解析
7、 不同的视图技术如何使用相应的模型数据?
因为Model是一个Map数据结构,很容易支持其他视图技术
在此我们可以看出具体的核心开发步骤:
1、 DispatcherServlet在web.xml中的部署描述,从而拦截请求到SpringWebMVC
2、 HandlerMapping的配置,从而将请求映射到处理器
3、 HandlerAdapter的配置,从而支持多种类型的处理器
4、 ViewResolver的配置,从而将逻辑视图名解析为具体视图技术
5、处理器(页面控制器)的配置,从而进行功能处理
1.4SpringWebMVC优势
1、清晰的角色划分:
前端控制器(DispatcherServlet)、请求到处理器映射(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、处理器或页面控制器(Controller)、验证器( Validator)、命令对象(Command 请求参数绑定到的对象就叫命令对象)、表单对象(FormObject提供给表单展示和提交到的对象就叫表单对象)。
2、分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要;
3、由于命令对象就是一个POJO,无需继承框架特定API,可以使用命令对象直接作为业务对象;
4、和Spring其他框架无缝集成,是其它Web框架所不具备的;
5、可适配,通过HandlerAdapter可以支持任意的类作为处理器;
6、可定制性,HandlerMapping、ViewResolver等能够非常简单的定制;
7、功能强大的数据验证、格式化、绑定机制;
8、利用Spring提供的Mock对象能够非常简单的进行Web层单元测试;
9、本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
10、强大的JSP标签库,使JSP编写更容易。
………………还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配置支持等等。
1.5 HelloWorld入门
1.5.1开发环境准备
1.5.1.1添加springmvc依赖
Springmvc依赖于spring核心,也就是IOC&DI以及AOP,所以需要在原有spring项目基础上添加springmvc的依赖。
在pom.xml文件中添加
--springmvc依赖库-->
org.springframework
spring-webmvc
${spring.version}
1.5.2前端控制器的配置
在我们的web.xml中添加如下配置:
dispatcherServlet
org.springframework.web.servlet.DispatcherServlet
--初始化參數-->
--通過初始化參數contextConfigLocation指定springmvc配置文件的路徑-->
contextConfigLocation
classpath:
/spring-mvc.xml
--当应用启动时加载该servlet-->
1
dispatcherServlet
--
/:
支持RESTful,便于检索。
/*:
不能返回视图。
*.do(必须以.do结尾的路径才能访问。
)
-->
/
oad-on-startup:
表示启动容器时初始化该Servlet;
url-pattern:
表示哪些请求交给SpringWebMVC处理,“/”是用来定义默认servlet映射的。
也可以如“*.html”表示拦截所有以html为扩展名的请求。
自此请求已交给SpringWebMVC框架处理,因此我们需要配置Spring的配置文件,默认DispatcherServlet会加载WEB-INF/[DispatcherServlet的Servlet名字]-servlet.xml配置文件。
本示例为WEB-INF/spring-mvc.xml。
PS:
springmvc的控制器的映射路径一般写成/,除此之外还可以是:
/:
支持RESTful,便于检索。
/*:
不能返回视图。
*.do(必须以.do结尾的路径才能访问。
)
1.5.3springmvc配置文件的实现
在resource目录下建立springmvc.xml文件.
1.5.3.1Spring配置文件中配置HandlerMapping、HandlerAdapter
--HandlerMapping-->
--HandlerAdapter-->
BeanNameUrlHandlerMapping:
表示将请求的URL和Bean名字映射,如URL为“上下文/hello”,则Spring配置文件必须有一个名字为“/hello”的Bean,上下文默认忽略。
SimpleControllerHandlerAdapter:
表示所有实现了org.springframework.web.servlet.mvc.Controller接口的Bean可以作为SpringWebMVC中的处理器。
如果需要其他类型的处理器可以通过实现HadlerAdapter来解决。
1.5.3.2在Spring配置文件中配置ViewResolver
InternalResourceViewResolver:
用于支持Servlet、JSP视图解析;
viewClass:
JstlView表示JSP模板页面需要使用JSTL标签库,classpath中必须包含jstl的相关jar包;故在pom.xml中需要加入:
--添加jstl依赖-->
jstl
jstl
${jstl.version}
javax
javaee-api
${javaee.version}
prefix和suffix:
查找视图页面的前缀和后缀(前缀[逻辑视图名]后缀),比如传进来的逻辑视图名为hello,则该该jsp视图页面应该存放在“WEB-INF/jsp/hello.jsp”;
1.5.4开发处理器/页面控制器
建立控制类,HellowordController,代码如下
1.5.5开发页面
在/WEB-INF/jsp目录下建立hello.jsp文件,代码如下:
1.5.6启动web应用,测试helloword
启动tomcat,若项目为配置tomcat的,请根据以前的学习自行配置
tomcat启动无异常后,在浏览器输入:
http:
//ip:
port/上下文/hello
访问helloword,结果如下:
PS:
疑问问题
1.为什么输入的地址是/hello
原因:
因为springmvc中是通过BeanNameUrlHandlerMapping实现路径映射,将请求的URL和Bean名字映射,我们这里bean的name属性值为/hello,所以我们访问时也是/hello。
2.我访问的是controller,但为什么在客户端看到的却是hello.jsp的内容
原因:
因为springmvc中,用户通过/hello请求服务器,DispatcherServlet将会指派name为/hello的bean来处理用户请求,而且会执行handleRequest方法。
过程如下
运行步骤:
1、 首先用户发送请求http:
//localhost:
9080/springmvc-chapter2/hello——>web容器,web容器根据“/hello”路径映射到DispatcherServlet(url-pattern为/)进行处理;
2、 DispatcherServlet——>BeanNameUrlHandlerMapping进行请求到处理的映射,BeanNameUrlHandlerMapping将“/hello”路径直接映射到名字为“/hello”的Bean进行处理,即HelloWorldController,BeanNameUrlHandlerMapping将其包装为HandlerExecutionChain(只包括HelloWorldController处理器,没有拦截器);
3、 DispatcherServlet——>SimpleControllerHandlerAdapter,SimpleControllerHandlerAdapter将HandlerExecutionChain中的处理器(HelloWorldController)适配为SimpleControllerHandlerAdapter;
4、 SimpleControllerHandlerAdapter——>HelloWorldController处理器功能处理方法的调用,SimpleControllerHandlerAdapter将会调用处理器的handleRequest方法进行功能处理,该处理方法返回一个ModelAndView给DispatcherServlet;
5、 hello(ModelAndView的逻辑视图名)——>InternalResourceViewResolver,InternalResourceViewResolver使用JstlView,具体视图页面在/WEB-INF/jsp/hello.jsp;
6、 JstlView(/WEB-INF/jsp/hello.jsp)——>渲染,将在处理器传入的模型数据(message=HelloWorld!
)在视图中展示出来;
7、 返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
2springmvc进阶-基于注解开发
在第一章的helloword的例子中,我们已经完成了springmvc的第一个实例,但是在该实现中我们发现以下问题:
1.每个controller必须实现controller接口,增加耦合性
2.每个controller必须在配置文件中定义bean,太麻烦,是否支持注解的方式定义;
3.每个controller必须通过方法handleRequest来处理用户请求,且一个controller只能处理一个请求,不能做到业务整合;
4.每次请求都要去封装modelAndView对象,太麻烦。
Andsoon…
2.1基于注解的方式来开发springmvc
Springmvc也支持注解的方式来定义bean
2.1.1Spring-mvc.xml中的变化
因涉及注解所以必须添加自动包扫描的配置:
PS:
如果是在原有的spring项目上加springmvc,现在的自动扫描包请明确到你的Controller所在的正确目录,否则可能会出现加载其他的注解出错。
开启注解支持,
开启springmvc的注解支持
取消掉原来在spring-mvc.xml中配置的HelloWordController的bean
2.1.2HelloWordController中的变化
1.取消实现接口Controller,将该类变成最普通的java类,并通过注解将其定义为一个Controller,通过@Controller注解
2.定义一个普通的方法来处理用户,该方法返回一个字符串
2.1.3启动tomcat,访问之
启动tomcat,通过http:
//localhost:
7001/sayhello访问,结果如下
问题:
1.在Controller类的方法直接返回一个字符串是什么意思?
2.Controller中没有传递数据给jsp
2.1.4controller处理请求的方法的返回值
Controller的方法中直接返回一个字符串,代表的是设置一个视图的名称,他将会根据我们在spring-mvc.Xml中定义的规则自动增加前缀和后缀,此处返回hello,那么结果就是:
/WEB-INF/jsp/hello.jsp
其规则如下:
1.return“list”
如果定义了视图解析器,则会将请求转发到对应的视图页面,比如本案例中定义了
Springmvc会将请求转发到prefix+你的return+suffix地址去,即本案例的/WEB-INF/hello.jsp。
此处加/不代表上下文根路径,仅仅作为字符串拼接所用。
2.return“redirect:
/list”;
重定向到另外一个action地址,该地址是已经定义的,加/代表上下文根路径;不加代表相对路径,建议加上。
3.return“forward:
/list”;
请求转发到另外一个action地址,该地址是已经定义的,加/代表上下文根路径;不加代表相对路径,建议加上。
2.1.5Controller中如何传递数据给JSP视图
2.1.5.1将方法的返回值改为ModelAndView在返回时,将数据存储在ModelAndView对象中如:
在这里要注意的是数据是默认被存放在request中的。
2.1.5.2通过方法带Model参数的,然后调用model.addAttribute(Stringkey,Objectvalue)的方式传递,在JSP中可以从request作用域中获取。
2.1.6处理springMVC中的静态资源问题
在本例中,我们在web资源的根目录即webapp下建立一个html文件my.html,浏览器通过地址:
http:
//ip:
port/上下文/my.html访问,会发现该资源不可访问,通过查看debug调测日志可以发现springmvc将我们的静态资源也一起拦截了,而且尝试去找到对应的Controller处理方法,但是找不到对应的映射。
解决方案为去掉以下两个bean的定义,
修改为springmvc为我们提供的默认Handler处理方式。
此方式会过滤掉静态资源的请求
2.1.7springmvc中处理post请求中的乱码问题
从以前jsp的学习中,我们就知道post的请求参数若带有全角文字,我们必须在获取参数前通过request.setCharactor(编码)的方式设置后方可正确获取,而因为一个应用中多次需要使用且都是在请求获取前处理,所以我们曾经使用过滤器的方式来实现post的中文乱码问题,而在springmv