SpringMVC實(shí)現(xiàn)文件上傳與下載、攔截器、異常處理器等功能
文件下載
使用ResponseEntity實(shí)現(xiàn)下載文件的功能
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http:www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首頁(yè)</title>
</head>
<body>
<a th:href="@{/testDown}" rel="external nofollow" >點(diǎn)擊下載</a>
</body>
</html>
控制器
@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
//獲取ServletContext對(duì)象
ServletContext servletContext = session.getServletContext();
//獲取服務(wù)器中文件的真實(shí)路徑
String realPath = servletContext.getRealPath("/static/img/1.jpg");
//創(chuàng)建輸入流
InputStream is = new FileInputStream(realPath);
//創(chuàng)建字節(jié)數(shù)組
byte[] bytes = new byte[is.available()];
//將流讀到字節(jié)數(shù)組中
is.read(bytes);
//創(chuàng)建HttpHeaders對(duì)象設(shè)置響應(yīng)頭信息
MultiValueMap<String, String> headers = new HttpHeaders();
//設(shè)置要下載方式以及下載文件的名字
headers.add("Content-Disposition", "attachment;filename=1.jpg");
//設(shè)置響應(yīng)狀態(tài)碼
HttpStatus statusCode = HttpStatus.OK;
//創(chuàng)建ResponseEntity對(duì)象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
//關(guān)閉輸入流
is.close();
return responseEntity;
}
注意:如果報(bào)500錯(cuò)誤,可能是項(xiàng)目中無(wú)法找到靜態(tài)資源文件,需要對(duì)項(xiàng)目重新打包。
文件上傳
文件上傳要求form表單的請(qǐng)求方式必須為post,并且添加屬性enctype="multipart/form-data"以二進(jìn)制方式上傳
SpringMVC中將上傳的文件封裝到MultipartFile對(duì)象中,通過(guò)此對(duì)象可以獲取文件相關(guān)信息
上傳步驟:
添加依賴
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
在SpringMVC的配置文件springMVC.xml中添加配置
<!--必須通過(guò)文件解析器的解析才能將文件轉(zhuǎn)換為MultipartFile對(duì)象--> <!--必須設(shè)置id屬性,springMVC是根據(jù)id獲取,且id必須設(shè)置為multipartResolver--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
index.html
<form method="post" th:action="@{/testUp}" enctype="multipart/form-data">
<input type="file" name="photo">
<input type="submit" value="上傳">
</form>
控制器
@RequestMapping("/testUp")
//MultipartFile的形參名必須與index.html中的file標(biāo)簽的name一致
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
//獲取上傳的文件的文件名
String fileName = photo.getOriginalFilename();
//處理文件重名問(wèn)題
String hzName = fileName.substring(fileName.lastIndexOf("."));
fileName = UUID.randomUUID().toString() + hzName;
//獲取服務(wù)器中photo目錄的路徑
ServletContext servletContext = session.getServletContext();
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
if(!file.exists()){
file.mkdir();
}
String finalPath = photoPath + File.separator + fileName;
//實(shí)現(xiàn)上傳功能
photo.transferTo(new File(finalPath));
return "success";
}
攔截器
攔截器的配置
SpringMVC中的攔截器用于攔截控制器方法的執(zhí)行
SpringMVC中的攔截器需要實(shí)現(xiàn)HandlerInterceptor接口
HandlerInterceptor源碼
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
HandlerInterceptor接口有三個(gè)默認(rèn)方法
- preHandle:控制器方法執(zhí)行之前執(zhí)行preHandle(),其boolean類型的返回值表示是否攔截或放行,返回true為放行,即調(diào)用控制器方法;返回false表示攔截,即不調(diào)用控制器方法
- postHandle:控制器方法執(zhí)行之后執(zhí)行postHandle()
- afterCompletion:處理完視圖和模型數(shù)據(jù),渲染視圖完畢之后執(zhí)行afterCompletion()
控制器
FirstInterceptor.java
public class FirstInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor-->preHandle");
return false;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor-->postHandle");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor-->afterCompletion");
}
}
SpringMVC的攔截器必須在SpringMVC的配置文件中進(jìn)行配置:
方式一
<mvc:interceptors>
<bean class="com.gonghr.springmvc.interceptors.FirstInterceptor"></bean>
</mvc:interceptors>
輸出:
FirstInterceptor-->preHandle
方式二
<mvc:interceptors>
<ref bean="firstInterceptor"></ref>
</mvc:interceptors>
注意提前開(kāi)啟注解掃描,并把攔截器放入Ioc容器
輸出:
FirstInterceptor-->preHandle
注意:以上兩種配置方式都是對(duì)DispatcherServlet所處理的所有的請(qǐng)求進(jìn)行攔截。
方式三
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/> <!--攔截所有請(qǐng)求-->
<mvc:exclude-mapping path="/"/> <!--不攔截主頁(yè)-->
<ref bean="firstInterceptor"></ref>
</mvc:interceptor>
</mvc:interceptors>

