SpringMVC(一)框架设计及流程

版权声明:From Lay https://blog.csdn.net/Sadlay/article/details/84034135

Spring MVC(一)框架设计及流程

SpringMVC框架设计

框架设计图如下
在这里插入图片描述

上图是SpringMVC框架运行的流程。处理请求先到达控制器(Controller),控制器的作用是进行请求转发,这样它会根据请求的内容去访问模型层(Model);在现今互联网体系中,数据主要从数据库和NoSQL中来,而且对于数据库而言往往还存在事务的机制,为了适应这样的变化,设计者会把模型层再细分为两层,即服务层(Service)和数据访问层(DAO);当控制器获取到由模型层返回的数据后,将数据渲染到视图中,这样就能够展示给用户了。

SpringMVC流程

流程图

流程图

流程和组件是SpringMVC的核心。

SpringMVC的流程都是围绕着DispatcherServlet而工作的。严格来说,springMVC处理请求并非一定需要经过全流程,有时候一些流程并不存在,比如我们加入@ResponseBody注解时,是没有经过视图解析器和视图渲染的,关于这个后面会讨论到。

首先,在Web服务器启动的过程中,如果在Spring Boot的机制下启用SpirngMVC,它就开始初始化一些重要组件,如DispactherServlertHandlerAdatper的实现类RequestMappingHandlerAdatper等对象组件。关于组件的初始化,我们在spring-webmvc-xxx.jar包的属性文件DispatcherServler.properties,它定义的对象都是在SpringMVC开始时就初始化,并且存放在SpringIoC容器中。其源码如下

DispatcherServler.properties源码

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

#国际化解析器
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

#主题解析器
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

# HandlerMapping实例
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

#处理器适配器
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

#处理器异常解析器
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

#策略视图名称转换器,当没有返回视图逻辑名称的时候,通过它可以生成默认的视图名称
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

#视图解析器
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

#FlashMap管理器,不常用
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

这些组件会在SpringMVC得到初始化,所以我们并不需要太多的配置就能够开发SpringMVC程序。

普通视图

定义控制器

@RequestMapping(value = "/person")
@Controller
public class PersonController {

    //注入用户服务类
    @Autowired
    PersonService personService;
	
 	//展示人员详情
    @RequestMapping("/details")
    public ModelAndView details(Long id) {
        //访问模型层得到数据
        Person perosn = personService.getPerson(id);
        //模型和视图
        ModelAndView mv = new ModelAndView();
        //定义模型视图
        mv.setViewName("person/details");
        //加入数据模型
        mv.addObject("person", perosn);
        //返回视图
        return mv;
    }
}

@Controller:表明这是一个控制器

@RequestMapping:代表请求路径和控制器(或方法)的映射关系,它会在Web服务启动SpringMVC的时,就被扫描到HandlerMapping的机制中存储,之后再用户发起请求被DispatcherServlert拦截后,通过URI和其他的条件,通过HandlerMapper机制就能够找到对应的控制器或其方法进行响应。只是通过HandlerMapping返回的是一个HandlerExecutionChain对象,源码如下

HandlerExecutionChain源码

 public class HandlerExecutionChain {
    //日志
    private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
    //处理器
    private final Object handler;
    //拦截器数组
    @Nullable
    private HandlerInterceptor[] interceptors;
    //拦截器列表
    @Nullable
    private List<HandlerInterceptor> interceptorList;
    //拦截器当前下标
    private int interceptorIndex;
    //....
}

HandlerExecutionChain对象包含一个处理器(handler)。这里的处理器就是对控制器(controller)的包装。因为我们的控制器方法可能存在参数,那么处理器就可以读入http和上下文的相关参数,然后再传递给控制器方法。而在控制器执行完成返回后,处理器又可以通过配置信息和对控制器的返回结果进行处理。可以看出,处理器包含了控制器方法的逻辑,此外还有处理器的拦截器(interceptor),这样就能够通过拦截处理器进一步增强处理器的功能。

得到了处理器(handler)。还需要去运行,但是我们有普通的http请求,也有按BeanName的请求,设置是WebSocket的请求,所以它还需要一个适配器去运行HandlerExecutionChain对象包含的处理器,这就是HandlerAdapter接口定义的实现类。从源码中可以看到SpringMVC中最常用的HandlerAdapter的实现类,便是HttpRequestHandlerAdapter。通过请求的类型,DispatcherServlet就会找到它来执行Web请求的HandlerExecutionChain对象包含的内容,这样就能够执行我们的处理器(handler)了。

在处理器调用控制器时,它首先通过模型层得到数据,再放入数据模型中,最后将返回模型和视图对象(ModelAndView),这里控制器设置的视图名称设置为"person/details"这样就走到了视图解析器(ViewResolver),去解析视图逻辑名称了。

SpringMVC的ViewResolver的实现类是InternalResourceViewResolver,为了定制,我们可以在application.properties文件中进行配置

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html

通过这样的配置,就能能在Spring Boot机制下定织InternalResouceViwResolver这个视图解析器的初始化,也就是在返回视图名称之后,它会以前缀(prefix)和后缀(suffix)以及视图的名称组成全路径定位视图。例如,在控制器返回的"person/details",这里前缀为/,等于spring boot默认路径"/src/main/resources/templates",那么它就会找到"/src/main/resources/templates/person.html"作为视图。

视图解析器定位到视图后,视图的作用是将数据模型(Model)渲染,这样就能够响应数据的请求。这一步就是视图将数据模型渲染(View)出来,用来展示给用户看。

/person/details.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <meta charset="UTF-8">
    <title>用户详情</title>
</head>
<body>
<center>
    <table border="1">
        <tr>
            <td>标签</td>
            <td></td>
        </tr>
        <tr>
            <td>用户编号</td>
            <td th:text="${person.id}"></td>
        </tr>
        <tr>
            <td>用户名称</td>
            <td th:text="${person.personName}"></td>
        </tr>
        <tr>
            <td>用户备注</td>
            <td th:text="${person.note}"></td>
        </tr>
    </table>
</center>

</body>
</html>

这里因为我们的控制器里绑定数据模型的时候,属性名称为person,而属性为person对象,所以就有了${person.id}代表perosn对象的id属性,其余属性是一样的。

流程如下

实例流程

JSON视图

有时候我们需要的只是JSON数据集,因为目前前后台分离的趋势,使用JSON已经是主流的方式。正如@ResponseBody注解表明方法一样,springMVC会把数据转换为JSON数据集,但是这里不谈@ResponseBody,因为它会采用处理器内部的机制。这里先用MappingJackson2JsonView转换出JSON。


    //使用json视图
    @RequestMapping("/detailsForJson")
    public ModelAndView detailsForJson(Long id) {
        Person person = personService.getPerson(id);
        ModelAndView mv = new ModelAndView();
        MappingJackson2JsonView jsonView = new MappingJackson2JsonView();
        mv.setView(jsonView);
        mv.addObject("person", person);
        return mv;
    }

其流程如下
SpringMVC全流程使用JSON视图
流程中我们可以看到并没有视图解析器,是因为MappingJackson2JsonView是一个非逻辑视图。它不需要视图解析器进行定位,它的作用只是将数据模型渲染为JSON数据集来响应请求。

猜你喜欢

转载自blog.csdn.net/Sadlay/article/details/84034135
今日推荐