文件上传下载
文件上传
文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。
文件上传三要素
- 表单的提交方式 method=“POST”
- 表单的enctype属性是多部分表单形式 enctype=“multipart/form-data"
- 表单项(元素)type=“file”
页面准备
<h2>上传页面</h2> <form action="/upload" enctype="multipart/form-data" method="post"> 用户:<input type="text" name="username"> <br/> 上传:<input type="file" name="file"/><br/> <input type="submit" value="上传"> </form>
添加依赖
Spring MVC使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类,因此,SpringMVC的文件上传还需要依赖Apache Commons FileUpload的组件。
<!--文件上传--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
文件上传解析器
springmvc-config.xml的配置文件中
<!-- 定义文件上传解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设定默认编码 --> <property name="defaultEncoding" value="UTF-8"/> <!-- 设定文件上传的最大值5MB,5*1024*1024 ,指的是所有文件的总和 --> <property name="maxUploadSize" value="5242880"/> </bean>
controller实现
@Controller @RequestMapping("test") public class TestController { @RequestMapping("show8") public String upload(@RequestParam("file") MultipartFile multipartFile,HttpServletRequest request) throws IOException { String fileName = multipartFile.getOriginalFilename(); // 获取文件的名称 String path = request.getServletContext().getRealPath("/upload"); // 获取真实路径 File file = new File(path); // 将path封装为File对象 if (!file.exists()) { file.mkdir(); } multipartFile.transferTo(new File(file,fileName));//上传 System.out.println(path); return "forward:/success.html"; } }
文件下载
工具类
package cn.yanqi.utils; import java.io.*; import java.net.URLEncoder; import javax.servlet.http.HttpServletResponse; public class DownLoadUtils { public static void downLoadMyFile(File file, HttpServletResponse response) { try { if (file.exists()) { // 获取下载文件名 String filename = file.getName(); // 1: 设置下载的响应头 response.setHeader("Content-Disposition", "attachment;fileName="+ URLEncoder.encode(filename, "UTF-8")); //2、 读取文件--输入流 InputStream input=new FileInputStream(file); //3、 写出文件--输出流 OutputStream out = response.getOutputStream(); byte[] buff =new byte[1024]; int index=0; //4、执行 写出操作 while((index= input.read(buff))!= -1){ out.write(buff, 0, index); out.flush(); } out.close(); input.close(); } else { throw new RuntimeException("文件不存在...."); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
代码实现
@Controller @RequestMapping("test") public class TestController { @RequestMapping("dowloadFile") @ResponseStatus(HttpStatus.OK) public void dowload(HttpServletRequest request, HttpServletResponse response){ //获取文件的真实路径 String realPath = request.getServletContext().getRealPath("/upload/一燕.jpg"); File file = new File(realPath);//下载文件路径 // 工具类 DownLoadUtils.downLoadMyFile(file,response); } }
SpringMVC拦截器
概述
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。
preHandle | 执行目标方法之前进行拦截; true 放行 false 拦截不放行 |
postHandle | 在目标方法执行之后,进行增强 |
afterCompletion | 在视图渲染完毕后,进行资源释放 |
拦截器实现
自定义拦截器
使用自定义拦截器,SpringMVC提供了 HandlerInterceptor 接口。我们重写
preHandle
、postHandle
、afterCompletion
这三个方法!
/** * @Auther: yanqi * @Desc 自定义拦截器 */ public class MyInterceptor implements HandlerInterceptor { //执行目标方法之前进行拦截 true 放行 false 拦截不放行 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("执行目标方法之前进行拦截"); //放行 return true; } //目标方法执行之后,进行增强 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("目标方法执行之后,进行增强"); } //在视图渲染完毕后,进行资源释放 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("在视图渲染完毕后,进行资源释放"); } }
配置拦截器
- springmvc-servlet.xml
<!--拦截器--> <mvc:interceptors> <mvc:interceptor> <!--/** 所有controller请求都会进入拦截器--> <mvc:mapping path="/**"/> <!--指定拦截器--> <bean class="cn.yanqi.controller.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors>
指定和排除拦截
<!--指定拦截--> <mvc:interceptors> <mvc:interceptor> <!--指定拦截,写什么路径拦截什么路径--> <mvc:mapping path="/UserController/show1.do"/> <!--指定拦截器--> <bean class="cn.yanqi.controller.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors>
<!--排除拦截--> <mvc:interceptors> <mvc:interceptor> <!--所有controller请求都会进入拦截器--> <mvc:mapping path="/**"/> <!--拦截所有,排除拦截--> <mvc:exclude-mapping path="/hello2/show1.do"/> <mvc:exclude-mapping path="/hello2/show2.do"/> <!--指定拦截器--> <bean class="cn.yanqi.controller.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors>
- 访问测试
注意事项
只拦截controller请求
在拦截器链实现过程中,如果第一个拦截器中的preHandle的返回值是false,第二个拦截器将不会执行!
拦截器链
什么是拦截器链
多个拦截器,拦截同一个目标资源,形成一个链条,就是拦截器链!
拦截器链执行顺序
- 拦截方法的执行顺序
先进后出
- 拦截器的执行顺序
跟springmvc配置文件中的配置顺序有关系
mvc:interceptor 谁先配置谁先执行!
拦截器链实现
<!--配置拦截--> <mvc:interceptors> <!--第一个拦截器--> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.yanqi.Interceptor.MyInterceptor1"/> </mvc:interceptor> <!--第二个拦截器--> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.yanqi.Interceptor.MyInterceptor2"/> </mvc:interceptor> </mvc:interceptors>
过滤器与拦截器的区别
/** * @Desc Filter过滤器: * 1、实现Filter接口 * 2、通过web.xml或注解方式完成配置 * 3、重写的方法 init doFilter destroy * 4、过滤器过滤的是所有请求,不分controller和页面 */ public class MyFilter implements Filter {}
/** * @Desc Interceptor拦截器 * 1、实现HandlerInterceptor接口 * 2、需要在springmvc核心配置文件中配置 * 3、重写的方法 * preHandle 调用handler方法之前执行,true表示放行,false表示不放行 * postHandle 调用handler方法之后执行 * afterCompletion 视图渲染之后执行 * 4、只拦截controller请求 */ public class MyInterceptor implements HandlerInterceptor {}
RestFul
什么是RESTfull
REST(英文:Representational State Transfer,简称REST,意思:表述性状态转换,描述了一个架构样式的网络系统,比如web应用)。
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
- 应用场景
应用场景:前后端分离开发的架构中
RESTfull与传统URL对比
传统URL
前端 | 后台 | 描述 |
http://localhost:8080/user/findAllUsers | @RequestMapping(/user/findAllUsers) public List findAllUsers() |
查询所有用户 |
http://localhost:8080/user/findUserById?id=1 | @RequestMapping(/user/findUserById) public User findUserById(int id) |
查询指定用户 |
http://localhost:8080/user/addUser | @RequestMapping(/user/addUser) public void addUser(User user) |
添加用户 |
http://localhost:8080/user/updateUser | @RequestMapping(/user/updateUser) public void updateUser(User user) |
修改用户 |
http://localhost:8080/user/deleteUserById?id=1 | @RequestMapping(/user/deleteUserById) public User deleteUserById(int id) |
删除用户 |
RESTfull风格
Restful风格的请求是使用==“url+请求方式”(名饲+动词)==表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:
请求方式 | 描述 |
GET | 用于获取资源 |
POST | 用于新建资源 |
PUT | 用于更新资源 |
DELETE | 用于删除资源 |
- RESTfull风格请求的格式
前端 | 后台 | 描述 |
http://localhost:8080/user/ | @RequestMapping(/user,method=GET) public List findAllUsers() |
GET查询所有用户 |
http://localhost:8080/user/1 | @RequestMapping(/user/{id},method=GET) public User findUserById(@PathVariable int id) |
GET查询id为1用户 |
http://localhost:8080/user/ | @RequestMapping(/user,method=POST) public void addUser(User user) |
POST添加用户 |
http://localhost:8080/user/1 | @RequestMapping(/user/{id},method=PUT) public void updateUser(@PathVariable int id) |
PUT修改id为1用户 |
http://localhost:8080/user/1 | @RequestMapping(/user/{id},method=DELETE) public User deleteUserById(@PathVariable int id) |
DELETE删除id为1的用户 |
上述url地址/user/1中的1就是要获得的请求参数,在SpringMVC中可以使用占位符进行参数绑定。RequestMapping中/user/1可以写成/user/{id},占位符{id}对应的就是1的值。在业务方法中我们可以使用@PathVariable注解进行占位符的匹配获取工作。
@Controller @ResponseBody public class RestfullController { @GetMapping("/users") public String findAll() { return "findAll"; } @GetMapping("/users/{id}") public String findUserById(@PathVariable Integer id) { return "findUserById:"+id; } @PostMapping("/users") public String addUser() { return "addUser"; } // @RequestMapping(value = "/users/{id}",method = RequestMethod.PUT) @PutMapping("/users/{id}") public String updateUser(@PathVariable Integer id) { return "updateUser:" + id; } // @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE) @DeleteMapping("/users/{id}") public String deleteUser(@PathVariable Integer id) { return "deleteUser:" + id; } }
测试Restfull请求
浏览器默认只能发送:get、post请求,put delete请求是没办法测试的。我们需要借助于一个工具postman来模拟发送 GET POST PUT DELETE请求。
postman接口测试