最全最经典spring-mvc教程


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 配置文件,代码如下: spring org.springframework.web.servlet.Dispat cherServlet 1 spring *.do 步骤三、建立 spring-servlet.xml 文件,它的命名规则:servlet-name-servlet.xml。 它的主要代码如下: 1. 2. 3. 11. 12. 14. 15. 16. 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()+":"+requ est.getServerPort()+path+"/"; 5. %> 6. 7. 8. 9. 10. 11. 12. My JSP 'hello.jsp' starting page 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. 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. this.username = 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. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. regControl 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()+":"+requ est.getServerPort()+path+"/"; 5. %> 6. 7. 8. 9. 10. 11. 12. My JSP 'index.jsp' starting page 13. 14. 15. 16. 17. 18. 21. 22. 23. 24.
25. 用户名:
26. 年龄:
27. 28.
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()+":"+requ est.getServerPort()+path+"/"; 5. %> 6. 7. 8. 9. 10. 11. 12. My JSP 'hello.jsp' starting page 13. 14. 15. 16. 17. 18. 19. 22. 23. 24. 25. 26. 世界,你好!(WEB-INF/page) 27. 用户名:${user.username } 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(this.commandClass); 由于在此处必须根据 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. 2. 3. 4. list 5. add 6. edit 7. 8. 9. 10. 11. 12. 14. 15. 16. 复制代码 说明:methodNameResolver 负责从请求中解析出需要调用的方法名称。Spring 本身已经提供了一系列 MethodNameResolver 的实现,当然也可以编写自己的 实现。在这里我们使用了 Pro 方式来解析,具体表现如下: list 请求 list.do 时调用 list 方法 add 请求为 add.do 时调用 add 方法 edit 请求为 edit.do 时调用 edit 方法 然后通过把 springMethodNameResolver 解析器注入给 UserManagerController 的 methodNameResolver,这样配置后才完成了一个真正的具有请求转发能力 的 MultiActionController 控制器对象——UserManagerController 强调:此步骤 实质完成了一个工作:就是为 UserManagerController 控制器配置一个方法解析 器。 步骤三:配置请求转发的访问路径,在 spring-servlet.xml 中添加如下代码 1. 2. 3. 4. userManagerController 5. userManagerController 6. 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. 2. 3. 4. userManagerController 5. 6. 7. 8. 9. 10. 11. 12. 13. 15. 17. 18. 19. 复制代码 访问路径为…/user.do?crud=list(add|edit) spring mvc 学习教程(四)-映射处理器(上) 三、映射处理器 Handler Mapping 1.简析映射处理器 在 spring mvc 中,使用映射处理器可以把 web 请求映射到正确的处理器上, spring 内置了很多映射处理器,而且我们也可以自定义映射处理器。下面的实例 展示 spring 中最常用的两个映射处理器:BeanNameUrlHandlerMapping 和 SimpleUrlHandlerMapping。在正式开始前有必要了解以下相关要点: (1)映射处理器都能把请求传递到处理器执行链接(HandlerExecutionChain) 上,并且处理器执行链接必须包含能处理该请求的处理器(实质就是处理器链上 动态添加了了此处理器,可以结合 filter 工作原理理解),而且处理器链接也能 包含一系列拦截器。 (2)上面列举的 spring 最常用的两种处理器都是继承自 AbstractHandlerMapping 类,因而它们具备父类的属性。 2.实例:BeanNameUrlHandlerMapping 建立 springMVC_03_handlerMappingsweb 项目,并导入相关 jar 包。 步骤一:建立后端控制器 MessageController.java,代码如下: Java 代码 1. package com.asm; 2. //...省略导入的相关类 3. public class MessageController implements Controller { 4. public ModelAndView handleRequest(HttpServletRequest arg 0, HttpServletResponse arg1) throws Exception { 5. ModelAndView mav = new ModelAndView("message"); 6. mav.addObject("message", "您好!spring MVC"); 7. return mav; 8. } 9. } 步骤二:配置 web.xml,代码如下: Xml 代码 1. 2. 6. 7. spmvc 8. 9. org.springframework.web.servlet.DispatcherServle t 10. 11. 1 12. 13. 14. spmvc 15. *.do 16. 17. 步骤三:配置 spmvc-servlet.xml,代码如下: Xml 代码 1. 2. 9. 10. 11. 12. 13. 14. 步骤四:在 WEB-INF/page 目录下建立 message.jsp,主 要 代码如下: Message:${message} 步骤五:启动服务器,输入…/message.do 访问测试。 简析执行过程 (1)启动服务器后,当我们向服务器发送 message.do 请 求时,首先被在 web.xml 中配置的前端控制器 DispatcherServlet 拦截到。 (2)前端控制器把此请求转交给后端控制器,下面分析转 交过程:当在 spmvc-servlet.xml 中查找能执行 message.do 请求的映射处理器时,发现没有能处理此请求的映射处理器, 这时便使用默认的映射处理器 BeanNameUrlHandlerMapping:This is the default implementation used by theDispatcherServlet, along with DefaultAnnotationHandlerMapping (on Java 5 and higher). 我们还需注意:这种后端控制器的 bean Name 必须以“/”开头,并且要结合 DispatcherServlet 的映射配置。 同时 beanName 支持通配符配置。比如如果配置: 时,当访问 messasge.do 时也可以成功访问到 MessageController 类。 (3)BeanNameUrlHandlerMapping 处理器,会查找在 spring 容器中是否在名为“message.do”的 bean 实例。当查 找到此实例后,则把此 bean 作为处理此请求的后端控制器。 同时把自身加到映射处理器链上,并向处理器链传递此请求。 (4)后端控制器进行处理,并返回视图 spring mvc 学习教程(五)-映射处理器(下) 3.实例:SimpleUrlHandlerMapping 步骤一:建立后端控制器 UserContrller.java.代码如下: Java 代码 1. package com.asm; 2. //...省略导入的相关类 3. public class UserController extends SimpleFormController { 4. protected ModelAndView processFormSubmission(HttpServletRe quest request, HttpServletResponse response, 5. Object command, BindException errors) throws Excep tion { 6. System.out.println("调用逻辑层,处理表单"); 7. ModelAndView mav = new ModelAndView("loginSuc"); 8. return mav; 9. } 10. } 步骤二:在 spmvc-servlet.xml 中增加如下配置: Xml 代码 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. userController 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 22. 23. 24. 说明:(1)通过前面实例我们可以知道,SimpleController 这样的后端控制器必须绑定一个 commandClass 对象,在这 里我们通过配置文件 绑定。 (2)userController配置说明只要访 问是以 op 开头,中间*可以是任意字符,并以 login.do 结尾 的请求,便能访问到 userController 控制器。 (3)SimpleUrlHandlerMapping 是一个更强大的映射处理器,它 除了支持上面的这种配置,还支持 Ant 风格的路径匹 配。另外也可以进行如下形式的配置: /op/*/login.do=userController (4)拦截器:为了为某些特殊请求提供特殊功能,spring 为映射处理器提供了拦截器支持。它的配置文件很简单:一 是把拦截器类纳入 spring 容器管理,二是在映射处理器引入 配置的拦截器 bean。 步骤三:编写拦截器 LoginTimeInterceptor.java,主要代码如下: Java 代码 1. package com.asm; 2. //...省略导入的相关类 3. public class LoginTimeInterceptor extends HandlerInterceptorAd apter { 4. private int startTime; 5. private int endTime; 6. 7. public void setStartTime(int startTime) { 8. this.startTime = startTime; 9. } 10. public void setEndTime(int endTime) { 11. this.endTime = endTime; 12. } 13. 14. public void afterCompletion(HttpServletRequest request, Ht tpServletResponse response, Object handler, 15. Exception ex) throws Exception { 16. System.out.println("执行 afterCompletion 方法-->03"); 17. super.afterCompletion(request, response, handler, e x); 18. } 19. 20. public void postHandle(HttpServletRequest request, HttpSer vletResponse response, Object handler, 21. ModelAndView modelAndView) throws Exception { 22. System.out.println("执行 postHandle 方法-->02"); 23. super.postHandle(request, response, handler, modelAndV iew); 24. } 25. 26. public boolean preHandle(HttpServletRequest request, HttpS ervletResponse response, Object handler) 27. throws Exception { 28. System.out.println("执行 preHandle 方法-->01"); 29. Calendar cal = Calendar.getInstance(); 30. int hour = cal.get(Calendar.HOUR_OF_DAY); 31. if (startTime <= hour && hour < endTime) { 32. return true; 33. } else { 34. response.sendRedirect("http://www.iteye.com"); 35. return false; 36. } 37. } 38. } 说明:此拦截器作用:如果用户没有在 6-18 点登录,则重定向到 javaeye 站点 (1)拦截器必须 HandlerInterceptorAdapter 接口(2)preHandle 方法在后端 控制器执行前被调用,postHandle 方法在后端控制器执行后被调用; afterCompletion 方法在整个请求处理完成后被调用。(3) preHandle 方法:返回 true,映射处理器执行链将继续执行;当返回 false 时,DispatcherServlet 处理 器认为拦截器已经处理完了请求,而不继续执行执行链中的其它拦截器和处理器。 它的 API 文档解释如下:true if the execution chain should proceed with the next interceptor or the handler itself. Else, DispatcherServlet assumes that this interceptor has already dealt with the response itself.(4)这三个方法都是相同 的参数,Object handler 参数可以转化成一个后端控制器对象,比如这里可以转 换成 UserController 对象。 步骤四:完成其它相关代码的编写 User.java 代码 package com.asm; public class User { private String username; private String password; //省略 getter/setter 方法 } WEB-INF/page/loginSuc.jsp,主要代码如下: 登录成功!欢迎来到后台管理页面 index.jsp 代码:
用户名:
密 码:
步骤五:访问 index.jsp 页面,完成测试。 分析执行过程:为了清晰体会到整个处理器执行过程,我们首先在 UserController.java 中增加如下代码: Java 代码 1. protected Object formBackingObject(HttpServletRequest reques t) throws Exception { 2. System.out.println("formBackingObject 方法执行-->01"); 3. return super.formBackingObject(request); 4. } 5. protected void initBinder(HttpServletRequest request, ServletR equestDataBinder binder) throws Exception { 6. System.out.println("initBinder 方法执行-->02"); 7. super.initBinder(request, binder); 8. } 9. protected void onBind(HttpServletRequest request, Object comma nd) throws Exception { 10. System.out.println("onBind 方法执行-->03"); 11. super.onBind(request, command); 12. } 13. protected void onBindAndValidate(HttpServletRequest request, O bject command, BindException errors) 14. throws Exception { 15. System.out.println("onBindAndValidate 方法执行-->04"); 16. super.onBindAndValidate(request, command, errors); 17. } (1)当访问…/login.do 时,会首先被前端控制器 DispatcherServlet 拦截到,前端控制器通过查找 spmvc-servlet.xml 配置文件,并交给后端控制器处理。 (2)执行后,得到如下打印结果,通过打印结果我们知道它的 一个大致执行过程。 执行 preHandle 方法-->01 formBackingObject 方法执行-->01 initBinder 方法执行-->02 onBind 方法执行-->03 onBindAndValidate 方法执行-->04 调用逻辑层,处理表单 Admin----123456 执行 postHandle 方法-->02 执行 afterCompletion 方法-->03 spring mvc 学习教程(六)- 视图与视图解析器(上) 四、视图与视图解析器 通常像 spring mvc 这样的 web 框架都会有相应的定位视图 技术,spring 提供了视图解析器来解析 ModelAndView 模型 数据到特定的视图上,spring 提供了 ViewResolver 和 View 两个特别重要的接口,ViewResolver 提供了从视图名称到实 际视图的映射,View 处理请求的准备的工作,并将该请求提 交给某种具体的视图解析器 1.使用 Excel 作为视图(了解) 步骤一:建立后端控制器 ExcelControl.java,主 要 代 码 如 下 : Java 代码 1. package com.asm; 2. //...省略导入的相关类 3. public class ExcelControl extends AbstractController { 4. @Override 5. protected ModelAndView handleRequestInternal(HttpServletRe quest request, HttpServletResponse response) throws Exceptio n { 6. Map map = new HashMap(); 7. List wordList = new ArrayList(); 8. 9. wordList.add("first"); 10. wordList.add("second"); 11. wordList.add("third"); 12. 13. map.put("wordList", wordList); 14. return new ModelAndView("exl", map); 15. } 16. } 步骤二:编写 web.xml(参前面实例),编写配置 spmvc-servlet.xml 文件,主 要代码如下: Xml 代码 1. 2. 3. 4. 5. 6. 7. 8. 9. excelControl 10. 11. 12. 13. 14. 简析:ResourceBundleViewResolver 视图解析器会在 classpath 中寻找 properties 属性文件,根据此 bean 配置的说明寻找的 properties 文件名为 view.properties。说明了此解析器在整个解析链接中的顺序。 步骤三:编写 view.properties 文件,主要代码如下: exl.(class)=com.asm.ExcelViewBuilder 说明:在控制器中返回的视图名称 exl——>return new ModelAndView("exl", map),所以这里要用 exl.(class)。而 exl 视图会交给 com.asm.ExcelViewBuilder 进行预处理。 步骤四:编写 AbstractExcelView.java,由于此类用到了生成 Excel 文件相关的 jar 包,所以应先下载 poi-2.5.1.jar 并导入。主要代码如下: Java 代码 1. package com.asm; 2. //...省略导入的相关类 3. public class ExcelViewBuilder extends AbstractExcelView { 4. protected void buildExcelDocument(Map model, HSSFWorkboo k wb, HttpServletRequest req, HttpServletResponse resp) thro ws Exception { 5. HSSFSheet sheet; 6. HSSFCell cell; 7. 8. sheet = wb.createSheet("Spring's Excel"); // 创建一张 表; 9. // sheet = wb.getSheetAt(0);//根据索引,得到第一张存在的 表 10. sheet.setDefaultColumnWidth((short) 10); // 设置列数为 1 0:即 A-J 11. cell = getCell(sheet, 0, 0); //第二个参数-->excel 表数字 序号;第三个参数-->excel 表字母序号,比如此处,构建 A1 单元格 12. setText(cell, "Spring-Excel test"); // 把内容写入 A1 13. List words = (List) model.get("wordList"); 14. for (int i = 0; i < words.size(); i++) { 15. cell = getCell(sheet, 2, i);// A3-B3-C3 16. setText(cell, (String) words.get(i)); 17. } 18. } 19. } 步骤五:启动服务器,输入…/getExcel.do,将访问到 excel 文件。 简析执行过程:当后端控制器接受到前端控制派发的请求 时,后端控制器会首先准备 Model,这 里 即 Map 对象,然后 返回 exl 视图。在返回视图前,会查找 spmvc-servlet.xml 配置文件,当查找名为 exl 的视图是由 ResourceBundleViewResolver 视图解析器进行解析时,这时 根据此视图解析的解析规则,会对每个待解析的视图, ResourceBundle 里(这时即 view.properties 文件)的[视图 名].class 所对应的值就是实现该视图的类。 同样,[视图 名].url 所对应的值是该视图所对应的 URL。当视图类成 功完成视图的预处理工作后,会把此视图返回给客户端。 spring mvc 学习教程(七)- 视图与视图解析器(下) Xml 代码 1. 2.使用 FreeMarker 作为视图 步骤一:建立后端控制器 FreeMarkerController.java,主要代码如下: Java 代码 1. package com.asm; 2. //...省略导入的相关类 3. @SuppressWarnings("deprecation") 4. public class FreeMarkerController extends AbstractCommandContr oller { 5. @Override 6. protected ModelAndView handleRequestInternal(HttpServletRe quest reqeust, HttpServletResponse response) 7. throws Exception { 8. ModelAndView mav = new ModelAndView("base"); 9. mav.addObject("username", "张三"); 10. mav.addObject("time", new Date().toString()); 11. return mav; 12. } 13. 14. @Override 15. protected ModelAndView handle(HttpServletRequest reques t, HttpServletResponse response, Object command, 16. BindException errors) throws Exception { 17. return null; 18. } 19. } 步骤二:在 spmvc-servlet.xml 中配置: Xml 代码 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 并在映射处理器中配置映射路径为:fmControl 步骤三:通过步骤二的配置,我们还需在 WEB-INF/freemarker 路径下编写 base.ftl(base 即后端控制器返回的视图名),主要代码如下: 欢迎来到:FreeMarker 模板页面
welcome ${username}
当前时间:${time} 步骤四:启动服务器,输入…/freemarker.do 完成测试。 3.小结视图技术 (1)ModelAndView 所表示的视图名很关键,视图解析链会依此名来选择一个 正确的视图。 (2)不同的视图解析器解析视图规则不相同,但是他们实质都是实现了 ViewResolver 接口,并会依赖于配置 View 对象来处理请求的准备工作。 (3)spring 内置了多种视图解析器,列表如下: ViewResolver 描述 AbstractCachingViewResolve r 抽象视图解析器实现了对视 图的缓存。在视图被使用之 前,通常需要进行一些准备 工作。 从它继承的视图解析 器将对要解析的视图进行缓 存。 XmlViewResolver XmlViewResolver 实现 ViewResolver,支持 XML 格 式的配置文件。 该配置文件 必须采用与 Spring XML Bean Factory 相同的 DTD。默认的 配置文件 是 /WEB-INF/views.xml。 ResourceBundleViewResolver ResourceBundleViewResolv er 实现 ViewResolver, 在 一个 ResourceBundle 中寻找 所需 bean 的定义。 这个 bundle 通常定义在一个位于 classpath 中的属性文件中。 默认的属性文件是 views.properties。 UrlBasedViewResolver UrlBasedViewResolver 实现 ViewResolver, 将视图名直 接解析成对应的 URL,不 需 要 显式的映射定义。 如果你的 视图名和视图资源的名字是 一致的,就可使用该解析器, 而无需进行映射。 InternalResourceViewResolv er 作为 UrlBasedViewResolver 的子类, 它支持 InternalResourceView(对 Servlet 和 JSP 的包装), 以 及其子类 JstlView 和 TilesView。 通过 setViewClass 方法,可以指 定用于该解析器生成视图使 用的视图类。 更多信息请参 考 UrlBasedViewResolver 的 Javadoc。 VelocityViewResolver / FreeMarkerViewResolver 作为 UrlBasedViewResolver 的子类, 它能支持 VelocityView(对 Velocity 模版的包装)和 FreeMarkerView 以及它们的 子类。 (4)Spring 支持多个视图解析器一起使用,即视图解析链。 视图解析链包含 一系列视图解析器,更方便开发人员处理某些特殊请求,比如在特定情况下重新 定义某些视图(为某个视图解析器使用 order,可以改变此视图解析器在整个视 图解析链中的解析顺序:order 值越大,它在整个视图解析链中的顺序越靠前, 即它越会被优先选作为视图解析器)。 4.视图解析链 通过前面的两个实例,在 spmvc-servlet.xml 配置文件便具备了两个视图解析器, 它们共同构成了视图解析链。下面我们将再增加一个视图解析器来解析 jsp 视图, 并编写一个后端控制器来负责调用特定的请求。 步骤一:编写后端控制器.java,主要代码如下: Java 代码 1. package com.asm; 2. //...省略导入的相关类 3. public class SelectViewController implements Controller { 4. public ModelAndView handleRequest(HttpServletRequest reque st, HttpServletResponse response) throws Exception { 5. String param = request.getParameter("op"); 6. ModelAndView mav = new ModelAndView("display"); 7. if ("fm".equals(param)) { 8. // mav = new ModelAndView(new RedirectView("freeMa rker.do")); 9. // mav =new ModelAndView("redirect:freeMarker.do "); 10. mav = new ModelAndView("forward:freeMarker.do"); 11. return mav; 12. } else if ("excel".equals(param)) { 13. mav = new ModelAndView(new RedirectView("getExcel. do")); 14. return mav; 15. } else { 16. return mav; 17. } 18. } 19. } 简析:如果请求参数 op 为 fm,则调用 freemarker.do,如果 op 为 excel,则调 用 getExcel.do,否则显示 display.jsp 视图。调用 freemarker.do 和 getExcel.do 我们可以使用重定向技术和直接使用 forward 跳转:使用 forward 跳转,forward: 视图名;使用重定向,redirect:视图名(也可以 RedirectView 对象实现)。 步骤二:在 spmvc-servlet.xml 中增加 jsp 视图解析器(它与前面定义的两个视 图解析器共同构成了视图解析链),并配置后端处理器及映射路径。 Xml 代码 1. 2. 3. 4. 5. 6. 8. 9. 10. excelControl 11. fmControl 12. svControl 13. 14. 15. 16. 说明:irViewResolver 视图解析器应放在前面两个视图解析器后面,理解视图解 析顺序,可以把 irViewResolver 视图解析器放在视图解析链的最前面试下执行 效果,当然也可以为视图解析器定义 order 值来进一步理解视图解析顺序。 步骤三:在 WEB-INF/page 目录下编写 display.jsp, 主要代码如下: 欢迎来到 display 页面,你可以选择如下操作:
Excel 页面 freeMarker页面 jsp 页面 步骤四:index.jsp 页面主要代码如下: Excel 页面 freeMarker页面 jsp 页面 步骤五:启动服务器,访问首面测试。 spring mvc 学习教程(八)- 使用注解(上) 五、使用注解 1.简单实例 建立 springMVC_05_annotation web 项目,并导入相关的 jar 包。 步骤一:编写 web.xml 文件,主要代码如下: Java 代码 1. spmvc 2. 3. org.springframework.web.servlet.DispatcherServle t 4. 5. 1 6. 7. 8. spmvc 9. *.do 10. 步骤二:编写后端控制器,主要代码如下:package com.asm; Java 代码 1. //...省略导入的相关类 2. @Controller 3. public class SimpleAnnotationControl { 4. @RequestMapping("/anno.do") 5. public ModelAndView show() { 6. ModelAndView mav = new ModelAndView("anno"); 7. mav.addObject("message", "welcome annotation demo"); 8. return mav; 9. } 10. } 步骤三:编写 springmvc-servlet.xml 配置文件,主要代码如下: Xml 代码 1. 7. 8. 9. 10. 11. 12. 13. 14. 说明:在 spring 中,通过配置一个自动扫描器,可以自动扫描到某个范围下的 所有组件,这些组件必须是标记有特定注解,比较常用的特定注解有 @Component、@Repository、 @Service 和@Controller。 比如这里就会把 SimpleAnnotationControl 类纳入 spring 容器管理。关于 spring 自动扫描管理 bean 可以参它的相关文档。 步骤四:在 WEB-INF/page 目录下编写 anno.jsp 页面,主要代码如下: 欢迎来到注解页面
${message} 步骤五:启动服务器,访问…/anno.do 完成测试。 简析注解:在本实例中,我们使用了两个注解,一是 Controller 注解,此注解 的作用是把控制器 SimpleAnnotationControl 纳入 spring 容器管理;二是 @RequestMapping 注解。下面我们重点分析此注解:在本例中,我们使 用 @RequestMapping("/anno.do")这种简写形式,实际它的完整形式应为: @RequestMapping(value = "/anno.do")。value 属性指明了它的映射路径,比如 这里的映射路径为 anno.do。此注解除了 value 属性外,还有如下属性:method、 headers、params。 @RequestMapping(value = "/anno.do", method = RequestMethod.GET) 此配置说明只有 GET 请求才能访问 anno.do。可以增加如下 POST 请求代码测 试:
发现此种 POST 请求方式是不能访问 anno.do 得 @RequestMapping(value = "/anno.do", params = { "username=admin", "password=123456" }) 此配置说明只有附带正确的请求 参数才能访问,比如在这里只能 是…/anno.do?username=admin&password=123456 才能正确访问。 spring mvc 学习教程(九)- 使用注解(下) 2.类级别的基路径请求 在上面的实例中,我们通过为方法配置请求路径来进行访问,而下面我们将为类 配置一个请求实例,这种类似于 struts2 中 package-namespace。 控制器代码如下:package com.asm; Java 代码 1. //...省略导入的相关类 2. @Controller 3. @RequestMapping("/myRoot") 4. public class AnnotationControl { 5. @RequestMapping(value = "/the/{name}.do") 6. public String getName(@PathVariable 7. String name, Model model) { 8. model.addAttribute("message", "名字:" + name); 9. return "anno"; 10. } 11. 12. @RequestMapping("/age.do") 13. public ModelAndView getAge(@RequestParam 14. int age) { 15. ModelAndView mav = new ModelAndView("anno"); 16. mav.addObject("message", "年龄:" + age); 17. return mav; 18. } 19. } (1)访问 getAge 方法 这样如果想访问到上面的两个方法都必须是以 myRoot 作为开头。下面我们先对 getAge 方法进行访问测试,在 index.jsp 页面增加如下代码:
这样提交请求时,将会访问到 getAge 方法,并且 age 会作为参数传递给此方法, 这样我们便可以得到客户端输入的 age。 @RequestParam 注解:Annotation which indicates that a method parameter should be bound to a web request parameter,意为此注解将会为方法中的参数绑定对应(对应是指名字上,比如 这里表单和方法中参数名都用了 age)的 web 请求参数。强调:访问路径必须 是以 myRoot 作为一个基路径,因为类上配置了请求基路径。@RequestParam 注解实现 web 请求到方法参数的绑定。 (2)访问 getName 方法 对于 getName 方法它的访问路径应该是这样的:…/myRoot/the/jack.do 这 样我们得到@PathVariable:Annotation which indicates that a method parameter should be bound to a URI template variable,意思是此注解将会 把一个 uri 路径中对应的变量和方法中的参数绑定,这里我们用 jack 来代替来 {name},所以实质就是把 jack 作为参数和方法中 name 参数绑定,如果想传 递其它值,只须把 jack 换下就可以了,比如:…/myRoot/the/tom.do 等。 3.自动表单 在 struts 框架中,表单参数能成功地交给 struts Action 来处理,在前面的实例中 我们使用 springmvc 也完成了类似功能,下面我们使用 spring mvc 注解方式来 完成表单参数和业务层实体的绑定。 步骤一、准备业务层实体 Bean,User.java 主要代码如下: Java 代码 1. package com.asm; 2. public class User { 3. private String username; 4. private String password; 5. //省略 getter/setter 方法。 6. } 步骤二:编写控制层代码 Java 代码 1. package com.asm; 2. //省略导入的相关类 3. @Controller 4. public class FormAnnotationControl { 5. @ModelAttribute("user") 6. public User initUser() { 7. User user = new User(); 8. user.setUsername("在此处填写用户名"); 9. return user; 10. } 11. 12. @RequestMapping("reg.do") 13. public String addUI() { 14. return "reg"; 15. } 16. 17. @RequestMapping("save.do") 18. public String add(@ModelAttribute 19. User user, Model model) { 20. model.addAttribute(user); 21. return "userInfo"; 22. } 23. 24. @RequestMapping("login.do") 25. public ModelAndView login(@ModelAttribute 26. User user) { 27. ModelAndView mav = new ModelAndView(new RedirectView(" manage.do")); 28. if (!"admin".equals(user.getUsername())) { 29. mav = new ModelAndView("error"); 30. } 31. return mav; 32. } 33. 34. @RequestMapping("manage.do") 35. public String manage() { 36. return "list"; 37. } 38. } 说明:@ModelAttribute :Annotation that binds a method parameter or method return value to a named model attribute, exposed to a web view. Supported for RequestMapping annotated handler classes,此注解 可以用于 web 请求参数和方法参数的绑定,也可用于方法的返回值作为模型数 据(这种模型数据在类中全局有效,比如这里 initUser 方法绑定的模型数据在此 类的任何方法中都能访问到这种模型数据)。 步骤三、编写相关的 jsp 页面 reg.jsp
用户名:
密 码: < br/>
userInfo.jsp 保存用户成功,信息如下:
用户名:${user.username}
密 码:${user.password} list.jsp 列出所有用户 error.jsp 用户你好,你没权力进入后台 步骤四、输入相关信息进行测试。 reg.do,对应于 addUI()方法的访问:我们输入..../reg.do,可以看到页面显示如 下内容: “在此处填写用户名”,这几个字是由于我们在 reg.jsp 中使用了${user.usernam}, 并且在 initUser 方法中我们通过 ModelAttribute 注解初始化了一个模型数据,这 样我们便可以在此类对应的任何方法映射的视图中访问到此模型数据,这也即是 前面提到这种模型数据在类中全局有效。然后填写相关数据,提交表单给 sava.do,即是提交给给 save 方法,在 save 方法中我们同样使用了 ModelAttribute 注解,此注解在 save 方法中实现了 web 请求参数和方法参数的 绑定的功能,也即是说把 web 中 username、password 和 ModelAttribute 指示 的 user 中的 username、password 进行绑定,这种绑定和 struts2 中的模型驱 动 ModerDriven 极为相似。 步骤五、访问登录页面,在 login 方法中我们对登录进行了简单的校验,如果用 户名是 admin 则允许后台进行管理操作,如果不是则提示用户没有权力进行此 操作。在前面我们对 save 方法进行了简要分析,这里的 login 方法也是类似得。 另在此方法中如果是 admin 登录我们重定向到管理页面,如果不是 admin 登录, 我们使用 forward 进行转发。访问 login.do 的 jsp 页面代码如下:
Java 学习论坛 www.boydavid.com Java 软件开发学习群 94897353
还剩43页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 3 人已下载

下载pdf

pdf贡献者

liyajunge

贡献于2016-09-05

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf