spring(7)spring mvc 的高级技术
2.1)CommonsMultipartResolver:使用 Jakarta Commons FileUpload 解析 multipart请求;2.2)StandardServletMultipartResolver:依赖于Servlet3.0 对 multipart 请求 的支持;(干货——优选方案,因为它不依赖于第三方库)
@Beanpublic MultipartResolver multipartResolver() throws IOException {return new StandardServletMultipartResolver();}
2.1)看个荔枝:最基本的 DispatcherServlet multipart配置,它将临时路径设置为 "/tmp/spittr/uploads"DispatcherServlet ds = new DispatcherServlet(); Dynamic registration = context.addServlet("appServlet", ds); registration.addMapping("/"); registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads"));
2.2)如果配置DispatcherServlet 的 Servlet初始化类继承了 AbstractAnnotationConfigDispatcherServletInitializer 或 AbstractDispatcherServletInitializer,那么我们就不会直接创建 DispatcherServlet实例并将其注册到 Servlet上下文中;这样的话,将不会有对 Dynamic Servlet registration 的引用供我们使用了。但我们可以通过重载 customizeRegistration() 方法 来配置 multipart 的具体细节;@Override protected void customizeRegistration(Dynamic registration) {registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads")); }
对以上代码的分析(Analysis):上述代码所使用的 只有一个参数的 MultipartConfigElement 构造器,指定的是文件系统中的一个绝对目录,上传文件将会临时写入到该目录中;
parameter1)上传文件的最大容量(以字节为单位),默认是没有限制的;parameter2)整个mulitpart 请求的最大容量(以字节为单位),不会关心有多少个part以及每个part的大小,默认是没有限制的;parameter3)在上传的过程中,如果文件大小得到了一个指定最大容量(以字节为单位),将会写入到临时文件路径中。默认值为0.也就是所上传的文件都会写入到磁盘上;
3.1)看个荔枝:限制文件大小不超过2M,整个请求不超过4M,而且所有的文件都写到磁盘上,则设置为:@Override protected void customizeRegistration(Dynamic registration) {registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads",2097152, 4194304, 0)); }
<servlet><servlet-name>appServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>1</load-on-startup><multipart-config><location>/tmp/spittr/uploads</location><max-file-size>2097152</max-file-size> <max-request-size>4194304</max-request-size></multipart-config> </servlet>
2.1)将CommonsMultipartResolver 声明为 spring bean的 简单方式如下:@Bean public MultipartResolver multipartResolver() {return new CommonsMultipartResolver(); }
2.2)CommonsMultipartResolver:不会强制要求设置临时文件路径,默认case下,这个路径就是 Servlet容器的临时目录;不过通过 updateTempDir属性类设置不同 位置;
@Bean public MultipartResolver multipartResolver() throws IOException {CommonsMultipartResolver multipartResolver =new CommonsMultipartResolver();multipartResolver.setUploadTempDir(new FileSystemResource("/tmp/spittr/uploads"));return multipartResolver; }
2.3)看个荔枝: 设置最大的文件容量为2M,最大的内存大小为0字节(所有的文件都会写到磁盘中),与MultipartConfigElement 不同的是,我们无法设置 multipart 请求整体的最大容量;@Bean public MultipartResolver multipartResolver() throws IOException {CommonsMultipartResolver multipartResolver =new CommonsMultipartResolver();multipartResolver.setUploadTempDir(new FileSystemResource("/tmp/spittr/uploads"));multipartResolver.setMaxUploadSize(2097152);multipartResolver.setMaxInMemorySize(0);return multipartResolver; }
method1)multipartFile;method2)part形式
2.1)修改前台模板添加上传图片插件;(省略)2.2)修改控制器方法@RequestMapping(value="/register", method=POST)public String processRegistration(@RequestPart("profilePicture") byte[] profilePicture, // highlight line.@Valid Spitter spitter,Errors errors) { //... }
对以上代码的分析(Analysis):
A1)profilePicture属性:将会给定一个 byte数组,这个数组中包含了请求中对应的part数据(通过@RequestPart类指定);如果用户提交表单的时候没有选择文件,那么这个数组是空的(而不是null);A2)获取到图片数据后:processRegistration方法接下来就是将文件保存到某个位置了;(下面讲如何处理文件的存储)
A1)Multipart提供了获取上传文件byte的方式,但是它所提供的功能并不仅限于此,还能获得原始的文件名,大小以及内容类型;A2)它还提供了一个 InputStream,用来将文件数据以流的方式进行读取;A3)MultipartFile 还提供了一个便利的 transferTo()方法,能够帮助我们将上传的文件写入到文件系统中;profilePicture.transferTo(new File("/data/spittr/" + profilePicture.getOriginalFilename()));
@RequestMapping(value="/register", method=POST)
public String processRegistration(@RequestPart("profilePicture") Part profilePicture,@Valid Spitter spitter,Errors errors) {//...
}
package javax.servlet.http;
import java.io.*;
import java.util.*;
public interface Part {
public InputStream getInputStream() throws IOException;public String getContentType();public String getName();public String getSubmittedFileName();public long getSize();public void write(String fileName) throws IOException;public void delete() throws IOException;public String getHeader(String name);public Collection<String> getHeaders(String name);public Collection<String> getHeaderNames();
}
A1)Part方法与 MultipartFile 方法有些类似:如getSubmittedFileName() 方法 同 getOriginalFilename()方法类似,write()方法 与 transferTo()方法类似;A2)借助于该方法(write方法),可以将上传的文件写入文件系统中:profilePicture.write("/data/spittr/" +profilePicture.getOriginalFilename());
Attention)只有使用 MultipartFile 的时候才需要 MultipartResolver;
way1)特定的spring 异常将会自动映射为指定 的 HTTP 状态码;way2)异常上可以添加 @ResponseStatus注解,从而将其映射为某一个HTTP 状态码;way3)在方法上添加 @ExceptionHandler 注解,使其用来处理异常;
2)处理异常的最简单的方法:就是将其映射到 HTTP 状态码上,进而放到响应中;
2.1)不加 @ResponseStatus注解的case:SpittleNotFoundException 将会产生500状态码的响应,实际上,如果出现任何没有映射的异常,响应都会带有500状态码;2.2)加上 @ResponseStatus注解的case:使用该注解将 SpittleNotFoundException 映射为 HTTP 状态码 404;@ResponseStatus(value=HttpStatus.NOT_FOUND,reason="spittle not found") public class SpittleNotFoundException extends RuntimeException{ }
1.1)problem:如果我们想在响应中不仅要包括状态码,还要包含所产生的错误,怎么来处理?1.2)solution:我们不能将异常视为 HTTP 错误了,而是要按照处理请求的方式来处理异常;
3.1)step1:首先将saveSpittle方法中的异常处理剥离掉;3.2)step2:为SpittleController 添加新方法,处理抛出的异常;
func1)@ExceptionHandler 注解标注的方法;func2)@InitBinder注解标注的方法;func3)@ModelAttribute注解标注的方法;
1.1)传递简单数据(如String,int类型):使用 URL 模板进行重定向;1.2)传递复杂数据(如对象):使用 Flash 属性;
2.1)problem:正在发起重定向功能的方法该如何发送数据给重定向的目标方法呢?一般来讲,当一个处理器方法完成后,该方法所指定的模型数据将会copy 到 请求中,并作为请求中的属性,请求会转发(forward)到视图上进行渲染。因为控制器方法和视图所处理的是同一个请求,所以在转发过程中,请求属性能够得以保存;但是重定向(redirect) 的case就不同了;2.2)solution:如下图所示,当控制器的结果是重新向的话,原始的请求就结束了,并且会发出一个新的 GET 请求;原始请求中所带有的模型数据也就消亡了;
way1)使用 URL 模板以路径变量 或/和 查询参数的形式传递数据;way2)通过flash 属性发送数据;
return "redirect:/spitter/{username}";
@RequestMapping(value="/register", method=RequestMethod.POST)public String processRegistration(Spitter spitter, Model model) {spitterRepository.save(spitter);model.addAttribute("username", spitter.getUsername());return "redirect:/spitter/{username}";}
@RequestMapping(value = "/register", method = RequestMethod.POST)public String processRegistration2(Spitter spitter, Model model) {spitterRepository.save(spitter);model.addAttribute("username", spitter.getUsername()); // highlight line.model.addAttribute("spitterId", spitter.getId()); // highlight line.return "redirect:/spitter/{username}";}
1.1)problem:发送实际的 Spitter对象,而不是简单的int类型数据;1.2)solution:
1.2.1)schema1:将Spitter对象 放入到 会话中,然后重定向后再将其从会话中取出;1.2.2)schema2:spring 提供了提供了将数据发送为 flash 属性的功能。flash 属性会一直携带这些数据直到下一次请求才会消失;(干货——flash属性的作用)
spring(7)spring mvc 的高级技术相关推荐
- spring api 中文_Spring高级技术梳理
序言 本系列除了SpringData部分, 其余部分全部是基于SpringBoot 2.0以上版本, 更新则更强, 尽量不与主流脱节. 我们不是时代的弄潮儿, 我们只是先进技术的追随者~~~ Spri ...
- Spring MVC Boot Cloud 技术教程汇总
转载自 Spring MVC & Boot & Cloud 技术教程汇总 昨天我们发布了Java成神之路上的知识汇总,今天继续. Java成神之路技术整理(长期更新) 以下是Java技 ...
- Spring MVC Boot Cloud 技术教程汇总(长期更新)
昨天我们发布了Java成神之路上的知识汇总,今天继续. Java成神之路技术整理(长期更新) 以下是Java技术栈微信公众号发布的关于 Spring/ Spring MVC/ Spring Boot/ ...
- Spring高级技术梳理
Spring高级技术梳理 序言 正文 SpringData部分 Spring全家桶之SpringData--预科阶段 Spring全家桶之SpringData--Spring 整合Hibernate与 ...
- Spring、Spring MVC、Spring Boot三者的关系还傻傻分不清楚?
点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 在本文中,你将获取到有关于Spring,Spring MVC和Spring Boot的概述, ...
- Spring、Spring MVC、Spring boot、Spring Cloud面试题(史上最全面试题,精心整理100家互联网企业,面试必过)
最全面试题,精心整理100家互联网企业面经,祝你面试成功.面试必过(2023优化版)已发布在个人微信公众号[面向Offer学编程],优化版首先修正了读者反馈的部分答案存在的错误,同时根据最新面试总结, ...
- Redis+Nginx+设计模式+Spring全家桶+Dubbo阿里P8技术精选文档
最近花了很长的时间去搜罗Java核心技术好文,我把每个Java核心技术的优选文章都整理成了一个又一个的文档.昨天也是终于全部整理好了,今天就把这些东西分享给老铁们,也能为老铁们省去不少麻烦,想学什么技 ...
- Redis+分布式+设计模式+Spring全家桶+Dubbo阿里P8技术精选文档
最近花了很长的时间去搜罗Java核心技术好文,我把每个Java核心技术的优选文章都整理成了一个又一个的文档.昨天也是终于全部整理好了,今天就把这些东西分享给老铁们,也能为老铁们省去不少麻烦,想学什么技 ...
- 福利继续:赠书《Spring Cloud微服务-全栈技术与案例解析》
<Spring Cloud微服务-全栈技术与案例解析> 在互联网时代,互联网产品的最大特点就是需要快速发布新功能,支持高并发和大数据.传统的架构已经慢慢不能支撑互联网业务的发展,这时候微服 ...
最新文章
- arp/ip地址/路由--总之很乱
- CUBRID学习笔记 1 简介 cubrid教程
- P1005 采药(Tyvj)
- Mysql的date_format与date_sub
- #0 scrapy爬虫学习中遇到的坑记录
- Win10网络共享设置的方法步骤
- java 中文 转义_java下载url路径包含中文需要转义的操作
- 【java】深入了解JAVA可变长度的参数
- 网络媒体教程:人物素描
- 关于Word样式自动更新的详解
- CVPR2021 MotionRNN: A Flexible Model for Video Prediction with Spacetime-Varying Motions
- Python - 深度学习系列2-人脸比对 Siamese
- android7.1的SnapdragonCamera之CameraActivity逻辑流程分析整体
- 原始套接(ARP协议的使用)
- godot mysql_Go 每日一库之 godotenv
- 2016年linux认证考试,2016年Linux认证考试复习要点辅导
- C#中BackgroundImage与Image的区别
- Chrome 浏览器 原生工具进行网页长截图
- 全基因组尺度的增强子--靶基因映射图谱解码非编码突变
- android应用更新升级
热门文章
- Cities(2020昆明C)
- Acwing1086. 恨7不成妻(未解决)
- 洛谷P3357:最长k可重线段集问题(网络流)
- CF1556F-Sports Betting【状压dp,数学期望】
- P7726-天体探测仪(Astral Detector)【构造】
- CF848E-Days of Floral Colours【dp,分治NTT】
- nssl1446-小智的旅行【dp】
- nssl1320,jzoj(初中)2108-买装备【dfs,水题】
- POJ3348-Cows【凸包,计算几何】
- jzoj3793,P2090-数字对【更相减损术,欧几里得算法,数论】