S pring MVC 3.0 深入


核心原理


1.  用户发送请求给服务器。 url : user.do


2.  服务器收到请求。发现 DispatchServlet 可以处理。于是调用 DispatchServlet 。


3.  DispatchServlet 内部,通过 HandleMapping 检查这个 url 有没有对应的 Controller 。如果有,则调用 Controller 。


4.  Controller 开始执行。


5.  Controller 执行完毕后,如果返回字符串,则 ViewResolver 将字符串转化成相应的视图对象;如果返回 ModelAndView 对象,该对象本身就包含了视图对象信息。


6.  DispatchServlet 将执视图对象中的数据,输出给服务器。


7.  服务器将数据输出给客户端。


spring是一个轻型容器(light-weight Container),其核心是Bean工厂(Bean Factory),用以构造我们所需要的M(Model)。在此基础之上,Spring提供了AOP(Aspect-Oriented Programming, 面向层面的编程)的实现,用它来提供非管理环境下申明方式的事务、安全等服务;对Bean工厂的扩展ApplicationContext更加方便我们实现J2EE的应用;DAO/ORM的实现方便我们进行数据库的开发;Web MVC和Spring Web提供了Java Web应用的框架或与其他流行的Web框架进行集成。

1)开源框架
2)IoC(控制反转),将类的创建和依赖关系写在配置文件里,由配置文件注入,实现了松耦合
3)AOP 将安全,事务等于程序逻辑相对独立的功能抽取出来,利用spring的配置文件将这些功能插进去,实现了按照方面编程,提高了复用性

spring3.0中相关jar包的含义

org.springframework.aop-3.0.3.RELEASE.jar

spring的aop面向切面编程

org.springframework.asm-3.0.3.RELEASE.jar

spring独立的asm字节码生成程序

org.springframework.beans-3.0.3.RELEASE.jar

IOC的基础实现

org.springframework.context-3.0.3.RELEASE.jar

IOC基础上的扩展服务

org.springframework.core-3.0.3.RELEASE.jar

spring的核心包

org.springframework.expression-3.0.3.RELEASE.jar

spring的表达式语言

org.springframework.web-3.0.3.RELEASE.jar

web工具包

org.springframework.web.servlet-3.0.3.RELEASE.jar

mvc工具包


@Controller控制器定义

和Struts1一样,Spring的Controller是Singleton的。这就意味着会被多个请求线程共享。因此,我们将控制器设计成无状态类。

在spring 3.0中,通过@controller标注即可将class定义为一个controller类。为使spring能找到定义为controller的bean,需要在spring-context配置文件中增加如下定义:

<context:component-scan base-package="com.sxt.web"/>

注:实际上,使用@component,也可以起到@Controller同样的作用。

@RequestMapping

在类前面定义,则将url和类绑定。

在方法前面定义,则将url和类的方法绑定,如下所示:


package com.sxt.web;
 
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.sxt.service.UserService;
 
@Controller
@RequestMapping("/user.do")
public class UserController  {
 
@Resource
private UserService userService;
//http://localhost:8080/springmvc02/user.do?method=reg&uname=zzzz
@RequestMapping(params="method=reg")
public String reg(String uname) {
System.out.println("HelloController.handleRequest()");
userService.add(uname);
return "index";
}
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
 
}




@RequestParam  

一般用于将指定的请求参数付给方法中形参。示例代码如下:


@RequestMapping(params="method=reg5")
public String reg5(@RequestParam("name")String uname,ModelMap map) {
System.out.println("HelloController.handleRequest()");
System.out.println(uname);
return "index";
}




这样,就会将name参数的值付给uname。当然,如果请求参数名称和形参名称保持一致,则不需要这种写法。

@SessionAttributes

将ModelMap中指定的属性放到session中。示例代码如下:


