SpringMVC-文件上传 拦截器

文件上传和下载

文件下载

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

需要在 webapp/static/img 下 放一张叫 1.png的图片

 @RequestMapping("/testDown")
  public ResponseEntity<byte[]> test(HttpSession session) throws Exception {
     //获取ServletContext对象
     ServletContext servletContext = session.getServletContext();
     //获取服务器中的文件的真实路径
     String realPath = servletContext.getRealPath("/static/img/1.png");
     //创建输入流
     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.png");
     //设置响应状态码
     HttpStatus code = HttpStatus.OK;
     //创建ResponseEntity对象
     ResponseEntity<byte[]> entity = new ResponseEntity<>(bytes,headers,code);
     //关闭输入流
     is.close();
     return entity;
 }

文件上传

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

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

上传步骤:

  1. 添加依赖

     <dependency>
         <groupId>commons-fileupload</groupId>
         <artifactId>commons-fileupload</artifactId>
         <version>1.3.3</version>
     </dependency>

  2. 在springmvc配置文件中 添加配置

     <!--配置文件上传解析器,将上传的文件封装为MultipartFile
       springmvc 根据id获取 这个id 必须为multipartResolver
     -->
     <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     ​
     </bean>

  3. 编写html

     <form th:action="@{/testUp}" method="post" enctype="multipart/form-data">
        头像: <input type="file" name="photo"/><br>
         <input type="submit" value="上传"/>
     </form>

  4. 编写controller

     @RequestMapping("/testUp")
     public String testUp(MultipartFile photo,HttpSession session) throws IOException {
         String fileName = photo.getOriginalFilename();//上传文件名
         //获取ServletContext对象
         ServletContext servletContext = session.getServletContext();
         //获取服务器中的文件的真实路径
         String realPath = servletContext.getRealPath("photo");
         System.out.println(realPath);
         File file = new File(realPath);
         //判断路径是否存在
         if(!file.exists()){
             file.mkdir();
         }
         String finalPath = realPath+File.separator+fileName;
         photo.transferTo(new File(finalPath));
         return "success";
     }

  5. 上面的代码可以实现上传,但是 会存在一个问题, 当文件名重复时 就会出现覆盖问题, 如何解决????

    一般就是换个名字,

     
    @RequestMapping("/testUp")
     public String testUp(MultipartFile photo,HttpSession session) throws IOException {
         //获取上传文件名
         String fileName = photo.getOriginalFilename();
         //获取上传文件的后缀名
         String suffix = fileName.substring(fileName.lastIndexOf("."));
         //将UUID作为文件名
         String uuid = UUID.randomUUID().toString().replaceAll("-","");//可以替换也可以不替换,不替换就有-
         //将uuid与后缀拼接后 作为 文件名
         fileName = uuid+suffix;
         //获取ServletContext对象
         ServletContext servletContext = session.getServletContext();
         //获取服务器中photo的真实路径
         String realPath = servletContext.getRealPath("photo");
         System.out.println(realPath);
         File file = new File(realPath);
         //判断路径是否存在
         if(!file.exists()){
             file.mkdir();
         }
         String finalPath = realPath+File.separator+fileName;
         photo.transferTo(new File(finalPath));
         return "success";
     }

拦截器

过滤器和拦截器的区别:

1、过滤器是基于函数回调,拦截器是基于java的反射机制的。

2、过滤器是servlet规范规定的,只能用于web程序中,而拦截器是在spring容器中,它不依赖servlet容器。

3、过滤器可以拦截几乎所有的请求(包含对静态资源的请求),而拦截器只拦截action请求(不拦截静态资源请求)。

4、滤器不能访问action上下文、值栈里的对象,拦截器可以访问action上下文、值栈里的对象。

5、在action的生命周期中,过滤器只能在容器初始化时被调用一次,拦截器可以多次被调用,而。

6、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

7、拦截器是被包裹在过滤器之中。

过滤器、拦截器、aop 顺序

  拦截顺序:filter—>Interceptor—->@Aspect -->Interceptor)

过滤器:   依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等。

拦截器:   依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。

执行顺序 :

  SpringMVC的机制是由同一个Servlet来分发请求给不同的Controller,其实这一步是在Servlet的service()方法中执行的。所以过滤器、拦截器、service()方法,dispatc()方法的执行顺序应该是这样的

