Spring MVC
这个词,我们在工作中非常常见,但他到底是什么呢?他是由什么组成的?有什么用,有什么优缺点,怎么用。是我们需要去学习的知识。本篇为理论基础和基础实践,对于SpringMVC,我们可以说spring MVC是spring框架的一个模块,spring MVC和spring无需通过中间整合层进行整合。也可以说是一种设计理念,这种解释方式比较合理,MVC是指,C[Controller]控制层,M[Model]模块层,V[View]显示层这样的设计理念,其本质即核心思想也就是业务数据抽取同业务数据呈现相分离。用处就是使场景简单化,单一化。更利于我们去实现这些场景下的功能。
MVC 采用了程序分层设计概念,如
- Model层
- View层
- Controller层
MVC采用了分工合作的设计。如
前端控制器 Front Controller(MVC)
实际上,如下图,名为前端控制器
的图解:
我的大致理解为: 前端的http
请求通过解析域名等渠道到达我们服务端口的前端控制器,前端控制器根据其请求中包含的指定信息来识别并指定请求分发给谁来进行处理,然后呢,将这个请求给具体的Controller
也就是图中黄色的部分来代理,通过识别信息了解需要哪些业务逻辑类,调用业务逻辑类生成对应的数据,将在调用了业务逻辑生成业务数据后,把数据返还给前端控制器。此时前端控制器呢,将业务逻辑数据分发给我们的Viewtemplate
,也就是业务视图。由业务视图来呈现最终的用户的看到的页面。业务视图将数据挂载在待展示的页面信息里面后,将页面代码数据送至前端控制器,此时,前端控制器将页面数据信息返回给前端。
相关定义
那么,问题来了,为什么称为
前端控制器
[Front Controller]呢?
其实,通过这个部件对应的功能,我们可以将它归类并且进行定义其名称,也就是说,它的名字是如他具体功能所定义,现在来举个例子来说明图中个部件的作用。假设现在有个市级医院,里面有很多类型门诊,比如外科门诊、内科门诊、神经科门诊、拍片科门诊等。这些就好比对应模块的Controller
[黄色图形区域],这些区域负责接收各类病人,这些病人的对号入座行为就类似于你从分诊台[这里分诊台扮演了Front Controller
角色]拿到了就诊单,于是准备去对应门诊进行治疗。前端请求到达分诊台后进行判断。
Front Controller
类似于SpringCloud中的zuul网关服务吧、就是接客、引导和带路同时兼并送客的功能的部分模块。
View template
负责呈现展现给用户看的页面视觉的部分模块,重点关注数据的呈现。.
Controller
负责根据对应请求处理业务逻辑,通常也和数据库打交道,总之就是个跟数据打交道的家伙。
Model
Model,模型,其实就是一个或多个实体类组成的。关注支撑业务的信息构成。通常是多个业务实体的组成。
Spring MVC的基本概念
上面讲Front Controller
结构图的时候,我们需要知道其中前端控制器里面的什么类来进行工作,将这些请求分发到对应的Controller
那边去,那就是其DispatcherServlet
这个类,这个类负责连接分发各模块,如下:
从上图和下图可以看出,DispatcherServlet
可以通过处理器适配器类HandlerAdapter调用具体的处理器(Controller)如下图注解。
可以说DispatchServlet
类是实现前端控制器的核心类,而HandlerAdapter是使自定义Controller能被识别到的适配类,因为我们可能会自己开发对应的Controller,但是DispatchServlet发现不了我们自定义的Controller啊,这时候,就需要将自己定义的Controller类上加上注解,也就是Anotation,其核心就是HandlerAdapter类。
自定义的controller加上此声明后,可以被HanderAdapter发现,而HandlerAdapter则可以被DisPatchServlet来进行使用,并且通过HanderAdapter找到对应的controller类,也就是我们定义的controller:
在自己写MVC设计理念实际操作之前,咱还是要先了解其部分相关概念,上面的DisPatchServlet、HandlerAdaapter、都是我们需要了解的知识。
下面还要说的是 HandlerMapping类,这个类是用来干什么的呢?这个类,啊,是dispatchservlet调用controll的中间过渡的对象,什么意思?就是说。他是辅助调用Controller的类。能够帮助dispatchServlet,在工作完毕后,能够返回一个HanderAdapter给dispatchSrvlet。
除此之外,HandlerMapping类返回给你了HandlerInterceptor以及HandlerExecutionChain、他们之间构成了一个执行的链条。链条关系如下:
这个链条是利用java反射原理实现的。现在只需要了解就行了。
在springMVC中,有着关联和转化Model和Map等类的类。就是说,当调用controll返回的是一个model、或者是一个map、set、List。返回给Front controll的时候,其会自动的将返回的类进行转化成Model。其就用了ModelAndView。
ViewResolver
,也被称为视图解析器。他会告诉dispatchServlet
,你需要哪个视图,来进行呈现。
View
,负责呈现页面。
总结:
-
DispatcherServlet
——>前端控制器-服务的调度 -
Contorller
——>控制器,调用业务处理逻辑类 -
HandlerAdapter
——>操作适配器,用于发现controll或者供dispatchServlet使用等 -
HandlerInterceptor
——>操作拦截器,对配置的url进行拦截。。 -
HandlerMapping
——>操作映射射,是dispatchservlet分发controll的 ‘ 过渡类 ’ -
HandlerExecutionChain
——>操作执行链 -
ModelAndView
——>模型和视图 -
ViewResolver
——>视图分离 -
View
——>视图
上面是不是很离谱?看不懂?下面来个流程图帮助你理解,= =
这个就是流程图。然后呢,从request
说起,request
是发送请求,其被前端控制器DispatchServlet
识别后,DsipatchServlet
使用HandlerAdapter
识别并判断需要用哪个controller
,如果需要配置和处理拦截对象的话,那么也需要去调用HandlerInterceptor
来发现自定义的拦截器。那么调用controller
后,返回的是Model
,此时有数据了,那需要把这些数据放到页面上去啊。那么。DispatchServlet
根据返回的Model
后,将这个Model
送至View
,然后呢,ViewResolver
呢,解析Model
并搭载数据到指定的VIew
。完毕后,返回给DispatchServlet
一个ModelAndView
对象。此时,DispatchServlet
将这个对象解析成json
格式,返回给前端。也就是图中的Responce
请求。那,上面图中,哪些是需要我们写的呢?其中,黑色的是框架自带。不需要我们去实现,粗体Controller
是需要我们写的,对应的斜体可以写,可以不写。其余蓝色的不粗的,只需要配置就行,总体来说,需要我们写的东西不多。
那么,下面的图就是较上面描述的比较详细的官方的Chart:
创建Spring MVC项目
使用IDEA创建Spring MVC项目步骤就那么几步。如下
- 打开idea,新建项目,如下
-
等待下载好后,发现如下结构图
其中web.xml是用来启动DispatcherServlet的,如下:
web.xml
中,根据上面讲解的理论知识,其中servlet
标签有啥用呢?
害,是注册Servlet啊,我们知道,SpringMVC是基于Spring项目的,我们还知道在Spring中,注册成为一个Bean对象让IOC容器发现并为止所用是使用啥标签呢。是Beans标签,里面有用户自定义的Bean标签,所以说,这个Servlet是类似,在里面中,定义指定的Servlet,使之发现并且进行注册。但系统配置自动生成后,就默认是dispatchServlet,当然也可以自定义其他的。
那servlet-mapping
标签又有啥用呢?
如果
url-pattern
定义的是路径,那么以后所有对这个路径下资源的请求都会由servlet-name
中定义的servlet
处理;
如果url-pattern
定义的是资源格式例如*.form
等,那么对于所有符合这种格式的资源的请求都由指定的servlet
处理。这里的话,我们将
url-pattern
改成 /
- 之后,创见文件夹目录结构如下:
-
接下来配置
dispatcher-servlet.xml
修改
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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 扫包,这个学过spring的同学就知道的。 --> <context:component-scan base-package="controller"></context:component-scan> <!-- 配置视图解析器 如何把handler 方法返回值解析为实际的物理视图 --> <!--prefix和suffix:查找视图页面的前缀和后缀(前缀[逻辑视图名]后缀), --> <!-- 比如传进来的逻辑视图名为hello,则该该jsp视图页面应该存放在“/WEB-INF/hello.jsp” --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
哎,咱学过Spring,知道其手动装配和注册bean对象这么一回事,这里就不解释。要注意的是,这里是自定义装配
InternalResourceViewResolver
这个类。在spring中也叫作设值注入,自定义存放的资源目录,。 -
在WecomeDemo.java中码上代码
package controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/demo") /** * @Deprecated charlinheng * @date:2020-6-7 */ public class WecomeDemo { @RequestMapping(value = "/helloMVC",method = RequestMethod.GET) public String sayHello(){ return "hello"; } }
如下:
- 此时目录结构图
- 配置和运行[这个需要在Deployment中添加artifact,参照底部的提示]
点击运行,忽略那些控制台一些日志黄色警告,看浏览器截图如下:
此时,成功的调用controller的helloMVC
这个接口,然后返回的字符串通过ViewResolver
解析出页面视图。
如果有严重警告报错没法正常,打开file---->project-structure,然后看到如下:
那就说明还缺少项目模型,这时候我们需要点击右下角的Fix,选择 Add all mssing 点击 apply 以及ok。
然后重新运行项目