Spring MVC
Spring MVC是目前主流的实现MVC设计模式的企业级开发框架,Spring框架的一个子模块,无需整合,开发起来更加便捷。
什么是MVC设计模式
将应用程序分为Control、Model、View三层,Controller接受客户端请求,调用Model生成业务数据,传递个View。
Spring MVC就是对这套流程的封装,屏蔽了很多底层代码,开放出接口,使开发者更加轻松和便捷的开发出web应用
Spring MVC的核心组件
- DispatcherServlet:前置控制器,是整个流程控制的核心,控制其他组件的执行,进行统一调度,降低组件之间的耦合性,相当于总指挥。
- Handler:处理器,完成具体的业务逻辑,相当于Servlet和Action。
- HandlerMapping:DispatcherServlet接受请求之后,通过HandlerMapping将不同的请求映射到不同的Handler。
- HandlerInterceptor:处理器拦截器,是一个接口,如果需要完成一些拦截器处理,可以实现该接口。
- HandleExecutionChain:处理器执行链,包括两部分内容:Handler和HanlerInterceptor(系统会有一个默认HanlerInterceptor,如果需要各位设置拦截,可以添加拦截器)。
- HandlerAdapter:处理器适配器,Handler执行业务方法之前,需要进行一系列的操作包括表单数据的验证、数据类型的转换、将表单数据分装到javabean等。这些操作都是由HandlerAdapter完成,开发者注意力集中在业务逻辑的处理上,DispatcherServlet通过HandlerAdapter执行不同的Handler.
- ModelAndView: 装载了模型数据和视图信息,作为Handler的处理结果,返回给DispatcherServlet。
- ViewResolver:视图解析器,DispatcherServlet通过它将逻辑视图解析为物理视图。
Spring MVC的工作流程
- 客户端请求被DispatcherServlet接受。
- 根据HandlerMapping映射到Handler
- 生成Handler和HandlerInterceptor。
- Handler和HandlerInterceptor以HandleExecutionChain的形式一并返回给DispatcherServlet。
- DispatcherServlet通过HandlerAdapter调用Handler的方法完成业务逻辑处理。
- Handler返回ModelAndView给DispatcherServlet。
- DispatcherServlet将获取的ModelAndView对象传给ViewResolver视图解析器,将逻辑视图解析为物理视图View。
- ViewResolver返回一个View给DispatcherServlet。
- DispatcherServlet根据View进行视图渲染(将模型数据Model填充到视图View中)。
- DispatcherServlet将渲染后的结果上传服务器。
SpringMVC流程非常复杂,实际开发起中很简单,因为大部分的组件不需要开发者创建、管理,只需要通过配置文件的方式完成配置即可。真正需要开发者进行处理的只有Handler、View。
如何使用?
1.创建maven工程,pom.xml
1 <dependency>
2 <groupId>org.springframework</groupId>
3 <artifactId>spring-webmvc</artifactId>
4 <version>5.0.11.RELEASE</version>
5 </dependency>
2.在web.xml添加一个servlet。
1 <!DOCTYPE web-app PUBLIC
2 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
3 "http://java.sun.com/dtd/web-app_2_3.dtd" >
4
5 <web-app>
6 <display-name>Archetype Created Web Application</display-name>
7 <servlet>
8 <servlet-name>dispatcherServlet</servlet-name>
9 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
10 <init-param>
11 <param-name>contextConfigLocation</param-name>
12 <param-value>classpath:springmvc.xml</param-value>
13 </init-param>
14 </servlet>
15
16 <servlet-mapping>
17 <servlet-name>dispatcherServlet</servlet-name>
18 <url-pattern>/</url-pattern>
19 </servlet-mapping>
20 </web-app>
3.springmvc.xml中进行配置
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:context="http://www.springframework.org/schema/context"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
6
7 <!-- 自动扫描 -->
8 <context:component-scan base-package="com.wiggin"></context:component-scan>
9
10 <!-- 视图解析器(逻辑视图解析成物理视图) -->
11 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
12 <!-- 前置字符和后置字符 -->
13 <property name="prefix" value="/"></property>
14 <property name="suffix" value=".jsp"></property>
15 </bean>
16 </beans
4.创建Handler
1 package com.wiggin.controller;
2
3 import org.springframework.stereotype.Controller;
4 import org.springframework.web.bind.annotation.RequestMapping;
5
6 @Controller // 交给了ioc以及包含了控制器功能
7 public class HelloHandler {
8 @RequestMapping("/index") // 返回给index视图
9 public String index(){
10 System.out.printf("执行了index..");
11 return "index";
12 }
13 }
注解:
- @ Controller表示该控制器的每一个业务方法的返回值会交给视图解析器来解析在类的定义处添加,将该类交给IoC容器来管理(结合springmvc.xml的自动扫描配置使用),同时使其成为一个控制器,可以接收客户的请求
- @RequestMapping
Spring MVC通过@RequestMapping注解将URL请求与业务方法进行映射,在Handler的类定义处以及方法定义处都可以添加@RequestMapping,在类定义处添加,相当于客户端多了一层访问路径。
相关参数:
1.value:指定URL请求地实际地址,是@RequestMapping的默认值
1 @RequestMapping("/index") // 返回给index视图
2 public String index(){
3 System.out.printf("执行了index..");
4 return "index";
5 }
等于
1 @RequestMapping(value = "/index") // 返回给index视图
2 public String index(){
3 System.out.printf("执行了index..");
4 return "index";
5 }
2.method: 指定请求method类型,GET,POST,PUT,DELET。
1 @RequestMapping(value = "/index",method = RequestMethod.GET) // 返回给index视图
2 public String index(){
3 System.out.printf("执行了index..");
4 return "index";
5 }
index的方法只能使用GET请求。
3.parms: 请求中必须包含的参数,否则无法调用该方法
1 @RequestMapping(value = "/index",method = RequestMethod.GET,params = {"name","id=10"}) // 返回给index视图
2 public String index(){
3 System.out.printf("执行了index..");
4 return "index";
5 }
关于参数绑定,在形参列表中通过添加@RequestParam注解完成Http请求参数与业务方法的形参的映射。
1 @RequestMapping(value = "/index",method = RequestMethod.GET,params = {"name","age=10"}) // 返回给index视图
2 public String index(String name,@RequestParam("age") int id){
3 System.out.println(name);
4 System.out.println(id);
5 System.out.println("执行了index..");
6 return "index";
7 }
上述代码的中的请求参数name和age分别赋值给了形参name和age,HandlerAdaptor请求参数name和age的类型自动转型为形参name和age的形式。
执行原理:DispatcherServlet捕获url,根据HandlerMapping映射到Handler,即有@RequestMapping("/index")的@Controller,由springmvc执行方法,最后返回逻辑视图到DispatcherServlet中,由ViewResolver将返回视图名添加前后缀,变为物理视图,最后找到target文件所对应的jsp文件,将其返回给客户端。
补充:Spring MVC也支持RESTful风格的URL。
传统类型 http://localhost:8080/hello/index?name=wiggin&age=10
REST: http://localhost:8080/hello/index/wiggin/10
1 @RequestMapping("/rest/{name}/{age}")
2 public String rest(@PathVariable("name") String name,@PathVariable("age") int age){
3 System.out.println(name);
4 System.out.println(age);
5 return "index";
6 }
REST风格URL必须要加@PathVariable来完成参数映射数映射
- 映射cookie
Spring MVC通过映射可以直接在业务方法中获取cookie的值
1 @RequestMapping("/cookie")
2 public String cookie(@CookieValue(value = "JSESSIONID") String sessionId){
3 System.out.println(sessionId);
4 return "index";
- 使用javaBean绑定参数
Spring MVC会根据请求参数名和javaBean属性名进行自动匹配,自动为对象填充属性值,同时支持及联属性。
1 package com.wiggin.entity;
2
3 import lombok.Data;
4
5 @Data
6 public class Address {
7 private String value;
8 }
----
1 package com.wiggin.entity;
2
3 import lombok.Data;
4
5 @Data
6 public class User {
7 private long id;
8 private String name;
9 private Address address;
10 }
----
1 <%--
2 Created by IntelliJ IDEA.
3 User: Administrator
4 Date: 2020/8/3
5 Time: 22:12
6 To change this template use File | Settings | File Templates.
7 --%>
8 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
9 <html>
10 <head>
11 <title>Title</title>
12 </head>
13 <body>
14 <form action="/hello/save" method="post">
15 用户id:<input type="text" name="id"></br>
16 用户名:<input type="text" name="name"></br>
17 用户地址:<input type="text" name="address.value"></br>
18 <input type="submit" value="注册">
19 </form>
20 </body>
21 </html>
----
1 @RequestMapping(value = "/save",method = RequestMethod.POST)
2 public String save(User user){
3 System.out.println(user);
4 return "index";
5 }
防止输入的值传入后台时中文出现乱码需要在web.xml中配置过滤器
1 <!-- 过滤器 -->
2 <filter>
3 <filter-name>encodingFilter</filter-name>
4 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
5 <init-param>
6 <param-name>encoding</param-name>
7 <param-value>UTF-8</param-value>
8 </init-param>
9 </filter>
10
11 <!-- 拦截所有的请求 -->
12 <filter-mapping>
13 <filter-name>encodingFilter</filter-name>
14 <url-pattern>/*</url-pattern>
15 </filter-mapping>
- JSP页面的转发和重定向
Spring MVC默认是转发的形式来响应JSP
1.转发
1 @RequestMapping("/forward")
2 public String forward(){
3 return "forward:/index.jsp";
4 // 相当于 return "index";
5 }
2.重定向
1 @RequestMapping("/redirect")
2 public String redirect(){
3 return "redirect:/index.jsp";
4 }