SpringMVC工作原理

SpringMVC简单介绍

什么是MVC?

​ MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。就是将业务逻辑、数据、显示分离的方法来组织代码。MVC主要作用是降低了视图与业务逻辑间的双向偶合。MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。

Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。

View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。

Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。 也就是说控制器做了个调度员的工作。

最典型的MVC就是JSP + servlet + javabean的模式。

SpringMVC

简而言之,springMVC是Spring框架的一部分,是基于java实现的一个轻量级web框架。

学习SpringMVC框架最核心的就是DispatcherServlet的设计,掌握好DispatcherServlet是掌握SpringMVC的核心关键。

springmvc-1

1
2
3
4
5
6
7
8
9
10
11
1、DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
2、HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
3、返回处理器执行链,根据url查找控制器,并且将解析后的信息传递给DispatcherServlet
4、HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
5、执行handler找到具体的处理器
6、Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
7、HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
8、DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
9、视图解析器将解析的逻辑视图名传给DispatcherServlet。
10、DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图,进行试图渲染
11、将响应数据返回给客户端

基于XML的Hello_SpringMVC

1.添加pom依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
</dependencies>

2.编写web.xml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--
关联springmvc的配置文件
此配置文件的属性可以不添加,但是需要在WEB-INF的目录下创建 前端控制器名称-servlet.xml文件
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
</servlet>
<!--匹配servlet的请求,
/:标识匹配所有请求,但是不会jsp页面
/*:拦截所有请求,拦截jsp页面

但是需要注意的是,当配置成index.html的时候,会发现请求不到
原因在于,tomcat下也有一个web.xml文件,所有的项目下web.xml文件都需要继承此web.xml
在服务器的web.xml文件中有一个DefaultServlet用来处理静态资源,但是url-pattern是/
而我们在自己的配置文件中如果添加了url-pattern=/会覆盖父类中的url-pattern,此时在请求的时候
DispatcherServlet会去controller中做匹配,找不到则直接报404
而在服务器的web.xml文件中包含了一个JspServlet的处理,所以不过拦截jsp请求
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

3、编写springmvc需要的spring配置文件,applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!--处理映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!--处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>

<!--视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--配置前缀-->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!--配置后缀-->
<property name="suffix" value=".jsp"></property>
</bean>

<bean id="/hello" class="com.controller.HelloController"></bean>
</beans>

4.HelloController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//创建模型和视图对象
ModelAndView mv = new ModelAndView();
//将需要的值传递到model中
mv.addObject("msg","helloSpringMVC");
//设置要跳转的视图,
mv.setViewName("hello");
return mv;
}
}

基于注解的Hello_SpringMVC

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
public class HelloController{
/*
* @RequestMapping就是用来标识此方法用来处理什么请求,其中的/可以取消
* 取消后默认也是从当前项目的根目录开始查找,一般在编写的时候看个人习惯
* 同时,@RequestMapping也可以用来加在类上,
*/
@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("msg","hello,SpringMVC");
return "hello";
}
}
1
2
3
4
5
6
7
8
具体的运行流程:
1、客户端发送请求http://localhost:8080/hello
2、由tomcat接受到对应的请求
3、SpringMVC的前端控制器DispatcherServlet接收到所有的请求
4、查看请求地址和@RequestMapping注解的哪个匹配,来找到具体的类的处理方法
5、前端控制器找到目标处理类和方法之后,执行目标方法
6、方法执行完成之后会有一个返回值,SpringMVC会将这个返回值用视图解析器进行解析拼接成完整的页面地址
7、DispatcherServlet拿到页面地址之后,转发到具体的页面

@RequestMapping

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@RequestMapping("/kuro")
public class HelloController{

/*
* @RequestMapping就是用来标识此方法用来处理什么请求,其中的/可以取消
* 取消后默认也是从当前项目的根目录开始查找,一般在编写的时候看个人习惯
* 同时,@RequestMapping也可以用来加在类上,
* */
@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("msg","hello,SpringMVC");
return "hello";
}