可以進(jìn)入首頁(yè)

發(fā)送任意請(qǐng)求都會(huì)被攔截
輸出:
FirstInterceptor-->preHandle
以上配置方式可以通過(guò)ref或bean標(biāo)簽設(shè)置攔截器,通過(guò)mvc:mapping設(shè)置需要攔截的請(qǐng)求,通過(guò)mvc:exclude-mapping設(shè)置需要排除的請(qǐng)求,即不需要攔截的請(qǐng)求
/**:攔截所有請(qǐng)求
/*:攔截一級(jí)目錄的請(qǐng)求
多個(gè)攔截器的執(zhí)行順序
第一個(gè)攔截器
@Component
public class FirstInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor-->preHandle");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor-->postHandle");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor-->afterCompletion");
}
}
第二個(gè)攔截器
@Component
public class SecondInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SecondInterceptor-->preHandle");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("SecondInterceptor-->postHandle");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("SecondInterceptor-->afterCompletion");
}
}
兩個(gè)攔截器都設(shè)置為對(duì)任意請(qǐng)求放行。
輸出:
FirstInterceptor-->preHandle
SecondInterceptor-->preHandle
SecondInterceptor-->postHandle
FirstInterceptor-->postHandle
SecondInterceptor-->afterCompletion
FirstInterceptor-->afterCompletion
- 若每個(gè)攔截器的preHandle()都返回true
此時(shí)多個(gè)攔截器的執(zhí)行順序和攔截器在SpringMVC的配置文件的配置順序有關(guān):
preHandle()會(huì)按照配置的順序執(zhí)行,而postHandle()和afterCompletion()會(huì)按照配置的反序執(zhí)行
如果設(shè)置第一個(gè)攔截器對(duì)所有請(qǐng)求放行,第二個(gè)攔截器對(duì)所有請(qǐng)求攔截。
第一個(gè)攔截器
@Component
public class FirstInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor-->preHandle");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor-->postHandle");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor-->afterCompletion");
}
}
第二個(gè)攔截器
@Component
public class SecondInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("SecondInterceptor-->preHandle");
return false;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("SecondInterceptor-->postHandle");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("SecondInterceptor-->afterCompletion");
}
}
輸出:
FirstInterceptor-->preHandle
SecondInterceptor-->preHandle
FirstInterceptor-->afterCompletion
- 若某個(gè)攔截器的preHandle()返回了false
preHandle()返回false和它之前的攔截器的preHandle()都會(huì)執(zhí)行,postHandle()都不執(zhí)行,返回false的攔截器之前的攔截器的afterCompletion()會(huì)執(zhí)行
異常處理器
基于配置的異常處理
SpringMVC提供了一個(gè)處理控制器方法執(zhí)行過(guò)程中所出現(xiàn)的異常的接口:HandlerExceptionResolver
HandlerExceptionResolver接口的實(shí)現(xiàn)類有:DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver
SpringMVC提供了自定義的異常處理器SimpleMappingExceptionResolver,使用方式:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--
properties的鍵表示處理器方法執(zhí)行過(guò)程中出現(xiàn)的異常
properties的值表示若出現(xiàn)指定異常時(shí),設(shè)置一個(gè)新的視圖名稱,跳轉(zhuǎn)到指定頁(yè)面
-->
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
<!--
exceptionAttribute屬性設(shè)置一個(gè)屬性名,將出現(xiàn)的異常信息在請(qǐng)求域中進(jìn)行共享
-->
<property name="exceptionAttribute" value="ex"></property>
</bean>
error.html
出現(xiàn)錯(cuò)誤
<p th:text="${ex}"></p>
index.html
<a th:href="@{/testException}">測(cè)試異常處理</a>

基于注解的異常處理
//@ControllerAdvice將當(dāng)前類標(biāo)識(shí)為異常處理的組件
@ControllerAdvice
public class ExceptionController {
//@ExceptionHandler用于設(shè)置所標(biāo)識(shí)方法處理的異常
@ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class})
//ex表示當(dāng)前請(qǐng)求處理中出現(xiàn)的異常對(duì)象
public String handleArithmeticException(Exception ex, Model model){
model.addAttribute("ex", ex);
return "error";
}
}

總結(jié)
到此這篇關(guān)于SpringMVC實(shí)現(xiàn)文件上傳與下載、攔截器、異常處理器等功能的文章就介紹到這了,更多相關(guān)SpringMVC文件上傳與下載、攔截器、異常處理器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在Android系統(tǒng)中使用WebViewClient處理跳轉(zhuǎn)URL的方法
這篇文章主要介紹了在Android系統(tǒng)中使用WebViewClient處理跳轉(zhuǎn)URL的方法,實(shí)現(xiàn)代碼為Java語(yǔ)言編寫,是需要的朋友可以參考下2015-07-07
Java實(shí)現(xiàn)小程序簡(jiǎn)單五子棋
這篇文章主要介紹了利用Java實(shí)現(xiàn)小程序簡(jiǎn)單五子棋,本程序適用于java初學(xué)者鞏固類與對(duì)象、事件響應(yīng)、awt包中各種工具的相關(guān)概念以及對(duì)邏輯能力的鍛煉,下面來(lái)看具體實(shí)現(xiàn)吧2021-12-12
利用Java的Struts框架實(shí)現(xiàn)電子郵件發(fā)送功能
這篇文章主要介紹了利用Java的Struts框架實(shí)現(xiàn)電子郵件發(fā)送功能,Struts框架是Java的SSH三大web開(kāi)發(fā)框架之一,需要的朋友可以參考下2015-12-12
Quarkus中實(shí)現(xiàn)Resteasy的文件上傳下載操作
這篇文章主要為大家介紹了Quarkus中實(shí)現(xiàn)Resteasy的文件上傳下載的操作過(guò)程步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02
druid ParserException類錯(cuò)誤問(wèn)題及解決
這篇文章主要介紹了druid ParserException類錯(cuò)誤問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Spring注解@Qualifier的詳細(xì)用法你知道幾種
本文給大家分享Spring注解@Qualifier的詳細(xì)用法,包括@Autowired和@Resource區(qū)別介紹,本文通過(guò)示例代碼給大家詳細(xì)介紹,感興趣的朋友跟隨小編一起看看吧2021-07-07
解決spring-data-jpa 事物中修改屬性自動(dòng)更新update問(wèn)題
這篇文章主要介紹了解決spring-data-jpa 事物中修改屬性自動(dòng)更新update問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家2021-08-08
SpringBoot中多環(huán)境啟動(dòng)配置的教程詳解
在SpringBoot項(xiàng)目的生命周期中,存在不同的環(huán)境,我們就需要針對(duì)不同環(huán)境制定不同名稱的配置文件,里面放置不同環(huán)境下所需的配置項(xiàng),下面小編就來(lái)和大家詳細(xì)講講SpringBoot如何進(jìn)行多環(huán)境啟動(dòng)配置的吧2024-02-02

