Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架。
易于同其它View框架(Tiles等)无缝集成,采用IOC便于测试。Spring MVC的核心为Controller控制器,用于处理请求产生响应。
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.14.RELEASEversion>
dependency>
dependencies>
spring-webmvc可以一次性引入spring的核心包,aop包和MVC需要的jar包
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-value>
init-param>
<load-on-startup>0load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
DispatcherServlet是Spring MVC的核心类用于拦截前端的请求,并根据HTTP请求路径调用相关的Controller控制器去处理。
如果没有添加
load-on-startup
标签,程序将在浏览器第一次进行访问时创建DispatcherServlet,所以为了提高程序的响应速度一般在服务启动后就开始创建
配置Spring核心配置文件,添加context和mvc约束。
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.spring.mvc"/>
<mvc:annotation-driven/>
<mvc:default-servlet-handler />
beans>
添加后对于前台请求的静态资源Servlet将不会再进行处理,提高程序效率
Spring MVC可以通过注解的形式为方法添加对应的URL映射,使核心控制器对前端的请求进行分发。常用的注解主要有一下三类:
注解 | 描述 |
---|---|
@GetMapping(value = “{url}”) | 获取前端的Get请求,加在方法上用于指定请求的处理方法 |
@PostMapping(value = “{url}”) | 获取前端的Post请求,加在方法上用于指定请求的处理方法 |
@RequestMapping(value = “{url}”) | 获取前端请求 若加在方法上不区分Get\Post请求,若需要指定请求方法可以添加 method = RequestMethod.GET 属性若加在类上,指定的连接地址则为请求地址的公有地址,例如 /employee/add 等增删改查的请求,可以在类上加@RequestMapping("/employee") ,控制器内的具体方法就可以写成@PostMapping("/add") |
Spring MVC提供了便捷方法可以在控制器方法中书写对应的请求参数,如此核心控制器会自动将请求中的参数赋值给方法中的参数上,极大简化了接收参数的方法。
对于参数的数据类型Spring MVC会自动进行转化,例如某一参数为Integer类型,Spring MVC会将请求中的参数自动转化为Integer类型。
当请求的参数名与控制器方法中的参数名不相同时,可以对方法参数添加@RequestParam
注解对请求参数进行映射。
若控制器的方法中为一个实体类,Spring MVC会根据请求的参数名称,自动去寻找实体类中名称相同的属性进行赋值并自动封装为实体类并传入控制器的方法中。
若控制器方法中即有实体类也有参数,且参数与实体类中的属性名称相同,Spring MVC会对所有名称相同的属性进行赋值,可以避免赋值遗漏
当前台需要传递复合数据时,可以在Controller方法中用一个数组来接收数据,例如:
@PostMapping("/apply")
@ResponseBody
public String apply(@RequestParam(value = "n",defaultValue = "ANON") String name, String course, Integer[] purpose){
System.out.println(name);
System.out.println(course);
for (Integer p : purpose) {
System.out.println(p);
}
return "SUCCESS";
}
当前端未传入合适的值给后台时,可以使用@RequestParam设置默认值以避免后续业务处理可能会产生的错误,defaultValue属性为默认值,value为映射的前端传递的参数名
在Controller方法中使用List对象的参数同样可以接收前端的复合数据,并且需要在参数前添加@RequestParam
就可以通知Controller使用List集合进行封装,例如:
@PostMapping("/apply")
@ResponseBody
public String apply(String name, String course, @RequestParam List<Integer> purpose){
System.out.println(name);
System.out.println(course);
for (Integer p : purpose) {
System.out.println(p);
}
return "SUCCESS";
}
复合数据类型同样可以使用Java Bean来接收,创建带有List属性的实体类,Spring MVC会自动进行封装
与使用List相同,当参数为Map类型时并添加@RequestParam注解后,Spring MVC就会自动将前台参数封装为Map集合,请求中的参数名为键参数值为值,例如:
@PostMapping("/apply")
@ResponseBody
public String apply(@RequestParam Map map){
System.out.println(map);
return "SUCCESS";
}
使用Map集合时要注意,当请求中包含复合数据时Map只会获取第一个值而无法获取复合数据中所有的数据,所以在使用Map集合时需要保证前端请求数据中不包含复合数据
当一个实体类中包含另一个实体类时,想要将前端请求能够自动封装关联的实体类中,就需要在前端请求的属性上加上关联类属性名的前缀,例如:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title>
head>
<body>
用户名:<input name="username">
密码:<input name="password">
姓名:<input name="idcard.name">
身份证:<input name="idcard.idno">
过期时间:<input name="idcard.expire">
body>
html>
public class User {
private String username;
private String password;
private IDCard idCard = new IDCard();
// getter/setter
......
}
前端请求都是以字符串传递,通过Spring MVC进行数据类型转化,对于时间类型的参数则需要使用注解@DateTimeFormat(pattern = "yyyy-MM-dd")
通知Spring MVC进行数据类型转换,无论是使用方法参数或者Java Bean都可以使用注解进行转化。
除了使用注解还可以使用自定义转换器:
package com.springmvc.converter;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyDateConverter implements Converter<String, Date> {
public Date convert(String s) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
Date d = sdf.parse(s);
return d;
} catch (ParseException e) {
return null;
}
}
}
实现自定义转换器需要继承Spring MVC的Converter
接口,实现convert()
方法,在此方法中可以实现时间格式的转换,并返回时间类型。创建好自定义转换器后,还需在配置文件中添加对应的实例,Spring MVC才能在需要的时候自动对时间格式进行转化。
<mvc:annotation-driven conversion-service="conversionService">
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.springmvc.converter.MyDateConverter"/>
set>
property>
bean>
修改Tomcat的servlet.xml文件,在Connector
标签中添加URIEncoding=utf-8
即可解决Get请求中的乱码。
在Servlet中解决乱码问题时通过构建过滤器在请求过程中拦截请求并对其进行编码转换,而Spring MVC中封装好了一个过滤器可以直接在web.xml中直接添加过滤器,例如:
<filter>
<filter-name>characterFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>characterFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<mvc:annotation-driven conversion-service="conversionService">
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=utf-8value>
list>
property>
bean>
mvc:message-converters>
mvc:annotation-driven>
Spring MVC中也封装好了HTTP文本消息的转换器,只需要在mvc
中实例化对应的类就可以解决响应中的乱码问题。
解决了在Spring MVC中如何接收请求后,此时就需要开始了解后台产生的数据如何传递给前台。Spring MVC提供了两种方案:@ResponseBody和ModelAndView。
使用注解@ResponseBody将会直接产生响应体,不会再涉及前端视图,@ResponseBody产生的响应体可以是JSON、XML、HTML或字符串等格式数据,且会受到StringHttpMessageConverter所影响。因此,对于复杂的前端页面注解方式无法达到灵活的为前端注入数据。
ModelAndView是Spring MVC中用于桥接视图与控制器的类,该类可以将数据对象与模板引擎进行绑定,而ModelAndView的默认模板引擎为JSP,因此可以通过EL表达式进行数据的输出。
示例:
@GetMapping("/printUser")
public ModelAndView printUser(User user) {
// 创建ModelAndView对象,并利用构造方法绑定视图
ModelAndView modelAndView = new ModelAndView("/success.jsp");
// 向对象中添加数据
modelAndView.addObject("user", user);
return modelAndView;
}
使用ModelAndView时要注意一下几个问题:
addObject()
方法时,数据默认是放在当前请求中的redirect:
前缀,例如:new ModelAndView("redirect:/success.jsp")
与ModelAndView用法相类似的还有一种String+ModelMap的用法,其本质上就是将MedolAndView的指定跳转页面和绑定数据分开实现,示例:
@GetMapping("/printUser")
public String printUser(User user, ModelMap modelMap) {
String view = "/success.jsp";
modelMap.addAttribute("user", user);
return view;
}