Springboot笔记<8>异常处理 文件上传
文件上传
springboot可以直接使用 org.springframework.web.multipart.MultipartFile实现文件上传功能。
1.创建form表单:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>hah</title>
</head>
<body>
<text>单文件上传</text>
<form method="post" action="/singleUpload" enctype="multipart/form-data">
<input type="file" name="headerImg"><br>
<input type="submit" value="提交">
</form>
<text>多文件上传</text>
<form method="post" action="/multiUpload" enctype="multipart/form-data">
<input type="file" name="photos"><br>
<input type="file" name="photos"><br>
<input type="file" name="photos"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
2.yaml配置:
spring:
servlet:
multipart:
enabled: true
file-size-threshold: 2KB
max-request-size: 215MB
3.官网对于上传文件yaml配置参数的解释:
## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.(单个文件的最大值)
spring.servlet.multipart.max-file-size=200MB
# Max Request Size(上传文件总的最大值)
spring.servlet.multipart.max-request-size=215MB
## File Storage Properties
# All files uploaded through the REST API will be stored in this directory
file.upload-dir=/Users/callicoder/uploads
4.写一个Controller验证:
- 单文件上传
- 多文件上传
@RestController
@Slf4j
public class UploadController {
//上传单个文件
@PostMapping("/singleUpload")
public String multiUpload(
@RequestPart("headerImg") MultipartFile headerImg) throws IOException {
log.info("上传的信息:headerImg={}",
headerImg.getSize());
if (!headerImg.isEmpty()) {
//保存到文件服务器,OSS服务器
String originalFilename = headerImg.getOriginalFilename();
headerImg.transferTo(new File("E:\\cache\\" + originalFilename));
}
return "singleUpload";
}
//上传多个文件
@PostMapping("/multiUpload")
public String singleUpload(
@RequestPart("photos") MultipartFile[] photos) throws IOException {
log.info("上传的信息:photos={}",
photos.length);
if (photos.length > 0) {
for (MultipartFile photo : photos) {
if (!photo.isEmpty()) {
String originalFilename = photo.getOriginalFilename();
photo.transferTo(new File("E:\\cache\\" + originalFilename));
}
}
}
return "multiUpload";
}
}
异常处理
默认情况下,Spring Boot为两种情况提供了不同的响应方式。
一种是浏览器客户端请求一个不存在的页面或服务端处理发生异常时,一般情况下浏览器默认发送的请求头中Accept: text/html,所以Spring Boot默认会响应一个html文档内容,称作“Whitelabel Error Page”。另一种是使用Postman等调试工具发送请求一个不存在的url或服务端处理发生异常时,Spring Boot会返回类似如下的Json格式字符串信息。Spring Boot 默认提供了程序出错的结果映射路径/error。这个/error请求会在BasicErrorController中处理,其内部是通过判断请求头中的Accept的内容是否为text/html来区分请求是来自客户端浏览器(浏览器通常默认自动发送请求头内容Accept:text/html)还是客户端接口的调用,以此来决定返回页面视图还是 JSON 消息内容。
自定义错误页面
error.html
先从最简单的开始,直接在/resources/templates下面创建error.html就可以覆盖默认的Whitelabel Error Page的错误页面,我项目用的是thymeleaf模板,对应的error.html代码如下:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
动态error错误页面
<p th:text="${error}"></p>
<p th:text="${status}"></p>
<p th:text="${message}"></p>
</body>
</html>
静态错误页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
静态404错误页面
</body>
</html>
静态页面资源目录下存放404.html,发生404错误时会访问到404.html
动态错误页面:
存放路径/resources/templates/error下,比如/resources/templates/error/4xx.html,/resources/templates/error/404.html
比如创建/resources/templates/error/4xx.html,则发生4打头的错误码时都会访问4xx.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
4xx动态error错误页面
<p th:text="${error}"></p>
<p th:text="${status}"></p>
<p th:text="${message}"></p>
</body>
</html>
页面优先级
- error.html会覆盖默认的 whitelabel Error Page 错误提示
- 静态错误页面优先级别比error.html高
- 动态模板错误页面优先级比静态错误页面高
重写ErrorController
在静态处理代码分析的时候我们说到了项目启动时候就会自动加载默认异常处理配置ErrorMvcAutoConfiguration,会默认加载BasicErrorController作为异常处理的控制器。那么我们想要自己定义处理逻辑的话,我们就直接覆盖掉BasicErrorController,然后重写一个就好了。
继承ErrorPageRegistrar
ErrorPageRegistrar是一个错误页面的注册器,在ErrorMvcAutoConfiguration中我们依然可以找到对应的源码代码,它默认帮我们写了一个ErrorPageCustomizer用于处理注册的错误页面,我们可以看到启动时候,会默认先把/error页面注册进去。
@ControllerAdvice注解处理异常
Spring正好提供了一个非常方便的异常处理方案——控制器通知 (@ControllerAdvice 或 @RestControllerAdvice),它将所有控制器作为一 个切面,利用切面技术来实现。可以减少因忘记写catch而出现错误的概率通过基于@ControllerAdvice或@RestContollerAdvice的注解可以对异常进行全局统一处理,默认对所有的Controller有效。如果要限定生效范围,则可以使用@ControllerAdvice支持的限定范围方式。
不一定需要组合来一起用,当我们需要在某个特定控制器里面处理特定异常时候,我们的@ExceptionHandler可以直接写在controller中,这样的话@ExceptionHandler就只能处理这个单个controller的异常。那有时候我们想全局处理所有的控制器的异常,于是就有了@ControllerAdvice,它会控制器增强,会应用到所有的controller上,这样就实现了我们想要的全局异常处理。
@ControllerAdvice支持的限定范围
- 按注解:@ControllerAdvice(annotations = RestController .class)。
- 按包名:@ControllerAdvice("org.example.controller")。
- 按类型:@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})。
示例1:处理全局异常Exception.class
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
String handleException(){
return "Exception";
}
}
方法 handleException() 就会处理所有 Controller 层抛出的 Exception 及其子类的异常。被 @ExceptionHandler 注解的方法的参数列表里,还可以声明很多种类型的参数。
示例2:处理多种异常
访问/exceptionMethod会抛出ArithmeticException,GlobalExceptionHandler对ArithmeticException和Exception都进行了处理,会优先调用handleArithmeticException。
@Slf4j
@RestController
public class ExceptionController {
@RequestMapping("/exceptionMethod")
public String exceptionMethod(Model model) throws Exception {
model.addAttribute("msg", "没有抛出异常");
int num = 1/0; //a处
log.info(String.valueOf(num));
return "home";
}
}
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
String handleException(){
return "Exception";
}
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
String handleArithmeticException(){
return "ArithmeticException";
}
@ExceptionHandler(value={java.lang.NullPointerException.class})
ModelAndView nullPointerExceptionHandler(Exception e){
System.out.println("goto NullPointerExceptionPage");
ModelAndView mv=new ModelAndView();
mv.addObject("error",e.toString());
mv.setViewName("NullPointerExceptionPage");
return mv;
}
}
Springboot笔记<8>异常处理 文件上传的更多相关文章
- [原创]java WEB学习笔记49:文件上传基础,基于表单的文件上传,使用fileuoload 组件
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- springboot实现简单的文件上传
承接上一篇,这里记录一下简单的springboot文件上传的方式 首先,springboot简单文件上传不需要添加额外的jar包和配置 这里贴一下后端controller层的实现代码 补一份前台的HT ...
- Spring MVC 全局异常处理&文件上传
Spring MVC 全局异常处理 使用SimpleMappingExceptionResolver实现异常处理 在welcome-servlet.xml进行如下配置: <bean class= ...
- SpringBoot整合SpringMVC完成文件上传
1.编写Controller /** * SPringBoot文件上传 */ //@Controller @RestController //表示该类下的方法的返回值会自动做json格式的转换 pub ...
- springboot(九)文件上传
在企业级项目开发过程中,上传文件是最常用到的功能.SpringBoot集成了SpringMVC,当然上传文件的方式跟SpringMVC没有什么出入.下面我们来创建一个SpringBoot项目完成单个. ...
- Springboot 一行代码实现文件上传 20个平台!少写代码到极致
大家好,我是小富~ 技术交流,公众号:程序员小富 又是做好人好事的一天,有个小可爱私下问我有没有好用的springboot文件上传工具,这不巧了嘛,正好我私藏了一个好东西,顺便给小伙伴们也分享一下,d ...
- struts2学习笔记之十:文件上传
Struts2的上传 1.Struts2默认采用了apache commons-fileupload 2.Struts2支持三种类型的上传组件 3.需要引入commons-fileupload相关依赖 ...
- PHP学习笔记--文件目录操作(文件上传实例)
文件操作是每个语言必须有的,不仅仅局限于PHP,这里我们就仅用PHP进行讲解 php的文件高级操作和文件上传实例我放在文章的最后部分.--以后我还会给大家写一个PHP类似于网盘操作的例子 注意:阅读此 ...
- Spring MVC 笔记 —— Spring MVC 文件上传
文件上传 配置MultipartResolver <bean id="multipartResolver" class="org.springframework.w ...
- 笔记:Struts2 文件上传和下载
为了上传文件必须将表单的method设置为POST,将 enctype 设置为 muiltipart/form-data,只有设置为这种情况下,浏览器才会把用户选择文件的二进制数据发送给服务器. 上传 ...
随机推荐
- DeepSeek 多模态大模型 Janus-Pro 本地部署教程
下载模型仓库 git clone https://github.com/deepseek-ai/Janus.git 国内下载仓库失败时,可以使用以下代理: git clone https://gith ...
- python 更新pip镜像源
前言 默认情况下 pip 使用的是国外的镜像,在下载的时候速度非常慢,下载速度是几kb或者几十kb,花费的时间比较长. 解决办法 国内目前有些机构或者公司整理了对应的镜像源,使得通过内网就能访问即可, ...
- go sync.map的使用
前言 数据竞争是并发情况下,存在多线程/协程读写相同数据的情况,必须存在至少一方写.另外,全是读的情况下是不存在数据竞争的. Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全 ...
- Mac port 443: Connection refused
MAC 安装brew raw.githubusercontent.com port 443: Connection refused 本人亲自认证过,踩过多种方案,最终认证的解决方案 原因:由于某些你懂 ...
- Tomcat性能优化以及 jvm 参数设置
linux ps 命令的结果中 VSZ,RSS,STAT 的含义和大小 参数名 含义 单位 USER 进程所属用户 PID 进程ID %CPU 进程占用CPU百分比 %MEM 进程占用内存 ...
- 网页P图
此篇文章记录一段比较好玩的网页P图代码 1.在你要修改的网页上Fn + F12或者F12打开控制台,然后在console里输入这样一段代码,回车 document.designMode = 'on' ...
- RegisterClass注册后getclass总是nil,why?
这个问题有点老.但是有点烦人. 一般流程是 RegisterClass后通过getclass or findclass就会成功. 可是莫名其妙出现总是返回nil.咱也不清楚,网上找了好久,一个久远的帖 ...
- [设计模式/Java/多线程] 设计模式之单例模式【9】
0 序 此文系对最常见的设计模式----单例模式的最全总结. 1 概述:单例模式 模式定义 单例模式: 保证1个类有且仅有1个实例,并提供1个访问它的全局访问点. 1个类有且仅有1个实例,并自行实例化 ...
- java基础之object类、Date类、System类、StringBuilder类、包装类、枚举类
一.public String toString() :默认返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值 重写后: @Override public String toStr ...
- Web前端入门第 38 问:CSS flex 弹性盒子与 grid 网格布局区别及应用场景
弹性盒子又称为 Flexbox,然而我更喜欢 flex 的叫法. flex 弹性盒子和 grid 网格布局作为前端开发中两把利器,它们的分界线没那么明显,虽然按照 MDN 的说法 flex 多用于一维 ...