Spring MVC概述
Spring MVC是Spring提供的一个轻量级Web框架,它实现了Web MVC设计模式。
SpringMVC的优势
- 清晰的角色划分
- 前端控制器(DispatcherServlet)
- 请求到处理器映射(HandlerMapping)
- 处理器适配器(HandlerAdapter)
- 视图解析器(ViewResolver)
- 处理器或页面控制器(Controller)
- 验证器(Validator)
- 命令对象(Command 请求参数绑定到的对象就叫命令对象)
- 表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)
- 是Spring框架的一部分,可以方便地利用Spring所提供的其他功能
- 灵活性强,易于与其他框架集成。
- 可自动绑定用户输入,并能正确地转换数据类型。
- 内置了常见的校验器,可以校验用户输入。如果校验不能通过,就会复位到输入表单
- 支持多种视图技术,如JSP、Velocity和FreeMarker等视图技术
- 使用基于XML的配置文件,在编辑后,不需要重新编译应用程序。
SpringMVC入门程序
项目的目录结构如下:
1.构建项目,搭建环境
创建Maven项目,并且在pom.xml文件中添加依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- 版本锁定 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.6.RELEASE</version> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
web.xml
在web.xml中配置Spring MVC的前端控制器DispatcherServlet。代码如下:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<!--配置前端控制器-->
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--初始化时加载配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-config.xml</param-value>
</init-param>
<!--表示容器来启动时立即加载Servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
在web.xml中,主要对< servlet >和< servlet-mapping >元素进行了配置。在< servlet >中配置了Spring MVC的前端控制器DispatcherServlet,并通过其子元素< init-param >配置了Spring MVC配置文件的位置,< load-on-startup >元素中的1表示容器在启动时立即加载这个Servlet;在< servlet-mapping >中,通过< url-pattern >元素的"/"拦截所有URL,并交由DispatcherServlet处理。
创建Controller类
创建控制器类ControllerTest,该类需要实现Controller接口,代码如下:
package com.ssm.controller;
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 ControllerTest implements Controller{
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//创建ModelAndView对象
ModelAndView m = new ModelAndView();
//向模型对象中添加一个名称为msg的字符串对象
m.addObject("msg","第一个Spring MVC程序");
//设置返回的视图路径
m.setViewName("/WEB-INF/jsp/welcome.jsp");
return m;
}
}
handleRequest()是Contoller接口的实现方法,ControllerTest类会调用该方法处理请求,并返回一个包含视图名或包含视图名与模型的ModelAndroid对象。我们向模型对象中添加了一个名称为msg的字符串对象,并设置返回的视图路径为WEB-INF/jsp/welcome.jsp,这样请求就会被转发到welcome.jsp页面。
springmvc-config.xml
创建配置文件springmvc-config.xml,在文件中配置控制器信息,代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--配置处理器Handle,映射controllerTest请求-->
<bean name="/controllerTest" class="com.ssm.controller.ControllerTest"/>
<!--处理器映射,将处理器Handle的name作为url进行查找-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理适配器,配置对处理器中handleRequest()方法的调用-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
</bean>
</beans>
在代码中,定义了一个"/ControllerTest"的Bean,该Bean会将控制器类ControllerTest映射到"/ControllerTest"请求中;
注意: 在老版本的Spring中,配置文件内必须要配置处理器映射器、处理器适配器和视图解析器。在Spring4.0以后,Spring内部会默认配置来完成相应的工作。
welcome.jsp
在welcome.jsp中使用EL表达式获取msg中的信息,代码如下;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>入门程序</title>
</head>
<body>
${msg}
</body>
</html>
将项目发布到Tomcat服务器并启动服务器,在浏览器中访问“http://localhost:8081/controllerTest”,会出现如下页面:
这说明我们第一个SpringMVC程序已经执行成功了。
入门案例执行流程分析
- 用户通过浏览器向服务器发送请求,请求会被SpringMVC的前端控制器DispatcherServlet所拦截。
- DispatcherServlet拦截到请求后,会调用HandlerMapping处理器映射器
- 处理器映射器根据请求URL找到具体的处理器,生成处理器对象及处理器拦截器(如果有就生成) 一并返回给DispatcherServlet
- DispatcherServlet会通过返回信息选择合适的HandlerAdapter(处理器适配器)
- HandlerAdapter会调用并执行Handler(处理器),这里的处理器就是程序中编写的Controller类,也被称为后端控制器。
- Controller执行完成后,会返回一个ModelAndView对象,该对象中包含视图名或包含模型与视图名。
- HandlerAdapter将ModelAndView对象返回给DispatcherServlet
- DispatcherServlet会根据ModelAndView对象选择一个合适的ViewResolver(视图解析器)
- ViewResolver解析后,会向DispatcherServlet中返回具体的View(视图)。
- DispatcherServlet对View进行渲染(即将模型数据填充至视图中)
- 视图渲染结果会返回给客户端浏览器显示。
在上述执行过程中,我们并不需要关心DispatcherServlet、HandlerMapping、HandlerAdapter和ViewResolver对象的工作是如何执行的,只需要配置前端控制器(DispatcherServlet),完成Controller中的业务处理,并在视图中(View)中展示相对应信息即可。
SpringMVC的注解
Controller注解类型
org.springframework.stereotype.Controller注解类型用于指定Spring类的实例是一个控制器,其注解形式为@Controller。使用了注解,我们就不需要再实现Controller接口。
@Controller注解在控制器类使用实例如下:
@Controller
public class ControllerTest{
.....
}
为了保证Spring能够找到控制器类,还需要再SpringMVC的配置文件中添加相应的扫描配置信息。具体如下:
- 在配置文件的声明引入spring-context
- 使用< context:component-scan >元素指定需要扫描的类包
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定需要扫描的包-->
<context:component-scan base-package="com.ssm.controller"/>
</beans>
上述代码中,com.ssm.controller包下所有标注了注解的类都会被Spring所处理。同时,Controller接口的实现类只能处理一个单一的请求动作,而基于注解的控制器可以同时处理多个请求动作,在使用上更加灵活。
注意: 使用注解时,需要依赖Spring的AOP包(spring.aop-5.0.2RELEASE.jar),否则程序运行时会报错。
RequestMapping注解类型
RequestMapping用于映射一个请求或一个方法,其注解形式为@RequestMapping,可以使用该注解标注在一个方法或一个类上。
标注在方法上
当标注在一个方法上时,该方法将成为一个请求处理方法,它会在程序接收到对应的URL请求时被调用,代码示例如下:
@Controller
public class AnnotationControllerTest{
@RequestMapping(value="/annotationController")
public ModelAndView handleRequest(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception(
return m;
)
}
使用@RequestMapping注解后,当访问http://localhost:8081/annotationController时,就会自动调用handleRequest()方法。
标记在类上
当标注在一个类上时,该类中的所有方法都将映射为相对于类级别的请求,表示该控制器所处理的所有请求都被映射到value属性值所指定的路径下。
@Controller
@RequestMapping(value="/controll")
public class AnnotationControllerTest{
@RequestMapping(value="/annotationController")
public ModelAndView handleRequest(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception(
return m;
)
}
由于在类上添加了@RequestMapping注解,当访问http://localhost:8081/controll/annotationController才会执行handleRequest方法,如果想访问该类中其他的方法,也需要在请求中加上"/control"。
@RequestMapping注解的属性
@RequestMapping注解除了可以指定value属性外,还可以指定其他一些属性,如下表所示:
所有属性都是可选的,但其默认属性是value。当value是其唯一属性时,可以省略属性名,例如下面两种标注:
@RequestMapping(value="/annotationController")
@RequestMapping("/annotationController")
组合注解
组合注解可以帮助我们简化常用的HTTP方法的映射,并更好的表达被注解方法的语言。其组合注解如下所示:
- @GetMapping:匹配GET方式的请求
- @PostMapping:匹配POST方式的请求
- @PutMapping:匹配PUT方式的请求
- @DeleteMapping:匹配DELETE方式的请求
- @PatchMapping:匹配PATCH方式的请求
以@GetMapping为例,它会将Http Get请求映射到特定的处理方法上
传统的@RequestMapping注解使用如下:
@RequestMapping(value="/user/{id}",method=RequestMethod.Get)
public String selectUserById(String id){
...
}
使用@GetMapping后,可以省略method属性,代码如下
@GetMapping(value="/user/{id}")
public String selectUserById(String id){
...
}
请求处理方法的参数类型和返回类型
在控制器类中,每一个请求处理方法都可以有多个不同类型的参数,以及一个多种类型的返回结果。在我们入门程序中,handleRequest()方法的参数就是对应请求的HttpServletRequest和HttpServletResponse两种参数类型。
除此之外,还可以使用其他的参数类型。例如在请求处理方法中需要访问HttpSession对象,就可以添加HttpSession作为参数,Spring会将对象正确地传递给方法,示例如下:
@RequestMapping(value="/annotationController")
public ModelAndView handleRequest(HttpSession session)(
return m;
)
在请求处理方法中,可以出现的参数类型如下:
- HttpServletRequest
- HttpServletResponse
- HttpSession
- WebRequest
- NativeWebRequest
- @PathVariable、@MatrixVariable、@RequestParam、@RequestHeader、@RequestBody、 @RequestPart、@SessionAttribute、@RequestAttribute注解
- Model
- ModelMap等等。
注意:
Model类型不是一个Servlet API类型,而是一个包含Map对象的Spring MVC类型。如果方法中添加了Model参数,那么每次调用该请求处理方法时,SpringMVC都会创建Model对象,并将其作为 参数传递给方法。
在我们入门程序中,请求处理方法返回的是一个ModelAndView类型的数据。除了这种类型外,请求处理方法还可以返回其他类型的数据。SpringMVC所支持的常见返回类型如下:
- ModelAndView
- Model
- Map
- View
- String
- void
- HttpEntity< ?>或ResponseEntity< ?>
- Callable< ?>
- DeferredResult< ?>
常见的返回类型有ModelAndView、String和void。其中ModelAndView类型中可以添加Model数据,并指定视图;String类型的返回值可以跳转视图,但不能携带数据。而void类型主要在异步请求是使用,它只返回数据,而不会跳转视图。
由于ModelAndView类型未能实现数据与视图之间的解耦。我们在开发中最常用使用String。虽然String类型的返回值不能携带数据给视图页面,但是我们可以通过Model参数类型将数据带入视图页面,代码示例如下:
@RequestMapping(value="/annotationController")
public ModelAndView handleRequest(HttpServletRequest arg0,
HttpServletResponse arg1,Model model) throws Exception(
model.addAttribute("msg","第一个SpringMVC程序")
return "/WEB-INF/jsp/welcome.jsp";
)
String类型除了可以返回上述代码中的视图页面外,还可以进行重定向与请求转发,具体如下:
redirect重定向
例如,在修改用户信息操作后,将请求重定向到用户查询方法上,代码如下:
@RequestMapping(value="/update")
public String update(HttpServletRequest arg0,
HttpServletResponse arg1,Model model) throws Exception(
return "redirect:queryUser";
)
forward请求转发
例如,用户执行修改操作时,转发到用户修改界面,代码如下:
@RequestMapping(value="/toEdit")
public String toEdit(HttpServletRequest arg0,
HttpServletResponse arg1,Model model) throws Exception(
return "forward:editUser";
)
关于重定向和转发这里只做相关的介绍,具体的使用后面的博客中会详细的介绍。
ViewResolver(视图解析器)
Spring MVC中的视图解析器负责解析视图,可以在配置文件中定义一个ViewResolver来配置视图解析器,代码如下:
<!--视图解析器-->
<bean id=“viewResolver”
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--设置前缀-->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!--设置后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
我们这样设置完视图解析器后,在入门程序中,逻辑视图名只需设置为"welcome",而不再需要设置为"/WEB-INF/jsp/welcome.jsp",在访问视图解析器会自动地添加前缀和后缀。
基于注解的SpringMVC应用
我们对上面的入门程序进行修改即可。
修改springmvc-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--定义扫描器-->
<context:component-scan base-package="com.ssm.controller"/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
首先通过组件扫描器指定了需要扫描的包,然后定义视图解析器。
修改Controller类
package com.ssm.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("/controll")
public class ControllerTest{
@RequestMapping("/annotationController")
public String handleRequest(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
model.addAttribute("msg","第一个SpringMVC程序");
return "welcome";
}
}
当我们访问http://localhost:8081/controll/annotationController的时候,会出现如下的界面:
从中可以看成,通过注解的方式同样实现了第一个SpringMVC程序的运行。