当前位置: 首页 > news >正文

springboot系列十二:拦截器和文件上传

文章目录

  • 基本介绍
  • 拦截器应用实例
    • 需求分析
    • 代码实现
    • 注意事项和细节
  • 文件上传
    • 需求说明
    • 代码实现
    • 注意事项和细节
    • 课后扩展

在这里插入图片描述

基本介绍

1.在Spring Boot项目中, 拦截器是开发中常用手段, 要来做登陆验证, 性能检查, 日志记录等.

2.基本步骤:
√ 编写一个拦截器实现HandlerInterceptor接口
√ 拦截器注册到配置类中(实现WebMvcConfigureraddInterceptors)
√ 指定拦截器规则
√ 回顾SpringMVC中写到的Interceptor: SpringMVC系列十一: 文件上传与自定义拦截器

拦截器应用实例

需求分析

需求: 使用拦截器防止用户非法登录. 使用拦截器就不需要在每个方法验证了.

●浏览器输入 http://localhost:8080/manage.html, 如果用户没有登录, 则返回登录页面

在这里插入图片描述

1.修改AdminController.java

使用Lombok支持日志输出

@Controller
@Slf4j
public class AdminController {//响应用户的登录请求@PostMapping("/login")public String login(Admin admin, HttpSession session, Model model) {//...}//处理用户请求 manage.html@GetMapping("/manage.html")public String mainPage(Model model,@SessionAttribute(value = "loginAdmin", required = false) Admin admin) {//这里暂时在方法中验证, 后面我们统一使用拦截器log.info("进入mainPage()");//用集合模拟用户数据, 放入到request域中, 并显示List<User> users = new ArrayList<>();users.add(new User(1, "张三", "123456", 23, "张三@163.com"));users.add(new User(2, "李四", "123456", 24, "李四@163.com"));users.add(new User(3, "王五", "123456", 25, "王五@163.com"));users.add(new User(4, "赵六", "123456", 26, "赵六@163.com"));users.add(new User(5, "田七", "123456", 27, "田七@163.com"));//将数据放入到request域中model.addAttribute("users", users);return "manage";//这里是我们的视图解析器,到 templates/manage.html}
}

2.修改 templates/manage.html, 去掉 [[${session.loginAdmin.name}]], 大体代码如下.

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>管理后台</title>
</head>
<body bgcolor="#CED3FE">
<img src="images/1.GIF"/>
<a href='#'>返回管理界面</a>  <a href='#' th:href="@{/}">安全退出</a>   欢迎您:
<hr/>
<div style="text-align: center"><h1>管理雇员~</h1><table border="1px" cellspacing="0" bordercolor="green" style="width:800px;margin: auto"><tr bgcolor="pink"><td>id</td><td>name</td><td>pwd</td><td>age</td><td>email</td></tr><tr bgcolor="#ffc0cb" th:each="user:${users}"><td th:text="${user.id}">a</td><td th:text="${user.name}">b</td><td th:text="${user.password}">c</td><td th:text="${user.age}">d</td><td th:text="${user.email}">e</td></tr></table><br/>
</div>
<hr/>
<img src="images/logo.png"/>
</body>
</html>

3.浏览器/Postman, 能够访问 http://localhost:8080/manage.html

在这里插入图片描述

代码实现

1.创建src/main/java/com/zzw/springboot/interceptor/LoginInterceptor.java

@Slf4j
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//为了让你们看到访问的URIString requestURI = request.getRequestURI();log.info("preHandle拦截到的请求的URI={}", requestURI);//进行登录的验证HttpSession session = request.getSession();Object loginAdmin = session.getAttribute("loginAdmin");if (loginAdmin != null) {//说明该用户已经成功登录//放行return true;}//拦截, 重新返回登陆页面request.setAttribute("error", "你没有登录, 请重新登录~");request.getRequestDispatcher("/").forward(request, response);return false;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("postHandle() 被执行...");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("afterCompletion() 被执行...");}
}

