Java Web 学习(4) —— Spring MVC 概览

Spring MVC 概览

一、 Spring MVC

Spring MVC 是一个包含了 Dispatcher Servlet 的 MVC 框架。
Dispatcher Servlet 实现了 :

  1. 根据 Uri 调用相应的 action
  2. 实例化正确的控制器类
  3. 根据请求参数值来构造表单 bean
  4. 调用控制器对象的相应方法
  5. 转向一个 JSP 页面

使用 Spring MVC 的好处:

  • Spring MVC 提供了一个Dispatcher Servlet,无需额外开发。
  • Spring MVC 使用基于XML的配置文件,可以编辑,而无需重新编译应用程序。
  • Spring MVC 实例化控制器,并根据用户输入来构造bean。
  • Spring MVC 可以自动绑定用户输入,并正确地转换数据类型。
  • Spring MVC 可以校验用户输入,若校验不通过,则重定向回输入表单。
  • Spring MVC 是Spring 框架的一部分,可以利用 Spring 提供的其他能力。
  • Spring MVC 支持国际化和本地化,支持根据用户区域显示多国语言。
  • Spring MVC 支持多种视图技术。

二、 DispatcherServlet

在 Spring MVC 中,org.springframework.web.servlet.Dispatcher扮演一个调度员的角色。

  1. 在请求离开浏览器时,会带有用户所请求内容的信息,至少会包含请求的 URL,但是还可能带有其他的信息,例如用户提交的表单信息。请求首先通过 DispatcherServlet。DispatcherServlet 作为前端控制器(front controller)处理所有请求,将请求发送给控制器。
  2. DispatcherServlet 需要确定将请求发送给哪个控制器,因此它会查询一个或多个处理器映射(handler mapping)。处理器映射会根据请求携带的URL信息进行决策。
  3. DispatcherServlet 将请求发送给目标控制器,卸下用户提交的信息,等待控制器(中的服务对象)处理业务逻辑。控制器完成逻辑处理后,通常会产生一些信息,需要返回给用户并在浏览器上显示。这些信息被称为模型(model)。信息需要发送给一个视图(view),比如 JSP。
  4. 控制器所做的最后一件事就是将模型数据打包,并且标示出用于渲染输出的视图名。它会将请求连同模型和视图名发送回 DispatcherServlet。
  5. 这样,控制器就不会与特定的视图相耦合,它仅仅传递了一个逻辑名称。DispatcherServlet 将会使用视图解析器(View Resolver)来将逻辑视图名匹配为一个特定的视图实现。
  6. DispatcherServlet 将模型数据交付给视图。视图将使用模型数据渲染输出,这个输出会通过响应对象传递给客户端。

要使用这个 Servlet,需要在部署描述符(web.xml)中配置。

<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>
    org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <!-- Spring MVC 配置文件位置 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/config/springmvc.xml</param-value>
    </init-param>
    <1oad-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

注意:Dispatcher Servlet 默认配置文件为 WEB-INF 路径下的 servletName-servlet.xml。可以通过contextConfigLocation可以修改配置文件路径。

三、 Controller

组件扫描

在 Spring MVC 配置文件中配置<componet-scan>元素,Spring 会扫描基本包,找到组件。

<context:component-scan base-package="basePackage"/>

请求处理

@Controller     // 声明为一个控制器
public class ProductController {
    // 处理对"/input-product"的 get 和 post 请求 
    @RequestMapping(value = "/input-product", method = {RequestMethod.POST, RequestMethod.GET})       
    public String inputProduct () {
        return "ProductForm";   // 返回名为 "ProductForm" 的视图
    }
}
@Controller
@RequestMapping("/product")
public class ProductController {
    // http://domain/context/product/input 将会映射为该方法
    @RequestMapping(value = "/input", method = RequestMethod.GET)       
    public String inputProduct () {
        return "ProductForm";
    }
}

在请求处理方法中可以出现的参数类型:

  • javax.servlet.ServletRequest 或 javax.servlet.http.HttpServletRequest
  • javax.servlet.ServletResponse 或 javax.servlet.http.HtpServletResponse
  • javax.servlet.http.HttpSession
  • org.springframework.web.context.request.WebRequest
  • org.springframework.web.context.request.NativeWebRequest
  • java.util.Locale
  • java.io.InputStream 或 java.io.Reader
  • java.io.OutputStream 或 java.io.Writer。
  • java.security.Principal
  • HttpEntity<?>paramters
  • java.util.Map 或 org.springframework.ui.Model
  • org.springframework.ui.ModelMap
  • org.springframework.web.servlet.mvc.support.RedirectAttributes
  • org.springframework.validation.Errors
  • org.springframework.validation.BindingResult
  • 命令或表单对象。
  • org.springframework.web.bind.support.SessionStatus
  • org.springframework.web.util.UriComponentsBuilder
  • @PathVariable @MatrixVariable @RequestParam @RequestHeader @RequestBody @RequestPart 注释的对象

