一. MVC概述

MVC模式是一种设计理念,其核心思想就是将系统中模块的解耦。早期javaweb开发使用servlet+javabean+jsp的模式,servlet负责接收用户http请求,然后调用javabean组件完成业务逻辑(读写数据库),最后servlet将处理结果(数据Model)转发给jsp用于展示给用户。在这个模式中,servlet扮演的是控制器角色(Controller),javabean负责处理业务逻辑并返回数据模型(Model),而jsp则是一种模板视图(View)技术。视图技术是多样化的,移动互联网的兴起使得JSON成为最流行的前后端数据交互方式。

二. SpringMVC基本组件的工作流程

SpringMVC是一种基于Servlet的技术,以DispatcherServlet为核心控制器。DispatcherServlet会拦截HTTP请求,然后根据请求的URI去查询前端控制器初始化时根据配置文件生成的HandlerMapping映射关系(@RequestMapping)找到指定的处理器(包括拦截器)去处理请求,处理器完成业务逻辑之后返回模型视图对象(ModelAndView),如果ModelAndView是逻辑视图(jsp / freemarker),那么DispatcherServlet将模型视图对象转发给对应的视图解析器(ViewResolver)处理,视图解析器将模型数据(Model)渲染到视图中去(jsp模板),如果不是逻辑视图(JSON),则将模型数据直接发送到客户端。

三. SpringMVC的基本demo

在web.xml部署文件中配置DispatcherServlet

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <!-- Spring IoC 容器的配置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 配置DispatcherServlet -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!-- 指定SpringMVC的配置文件位置 -->
            <param-value>classpath:spring/dispatcher-servlet.xml</param-value>
        </init-param>
        <!-- 服务器启动时就初始化DispatcherServlet -->
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <!-- 拦截所有请求后缀为".do"的http请求,交由springmvc来处理 -->
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

</web-app>

springmvc的配置文件dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 使用MVC注解驱动开发 -->
    <mvc:annotation-driven/>

    <!-- 扫描指定的包,加载相关MVC组件@Controller... -->
    <context:component-scan base-package="com.znker.*"/>

    <!-- 定义JSP的视图解析器
         物理视图 = 前缀 + 逻辑视图名 + 后缀
     -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

开发控制器,拦截执行相关HTTP请求:

package com.znker.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping(value = "/my")
public class MyController {

    @RequestMapping("/index")
    public ModelAndView index(){

        // 创建模型视图对象
        ModelAndView mv = new ModelAndView();
        // 设置逻辑视图名
        mv.setViewName("index");

        return mv;
    }
}

/WEB-INF/jsp目录下创建index.jsp文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=UTF-8">
    <title>springmvc demo</title>
</head>
<body>
    <h1>Hello Spring MVC!</h1>
</body>
</html>

四. SpringMVC的基本开发流程

  1. 配置映射关系:在控制器中使用@Controller注解标识JavaBean为一个控制器,在控制器的类或者方法上使用@RequestMapping注解标识映射关系,这样在容器初始化时就会注册URI和处理器之间的映射关系到内存中,同时记得在spring配置文件中配置组件扫描,将控制器注册为容器中的Bean
  2. 开发控制器:控制器核心内容包括1)获取HTTP请求参数,将请求参数封装到处理方法的形参中,2)调用容器中的Bean完成业务逻辑,返回模型数据,3)绑定模型数据和视图
@RequestMapping(value = "/getRole", method = RequestMethod.GET)
// @RequestParam注解用于获取HTTP请求中的参数,并将参数值绑定到处理器方法的形参中,
// 特别是前端传递的参数名和形参名不一样时可以使用@RequestParam注解绑定
// 在参数绑定的过程中,springmvc完成了数据类型的转换工作!!!
public ModelAndView getRole(@RequestParam("uid") Long id){
	// 调用容器中的Bean完成业务逻辑,返回模型数据
    Role role = roleService.getRole(id);

    ModelAndView mv = new ModelAndView();
    // 设置逻辑视图
    mv.setViewName("roleDetails");
    // 添加模型数据
    mv.addObject("role", role);
	// 转发给视图解析器,将数据模型渲染到jsp模板里返回给浏览器
    return mv;
}
  1. 开发视图:根据之前的配置,springmvc或默认使用jstlView进行视图渲染,将查询到的模型数据(Model)通过JSTL标签绑定到jsp模板文件中去,再发送到客户端(HTML)。如果是非逻辑视图,比如JSON格式的数据则不会交由视图解析器处理,而是直接将模型数据写回到客户端(需要引入Jackson的jar包)
@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/getUser")
    public ModelAndView getUserById(String id){
        User user = userService.getUserById(id);

        ModelAndView mv = new ModelAndView();
        // 绑定数据模型
        mv.addObject("user", user);
        // 指定视图类型为JSON
        mv.setView(new MappingJackson2JsonView());

        return mv;
    }

    @RequestMapping("/getList")
    @ResponseBody   // 告知springmvc将方法返回对象序列化为JSON数据返回给客户端
    public List<User> getUserList(){
        List<User> userList = userService.getUserList();

        return userList;
    }
}