2.注册拦截器到配置类中(实现WebMvcConfigurer接口的addInterceptors方法)

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册自定义拦截器 LoginInterceptorregistry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") //拦截所有的请求.excludePathPatterns("/", "/login","/images/**"); //指定要放行的, 后面可以根据业务需求, 添加放行的请求路径}
}

3.测试

在这里插入图片描述

注意事项和细节

1.将/images/**去掉会有什么后果.

1)首先, 浏览器禁用缓存, 重启(是为了去掉保存在session里的登录信息).

在这里插入图片描述

2)其次, 刷新页面 http://localhost:8080/, 图片请求被拦截.

在这里插入图片描述

3)因为static是类路径下, 所谓的静态资源访问, 所以可以写成images/**, 而不用写成static/images/**

4)在前端代码中, 图片url可以写成<img src="images/1.GIF">, <img src="images/logo.png">

2.URIURL的区别. HttpServletRequest常用方法
URI: Universal Resource Identifier
URL: Universal Resource Locator
Identifier: 标识符. Locator: 定位器, 从字面上来看, URI可以在站点内唯一标识一个资源, URL可以在全网内提供找到该资源的路径.

举例

String requestURI = request.getRequestURI();
String requestURL = request.getRequestURL().toString();
log.info("preHandle拦截到的请求的URI={}", requestURI);// /manage.html
log.info("preHandle拦截到的请求的URL={}", requestURL);// http://localhost:8080/manage.html

3.注册拦截器, 依然可以使用如下方式, 参考注册自定义转换器

@Configuration
public class WebConfig {@Beanpublic WebMvcConfigurer webMvcConfigurer() {/*class WebConfig2$1 implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册自定义拦截器 LoginInterceptorregistry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") //拦截所有的请求.excludePathPatterns("/", "/login", "/images/**"); //指定要放行的, 后面可以根据业务需求, 添加放行的请求路径}}WebMvcConfigurer webMvcConfigurer = new WebConfig2$1();return webMvcConfigurer;*/return new WebMvcConfigurer() {@Overridepublic void addInterceptors(InterceptorRegistry registry) {System.out.println("~~~~~匿名内部类注册拦截器~~~~~");//注册自定义拦截器 LoginInterceptorregistry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") //拦截所有的请求.excludePathPatterns("/", "/login", "/images/**"); //指定要放行的, 后面可以根据业务需求, 添加放行的请求路径}};}
}

文件上传

需求说明

需求: 演示在SpringBoot 中通过表单注册用户, 并支持上传图片.

回顾 SpringMVC文件上传

代码实现

1.创建templates/upload.html, 要求头像只能选择一个, 而宠物可以上传多张图片

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>文件上传</title>
</head>
<body bgcolor="#CED3FE">
<img src="images/1.GIF">
<div style="text-align: center;"><h1>注册用户~</h1><form action="#" th:action="@{/upload}" method="post" enctype="multipart/form-data">用户名:<input type="text" style="width: 150px" name="username"><br/><br/>邮 件:<input type="text" style="width: 150px" name="email"><br/><br/>年 龄:<input type="text" style="width: 150px" name="age"><br/><br/>职 位:<input type="text" style="width: 150px" name="job"><br/><br/>头 像:<input type="file" style="width: 150px" name="avatar"><br/><br/>宠 物:<input type="file" style="width: 150px" name="pets" multiple><br/><br/><input type="submit" value="注册"/><input type="reset" value="重新填写"></form>
</div>
<img src="images/logo.png">
</body>
</html>

2.指定拦截器放行upload.html. upload

@Configuration
public class WebConfig {@Beanpublic WebMvcConfigurer webMvcConfigurer() {return new WebMvcConfigurer() {@Overridepublic void addInterceptors(InterceptorRegistry registry) {System.out.println("~~~~~匿名内部类注册拦截器~~~~~");//注册自定义拦截器 LoginInterceptorregistry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**") //拦截所有的请求.excludePathPatterns("/", "/login", "/images/**", "/upload.html", "/upload"); //指定要放行的, 后面可以根据业务需求, 添加放行的请求路径}};}
}

3.创建src/main/java/com/zzw/springboot/controller/UploadController.java

@Controller
public class UploadController {//处理转发到用户注册页面upload.html-可以完成文件上传页面@RequestMapping("/upload.html")public String uploadPage() {return "upload";//thymeleaf进行视图解析, 转发到templates/upload.html}
}

4.浏览器访问 http://localhost:8080/upload.html, 测试

在这里插入图片描述

5.修改src/main/java/com/zzw/springboot/controller/UploadController.java

@Controller
@Slf4j
public class UploadController {//处理转发到用户注册页面upload.html-可以完成文件上传页面@RequestMapping("/upload.html")public String uploadPage() {return "upload";//thymeleaf进行视图解析, 转发到templates/upload.html}//处理用户的注册请求-包括处理文件上传@PostMapping("/upload")@ResponseBodypublic String upload(@RequestParam(value = "username") String name,@RequestParam(value = "email") String email,@RequestParam(value = "age") Integer age,@RequestParam(value = "job") String job,@RequestParam(value = "avatar") MultipartFile avatar,@RequestParam(value = "pets") MultipartFile[] pets) {//输出获取到的信息log.info("上传的信息 name={}, email={}, age={}, job={}, avartar={}, pets={}",name, email, age, job, avatar.getSize(), pets.length);//如果信息都注册成功, 我们就将文件保存到指定的目录, 比如保存在d:\\temp_upload//1.我们先将文件保存到指定到指定的目录, 比如d:\\temp_upload//2.后面我们再演示把文件保存到动态创建的目录return "用户注册成功/文件上传成功";}
}

6.修改src/main/java/com/zzw/springboot/controller/UploadController.java
SpringMVC系列十一: 文件上传与自定义拦截器

@Controller
@Slf4j
public class UploadController {//处理转发到用户注册页面upload.html-可以完成文件上传页面@RequestMapping("/upload.html")public String uploadPage() {return "upload";//thymeleaf进行视图解析, 转发到templates/upload.html}//处理用户的注册请求-包括处理文件上传@PostMapping("/upload")@ResponseBodypublic String upload(@RequestParam(value = "username") String name,@RequestParam(value = "email") String email,@RequestParam(value = "age") Integer age,@RequestParam(value = "job") String job,@RequestParam(value = "avatar") MultipartFile avatar,@RequestParam(value = "pets") MultipartFile[] pets) throws IOException {//输出获取到的信息log.info("上传的信息 name={}, email={}, age={}, job={}, avartar={}, pets={}",name, email, age, job, avatar.getSize(), pets.length);//如果信息都注册成功, 我们就将文件保存到指定的目录, 比如保存在d:\\temp_upload//1.我们先将文件保存到指定到指定的目录, 比如d:\\temp_upload//2.后面我们再演示把文件保存到动态创建的目录if (!avatar.isEmpty()) {//处理头像上传String originalFilename = avatar.getOriginalFilename();log.info("你要上传的文件名={}", originalFilename);//你要把文件上传到哪个路径[全路径: 包括文件名]String fileFullPath = "d:\\temp_upload\\" + originalFilename;File file = new File(fileFullPath);avatar.transferTo(file);}if (pets.length > 0) {//处理宠物图片[多张]for (MultipartFile pet : pets) {//循环遍历if (!pet.isEmpty()) {String originalFilename = pet.getOriginalFilename();//宠物图片名log.info("你要上传的宠物名={}", originalFilename);String fileFullPath = "d:\\temp_upload\\" + originalFilename;File file = new File(fileFullPath);pet.transferTo(file);}}}return "用户注册成功/文件上传成功";}
}

7.测试

在这里插入图片描述

8.修改src/main/java/com/zzw/springboot/controller/UploadController.java

@Controller
@Slf4j
public class UploadController {//处理转发到用户注册页面upload.html-可以完成文件上传页面@RequestMapping("/upload.html")public String uploadPage() {return "upload";//thymeleaf进行视图解析, 转发到templates/upload.html}//处理用户的注册请求-包括处理文件上传@PostMapping("/upload")@ResponseBodypublic String upload(@RequestParam(value = "username") String name,@RequestParam(value = "email") String email,@RequestParam(value = "age") Integer age,@RequestParam(value = "job") String job,@RequestParam(value = "avatar") MultipartFile avatar,@RequestParam(value = "pets") MultipartFile[] pets) throws IOException {//输出获取到的信息log.info("上传的信息 name={}, email={}, age={}, job={}, avartar={}, pets={}",name, email, age, job, avatar.getSize(), pets.length);//如果信息都注册成功, 我们就将文件保存到指定的目录, 比如保存在d:\\temp_upload//1.我们先将文件保存到指定到指定的目录, 比如d:\\temp_upload//2.后面我们再演示把文件保存到动态创建的目录//  比如E:\idea_project\zzw_springboot\springboot-usersys\target\classes\static\images\\upload\//得到类路径(运行的时候)String path = ResourceUtils.getURL("classpath:").getPath();//log.info("path={}", path);//动态创建指定的目录File parentFile = new File(path + "static/images/upload/");if (!parentFile.exists()) {//如果目录不存在, 就创建 java ioparentFile.mkdirs();}if (!avatar.isEmpty()) {//处理头像上传String originalFilename = avatar.getOriginalFilename();log.info("你要上传的文件名={}", originalFilename);//你要把文件上传到哪个路径[全路径: 包括文件名]//String fileFullPath = "d:\\temp_upload\\" + originalFilename;//File file = new File(fileFullPath);//这里我们需要指定保存文件的绝对路径: E:\idea_project\zzw_springboot\springboot-usersys\target\classes\static\images\\upload\//log.info("保存文件的绝对路径={}", parentFile.getAbsolutePath());//保存到动态创建的目录avatar.transferTo(new File(parentFile, originalFilename));}if (pets.length > 0) {//处理宠物图片[多张]for (MultipartFile pet : pets) {//循环遍历if (!pet.isEmpty()) {String originalFilename = pet.getOriginalFilename();//宠物图片名log.info("你要上传的宠物名={}", originalFilename);//String fileFullPath = "d:\\temp_upload\\" + originalFilename;//File file = new File(fileFullPath);//保存到动态创建的目录pet.transferTo(new File(parentFile, originalFilename));}}}return "用户注册成功/文件上传成功";}
}

9.测试

在这里插入图片描述

注意事项和细节

1.根据项目需求修改文件上传的参数,否则文件上传会抛出异常。MultipartProperties.java

@ConfigurationProperties用法

properties自动配置

在这里插入图片描述

在这里插入图片描述

2.修改src/main/resources/application.yml

spring:servlet:multipart:max-file-size: 10MBmax-request-size: 100MB

3.上传超大文件 8MB

在这里插入图片描述

在这里插入图片描述

课后扩展

1.解决文件覆盖问题, 如果文件名相同, 会出现覆盖问题, 如何解决.

2.解决文件分目录存放问题, 如果将文件都上传到一个目录下, 当上传文件很多时, 会造成访问文件速度变慢. 因此, 可以将文件上传到不同目录, 比如 一天上传的文件, 统一以年/月/日的形式放到一个文件夹, 比如2024/8/5目录.

3.参考 项目实战系列三: 家居购项目 第六部分
JavaWeb系列二十三: web 应用常用功能(文件上传下载)

代码实现
1.新建src/main/java/com/zzw/springboot/util/WebUtils.java

public class WebUtils {//定义一个文件上传的路径public static String UPLOAD_FILE_DIRECTORY = "static/images/upload/";//编写方法, 生成一个目录-根据当前日期, 生成 年/月/日public static String getUploadFileDirectory() {LocalDate ld = LocalDate.now();return ld.getYear() + "/" + ld.getMonthValue() + "/" + ld.getDayOfMonth() + "/";}
}

2.修改src/main/java/com/zzw/springboot/controller/UploadController.java

@Controller
@Slf4j
public class UploadController {//处理转发到用户注册页面upload.html-可以完成文件上传页面@RequestMapping("/upload.html")public String uploadPage() {return "upload";//thymeleaf进行视图解析, 转发到templates/upload.html}//处理用户的注册请求-包括处理文件上传@PostMapping("/upload")@ResponseBodypublic String upload(@RequestParam(value = "username", required = false) String name,@RequestParam(value = "email", required = false) String email,@RequestParam(value = "age", required = false) Integer age,@RequestParam(value = "job", required = false) String job,@RequestParam(value = "avatar", required = false) MultipartFile avatar,@RequestParam(value = "pets", required = false) MultipartFile[] pets) throws IOException {//输出获取到的信息log.info("上传的信息 name={}, email={}, age={}, job={}, avartar={}, pets={}",name, email, age, job, avatar.getSize(), pets.length);//如果信息都注册成功, 我们就将文件保存到指定的目录, 比如保存在d:\\temp_upload//1.我们先将文件保存到指定到指定的目录, 比如d:\\temp_upload//2.后面我们再演示把文件保存到动态创建的目录//  比如E:\idea_project\zzw_springboot\springboot-usersys\target\classes\static\images\\upload\//得到类路径(运行的时候)String path = ResourceUtils.getURL("classpath:").getPath();//log.info("path={}", path);//动态创建指定的目录File parentFile = new File(path + "static/images/upload/");if (!parentFile.exists()) {//如果目录不存在, 就创建 java ioparentFile.mkdirs();}if (!avatar.isEmpty()) {//处理头像上传String originalFilename = avatar.getOriginalFilename();log.info("你要上传的文件名={}", originalFilename);//对上传的文件名进行处理, 增加一个前缀, 保证是唯一的, 防止文件名重复造成覆盖String fileName = UUID.randomUUID().toString() + "_" + System.currentTimeMillis() + "_" + originalFilename;//你要把文件上传到哪个路径[全路径: 包括文件名]//String fileFullPath = "d:\\temp_upload\\" + originalFilename;//File file = new File(fileFullPath);//这里我们需要指定保存文件的绝对路径: E:\idea_project\zzw_springboot\springboot-usersys\target\classes\static\images\\upload\//log.info("保存文件的绝对路径={}", parentFile.getAbsolutePath());//保存到动态创建的目录File destPath = new File(parentFile, WebUtils.getUploadFileDirectory());if (!destPath.exists()) {destPath.mkdirs();}avatar.transferTo(new File(destPath, fileName));}if (pets.length > 0) {//处理宠物图片[多张]for (MultipartFile pet : pets) {//循环遍历if (!pet.isEmpty()) {String originalFilename = pet.getOriginalFilename();//宠物图片名log.info("你要上传的宠物名={}", originalFilename);//对上传的文件名进行处理, 增加一个前缀, 保证是唯一的, 防止文件名重复造成覆盖String fileName = UUID.randomUUID().toString() + "_" + System.currentTimeMillis() + "_" + originalFilename;//String fileFullPath = "d:\\temp_upload\\" + originalFilename;//File file = new File(fileFullPath);//保存到动态创建的目录File destPath = new File(parentFile, WebUtils.getUploadFileDirectory());if (!destPath.exists()) {destPath.mkdirs();}avatar.transferTo(new File(destPath, fileName));}}}return "用户注册成功/文件上传成功";}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Git使用错误分析
  • 如何保证电源的长期稳定性?
  • PHP开启多进程
  • SpringBoot基础(二):配置文件详解
  • 序列建模之循环和递归网络 - 引言篇
  • 一个很牛的学习网站分享 Developer Roadmaps
  • 【视频讲解】顶级期刊即插即用模块代码共享计划·2024第一期:02:非相邻层次间语义信息渐进式特征融合策略(2024 1区Top | 浙江大学开源)代码实现
  • 【SpringMVC】详细介绍SpringMVC的执行流程
  • 基于JSP、java、Tomcat三者的项目实战--校园交易平台系统--(实习,答辩皆可用到)--万字爆更
  • Python酷库之旅-第三方库Pandas(075)
  • rabbitmq出现Management API returned status code 500 -
  • 用爬虫玩转石墨文档(下)
  • LeetCode_sql_day15(262.行程与用户)
  • Node.js 常用命令集合
  • Linux的Chrome、Firefox浏览器无法加载简书的图片
  • JavaScript类型识别
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • magento 货币换算
  • mysql 数据库四种事务隔离级别
  • 诡异!React stopPropagation失灵
  • ​zookeeper集群配置与启动
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (1)常见O(n^2)排序算法解析
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (分布式缓存)Redis哨兵
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (学习日记)2024.01.19
  • (转载)hibernate缓存
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • .bashrc在哪里,alias妙用
  • .htaccess配置常用技巧
  • .mysql secret在哪_MySQL如何使用索引
  • .NET CLR基本术语
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .Net Core 中间件验签
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .net开发引用程序集提示没有强名称的解决办法
  • .NET学习全景图
  • .NET业务框架的构建
  • ??Nginx实现会话保持_Nginx会话保持与Redis的结合_Nginx实现四层负载均衡
  • @ComponentScan比较
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...
  • @JSONField或@JsonProperty注解使用
  • @private @protected @public
  • @select 怎么写存储过程_你知道select语句和update语句分别是怎么执行的吗?
  • @serverendpoint注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [@Controller]4 详解@ModelAttribute
  • [AI]文心一言出圈的同时,NLP处理下的ChatGPT-4.5最新资讯
  • [bzoj1901]: Zju2112 Dynamic Rankings
  • [Cloud Networking] Layer 2
  • [Day 65] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
  • [GESP202312 四级] 田忌赛马
  • [github配置] 远程访问仓库以及问题解决