Spring MVC是我们Web编程的基础,目前有很多应用都在用Spring MVC,而学习Spring MVC的核心在于流程和组件。MVC不是Spring/Java独有的,它只是一种架构的方法。满足高内聚低耦合的特点。
MVC的架构主要将应用拆分为模型层(Model)、控制层(Controller)和视图层(View)。
目前大部分的应用都是如下图这样的MVC结构:
这里需要注意的是Spring MVC架构中阿拉伯数字的顺序是执行的顺序。这里再具体进行说明。
和传统的Java Web围绕Servlet一样,Spring MVC是围绕DispatcherServlet来工作的,也就是Spring MVC的核心是DispatcherServlet。但是Spring MVC会提供一些组件来完成整体的工作。整体的流程如下图所示。
上图就是Spring MVC的全流程,注意并非全部请求都需要全流程进行响应(未来我们会学习到)。
其实在Spring MVC内部,已经帮助我们初始化了一些组件,关于这点,在我们引入spring-boot-starter-web后,可以看到spring-webmvc-x.y.z.jar中的包org.springframework.web.servlet,它里面有一个文件DispatcherServlet.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
# 处理器路由
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
org.springframework.web.servlet.function.support.RouterFunctionMapping
# 处理器适配器
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.function.support.HandlerFunctionAdapter
# 处理器异常处理器
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
# Flash管理器,不常用,后续不再论述
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
上面就是Spring MVC会帮助我们自动初始化的组件。所以一般,我们需要做的事情比较少。
这里我们需要引入spring MVC和|Thymeleaf两个包,因此可以使用Maven引入它们。
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
这里因为了Thymeleaf作为模板,这样就可以编写对应的模板了,你只需要将模板文件放在项目的/resources/templates目录下。下面我们编写一个Thymeleaf模板,名称为user_details.html,代码如下。
欢迎学习Spring MVC
,欢迎学习Spring MVC!
请注意到th:text="${user.userName}"的写法是要从数据模型中取出数据渲染,所以我们需要在控制器的ModelAndView中添加数据模型。为此需要添加一个控制器,代码如下。
package com.csdn.mvc.chapter1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller // 控制器
public class UserController {
@RequestMapping("/user/details") // 路由,让请求能映射到处理器
public ModelAndView userDetails(Long id) {
var mav = new ModelAndView();
// 视图名称,可以指向渲染的页面
mav.setViewName("user_details");
var user = new User();
user.setId(id);
user.setUserName("user_name_" + id);
user.setNote("note_" + id);
// 添加数据模型
mav.addObject(user);
return mav;
}
class User {
private Long id;
private String userName;
private String note;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
}
讲述开发的过程:
再次确认视图user_details.html的路径,如下图。
然后修改Spring Boot的启动文件,如下。
package com.csdn.mvc.chapter1.main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// 指定扫描的包,确保控制器能扫描到
@SpringBootApplication(scanBasePackages = "com.csdn.mvc.chapter1")
public class Chapter1Application {
public static void main(String[] args) {
SpringApplication.run(Chapter1Application.class, args);
}
}
这个文件只需要保证能够扫描到我们开发的控制器即可。
然后运行它,请求路径:
http://localhost:8080/user/details?id=12
得到如下结果,可见运行已经成功了。
学习Spring MVC最重要的是组件和流程,所以一定要熟悉它们,这里再分析我们上面的结果,来给大家增加印象,一定要好好体会分析的过程。
首先是请求的路径能够映射到处理器(它会包装控制器和其方法),因此这里在UserController.java中使用了@RequestMapping,这就是一种HandlerMapping的机制。Spring就会把方法包装为处理器了,然后通过路径能映射到这个处理器上。
控制器需要做的是确定自己的数据模型和视图(ModelAndView),从而完成业务功能。
ModelAndView需要给出视图名称和数据模型。它会根据视图名称通过映射得到具体的视图位置,这个过程需要一个视图解析器(ViewResolver)去定位,而视图的作用是将控制器中的数据模型渲染出来,展示给用户查看。
整个流程,如下图所示。
到这里,我们只是完成简单的Spring MVC,而核心是流程和组件,后续我们还会深入的介绍Spring MVC,期待下一篇哦。