一. 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的基本开发流程
- 配置映射关系:在控制器中使用
@Controller
注解标识JavaBean为一个控制器,在控制器的类或者方法上使用@RequestMapping
注解标识映射关系,这样在容器初始化时就会注册URI和处理器之间的映射关系到内存中,同时记得在spring配置文件中配置组件扫描,将控制器注册为容器中的Bean - 开发控制器:控制器核心内容包括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;
}
- 开发视图:根据之前的配置,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;
}
}