spring mvc学习教程(一)-入门实例
引言
1.MVC:Model-View-Control
框架性质的C层要完成的主要工作:封装web请求为一个数据对象、调用业务逻辑层来处理数据对象、
返回处理数据结果及相应的视图给用户。
2.简要概述springmvc
Spring C 层框架的核心是DispatcherServlet,它的作用是将请求分发给不同的后端处理器,也即使用
了一种被称为Front Controller 的模式(后面对此模式有简要说明)。Spring 的C 层框架使用了后端控
制器来、映射处理器和视图解析器来共同完成C 层框架的主要工作。并且spring 的C 层框架还真正地把
业务层处理的数据结果和相应的视图拼成一个对象,即我们后面会经常用到的ModelAndView 对象。
一、入门实例
1. 搭建环境
在spring的官方API文档中,给出所有包的作用概述,现列举常用的包及相关作用:org.springframework.aop-3.0.5.RELEASE.jar:与Aop编程相关的包
org.springframework.beans-3.0.5.RELEASE.jar:提供了简捷操作bean的接口
org.springframework.context-3.0.5.RELEASE.jar:构建在beans包基础上,用来处理资源文件及国际
化。
org.springframework.core-3.0.5.RELEASE.jar:spring核心包
org.springframework.web-3.0.5.RELEASE.jar:web核心包,提供了web层接口
org.springframework.web.servlet-3.0.5.RELEASE.jar:web 层的一个具体实现包,DispatcherServlet也位于此包中。
后文全部在spring3.0 版本中进行,为了方便,建议在搭建环境中导入spring3.0 的所有jar 包(所
有jar 包位于dist 目录下)。
2.编写HelloWorld实例
步骤一、建立名为springMVC_01_helloword,并导入上面列出的jar 包。
步骤二、编写web.xml配置文件,代码如下:
1.
2. 3. xmlns:xsi="https://www.sodocs.net/doc/3b4448444.html,/2001/XMLSchema-instance" 4. xsi:schemaLocation="https://www.sodocs.net/doc/3b4448444.html,/xml/ns/javaee 5. https://www.sodocs.net/doc/3b4448444.html,/xml/ns/javaee/web-app_2_5.xsd"> 6. 7. 8. rServlet 9. 10. 11. 12. 13. 14. 15.
16.
17.
复制代码
步骤三、建立spring-servlet.xml文件,它的命名规则:servlet-name-servlet.xml。它的主
要代码如下:
1.
2.
3. 4. xmlns:xsi="https://www.sodocs.net/doc/3b4448444.html,/2001/XMLSchema-instance" xmlns:p="https://www.sodocs.net/doc/3b4448444.html,/schema/p" 5. xmlns:mvc="https://www.sodocs.net/doc/3b4448444.html,/schema/mvc" xmlns:context="https://www.sodocs.net/doc/3b4448444.html,/schema/context" 6. xmlns:util="https://www.sodocs.net/doc/3b4448444.html,/schema/util" 7. xsi:schemaLocation="https://www.sodocs.net/doc/3b4448444.html,/schema/beans https://www.sodocs.net/doc/3b4448444.html,/schema/beans/spring-beans-3.0.xsd 8. https://www.sodocs.net/doc/3b4448444.html,/schema/context https://www.sodocs.net/doc/3b4448444.html,/schema/context/spring-context-3.0.xsd 9. https://www.sodocs.net/doc/3b4448444.html,/schema/mvc https://www.sodocs.net/doc/3b4448444.html,/schema/mvc/spring-mvc-3.0.xsd 10. https://www.sodocs.net/doc/3b4448444.html,/schema/util https://www.sodocs.net/doc/3b4448444.html,/schema/util/spring-util-3.0.xsd"> 11. 12. 13. class="org.springframework.web.servlet.handler.SimpleUrl HandlerMapping"> 14. 15. 16. key="/hello.do">helloControl 17. 18. 19. 20. 21.
22.
复制代码
步骤四、完成HelloWord.java的编写,代码如下:
1.package controller;
2.
3.import javax.servlet.http.HttpServletRequest;
4.import javax.servlet.http.HttpServletResponse;
5.
6.import org.springframework.web.servlet.ModelAndView;
7.import org.springframework.web.servlet.mvc.Controller;
8.
9.public class HelloWord implements Controller {
10. public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response)
11. throws Exception {
12. ModelAndView mav = new ModelAndView("hello.jsp");
13. mav.addObject("message", "Hello World!");
14. return mav;
15. }
16. }
17./*
18.* 说明:ModelAndView对象是包含视图和业务数据的混合对象,即是说通过此对象,我们
可以知道所
19.返回的相应页面(比如这里返回hello.jsp页面),也可以在相应的页面中获取此对象所
包含的业务数据
20.(比如这里message-hello worrld)。*/
21.
复制代码
步骤五、在当前项目web根目录下编写hello.jsp,主要代码如下:
1.<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2.<%
3.String path = request.getContextPath();
4.String basePath =
request.getScheme()+"://"+request.getServerName()+":"+request.getServer
Port()+path+"/";
5.%>
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
22.
23.
24.
25.
26.获取值:${message}
27.
28.
29.
复制代码
步骤六:输入.../hello.do 进行测试。
如http://localhost/springmvc/hello.do
运行的结果是:获取值:Hello World!
4.简析spring mvc工作原理
(1)启动服务器,根据web.xml的配置加载前端控制器(也称总控制器)DispatcherServlet。在加载
时、会完成一系列的初始化动作。
(2)根据servlet的映射请求(上面的helloWorld实例中针对.do 请求),并参照“控制器
件”(即spring-servlet.xml这样的配置)文件,把具体的请求分发给特定的后端控制器进行处理(比
如上例会分发给HelloWorld控制器进行处理)
(3)后端控制器调用相应的逻辑层代码,完成处理并返回视图对象(ModelAndView)给前端处理器。
(4)前端控制器根据后端控制器返回的ModelAndView对象,并结合一些配置(后面有说明),返回一
个相应的页面给客户端。
小结:这种Front Controller模式常应用在主流的web框架中,比如典型的struts1.x框架.Front
Controller模式:所有请求先交给一个前端处理器(总控处理器)处理,然后前端处理器会参照一些配
置文件再把具体的请求交给相应的后端处理器。后端处理器调用逻辑层代码,并根据逻辑返回相应的视
图对象给前端控制器。然后前端控制器再根据视图对象返回具体的页面给客户端(提示:和spring mvc
一样,在struts1.x中前端控制器是Servlet,而在struts2中前端控制器是Filter)。概述Front Controller模式:前端控制器预处理并分发请求给后端控制器,后端控制器进行真正的逻辑处理并返回
视图对象,前端控器器根据视图对象返回具体页面给客户端。
5.初识spring mvc的视图
在前面的HelloWorld实例中,在HelloWorld.java中返回ModelAndView mav
=newModelAndView(
"hello.jsp") 参数为hello.jsp,它会对应于当前项目根目录下的hello.jsp页面。但spring mvc 为我们提供了
一个特别的视图定位方式,下面改进前面的HelloWord实例:
改进一:在spring-servlet.xml中增加如下代码:
1. class="org.springframework.web.servlet.view.InternalResourceViewResolve r"> 2. 3. 4.
复制代码
改进二:在HelloWorld.java重新定义返回的ModelAndView对象,即把ModelAndView mav =new
ModelAndView("hello.jsp") 改为ModelAndView mav =newModelAndView("hello")
改进三:在/WEB-INF/page目录下建立hello.jsp页面
进行上面三个改进操作后,重新访问hello.do会访问到WEB-INF/page/hello.jsp页面。
简析视图定位:当返回ModelAndView对象名称为hello时,会给hello加上前后缀变成
/WEB-INF/page/hello.jsp。因此在给前后缀赋值时,应特别注意它和返回的ModelAndView
组成一个正确的文件全路径。在前面的“简析spring mvc工作原理(4)”点中提到在根
据ModelAndView对象返回页面时,会结合一些配置。这里就是结合了视图定位方式,给viewName
加上前后缀进行定位
spring mvc学习教程(二)-后端控制器(上)
1.概述SpringMVC后端控制器
为了方便开发人员快捷地建立适合特定应用的后端控制器,springMVC实现Controller接口,自定义了许多特定控制器。这些控制器的层次关系如下:
-AbstractController
-AbstractUrlViewController
-UrlFilenameViewController
-BaseCommandController
-AbstractCommandController
-AbstractFormController
-AbstractWizardFormController
-SimpleFormController
-CancellableFormController
-MultiActionController
-ParameterizableViewController
-ServletForwardingController
-ServletWrappingController
下面重点分析两个特色控制器:
2.SimpleFormController控制器
在正式开发前,请先熟悉上前面的HelloWord实例。在保证熟悉前一个实例后,我们建立
名为springMVC_02_controllerweb项目,并导入相关的jar包。
步骤一:建立后端控制器RegControl.java代码如下:
1.package controller;
2.
3.import javax.servlet.http.HttpServletRequest;
4.import javax.servlet.http.HttpServletResponse;
5.
6.import org.springframework.validation.BindException;
7.import org.springframework.web.servlet.ModelAndView;
8.import org.springframework.web.servlet.mvc.SimpleFormController;
9.
10.public class RegControl extends SimpleFormController{
11. @SuppressWarnings("deprecation")
12. public RegControl() {
13. setCommandClass(User.class);
14. }
15.
16. protected ModelAndView processFormSubmission(HttpServletRequest arg0,
HttpServletResponse arg1,
17. Object formbean, BindException arg3) throws Exception {
18. User user = (User) formbean;
19. ModelAndView mav = new ModelAndView("hello");
20. mav.addObject("message", "Hello World!");
21. mav.addObject("user", user);
22. return mav;
23. }
24.
25. protected ModelAndView showForm(HttpServletRequest arg0,
HttpServletResponse arg1, BindException arg2)
26. throws Exception {
27. return null;
28. }
29.}
复制代码
User.java,代码如下:
1.package controller;
2.
3.public class User {
4. private String username;
5. private int age;
6. public String getUsername() {
7. return username;
8. }
9. public void setUsername(String username) {
10. https://www.sodocs.net/doc/3b4448444.html,ername = username;
11. }
12. public int getAge() {
13. return age;
14. }
15. public void setAge(int age) {
16. this.age = age;
17. }
18.
19.}
复制代码
简要说明:如果熟悉struts1.x相信很容易理解Object formbean参数,其实它就是和表单属性打交道的一个对象,也即是说表单参数会依据一定的规则填充给formbean对象。在struts1.x中,如果像把这种与formbean转换成User对象,必须要求User继承自ActionForm 类,这样才能把一个表单参数转换成一个具体的formbean对象(所谓具体实质是指参数formbean对象已经能成功地赋值给User对象)并与相应的Action绑定。但springmvc并不要求这种User一定要继承某个类,既然springmvc对这种User没有要求,那表单参数是怎样与User进行完美匹配的,注意在RegControl构造方法中有如下一句代码:setCommandClass(User.class); 这句代码就指明了此控制器绑定User类来和表单进行匹配。如果想验证此句代码的作用,可以注释掉这句代码并查看异常。后面将会分析这种控制器的一个执行过程(包括表单填充及验证过程)
概述此步要点:(1)继承SimpleFormController类(2)构造器中调用setCommandClass 方法绑定定命令对象(这里为User类)(3)转换formbean为User类进行业务逻辑操作步骤二:配置web.xml(和前面HelloWorld实例一样,在此省略)
步骤三:配置spring-servlet.xml文件,代码如下:
1.
2.
3. 4. xmlns:xsi="https://www.sodocs.net/doc/3b4448444.html,/2001/XMLSchema-instance" xmlns:p="https://www.sodocs.net/doc/3b4448444.html,/schema/p" 5. xmlns:mvc="https://www.sodocs.net/doc/3b4448444.html,/schema/mvc" xmlns:context="https://www.sodocs.net/doc/3b4448444.html,/schema/context" 6. xmlns:util="https://www.sodocs.net/doc/3b4448444.html,/schema/util" 7. xsi:schemaLocation="https://www.sodocs.net/doc/3b4448444.html,/schema/beans https://www.sodocs.net/doc/3b4448444.html,/schema/beans/spring-beans-3.0.xsd 8. https://www.sodocs.net/doc/3b4448444.html,/schema/context https://www.sodocs.net/doc/3b4448444.html,/schema/context/spring-context-3.0.xsd 9. https://www.sodocs.net/doc/3b4448444.html,/schema/mvc https://www.sodocs.net/doc/3b4448444.html,/schema/mvc/spring-mvc-3.0.xsd 10. https://www.sodocs.net/doc/3b4448444.html,/schema/util https://www.sodocs.net/doc/3b4448444.html,/schema/util/spring-util-3.0.xsd"> 11. 12. 13. 14. id="viewResolver" class="org.springframework.web.servlet.view.Internal ResourceViewResolver"> 15. 16. 17. 18. 19. id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.h andler.SimpleUrlHandlerMapping"> 20. 21. 22. 23. 24. 25. 26. 27. 28.
29.
复制代码
步骤四:根据配置文件完善相应页面
在index.jsp设定表单填写页面,主要代码如下:
1.<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2.<%
3.String path = request.getContextPath();
4.String basePath =
request.getScheme()+"://"+request.getServerName()+":"+request.getServer Port()+path+"/";
5.%>
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
21.
22.
23.
24.
29.
30.
31.
复制代码
/page/hello.jsp,主要代码如下:
1.<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2.<%
3.String path = request.getContextPath();
4.String basePath =
request.getScheme()+"://"+request.getServerName()+":"+request.getServer
Port()+path+"/";
5.%>
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
22.
23.
24.
25.
26.世界,你好!(WEB-INF/page)
27.用户名:${https://www.sodocs.net/doc/3b4448444.html,ername }
28.年龄:${user.age }
29.
30.
31.
复制代码
步骤五:启动服务器,访问到首页,填写表单完成测试。
spring mvc学习教程(三)-后端控制器(下)
3.细研SimpleController控制器
在RegControl.java中增加如下代码:
1.protected Object formBackingObject(HttpServletRequest request) throws
Exception {
2. System.out.println("formBackingObject方法执行-->01");
3. setCommandClass(User.class); //也可在此处调用
setCommandClass方法
4. return super.formBackingObject(request);
5. }
6.
7. protected void initBinder(HttpServletRequest request,
ServletRequestDataBinder binder) throws Exception {
8. System.out.println("initBinder方法执行-->02");
9. super.initBinder(request, binder);
10. }
11.
12. protected void onBind(HttpServletRequest request, Object command)
throws Exception {
13. System.out.println("onBind方法执行-->03");
14. super.onBind(request, command);
15. }
16.
17. protected void onBindAndValidate(HttpServletRequest request,
Object command, BindException errors)
18. throws Exception {
19. System.out.println("onBindAndValidate方法执行-->04");
20. super.onBindAndValidate(request, command, errors);
21. }
22.
复制代码
下面简要分析执行过程:
(1).当前端控制器把请求转交给此此控制器后,会首先调用formBackingObject方法,此方法的作用就是根据绑定的Command Class来创建一个Command对象,因此除了可以在构造方法中调用setCommandClass方法,也可以在此处调用setCommandClass方法。其实创建这个Command对象很简单,spring通过如下代码完成:
BeanUtils.instantiateClass(https://www.sodocs.net/doc/3b4448444.html,mandClass);
由于在此处必须根据commandClass来完成Command对象的创建,因此在此方法调用前应保证commandClass设置完成,所以我们可以在formBackingObject方法和构造方法中完成commandClass的设置。
(2).调用initBinder方法,初始化Command对象,即把表单参数与Command字段按名称进行匹配赋值。
(3).调用onBind方法,把Command对象和后端控制器绑定。
(4).调用onBindAndValidate方法,验证用户输入的数据是否合法。如果验证失败,我们可以通过修改errors参数,即新的errors对象将会绑定到ModelAndView上并重新回到表单填写页面。
(5).执行processFormSubmission方法,主要操作就是把绑定的Command对象转换成一个User这样的表单对象,并调用业务逻辑方法操作User对象,根据不同的逻辑返回不同的ModelAndView对象。
4.MultiActionController控制器
此控制器来将多个请求处理方法合并在一个控制器里,这样可以把相关功能组合在一起(它和struts1.x中的DispatchAction极为相似)。下面通过实例演示此控制器的使用。
步骤一:在springMVC_02_controllerweb项目下,建立后端控制器UserManagerController.java,代码如下:
1.package com.asm;
2.//...省略导入的相关类
3.public class UserManagerController extends MultiActionController {
4. public ModelAndView list(HttpServletRequest request,
HttpServletResponse response) {
5. ModelAndView mav = new ModelAndView("list");
6. return mav;
7. }
8.
9. public ModelAndView add(HttpServletRequest request,
HttpServletResponse response) {
10. ModelAndView mav = new ModelAndView("add");
11. return mav;
12. }
13.
14. public ModelAndView edit(HttpServletRequest request,
HttpServletResponse response) {
15. ModelAndView mav = new
ModelAndView("edit");
16. return mav;
17. }
18.
19.}
20.
复制代码
步骤二:配置web.xml(参前面实例),并在spring-servlet.xml中增加如下配置:
1. id="springMethodNameResolver" class="org.springframework. web.servlet.mvc.multiaction.PropertiesMethodNameResolver"> 2. 3. 4. 5. 6. 7. 8. 9.
10.
11. id="userManagerController" class="https://www.sodocs.net/doc/3b4448444.html,erManagerController"> 12. 13. ref="springMethodNameResolver"> 14. 15.
16.
复制代码
说明:methodNameResolver负责从请求中解析出需要调用的方法名称。Spring本身已经提供了一系列MethodNameResolver的实现,当然也可以编写自己的实现。在这里我们使用了Pro方式来解析,具体表现如下:
然后通过把springMethodNameResolver解析器注入给UserManagerController的methodNameResolver,这样配置后才完成了一个真正的具有请求转发能力的MultiActionController控制器对象——UserManagerController 强调:此步骤实质完成了一个工作:就是为UserManagerController控制器配置一个方法解析器。
步骤三:配置请求转发的访问路径,在spring-servlet.xml中添加如下代码
1. id="simpleUrlHandlerMapping" class="org.springframework.w eb.servlet.handler.SimpleUrlHandlerMapping"> 2. 3. 4. key="/list.do">userManagerController 5. key="/add.do">userManagerController 6. key="/edit.do">userManagerController 7. 8. 9.
10.
复制代码
步骤四:根据配置文件,完善jsp页面编写。
page/list.jsp,代码如下:
用户列表页面
page/add.jsp,代码如下:
用户添加页面
page/edi.jsp,代码如下:
用户修改页面
步骤五:启动服务器,访问…/list.do将调用到list方法并转向到list.jsp页面。
补充:细说MethodNameResolver解析器
InternalPathMethodNameResolver:默认MethodNameResolver解析器,从请求路径中获取文件名作为方法名。比如,…/list.do的请求会调用
list(HttpServletRequest,HttpServletResponse)方法。ParameterMethodNameResolver:解析请求参数,并将它作为方法名。比如,对
应…/userManager.do?method=add的请求,会调用add(HttpServletRequest, HttpServletResponse)方法。使用paramName属性定义要使用的请求参数名称。PropertiesMethodNameResolver :使用用户自定义的属性(Properties)对象,将请求的URL映射到方法名,具体可以参见实例。
使用ParameterMethodNameResolver作为MethodNameResolver的解析器时,主要配置代码如下:
1. id="simpleUrlHandlerMapping" class="org.springframework.w eb.servlet.handler.SimpleUrlHandlerMapping"> 2. 3. 4. key="/user.do">userManagerController 5. 6. 7.
8.
9. id="ParameterMethodNameResolver" class="org.springframewo rk.web.servlet.mvc.multiaction.ParameterMethodNameResolver"> 10. 11.
12.
13. 14. class="https://www.sodocs.net/doc/3b4448444.html,erManagerController"> 15. 16. ref="ParameterMethodNameResolver"> 17. 18.
19.
复制代码
访问路径为…/user.do?crud=list(add|edit)
spring mvc学习教程(四)-映射处理器(上)
Message:${message}
步骤五:启动服务器,输入…/message.do访问测试。
简析执行过程
(1)启动服务器后,当我们向服务器发送message.do请求时,首先被在web.xml 中配置的前端控制器DispatcherServlet拦截到。
(2)前端控制器把此请求转交给后端控制器,下面分析转交过程:当在
spmvc-servlet.xml中查找能执行message.do请求的映射处理器时,发现没有能处理此请求的映射处理器,这时便使用默认的映射处理器BeanNameUrlHandlerMapping:This is the default implementation used by
the DispatcherServlet, along
with DefaultAnnotationHandlerMapping (on Java 5 and higher).我们还需注意:这种后端控制器的bean Name必须以“/”开头,并且要结合DispatcherServlet的映射配置。同时beanName支持通配符配置。比如如果配置:
(3)BeanNameUrlHandlerMapping处理器,会查找在spring容器中是否在
名为“message.do”的bean实例。当查找到此实例后,则把此bean作为处理此请求的后端控制器。同时把自身加到映射处理器链上,并向处理器链传递此请求。(4)后端控制器进行处理,并返回视图
spring mvc学习教程(五)-映射处理器(下)