在请求处理方法中可以返回的对象类型:

  • ModelAndView
  • Model
  • 包含模型的属性的 Map
  • View
  • 代表逻辑视图名的 String
  • void
  • 提供对Servlet的访问,以响应HTTP头部和内容 HttpEntity 或 ResponseEntity 对象
  • Callable
  • DeferredResult
  • 其他任意类型,Spring 将其视作输出给 View 的对象模型

请求参数和路径变量

请求参数和路径变量都可用于发送值给服务器。二者都是 URL 的一部分。

请求参数采用key=value的形式,用&分隔。在 Spring MVC 中用@RequestParam获取。

http://localhost:8080/test/view-product?productId=3
public void sendProduct (@RequestParam int productId) {}

路径变量类似请求参数,但没有key部分。在 Spring MVC 中用@PathVariable获取。

http://localhost:8080/test/view-product/3
@RequestMapping(value="/view-product/{id}")
public String viewProduct(@PathVariable Long id, Model model) {}

传递模型

Spring MVC 在每次调用请求处理方法时,都会创建 Model 类型的一个实例。
Model 实际上就是一个 Map,它会作为请求(request)属性传递给视图,这样数据就可以渲染到客户端了。

@RequestMapping(value="/input-product")
public String inputProduct(Model model){
    model.addAttribute("book", new Book()); 
    return "BookAddForm";
}

addAttribute方法不指定 key 时,key 会根据 value 的类型推断。
当请求处理方法返回值是其他类型时,返回值会被放到模型中,逻辑视图名称会根据请求路径推断。

@RequestMapping(value="/input")   // 逻辑视图名为 input
public String inputProduct(Model model){
    return new Book();
}

Spring MVC 会在调用请求处理方法之前调用带 @ModelAtribute 注解的方法。带@ModelAttribute 注解的方法可以返回一个对象或一个 void 类型。
如果返回一个对象,则返回对象会自动添加到 Model 中。
如果方法返回void,则必须添加一个 Model 类型的参数,并自行将实例添加到Model中。

@ModelAttribute 
public Product addProduct(GRequestParam String productId){
    return productService. get(productId);
}
@ModelAttribute 
public void populateModel(@RequestParam String id, Model model) { 
    model.addAttribute(new Account(id));
}

用在方法参数上的@ModelAttribute注解指示了参数应该从模型(Model)中获取。
如果模型中不存在,参数会首先被实例化,然后添加到模型中。
如果模型中存在,这个参数的字段会被所有的名字匹配的请求参数所填充,即数据绑定。

四、 ViewResolver

ViewResolver 是视图解析器。ViewResolver 通过解析 ModelAndView,将 ModelAndView 转换成一个真正的 View 对象,并取出 Model。View 再对 Model 进行渲染,将渲染后的视图展示给用户。

Spring MVC 提供了13个视图解析器,如 BeanNameViewResolver,ResourceBundleViewResolver,UrlBasedViewResolver等。
InternalResourceViewResolver 是最常用的之一。

InternalResourceViewResolver 继承 UrlBasedViewResolver 继承 AbstractCachingViewResolver,实现了 ViewResolver 接口。
InternalResourceViewResolver 一般用于将视图名解析为 JSP 文件。

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
    <property name="order" value="100"/>
</bean>

当控制器返回"index"时,解析器会自动添加前后缀,寻找"/WEB-INF/jsp/index.jsp"

order 代表视图解析器优先级。当配置多个视图解析器时,控制器返回的逻辑视图(return String)会经过视图解析器链。前面的解析失败后,会由后面的解析器解析。
而 InternalResourceViewResolver 无论资源是否存在,都会尝试解析,即永远返回非空 View 对象,后面的解析器不会起作用。因此它的优先级必须设置为最低,即 order 最大。

如果没有配置视图解析器,Spring 默认会使用 BeanNameViewResolver,这个视图解析器会查找 ID 与视图名称匹配的 bean,并且查找的 bean 要实现 View 接口。





参考资料:《Spring MVC 学习指南》 Paul Deck 著
     《Spring 实战》 Craig Walls 著

猜你喜欢

转载自www.cnblogs.com/JL916/p/11876286.html