SpringMVC实现文件上传与下载、拦截器、异常处理器等功能

时间:2021-07-28 13:25:18

文件下载

使用ResponseEntity实现下载文件的功能

index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http:www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>首页</title>
</head>
<body>
<a th:href="@{/testDown}" rel="external nofollow" >点击下载</a>
</body>
</html>

控制器

@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
  //获取ServletContext对象
  ServletContext servletContext = session.getServletContext();
	
  //获取服务器中文件的真实路径
  String realPath = servletContext.getRealPath("/static/img/1.jpg");
	
  //创建输入流
  InputStream is = new FileInputStream(realPath);
	
  //创建字节数组
  byte[] bytes = new byte[is.available()];
	
  //将流读到字节数组中
  is.read(bytes);
	
  //创建HttpHeaders对象设置响应头信息
  MultiValueMap<String, String> headers = new HttpHeaders();
	
  //设置要下载方式以及下载文件的名字
  headers.add("Content-Disposition", "attachment;filename=1.jpg");
	
  //设置响应状态码
  HttpStatus statusCode = HttpStatus.OK;
	
  //创建ResponseEntity对象
  ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
	
  //关闭输入流
  is.close();
	
  return responseEntity;
}

注意:如果报500错误,可能是项目中无法找到静态资源文件,需要对项目重新打包。

 

文件上传

文件上传要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data"以二进制方式上传

SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息

上传步骤:

添加依赖

<!-- 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中添加配置

<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<!--必须设置id属性,springMVC是根据id获取,且id必须设置为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标签的name一致
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
  //获取上传的文件的文件名
  String fileName = photo.getOriginalFilename();
	
  //处理文件重名问题
  String hzName = fileName.substring(fileName.lastIndexOf("."));
  fileName = UUID.randomUUID().toString() + hzName;
	
  //获取服务器中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;
	
  //实现上传功能
  photo.transferTo(new File(finalPath));
  return "success";
}

 

拦截器

拦截器的配置

SpringMVC中的拦截器用于拦截控制器方法的执行

SpringMVC中的拦截器需要实现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接口有三个默认方法

  • preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法
  • postHandle:控制器方法执行之后执行postHandle()
  • afterCompletion:处理完视图和模型数据,渲染视图完毕之后执行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的配置文件中进行配置:

方式一

  <mvc:interceptors>
      <bean class="com.gonghr.springmvc.interceptors.FirstInterceptor"></bean>
  </mvc:interceptors>

输出:

FirstInterceptor-->preHandle

方式二

  <mvc:interceptors>
      <ref bean="firstInterceptor"></ref>
  </mvc:interceptors>

注意提前开启注解扫描,并把拦截器放入Ioc容器

输出:

FirstInterceptor-->preHandle

注意:以上两种配置方式都是对DispatcherServlet所处理的所有的请求进行拦截。

方式三

  <mvc:interceptors>
      <mvc:interceptor>
          <mvc:mapping path="/**"/>  <!--拦截所有请求-->
          <mvc:exclude-mapping path="/"/>  <!--不拦截主页-->
          <ref bean="firstInterceptor"></ref>
      </mvc:interceptor>
  </mvc:interceptors>

SpringMVC实现文件上传与下载、拦截器、异常处理器等功能

可以进入首页

SpringMVC实现文件上传与下载、拦截器、异常处理器等功能

发送任意请求都会被拦截

输出:

FirstInterceptor-->preHandle

以上配置方式可以通过ref或bean标签设置拦截器,通过mvc:mapping设置需要拦截的请求,通过mvc:exclude-mapping设置需要排除的请求,即不需要拦截的请求

/**:拦截所有请求

/*:拦截一级目录的请求

多个拦截器的执行顺序

第一个拦截器

@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");
  }
}

第二个拦截器

@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");
  }
}

两个拦截器都设置为对任意请求放行。

输出:

FirstInterceptor-->preHandle
SecondInterceptor-->preHandle
SecondInterceptor-->postHandle
FirstInterceptor-->postHandle
SecondInterceptor-->afterCompletion
FirstInterceptor-->afterCompletion

  • 若每个拦截器的preHandle()都返回true

此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:

preHandle()会按照配置的顺序执行,而postHandle()和afterCompletion()会按照配置的反序执行

如果设置第一个拦截器对所有请求放行,第二个拦截器对所有请求拦截。

第一个拦截器

@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");
  }
}

第二个拦截器

@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

  • 若某个拦截器的preHandle()返回了false

preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false的拦截器之前的拦截器的afterCompletion()会执行

 

异常处理器

基于配置的异常处理

SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver

HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver

SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver,使用方式:

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  <property name="exceptionMappings">
      <props>
      	<!--
      		properties的键表示处理器方法执行过程中出现的异常
      		properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面
      	-->
          <prop key="java.lang.ArithmeticException">error</prop>
      </props>
  </property>
  <!--
  	exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享
  -->
  <property name="exceptionAttribute" value="ex"></property>
</bean>

error.html

出现错误
<p th:text="${ex}"></p>

index.html

<a th:href="@{/testException}">测试异常处理</a>

SpringMVC实现文件上传与下载、拦截器、异常处理器等功能

基于注解的异常处理

//@ControllerAdvice将当前类标识为异常处理的组件
@ControllerAdvice
public class ExceptionController {

  //@ExceptionHandler用于设置所标识方法处理的异常
  @ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class})
  //ex表示当前请求处理中出现的异常对象
  public String handleArithmeticException(Exception ex, Model model){
      model.addAttribute("ex", ex);
      return "error";
  }

}

SpringMVC实现文件上传与下载、拦截器、异常处理器等功能

 

总结

到此这篇关于SpringMVC实现文件上传与下载、拦截器、异常处理器等功能的文章就介绍到这了,更多相关SpringMVC文件上传与下载、拦截器、异常处理器内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/gonghr/p/15235253.html