1.拦截器的配置

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

springmvc中的拦截器需要实现HandlerInterceptor

springmvc的拦截器必须在springmvc的配置文件中进行配置:

 //自定义拦截器
 public class FirstInterceptor implements HandlerInterceptor {
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         System.out.println("FirstInterceptor  preHandle ");
         return true;
     }
 ​
     @Override
     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
         System.out.println("FirstInterceptor  postHandle ");
     }
 ​
     @Override
     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
         System.out.println("FirstInterceptor  afterCompletion ");
     }
 }
 <!--配置拦截器   bean -->
 <mvc:interceptors>
     <!--对DispacherServlet所处理的所有请求进行拦截-->
     <bean class="ly.interceptor.FirstInterceptor"></bean>
 </mvc:interceptors>

或者 <!--配置拦截器 ref-->

 @Component
 public class FirstInterceptor implements HandlerInterceptor {}
 注意要添加 包的扫描到 拦截器所在的包
   <!--扫描组件-->
    <context:component-scan base-package="ly.controller,ly.dao,ly.interceptor"/>
 ​
 <!--配置拦截器-->
 <mvc:interceptors>
    <!-- <bean class="ly.interceptor.FirstInterceptor"></bean>-->
     <!--对DispacherServlet所处理的所有请求进行拦截-->
     <ref bean="firstInterceptor"/>
 </mvc:interceptors>

或者

 <!--配置拦截器-->
 <mvc:interceptors>
    <!-- <bean class="ly.interceptor.FirstInterceptor"></bean>-->
   <!--  <ref bean="firstInterceptor"/>-->
     <mvc:interceptor>
         <mvc:mapping path="/**"/><!--   /** 可以包含多级目录, /* 只拦截一层目录 -->
         <mvc:exclude-mapping path="/"/>
         <ref bean="firstInterceptor"/>
     </mvc:interceptor>
 </mvc:interceptors>
 ​
  <!-- 以上配置方式 可以通过ref或bean标签设置拦截器,
   通过 mvc:mapping 设置需要拦截的请求,通过mvc:exclude-mapping 设置需要排除的请求,即不需要拦截的请求
 -->
 ​

2.拦截器的三个抽象方法

springmvc中的拦截器有三个抽象方法:

  • preHandle( ):该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行 即调用控制器方法,返回 false 表示中断后续操作 即不调用控制器方法。

  • postHandle( ):该方法在控制器的处理请求方法调用之后、解析视图之前执行postHandle,可以通过此方法对请求域中的模型和视图做进一步的修改。

  • afterCompletion( ):该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行afterCompletion,可以通过此方法实现一些资源清理、记录日志信息等工作。

3.多个拦截器的执行顺序

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

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

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

 <mvc:interceptors>
    <ref bean="firstInterceptor"></ref>
     <ref bean="secondInterceptor"></ref>
 </mvc:interceptors>
 @Component
 public class SecondInterceptor implements HandlerInterceptor {
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         System.out.println("SecondInterceptor  preHandle ");
         return true;
     }
 ​
     @Override
     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
         System.out.println("SecondInterceptor  postHandle ");
     }
 ​
     @Override
     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
         System.out.println("SecondInterceptor  afterCompletion ");
     }
 }
 @Component
 public class FirstInterceptor implements HandlerInterceptor {
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         System.out.println("FirstInterceptor  preHandle ");
         return true;
     }
 ​
     @Override
     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
         System.out.println("FirstInterceptor  postHandle ");
     }
 ​
     @Override
     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
         System.out.println("FirstInterceptor  afterCompletion ");
     }
 }

打开页面: 控制台输出

FirstInterceptor preHandle --配置顺序 SecondInterceptor preHandle SecondInterceptor postHandle -反序 FirstInterceptor postHandle SecondInterceptor afterCompletion -反序 FirstInterceptor afterCompletion

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

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

 @Component
 public class SecondInterceptor implements HandlerInterceptor {
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         System.out.println("SecondInterceptor  preHandle ");
         return false;  //改为 false
     }
     }

控制台输出

FirstInterceptor preHandle SecondInterceptor preHandle FirstInterceptor afterCompletion

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

射手座的程序媛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值