/**
* Request的其他属性值
* value:要匹配的请求
* method:限制发送请求的方式: POST GET
* params:表示请求要接受的参数,如果定义了这个属性,那么发送的时候必须要添加参数
* params有几种匹配规则
* 1、直接写参数的名称,param1,param2
* params = {"username"}
* 2、表示请求不能包含的参数,!param1
* params = {"!username"}
* 3、表示请求中需要要包含的参数但是可以限制值 param1=values param1!=value
* params = {"username=123","age"}
* params = {"username!=123","age"}
* headers:填写请求头信息
* chrome:User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36
* firefox:User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0
*
* consumers:只接受内容类型是哪种的请求,相当于指定Content-Type
* produces:返回的内容类型 Content-Type:text/html;charset=utf-8
*
* @return
*/
@RequestMapping(value = "/hello2",method = RequestMethod.POST)
public String hello2(){
return "hello";
}

@RequestMapping(value = "/hello3",params = {"username!=123","age"})
public String hello3(String username){
return "hello";
}

@RequestMapping(value = "/hello4",headers = {"User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0"})
public String hello4(){
return "hello";
}

/**
* @Request包含三种模糊匹配的方式,分别是:
* ?:能替代任意一个字符
* *: 能替代任意多个字符和一层路径
* **:能代替多层路径
* @return
*/
@RequestMapping(value = "/**/h*llo?")
public String hello5(){
return "hello";
}
}

@PathVariable

如果需要在请求路径中的参数像作为参数应该怎么使用呢?可以使用@PathVariable注解,此注解就是提供了对占位符URL的支持,就是将URL中占位符参数绑定到控制器处理方法的参数中。

1
2
3
4
5
6
7
8
9
@Controller
@RequestMapping("/kuro")
public class HelloController{

@RequestMapping(value = "/pathVariable/{name}")
public String pathVariable(@PathVariable("name") String name){
return "hello";
}
}

REST

