MVC框架是什么?要做什么?
MVC是一套设计规范。
M(Model):数据模型层。包括Dao层(数据持久层)和Service层(业务层)。完成用户数据的封装,保存数据状态;实现业务逻辑。
V(View):视图层。显示页面。
C(Controller):控制器。取得表单数据;调用业务逻辑;转向指定的页面(重定向或转发)。
MVC框架要做的事情主要是:
- 将url映射到java类或java类的方法;
- 封装用户提交的数据;
- 处理请求-->调用相关的业务逻辑-->封装相应数据;
- 将响应的数据渲染到页面
SpringMVC原理
Spring的框架是围绕DispatcherServlet设计的。本质就是一个Servlet,接收请求、分派请求、提供业务功能。
SpringMVC的一个完整流程图如下:
客户发起请求被前置控制器拦截;控制器根据请求参数生成代理请求;找到请求对应的实际控制器;控制器处理请求,创建数据模型,访问数据库,将模型响应给中心控制器;控制器使用模型与视图渲染视图结果;将结果返回给中心控制器;最后将结果返回给请求者。
简要分析其中的流程步骤:
-
DispatcherServlet是前置控制器,也是整个SpringMVC的控制中心。 用户发出的请求,会被DispatcherServlet拦截并接收。 假设请求的url为:http://localhost:8080/SpringMVC/hello,该url可以被拆分为三部分:
- http://localhost:8080:服务器域名
- SpringMVC:部署在服务器上的web站点
- hello:控制器
因此这个url表示:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
-
HandlerMapping为处理器映射。由DispatcherServlet调用。根据请求url查找Handler。
-
HandlerExecution根据url查找控制器,如上url被查找控制器为:hello。
-
HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
-
HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler(可以是Controller或Servlet,还可以是Controller中的一个方法)。
-
Handler让具体的Controller执行。
-
Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
-
HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
-
DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的视图逻辑名。
-
视图解析器将解析的逻辑视图名传给DispatcherServlet。
-
DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
-
将视图呈现给用户。
参考:遇见狂神说
“Special Beans”
上面出现的奇怪名词到底是什么?
Special Beans是一类帮助DispatcherServlet来处理请求并呈现合理响应的特定实例对象。
说人话就是DispatcherServlet是一个派任务的boss,special beans是一群真正在干活的小弟。
HandlerMapping:处理器映射
解析url,并对应到Handler进行处理。
Handler可以是Controller里的一个方法,也可以是Servlet或Controller等。
HandlerAdapter:处理器适配器
调用具体的方法对用户请求进行处理。
Controller有很多种不同的类型。当HandlerMapping获取到执行请求的Controller时,DispatcherServlte会根据该Controller对应的Controller类型来调用相应的HandlerAdapter来进行处理。
例如,对于带有注解的Controller,就要调用注解类处理器。
HandlerAdapter的主要作用是对DispatcherServlet屏蔽这类操作。
ViewResolver:视图解析器
Controller根据请求执行完业务逻辑之后,返回一个ModelAndView。ModelAndView顾名思义就是一个Model(模型:处理之后的结果数据)和View(视图)。
ViewResolver的任务就是从ModelAndView中将View解析出来。
MVC初体验
试着写一个原生态的SpringMVC项目,发送请求并显示“HelloMVC!”。
一、导入依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.18</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
一定要确保项目的maven文件中,以及最后jar包的lib目标中都已经成功包含依赖,否则无法运行成功。
IDEA不会自动添加lib依赖,手动加一下。
二、配置web.xml,注册DispatcherServlet
<!--配置DispatcherServlet:请求分发器,前端控制器。SpringMVC的核心-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--DispatcherServlet要绑定Spring的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--设置启动级别:1(服务器启动的时候就同时启动)-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--在SpringMVC中,/与/*的区别:
/:只匹配所有的请求,不匹配jsp
/*:匹配所有的请求,包括jsp页面
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
三、配置Servlet
新建[servlet_Name]-servlet.xml。(其实就是一个Spring配置文件)
三件事情:
- 配置HandlerMapping(Spring提供);
- 配置HandlerAdapter(Spring提供);
- 配置ViewResolver(Spring提供)。
<!--Servlet的配置文件,其实就是一个Spring配置文件-->
<!--SpringMVC核心三要素:-->
<!--处理器映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
四、编写Controller处理业务
创建一个Controller,要么实现Controller接口,要么添加注解(对应不同的HandlerAdapter)。
处理具体的业务,并指定返回视图。最后返回一个ModelAndView。
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView();
//业务代码
//Model。封装数据。
String result = "HelloMVC!";
mv.addObject("msg", result);
//视图跳转
//View。
mv.setViewName("test"); //:/WEB-INF/jsp/test.jsp
return mv;
}
}
五、注册bean,将Controller交给Spring托管
在[servlet_Name]-servlet.xml里面把刚刚写的Controller,bean一下。
<!--BeanNameUrlHandlerMapping: bean-->
<bean id="/hello" class="com.chriss.controller.HelloController"/>
六、编写即将跳转的jsp页面
显示“HelloMVC!”
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
七、启动汤姆猫!
总结起来说,实际需要编写的只有Controller而已,并且要去相应的配置文件里面注册一下。剩下了其实Spring都帮我们做完了。
对应到开头的流程图,其实只有虚线是需要我们实现的。