目录
springMVC 是 spring 框架的一个模块,springMVC 和spring 无需通过中间整合层进行整合。
springmvc 是一个基于 mvc 的 web 框架,方便前后端数据的传输.
Spring MVC 拥有控制器,接收外部请求,解析参数传给服务层.

用 户 向 服 务 器 发 送 请 求 , 请 求 被 Spring 前端控制ServeltDispatcherServlet 捕获;
前端控制器DispatcherServlet接收请求后,调用处理器映射HandlerMapping。处理器映射器 HandlerMapping 根据请求的 url 找到处理该请求的处理器Handler ( 即 Controller ) , 将 处 理 器 Handler 返回给前端控制器DispatcherServlet。
DispatcherServlet 根 据 获 得 的 Handler ,选择一个合适的HandlerAdapter。 在填充 Handler 的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
HttpMessageConveter: 将请求消息(如 Json、xml 等数据)转换成一个对象,将对象转换为指定的响应信息
数据转换:对请求消息进行数据转换。如 String 转换成Integer、Double等
数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult 或 Error 中
Handler(自己的控制器)执行完成后,向 DispatcherServlet 返回一个ModelAndView 对象;
根据返回的 ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到 Spring 容器中的 ViewResolver)返回给 DispatcherServlet ;
ViewResolver 结合 Model 和 View,来渲染视图
将渲染结果返回给客户端。
DispatcherServlet:Spring 中提供了org.springframework.web.servlet.DispatcherServlet 类,它从HttpServlet 继承而来,它就是 Spring MVC 中的前端控制器(Frontcontroller)。
HandlerMapping: DispatcherServlet 自己并不处理请求,而是将请求交给页面控制器。那么在 DispatcherServlet 中如何选择正确的页面控制器呢?这件事情就交给 HandlerMapping 来做了,经过了HandlerMapping处理之后,DispatcherServlet 就知道要将请求交给哪个页面控制器来处理了。
HandlerAdapter:经过了 HandlerMapping 处理之后,DispatcherServlet 就获取到了处理器,但是处理器有多种,为了方便调用,DispatcherServlet 将这些处理器包装成处理器适配器 HandlerAdapter,HandlerAdapter 调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView 对象(包含模型数据、逻辑视图名)。
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>5.2.2.RELEASE</version>
- </dependency>
在 web.xml 文件中配置 DispatcherServlet 配置 spring 核心请求分发器
- <servlet>
- <servlet-name>application</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:application.xml</param-value>
- </init-param>
- <load-on-startup>0</load-on-startup>
- </servlet>
- <!-- 请求映射 -->
- <servlet-mapping>
- <servlet-name>application</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>

@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVCController 对象. Spring 配置中指定了自动扫描的 basepackage 后,Spring 会扫描这些包以及子包中的使用了@Controller 标识的类,然后将类加入到Spring IOC容器中,注入依赖。
@RequestMapping 注解是一个用来处理请求地址映射的注解,可用于类或方法上。
@RequestMapping
它的作用就是与请求相匹配,如果匹配上了,所修饰的方法才会被执行。这里我们只需要关注两个属性:
value :请求的路径,这个路径相对于应用的上下文,它是path 的别名。类型是一个 String[] ,也就是说它可以匹配多个请求路径
method: 请求的方法。我们知道 HTTP 协议的请求方式有GET 和POST. 或者使用@GetMapping, @PostMapping
当前的请求只有与@RequestMapping 上指定的属性都匹配的时候,才会执行它 标 注 的 方 法 。 下 面 分 析 几 个 例 子 , 假 设 应用的上下文路径为"http://localhost:9090/"
@RequestMapping("/users")请求的路径为 "http://localhost:9090/users", 请求方式没有限制,即可以是 GET 也可以是 POST,还能是其它的几个
@RequestMapping(value="/users", method= RequestMethod.GET) 请求路径为"http://localhost:9090/users", 请求方式只能是GET。
@RequestMapping(value="/users", method={ RequestMethod.GET, RequestMethod.POST}) 请求路径为“http://localhost:9090/users”, 请求方式只能是 GET 或者 POST。
我们编写处理器方法的目的,就是为了处理客户端提交的数据,而客户端的提交是按照 HTTP 协议报文格式来提交的,下面我们分析一段常见的HTTPPOST提交的报文来理解报文的各个部分与处理器方法参数的对应关系:
请求方法:对应到@RequestMapping 中的 method
请求 URI:中的"/students/create" 对应到@RequestMapping 中的value或者 path
请求头:比如获取 User-Agent 中的值则使用@RequestHeader("User-Agent") 来获取
请求参数:比如获取 name 参数的值,则使用@RequestParam("name")来获取。
- @Controller
- @RequestMapping("/students")
- public class StudentController {
- @RequestMapping(value="/create",method=RequestMethod.POST)
- public String create(
- @RequestParam("name") String name, @RequestParam("age") Integer age, @RequestHeader("User-Agent") String userAgent){
- return null;
- }
- }
如 果 请 求 参 数 的 名 称 与 处 理 器 方 法 中 的 参 数 名称相同,那么在使用@RequestParam 绑定的时候,可以省略参数,甚至连@RequestParam都可以省略。对于上面的例子,可以写成:
- @Controller
- @RequestMapping("/students")
- public class StudentController {
- @RequestMapping(value="/create",method=RequestMethod.POST)
- public String create(String name, Integer age){
- return null;
- }
- }
参数列表中还可以直接内置HttpServletRequest,HttpSession,HttpServletResponse 等对象. 使用 request 对象也可以接收

如果请求参数比较多,通常是将这些参数放到一个实体中,然后只需要在处理器方法上定义这个实体作为参数。HandlerAdapter 会将这个对象的实例创建出来,然后从请求参数中取出这些参数然后放到实体对象中,需要注意的是请求参数的名字需要与实体类中的属性一一对应,只有对应的属性才会提取参数的值
- public void edituser(User user){
- System.out.println(user);
- }
-
- //注意到在日期上添加了一个@DateTimeFormat,指定了Date 类型的格式. @DateTimeFormat(pattern="yyy-MM-dd")
- private Date birthday;