1
2
3
4
5
GET:获取资源   			/book/1
POST:新建资源 /book
PUT:更新资源 /book/1
DELETE:删除资源 /book/1
一切看起来都非常美好,但是大家需要注意了,我们在发送请求的时候只能发送post或者get,没有办法发送put和delete请求,那么应该如何处理呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Controller
public class RestController {

@RequestMapping(value = "/user",method = RequestMethod.POST)
public String add(){
return "success";
}

@RequestMapping(value = "/user/{id}",method = RequestMethod.DELETE)
public String delete(@PathVariable("id") Integer id){
return "success";
}

@RequestMapping(value = "/user/{id}",method = RequestMethod.PUT)
public String update(@PathVariable("id") Integer id){
return "success";
}

@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
public String query(@PathVariable("id") Integer id){
return "success";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("UTF-8");
servletResponse.setCharacterEncoding("UTF-8");
//过滤器链--传递
filterChain.doFilter(servletRequest,servletResponse);
}

public void destroy() {
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package org.springframework.web.filter;
public class HiddenHttpMethodFilter extends OncePerRequestFilter {
private String methodParam = "_method";

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest requestToUse = request;
//如果是个Post请求
if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {
//获取"key=_method"的value值,
String paramValue = request.getParameter(this.methodParam);
if (StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
if (ALLOWED_METHODS.contains(method)) {
//并把它的value当做请求参数转换成对应的请求方式
requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
}
}
}
//过滤器链继续
filterChain.doFilter((ServletRequest)requestToUse, response);
}
}
1
2
3
4
5
6
7
8
9
<!-- web.xml-->
<filter>
<filter-name>hiddenFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<form action="/user" method="post">
<input type="submit" value="增加">
</form>
<form action="/user/1" method="post">
<input name="_method" value="delete" type="hidden">
<input type="submit" value="删除">
</form>
<form action="/user/1" method="post">
<input name="_method" value="put" type="hidden">
<input type="submit" value="修改">
</form>
<a href="/user/1">查询</a><br/>
</body>

@RequestParam

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Controller
public class RequestController {

/**
* 如何获取SpringMVC中请求中的信息
* 默认情况下,可以直接在方法的参数中填写跟请求一样的名称,此时会默认接受参数
* 如果有值,直接赋值,如果没有,那么直接给空值
*
* @RequestParam:获取请求中的参数值,使用此注解之后,参数的名称不需要跟请求的名称一致,但是必须要写
* public String request(@RequestParam("user") String username){
*
* 此注解还包含三个参数:
* value:表示要获取的参数值
* required:表示此参数是否必须,默认是true,如果不写参数那么会报错,如果值为false,那么不写参数不会有任何错误
* defaultValue:如果在使用的时候没有传递参数,那么定义默认值即可
*
*
* @param username
* @return
*/
@RequestMapping("/request")
public String request(@RequestParam(value = "user",required = false,defaultValue = "hehe") String username){
return "success";
}
}

@RequestHeader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Controller
public class RequestController {

/**
* 如果需要获取请求头信息该如何处理呢?
* 可以使用@RequestHeader注解,
* public String header(@RequestHeader("User-Agent") String agent){
* 相当于 request.getHeader("User-Agent")
*
* 如果要获取请求头中没有的信息,那么此时会报错,同样,此注解中也包含三个参数,跟@RequestParam一样
* value
* required
* defalutValue
* @param agent
* @return
*/
@RequestMapping("/header")
public String header(@RequestHeader("User-Agent") String agent){
return "success";
}
}

@CookieValue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Controller
public class RequestController {

/**
* 如果需要获取cookie信息该如何处理呢?
* 可以使用@CookieValue注解,
* public String cookie(@CookieValue("JSESSIONID") String id){
* 相当于
* Cookie[] cookies = request.getCookies();
* for(Cookie cookie : cookies){
* cookie.getValue();
* }
* 如果要获取cookie中没有的信息,那么此时会报错,同样,此注解中也包含三个参数,跟@RequestParam一样
* value
* required
* defalutValue
* @param id
* @return
*/
@RequestMapping("/cookie")
public String cookie(@CookieValue("JSESSIONID") String id){
return "success";
}
}

乱码问题

GET请求:在tomcat的server.xml文件中,添加URIEncoding=“UTF-8”

POST请求:编写过滤器进行实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--解决post请求乱码-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!--解决响应乱码-->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

如果配置了多个过滤器,那么字符编码过滤器一定要在最前面,否则失效。

使用原生API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 /**
* SpringMVC也可以在参数上使用原生的Servlet API
*
* HttpSession
* HttpServletRequest
* HttpServletResponse
*
* java.security.Principal 安全协议相关
* Locale:国际化相关的区域信息对象
* InputStream:
* ServletInputStream inputStream = request.getInputStream();
* OutputStream:
* ServletOutputStream outputStream = response.getOutputStream();
* Reader:
* BufferedReader reader = request.getReader();
* Writer:
* PrintWriter writer = response.getWriter();
* @param session
* @param request
* @param response
* @return
*/

@RequestMapping("api")
public String api(HttpSession session, HttpServletRequest request, HttpServletResponse response){
request.setAttribute("requestParam","request");
session.setAttribute("sessionParam","session");
return "success";
}

响应数据

使用Model,Map,ModelMap、ModelAndView传输数据到页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@RequestMapping("output1")
public String output1(Model model){
model.addAttribute("msg","hello,Springmvc");
return "output";
}

@RequestMapping("output2")
public String output2(ModelMap model){
model.addAttribute("msg","hello,Springmvc");
return "output";
}

@RequestMapping("output3")
public String output1(Map map){
map.put("msg","hello,Springmvc");
return "output";
}

@RequestMapping("mv")
public ModelAndView mv(){
ModelAndView mv = new ModelAndView();
mv.setViewName("output");
mv.addObject("msg","hello.modelAndView");
return mv;
}

所有的参数值都设置到了request作用域中

@SessionAttribute

此注解可以表示,当向request作用域设置数据的时候同时也要向session中保存一份,此注解有两个参数,一个value(表示将哪些值设置到session中),另外一个type(表示按照类型来设置数据,一般不用,因为有可能会将很多数据都设置到session中,导致session异常)。

1
2
3
4
5
6
7
8
9
10
@Controller
@SessionAttributes(value = "msg")
public class OutputController {

@RequestMapping("output1")
public String output1(Model model){
model.addAttribute("msg","hello,Springmvc");
return "output";
}
}

@ModelAttribute

会在请求执行前先调用MyModelAttribute方法,在模板的基础上写入请求参数的值,使用都是的同一个Model对象,ModelAttribute除了可以使用设置值到model中之外,还可以利用返回值。

1
2
3
4
5
6
7
8
9
10
@RequestMapping("update")
public String update(@ModelAttribute("user") User user,Model model){

}

@ModelAttribute
public void MyModelAttribute(Model model){
User user = new User();
model.addAttribute("user",user);
}

forward

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 当使用转发的时候可以添加前缀forward:index.jsp,此时是不会经过视图解析器的,所以要添加完整的名称
*
* forward:也可以由一个请求跳转到另外一个请求
*
* @return
*/
@RequestMapping("/forward01")
public String forward(){
return "forward:/index.jsp";
}

@RequestMapping("/forward02")
public String forward2(){
return "forward:/forward01";
}

redirect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* redirect :重定向的路径
* 相当于 response.sendRedirect("index.jsp")
* 跟视图解析器无关
* @return
*/
@RequestMapping("redirect")
public String redirect(){
return "redirect:/index.jsp";
}

@RequestMapping("/redirect2")
public String redirect2(){
return "redirect:/redirect";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
转发:
由服务器的页面进行跳转,不需要客户端重新发送请求:
特点如下:
1、地址栏的请求不会发生变化,显示的还是第一次请求的地址
2、请求的次数,有且仅有一次请求
3、请求域中的数据不会丢失
4、根目录:localhost:8080/项目地址/,包含了项目的访问地址

重定向:
在浏览器端进行页面的跳转,需要发送两次请求(第一次是人为的,第二次是自动的)
特点如下:
1、地址栏的地址发生变化,显示最新发送请求的地址
2、请求次数:2次
3、请求域中的数据会丢失,因为是不同的请求
4、根目录:localhost:8080/ 不包含项目的名称

静态资源

由于DispatcherServlet会拦截所有的请求,而此时我们没有对应图片的请求处理方法,所以此时报错了,想要解决的话非常简单,只需要添加一个配置即可

1
2
3
4
5
<!--
此配置表示 我们自己配置的请求由controller来处理,但是不能请求的处理交由tomcat来处理
静态资源可以访问,但是动态请求无法访问
-->
<mvc:default-servlet-handler/>

但是加上此配置之后,大家又发现此时除了静态资源无法访问之外,我们正常的请求也无法获取了,因此还需要再添加另外的配置:

1
2
<!--保证静态资源和动态请求都能够访问-->
<mvc:annotation-driven/>

组件说明:

以下组件通常使用框架提供实现:

DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。

HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器。

ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等。

组件:
1、前端控制器DispatcherServlet(不需要工程师开发),由框架提供
作用:接收请求,响应结果,相当于转发器,中央处理器。有了dispatcherServlet减少了其它组件之间的耦合度。
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。

2、处理器映射器HandlerMapping(不需要工程师开发),由框架提供
作用:根据请求的url查找Handler
HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

3、处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。

4、处理器Handler(需要工程师开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要工程师根据业务需求开发Handler。

5、视图解析器View resolver(不需要工程师开发),由框架提供
作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由工程师根据业务需求开发具体的页面。

6、视图View(需要工程师开发jsp…)
View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)

核心架构的具体流程步骤如下:
1、首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
2、DispatcherServlet——>HandlerMapping, HandlerMapping 将会把请求映射为HandlerExecutionChain 对象(包含一个Handler 处理器(页面控制器)对象、多个HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
3、DispatcherServlet——>HandlerAdapter,HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
4、HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView 对象(包含模型数据、逻辑视图名);
5、ModelAndView的逻辑视图名——> ViewResolver, ViewResolver 将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
6、View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。

下边两个组件通常情况下需要开发:

Handler:处理器,即后端控制器用controller表示。

View:视图,即展示给用户的界面,视图中通常需要标签语言展示模型数据。


“本篇文章主要摘自参考资料

最后更新: 2020年11月05日 18:43

原始链接: https://midkuro.gitee.io/2020/09/11/springmvc-model/

× 请我吃糖~
打赏二维码