@Controller
@RequestMapping("/user.do")
@SessionAttributes({"u","a"})   //将ModelMap中属性名字为u、a的再放入session中。这样,request和session中都有了。
public class UserController  {
@RequestMapping(params="method=reg4")
public String reg4(ModelMap map) {   System.out.println("HelloController.handleRequest()");
map.addAttribute("u","uuuu");  //将u放入request作用域中,这样转发页面也可以取到这个数据。
return "index";
}
}




<body>

<h1>**********${requestScope.u.uname}</h1>

<h1>**********${sessionScope.u.uname}</h1>

</body>

注:名字为”user”的属性再结合使用注解@SessionAttributes可能会报错。

 

@ModelAttribute

这个注解可以跟@SessionAttributes配合在一起用。可以将ModelMap中属性的值通过该注解自动赋给指定变量。

示例代码如下:

package com.sxt.web;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
@RequestMapping("/user.do")
@SessionAttributes({"u","a"})  
public class UserController  {
@RequestMapping(params="method=reg4")
public String reg4(ModelMap map) {
System.out.println("HelloController.handleRequest()");
map.addAttribute("u","派大星");
return "index";
}
@RequestMapping(params="method=reg5")
public String reg5(@ModelAttribute("u")String uname,ModelMap map) {
System.out.println("HelloController.handleRequest()");
System.out.println(uname);
return "index";
}
}



先调用

reg4 方法,再调用 reg5 方法。我们发现控制台打印出来: 派大星


Controller类中方法参数的处理

Controller类中方法返回值的处理

1. 返回string(建议)

a) 根据返回值找对应的显示页面。路径规则为:prefix前缀+返回值+suffix后缀组成

b) 代码如下:

@RequestMapping(params="method=reg4")
public String reg4(ModelMap map) {
System.out.println("HelloController.handleRequest()");
return "index";
}

前缀为:/WEB-INF/jsp/    后缀是:.jsp

在转发到:/WEB-INF/jsp/index.jsp

 

2. 也可以返回ModelMap、ModelAndView、map、List、Set、Object、无返回值。一般建议返回字符串!

请求转发和重定向

代码示例:


package com.sxt.web;
 
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
 
@Controller
@RequestMapping("/user.do")
public class UserController  {
@RequestMapping(params="method=reg4")
public String reg4(ModelMap map) {
System.out.println("HelloController.handleRequest()");
//return "forward:index.jsp";
//return "forward:user.do?method=reg5"; //转发
//return "redirect:user.do?method=reg5";  //重定向
return "redirect:http://www.baidu.com";  //重定向
}
@RequestMapping(params="method=reg5")
public String reg5(String uname,ModelMap map) {
System.out.println("HelloController.handleRequest()");
System.out.println(uname);
return "index";
}
}

访问reg4方法,既可以看到效果。

获得reuest对象、session对象

普通的Controller类,示例代码如下:

@Controller
@RequestMapping("/user.do")
public class UserController  {
@RequestMapping(params="method=reg2")
public String reg2(String uname,HttpServletRequest req,ModelMap map){
req.setAttribute("a", "aa");
req.getSession().setAttribute("b","bb");
return "index";
}
}

ModelMap

是map的实现,可以在其中存放属性,作用域同request。下面这个示例,我们可以在modelMap中放入数据,然后在forward的页面上显示这些数据。通过el表达式、JSTL、java代码均可。代码如下:


package com.sxt.web;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
 
@Controller
@RequestMapping("/user.do")
public class UserControllerextends MultiActionController  {
@RequestMapping(params="method=reg")
public String reg(String uname,ModelMap map){
map.put("a", "aaa");
return "index";
}
}



JSP页面



<%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head></head>
  <body>
   <h1>${requestScope.a}</h1>
   <c:out value="${requestScope.a}"></c:out>
  </body>
</html>



ModelAndView模型视图类

见名知意,从名字上我们可以知道ModelAndView中的Model代表模型,View代表视图。即,这个类把要显示的数据存储到了Model属性中,要跳转的视图信息存储到了view属性