Spring MVC
一、Spring MVC流程
Spring MVC的流程是围绕 DispatcherServlet 而工作的,所以在 Spring MVC 中 DispatcherServlet 就是其最重要的内容 。 在 DispatcherServ let 的基础上,还存在其他的组件, 掌握流程和组件就是 SpringMVC 开发的基础。 关于Spring MVC的流程如下图所示
首先,在 Web 服务器启动的过程中,如果在 Spring Boot 机制下启 用 Spring MVC , 它就开始初始化一些重要的组件,如 DispactherServlet、 HandlerAdapter 的实现类 RequestMappingHandlerAdapter等组件对 象 。 关于这些组件的初始化,我们可以 看到 spring-webmvc-xxx.jar 包的属性文件DispatcherServlet.properties, 它定义的对象都是在 SpringMVC 开始时就初始化,并且存放在 Spring IoC容器中
其次是开发控制器(Controller)
package com.demo.controller
@Controller
@RequestMapping("/user")
public class UserController{
@AutoWired
private UserService userService=null;
@RequestMapping("details")
public ModelAndView details(Long id){
User user=Uservice.getUser(id);
ModelAndView mv=new ModelAndView();
mv.setViewName("user/details");
mv.addObject("user",user);
return mv;
}
}
@Controller 表明这是一个控制器,然后@RequestMapping 代表请求路径和控制器(或其方法)的映射关系,它会在 Web 服务器启动 Spring MVC 时,就被扫描到 HandlerMapping 的机制中存储,之后在用户发起请求被 DispatcherServlet拦截后,通过 U阳和其他的条件 , 通过 HandlerMapper机制就能找到对应的控制器(或其方法)进行响应 .是通过 HandlerMapping 返回的 是一个HandlerExecutionChain 对象
HandlerExecutionChain对象包含一个处理器(handler),这里的处理器是对控制器(controller)的包装,因为我们的控制器方法可能存在参数,那么处理器就可以读入HTTP和上下文的相关参数,传递给控制器方法。而在处理器包含了控制器方法的逻辑。此外还有处理器的拦截器(interceptor),这样就能够通过拦截器进一步的增强处理器的功能。
得到了处理器( handler ),还需要去运行,但是我们有普通 HTTP 请求,也有按 BeanName 的请求,甚至是 WebSocket 的请求,所以它还需要一个适配器去运行 HandlerExecutionChain 对象包含的处理器,这就是 HandlerAdapter 接口定义的实现类 。HttpRequestHandlerAdapter 是最常用的 HandlerAdapter 的实现类。通过请求的类型,DispatcherServlet 就会找到它来执行 Web 请求的 HandlerExecutionChain 对象包含的内容,这样就能够执行我们的处理器( handler)了 。
在处理器调用控制器时,它首先通过模型层得到数据,再放入数据模型中,最后将返回模型和视图( ModelAndView )对象,这里控制器设置的视图名称设置为“ user/details”,这样就走到了视图解析器( ViewResolver ),去解析视图逻辑名称了。
可以在application.properites.进行配置。
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
通过修改这样的配置,就能在 Spring Boot 的机制下定制InternalResourceViewResolver 这个视图解析器的初始化,也就是在返回视图名称之后,它会以前缀( prefix )和后缀( suffix )以及视图名称组成全路径定位视图 。视图解析器定位到视图后,视图的作用是将数据模型( Model )渲染,这样就能够响应用户的请求。这一步就是视图将数据模型植染( View )出来,用来展示给用户查看。按照我们控制器的返回,就是/WEB-INF/jsp/user/details .jsp 作为我们的视图
<% @ page pageEncoding="UTF- 8" %>
<% @ taglib prefix="c" uri= "http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title >用户详情</title>
</head>
<body>
<center>
<table border=”1 ” >
<tr>
<td>标签</td>
<td>值</td>
</tr>
<tr>
<td>用户编号</td>
<td><c:out value="${user.id}"></ c : out></td>
</tr>
<tr>
<td>用户名称</td>
<td><c:out value="${user.userName}"></c:out></td>
</tr>
<tr>
<td>用户备注</td>
<td><c:out value="${user.note}"></c:out></td>
</tr>
</table>
</center>
</body>
</html>
spring boot启动文件
@SpringBootApplication(scanBasePackages="com.demo")
@MappperScann(basePackages="com.demo",
annotationClass=Repository.class)
public class DemoApplication{
public static void main(String []args){
SpringApplication.run(DemoApplication.class,args);
}
}
二、处理器映射器
果 Web 工程使用 了 Spring MVC , 那么它在启动阶段就会将注解@RequestMapping 所配置的 内 容保存到处理器映射( HandlerMapping ) 机制 中去 , 然后等待请求的到来,通过拦截请求信息与 HandlerMapping 进行匹配,找到对应的处理器(它包含控制器的逻辑) , 并将处理器及其拦截器 保 存 到 HandlerExecutionChain 对 象中 , 返回给 DispatcherServlet ,这样DispatcherServlet 就可以运行它们 了。 从论述 中可以看 到, HandlerMapping 的主要任务是将请求定位到具体的处理器上 。
@RepuestMapping的源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.web.bind.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
//配置请求映射名称
String name() default "";
//通过路径映射
@AliasFor("path")
String[] value() default {};
//通过路径映射回path配置项
@AliasFor("value")
String[] path() default {};
//限定只响应HTTP请求类型,如GET、POST、HEAD、OPTIONs、PUT、TRACE等
//默认的情况下,可以相应所有的请求类型
RequestMethod[] method() default {};
//等存在对应的HTTP参数时才响应请求
String[] params() default {};
//限定请求头存在对应的参数才响应
String[] headers() default {};
//限定HTTP请求提交类型,如“application/json”,"text/html"
String[] consumes() default {};
//限定返回类型,仅当HTTP请求头中的(Accept)类型中包含指定参数类型时才返回
String[] produces() default {};
}
- value和path来设置请求的URL
- method限定HTTP的请求类型,为简化method配置项的配置,新增了@GetMapping 、@PostMapping、@PatchMappiing、@PutMapping、@DeleteMapping。可以看出@GetMapping对应的是HTTP的GET方法,@PostMapping 对应的是 Hπp 的 POST 方法。
三、获取控制器参数
处理器是对控制器的包装 ,在处理器运行的过程中会调度控制器的方法,只是
它在进入控制器方法之前会对 HTTP 的参数和上下文进行解析,将它们转换为控制器所需的参数。
1.在无注解下获取参数
在没有注解的情况下,springMVC 也可以获取参数,且允许参数为空,唯一的要求是参数名称和HTTP请求的参数名称保持一致。
package com.demo.cotroller;
@RequestMapping("/my")
@Controller
public class MyController{
@GetMapping("/no/annotation")
@ResponseBody
public Map<String,Object> noAnnotation(Integer intVal,Long longVal,String str){
Map<String,Object> paramsMap=new HashMap();
paramsMap.put("intVal",intVal);
paramsMap.put("longVal",longVal);
paramsMap.put("str",str);
return paramsMap;
}
}
浏览器输入
http : //localhost : 8080lmylnolannotation ?intVal=10&longVal=200
从代码中可以看出控制器方法参数中还有一个字符串参数 str,但因为参数在默认的规则下可以为空 ,所以这个请求并不会报锚,因为方法标注了@ResponseBody ,所以控制器返回的结果就会转化为 JSON 数据集。
2.使用@RequestParam获取参数
SpringMVC提供了@RequestParam来确定前后端参数的映射关系
package com.demo.cotroller;
@RequestMapping("/my")
@Controller
public class MyController{
@GetMapping("/annotation")
@ResponseBody
public Map<String,Object> requestParam(
@RequestParam("int_val")Integer intVal,
@RequestParam("long_val")Long longVal,
@RequestParam("str_val")String str){
Map<String,Object> paramsMap=new HashMap();
paramsMap.put("intVal",intVal);
paramsMap.put("longVal",longVal);
paramsMap.put("str",str);
return paramsMap;
}
}
在浏览器地址栏输入
http://localhost:8080/my/annotation?int_val=l & long_va1=2 & str_val=str
就能够看到请求的结果了 。 但如果把 3 个 HTTP 参数中的任意一个删去,就会得到异常报锚的信息,因为在默认的情况下@RequestParam 标注的参数是不能为空的
3.传递数组
SpringMVC中可以传递数组
@GetMapping("/requestArray")
@ResponseBody
public Map<String,Object> requestArray(
int[] intarr,
Long[] longArr,
String[] strArr){
Map<String,Object> paramsMap=new HashMap();
paramsMap.put("intarr",intarr);
paramsMap.put("longArr",longArr);
paramsMap.put("strArr",strArr);
return paramsMap;
}
h忧p ://localhost:8080/my/requestArray?intArr= l ,2,3& longArr=4 , 5,6&strr= str 1 ,str2,str3
可以 看 到 需要传递数组参数时, 每个参数的数组元素只需要通过逗号分隔即可 。
4.传递JSON(@RequestBody)
在当前前后端分离 的趋势下 ,使用 JSON 已经是十分普遍了 。 对于前端的页面或者于机应用,可以通过请求后端获取 JSON 数据集,这样它们就能很方便地将数据渲染到视图中 。 有时前端也需要提交较为复杂的数据到后端,为了更好组织和提高代码的可读性 , 可 以将数据转换为 JSON 数据集 ,通过 HTTP 请求体提交给后端 , 对此 SpringMVC 也提供了良好的支持 。
先搭建一个表单
<%@ page pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<heand>
<meta charset="UTF-8">
<title>新增用户</title>
<script src="https://code.jquery.com/jquery-3.2.0"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#submit").click(function(){
var userName=$("#userName").val();
var note=$("#note").val();
if($.trim(userName)==''){
alert("用户名不能为空")
return;
}
var params={
userName:userName,
note:note
};
$.post({
url="./insert",
contentType:"application/json";
data:JSON.Stringify(params),
successs:function(result){
if(result==null||result==null){
alert("插入失败")
return;
}
alert("插入成功")
}
})
});
});
</script>
</heand>
<body>
<div style="margin:20px 0;"></div>
<form id="insertForm">
<table>
<tr>
<td>用户名称</td>
<td><input id="userName" name="userName"</td>
</tr>
<tr>
<td>备注</td>
<td><input id="note" name="note"</td>
</tr>
<tr>
<td>用户名称</td>
<td align=right><input id="submit" type="button" value="提交"</td>
</tr>
</table>
</form>
</body>
</html>
这里定义了 一个简易的表单,它使用了 jQuery 进行 Ajax 提交。注意到加粗的代码,它指定了提交的请求地址 Curl )、数据( data )、提交类型( contentType )和事后事件( success ) 。 从脚本来看,这里先组织了一个 JSON 数据集, 而且把提交类型也设置为了 JSON 类型 ,然后才提交到控制器。这样控制器就可以得到一个 JSON 数据集的请求体了
为了打开这个表单,需要在 UserController 中编写一个 add 方法,它将返回一个字符串 , 映射到这个表单上,这样就能通过视图解析器( ViewResolver)找到它了 。然后再写一个相应新增用户的请求 insert 方法,它将从 HTTP 请求体中读出这个 JSON
package com.deml.controller
@Controller
@RequestMapping("/user")
public class UserController{
@Autowired
private UserService userService=null;
@GetMapping("/add")
public String add(){
return "/user/add";
}
@PostMapping("/insert")
@ResponseBody
public User insert(@RequestBody User user){
userService.insettUser(user);
return user;
}
}
接着录入表单 ,点击提交按钮, 这样通过 JavaScript 脚本提交 JSON 消息 , 就可以请求到控制器的 insert 方法 。 这个方法的参数标注为@RequestBody , 意味着它将接收前端提交的 JSON 请求体,而在 JSON 请求体与 User 类之间的属性名称是保持一致的,这样 Spring MVC 就会通过这层映射关系将 JSON 请求体转换为 User 对象
@RequestBody 标注在参数上,表示接收的是前端的JSON请求,同时会实现Json请求体到实参的转化
5.通过URL传递参数(@PathVariable)
SpringMVC 对此也提供 了 良好的支持 ,可以通过处理器映射和注解@PathVariable 的组合获取 URL 参数。首先通过处理器映射可以定位参数的位置和名称,而@PathVariable 则可以通过名称来获取参数
@GetMapping("/{id}")
@ResponseBody
public User get(@PathVariable("id")Long id){
return userService.getUser(id);
}
代码中首先通过@GetMapping 指定一个 URL , 然后用 {...}来标明参数的位置和名称。这里指定名称为 id , 这样 Spring MVC 就会根据请求去匹配这个方法。@PathVariable 配置的字符串为 id
6.获取格式化数据
在一些应用中往往需要格式化数据,其中最为典型的当属日期和货币。
springMVC也对此提供了支持@DataTimeFormat和@NumberFormat
@GetMapping ("/format/form")
public String showFormat () {
return "/format/formatter";
}
//获取提交参数
@PostMapping( "/format/commit")
@ResponseBody
public Map<String,Object> format(
@DateTimeFormat(iso=ISO.DATE) Date date ,
@NumberFormat(pattern ="# ,### .##") Double number ) {
Map<String , Object> dataMap =new HashMap<>() ;
dataMap .put ("date", date) ;
dataMap . put ("number", number) ;
return dataMap;
}
四、自定义参数转换规则
SpringMVC 提供的处理器会先以一套规则来实现参数的转换,在开发自定义转换规则时,就很有必要掌握这套转换规则了 。 而实际上处理器的转换规则还包含控制器返回后的处理,只是这节先讨论处理器是如何获取和转换参数的内容,其他的则留到后面再讨论,到时会揭开为什么使用注解@ResponseBody标注方法后,就能够把控制器返回转变为 JSON 数据集的秘密。
1.处理器获取参数逻辑
当一个请求来到时,在处理器执行的过程中,它首先会从HTTP请求上下文环境来得到参数。如果是简单的参数它会以简单的转发器进行转换,而这些简单的转发器是Spring MVC自身已经提供了的。但是如果是转化HTTP请求体(Body),它就会调用HttpMessageConverter接口的方法对请求体的信息进行转换。首先会先判断是否能对请求体进行转化,如果可以就会转化为Java类型
package org.springframework.http.converter;
import java.io.IOException;
import java.util.List;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
public interface HttpMessageConverter<T> {
//是否可读,其中var1为Java类型,var2为HTTP请求类型
boolean canRead(Class<?> var1, @Nullable MediaType var2);
//判断var1类型能否转化为var2类型,其中var1为Java类型,var2为HTTP请求类型
boolean canWrite(Class<?> var1, @Nullable MediaType var2);
//可支持的媒体类型列表
List<MediaType> getSupportedMediaTypes();
//当canRead验证通过后,读入HTTP请求信息
T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;
//当canWrite方法验证通过后,写入响应
void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}
之前代码中控制器方法的参数标注了@RequestBody,所以处理器会采用请求体( Body )的 内容进行参数转换,而前端的请求体为 JSON 类型,所以首先它会调用 canRead 方法来确定请求体是否可读 。 如果判定可读后,接着就是使用 read 方法,将前端提交的用户 JSON 类型的请求体转换为控制器的用户( User ) 类参数,这样控制器就能够得到参数了。
上面的 HttpMessageConveter 接口只是将 HTTP 的请求体转换为对应的 Java 对象,而对于 HTTP参数和其他内容,还没有进行讨论
为了讨论自定义的参数规则,很有必要先了解处理器转换参数的过程 。 在 Spring MVC 中, 是通过 WebDataBinder 机制来获取参数的 ,它的主要作用是解析 HTTP 请求的上下文, 然后在控制器的调用之前转换参数并且提供验证的功能,为调用控制器方法做准备 。 处理器会从 HTTP 请求中读取数据,然后 通过 三 种接口来进行各类参数转换,这 三 种接口是 Converter 、 Formatter 和GenericConverter 。 在 Spring MVC 的机制中这三种接 口的实现类都采用了注册机的机制, 默认的情况下 SpringMVC 己经在注册机内注册了许多的转换器,这样就可以实现大部分的数据类型的转换 , 所以在大部分的情况下无须开发者再提供转换器,这就是在上述章节中可以得到整型( Integer ) 、 长整型( Long )、字符串 C String )等各种各样参数的原因。同样地,当需要自定义转换规则时, 只需要在注册机上注册自己的转换器就可以了
WebDataBinder 机制还有一个重要的功能,那就是验证转换结果。关于验证机制,后面会再讨论。有了参数的转换和验证,最终控制器就可 以得到合法的参数。得到这些参数后,就可以调用控制器的方法了 。下图展示的是 HTTP 请求体( Body )的消息转换全流程图。
对于数据类型转换, SpringMVC 提供了 一个服务机制去管理,它就是 ConversionService 接口 。在默认的情况下,会使用这个接口的子类 DefaultFormattingConversionService 对象来管理这些转换类, 即注册机
在 Spring Boot 中还提供了特殊的机制来管理这些转换器。 Spring Boot 的 自动配置类 WebMvcAutoConfiguration 还定义了 一个内部WebMvcAutoConfigurationAdapter 其源码为
public void addFormatters(FormatterRegistry registry) {
Iterator var2 = this.getBeansOfType(Converter.class).iterator();
while(var2.hasNext()) {
Converter<?, ?> converter = (Converter)var2.next();
registry.addConverter(converter);
}
var2 = this.getBeansOfType(GenericConverter.class).iterator();
while(var2.hasNext()) {
GenericConverter converter = (GenericConverter)var2.next();
registry.addConverter(converter);
}
var2 = this.getBeansOfType(Formatter.class).iterator();
while(var2.hasNext()) {
Formatter<?> formatter = (Formatter)var2.next();
registry.addFormatter(formatter);
}
}
通过这个方法,可以看到在 Spring Boot 的初始化中 , 会将
对应用户自定义的 Converter、 Formatter 和 GenericConverter 的实现类所创建的 Spring Bean 自动地注册到 DefaultForma忧ingConversionService 对象中 。 这样对于开发者只需要自定义 Converter 、 Formatter和 GenericConverter 的接口 的 Bean, Spring Boot 就会通过这个方法将它们注册到 ConversionService对象中
2.一对一转换器(Converter)
Converter是一对一转发器,也就是从一种类转化为另一种类型.接口为
package org.springframework.core.convert.converter;
import org.springframework.lang.Nullable;
@FunctionalInterface
public interface Converter<S, T> {
@Nullable
//S为源类型,T为目标类型
T convert(S var1);
}
自定义转换器
package com.demo.converter
@Component
public class StringToUserConverter implements Converter<String ,user>{
@Override
public User convert(String userStr){
User user=new User();
String []strArr=userStr.split("-");
Long id=Long.praseLong(strArr[0]);
String userName=strArr[1];
String note=StrArr[2];
user.setId(id);
user.setUserrName(userName);
user.setNote(note);
return user;
}
}
类标注为@Component,并且实现了 Converter 接口,这样 Spring 就会将这个类扫描并装配到 IoC 容器中 。 对于 Spring Boot,之前分析过它会在初始化时把这个类 自动地注册到转换机制中,所以注册这步并不需要人工再处理。 这里泛型指定为 String 和 User,这样 SpringMVC 就会通过 HTTP的参数类型(String)和控制器的参数类型( User)进行匹配,就可以从注册机制中发现这个转换类,这样就能够将参数转换出来.
3.GenericConverter 集合和数组转换
GenericConverter 是数组转换器。因为 Spring MVC 自身提供了 一些数组转换器,需要自定义 的并不多 ,所以这里只介绍 SpringMVC 自定义的数组转换器。假设需要 同时新增多个用户,这样便需要传递一个用户列表 C List<User>)给控制器。此时SpringMVC 会使用 StringToCollectionConverter 转换它,这个类实现了 GenericConverter 接 口,并且是 Spring MVC 内部己经注册的数组转换器 。 它首
先会把字符串用逗号分隔为一个个的子宇符串,然后根据原类型泛型为 String、目标类型泛型为 User类,找到对应的 Converter 进行转换,将子字符串转换为 User 对象
五、数据模型
在 Spring MVC 流程中,控制器是业务逻辑核心内 容 ,而控制器的核心内容之一就是对数据的处理 。 SpringMVC 全流程的学习,可以看到允许控制器自定义模型和视图( ModelAndView ),其中模型是存放数据的地方,视图则是展示给用户 。
数据模型的作用是绑定数据。为后面的视图渲染做准备。SpringMVC使用的模型接口和类进行探讨
类 ModelAndView 中存在一个 Mode!Map 类型的属性, Mode!Map 继承
了 Linked.HashMap 类 , 所以它具备 Map 接口的一切特性,除此之外它还可以增加数据属性 。 在 SpringMVC 的应用中,如果在控制器方法的参数中使用 ModelAndView 、 Model 或者 ModelMap 作为参数类型, SpringMVC 会自动创建数据模型对象 .
package com.demo.controller;
@RequestMapping("/data")
@Controller
public class DataModelController{
// 注入用户服务类
@Autowired
private UserService userService=null;
//Model
@GetMapping("/model")
public String useModel(Long id, Model model){
User user=userService.getUser(id);
model.addAttribute("user",user);
return "data/user";
}
//ModeMap
@GetMapping("/modelMap")
public ModelAndView userModelMap(Long id,ModelMap modelMap){
User user =userService.getUser(id);
ModelAndView mv=new ModelAndView();
mv.setViewName("data/user");
modelMap.put("user",user);
return mv;
}
//ModelAndView
@GetMapping("/mav")
public ModelAndView useModelAndView(Long id,ModelAndView mv){
User user=userService.getUser(id);
mv.addObject("user",user);
mv.setViewName("data/user");
return mv;
}
}
六、视图与视图解析器
视图是渲染数据模型展示给用户的组件 , 在 Spring MVC 中又分为逻辑视图和非逻辑视图。逻辑视图是需要视图解析器( ViewResolver ) 进行进一步定位的 。 例如, 之前的例子所返回 的字符串之所以能找到对应 的 JSP , 就是因为使用了逻辑视 图 , 经 由视图解析器 的定位后 ,才能找到视图将数据模型进行渲染展示给用户查看。对于非逻辑视图 ,则并不需要进一步地定位视图 的位置 , 它只需要直接将数据模型渲染出来即可
在实际的工作中视图解析器 Interna!ResourceViewResolver 是 比较常用的
1.视图设计
对于视图,除了JSON和JSP视图之外,还有其他类型的视图如Excel、PDF。他们都会实现Spring MVC 定义的视图接口View,其源码如图所示。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.web.servlet;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
public interface View {
//响应状态属性
String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
//路径变量
String PATH_VARIABLES = View.class.getName() + ".pathVariables";
//选择内容类型
String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";
//相应类型
@Nullable
default String getContentType() {
return null;
}
//渲染方法
void render(@Nullable Map<String, ?> var1, HttpServletRequest var2, HttpServletResponse var3) throws Exception;
}
- getContentType 方法是获取 HTTP 响应类型的 ,它可以返回的
类型是文本、 JSON 数据集或者文件等 - render方法则是将数据模型渲染到视图的,这是视图的核心方法,在它 的参数中 , model 是数据模型,实际就是从控制器(或者由处理器自动绑定)返回的数据模型,这样 render 方法就可以把它渲染出来。渲染视图是比较复杂的过程,为了简化视图渲染的开发,在 SpringMVC 中已经给开发者提供了许多开发好的视图类 , 所以在大部分的情况下并不需要自己开发自己的视图
七、文件上传
1.Spring MVC对文件上传的支持
首先,DispatcherServlet会使用适配器模式,将HttpServletRequest接口转化为MultipartHttpServletRequest对象。MultipartHeepSrvletRequest接口扩展了HttpServletRequest接口的所有方法。而且定义了一些操作文件的方法。这样通过这些方法就可以实现对上传文件的操作
对于文件上传的场景,spring MVC 将HttpServletRequest对象转化为MultipartHttpServletRequest对象。MultipartHttpServletRequest接口存在许多的方法用来处理文件。在使用时放需要配置Spring MVC上传文件时,还需要配置MultipartHeepServletRequest,这个任务时通过MultipartResolver接口实现的,它包含两个实现类StandardSrvletMultipartResolver和CommonsMultipartResolver,这两个类都可以实现文件上传,但是推荐使用StandardServletMultipartResolver.
在Spring boot 中如果你没有自定义的MultipartResover对象。那么自动配置机制会自动创建MultipartResolver对象。
application.properties中关于文件上传的配置
#MULTIPART(MultiartProperties)
#是否启用SpringMVC多分部上传gongn
spring.servlet.multipart.enable=true
#将文件写入磁盘的阈值。值可以使用后缀”MB“或者”KB“来表示兆字节大小
spring.servlet.multipart.file-size-threshold=0
#指定默认上传的文件夹
spring.servlet.multipart.location=
#限制单个文件最大大小
spring.servlet.multipart.max-file-size=1MB
#限制所有文件最大大小
spring.servlet.multipart.max-request-size=10MB
#是否延迟多部件文件请求的参数和文件的解析
sping.servlet.multipart.resolve-lazily=false
根据配置Spring Boot会自动生成StandardServletMultipartResolver对象,这样就能够对上传的文件进行配置。对于文件的上传可以使用Servlet API 提供的Part接口或者Spring Mvc提供的MultipartFile接口作为参数。其实无论使用哪种类都是允许的。推荐使用Part
2.开发上传功能
applicaiton.properties配置
spring.servlet.multipart.location=d:/demo
spring.servlet.multipart.max-file-size=524880
spring.servlet.multipart.max-request-size=20Mb
上传文件的JSP页面
<%@ page language="java" contentType="text/html";charset="UTF-8”
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD html 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dta">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html";charset="UTF-8">
<tiltle>文件上传</tiltle>
</head>
<body>
<form method="post" action="./request" enctype="multipart/form-data">
<input type="file" name="file" value="请选择上传的文件">
<input type="submit" value="提交" />
</form>
</body>
</html>
注意