第2天:SpringBoot文件上传+拦截器

文章介绍了如何在SpringBoot中实现文件上传功能,包括设置静态资源路径,调整文件大小限制,并展示了使用MultipartFile保存上传文件的代码示例。同时,文章还讲解了SpringBoot中的拦截器机制,用于权限检查、性能监控等场景,并给出了自定义拦截器的实现及注册方法。

静态资源访问

  • 使用IDEA创建Spring Boot项目,会默认创建出classpath:/static/目录,静态资源(网站图片,css,js)一般放在这个目录即可。【若前后端分离开发,该目录不存放内容】
  • 如果默认的静态资源过滤策略不能满足开发需求,可以自定义静态资源过滤策略。
  • 在application.properties中直接定义过滤规则和静态资源位置:
spring.mvc.static-path-pattern=/images/**
spring.resources.static-locations=classpath:/css
  • 过滤规则为/static/**,静态资源位置为classpath:/static/

文件上传

  • 表单的enctype属性规定在发送到服务器之前应该如何对表单数据进行编码。
  • 当表单的enctype=“application/x-www-form-urlencoded”(默认)时,form表单中的数据格式为:key=value&key=value
  • 当表单的enctype=“multipart/form-data”时,其传输数据形式如下:
    在这里插入图片描述

SpringBoot实现文件上传功能

SpringBoot工程嵌入的tomcat限制了请求的文件大小,每个文件的配置最大为1Mb,单次请求的文件的总数不能大于10Mb(单次可以请求多个文件)。
要更改这个默认值需要在配置文件(application.properties)中加入两个配置:

#单个文件大小
spring.servlet.multipart.max-file-size=10MB
#单次请求所有文件的大小总和
spring.servlet.multipart.max-request-size=10MB

当表单的enctype=“multipart/form-data”时,可以使用MultipartFile获取上传的文件数据,再通过TransferTo方法将其写到磁盘中(可以写入到服务器的某个目录中)。

@RestController
public class FileUploadController {

    @PostMapping("/upload")
    public String up(String nickname, MultipartFile photo, HttpServletRequest request) throws IOException{
        System.out.println(nickname);
        // 获取图片的原始名称
        System.out.println(photo.getOriginalFilename());
        // 获取文件类型
        System.out.println(photo.getContentType());

        // 获取服务器对应的路径,web服务器运行目录(动态变化,部署到其他服务器则路径改变,动态获取)
        String path=request.getServletContext().getRealPath("/upload/");
        System.out.println(path);
        saveFile(photo,path);
        return "上传成功";
    }

    public void saveFile(MultipartFile photo,String path) throws  IOException{
//        判断存储的目录是否存在,如果不存在则创建
//        创建File对象,将路径传到该对象进行判断
        File dir=new File(path);
        if(!dir.exists()){
//            创建目录
            dir.mkdir();
        }
//        最终存储的文件
        File file = new File(path+photo.getOriginalFilename());
        photo.transferTo(file);

    }

拦截器

拦截器在Web系统中很常见,对于某些全局统一的操作,可以提取到拦截器中实现(不同的控制器统一的操作,拦截器用于拦截请求,对统一操作做处理)。拦截器大致有以下几种使用场景:

  • 权限检查:如登录检测,进入处理程序检测是否登录,如果没有,直接返回登录页面。
  • 性能监控:有时系统在某段时间莫名其妙很慢,可以通过拦截器在进入处理程序之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间。
  • 通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有提取Locale、Theme信息等,只要是多个处理程序都需要的,即可使用拦截器实现。

SpringBoot中拦截器

SpringBoot定义了HandlerInterceptor接口来实现自定义拦截器的功能,该接口定义了preHandle(最常用)、postHandle、afterCompletion三种方法,通过重写这三种方法实现请求前、请求后等操作。
SpringBoot中拦截器工作示意图:
在这里插入图片描述
在这里插入图片描述

public class LoginInterceptor implements HandlerInterceptor {

//    在请求处理之前调用(Controller方法调用之前)
//    preHandle方法默认return true
//    request为前端发来的请求,response为后端给前端的响应
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws  Exception{
        System.out.println("LoginInterceptor");
        //添加判断
        return true;
    }
}

拦截器注册

  • addPathPatterns方法定义拦截的地址
  • excludePathPatterns定义排除某些地址不被拦截
  • 添加的一个拦截器没有addPathPatterns任何一个url,则默认拦截所有请求
  • 如果没有excludePathPatterns任何一个请求,则默认不放过任何一个请求
//加上@Configuration注解Springboot会自动读取这个类,以下的配置才能生效
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry){
//        如果不使用addPathPatterns添加路径,则拦截所有请求
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/**");
    }

}
### SpringBoot、Vue 和联盟链组合的系统业务架构设计 #### 1. 系统概述 在现代分布式应用开发中,Spring Boot 提供了强大的后端服务支持,Vue 则作为前端框架提供了优秀的用户体验交互能力,而联盟链技术则用于实现去中心化信任机制和不可篡改的数据存储。三者结合能够构建一个高效、安全且可扩展的企业级解决方案。 这种架构通常适用于需要多方协作并确保数据透明性和可信度的应用场景,例如供应链管理、金融交易记录共享以及身份认证等[^4]。 #### 2. 架构分层说明 以下是基于 Spring Boot、Vue 和联盟链的技术栈所组成的典型三层架构: ##### (1) 前端层 - Vue.js - **职责**: 用户界面展示与交互逻辑处理。 - 使用 Vue.js 或其增强版 Nuxt.js 来构建单页面应用程序(SPA),通过 RESTful API 或 GraphQL 同步前后端数据通信。 示例代码片段展示了如何配置 Axios 请求拦截器以便统一管理 HTTP 请求头信息: ```javascript import axios from 'axios'; const instance = axios.create({ baseURL: process.env.VUE_APP_API_URL, timeout: 5000, // 设置超时时间 }); // 添加请求拦截器 instance.interceptors.request.use(config => { const token = localStorage.getItem('authToken'); if (token) config.headers.Authorization = `Bearer ${token}`; return config; }, error => Promise.reject(error)); export default instance; ``` ##### (2) 中间件/网关层 - Spring Cloud Gateway + Zuul - 如果项目规模较大或者存在微服务体系,则推荐引入 Spring Cloud Gateway/Zuul 担任路由转发角色。 - 它们不仅简化跨域访问难题还能配合 OAuth2/OIDC 协议完成用户权限校验工作。 注意这里提到的身份验证部分可能涉及自动化流程如员工入职离职业务触发事件驱动型变更通知给关联子模块执行具体动作。 ##### (3) 后端服务层 - Spring Boot - 主要负责核心业务逻辑编写及对外暴露标准化接口文档遵循 OpenAPI/Swagger 规范便于第三方集成测试。 - 对接区块链节点客户端SDK发起智能合约调用读写操作同时维护本地缓存副本提升查询效率减少网络延迟影响性能表现。 下面给出一段简单的 Controller 方法定义样例用来接收来自前端提交过来的新订单详情参数对象OrderDTO并通过Feign远程调用其他内部依赖的服务组件实例获取额外补充资料最后组装完毕后再保存至数据库表Orders当中: ```java @RestController @RequestMapping("/api/orders") public class OrderController { @Autowired private IProductService productService; @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<String> create(@RequestBody OrderDTO orderDto){ try{ ProductVO productInfo = productService.getProductById(orderDto.getProductId()); Orders newRecord=new Orders(); BeanUtils.copyProperties(orderDto,newRecord); newRecord.setProductName(productInfo.getName()); ordersRepository.save(newRecord); return ResponseEntity.ok("Success"); }catch(Exception ex){ log.error(ex.getMessage(),ex); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error occurred."); } } } ``` ##### (4) 存储持久化层 - MySQL + 区块链账本 - 关系型数据库(MySQL)适合结构化程度较高的元数据管理比如客户档案商品分类目录等等; - 而对于那些一旦生成便不允许修改的历史凭证类文件建议上传到 Fabric/Hyperledger 这样的私有许可制联盟链上永久留存下来形成证据链条防止伪造篡改行为发生从而保障各方权益不受侵害。 此外还需特别关注事务一致性问题即当某笔交易既包含了传统关系型DB又涉及到区块链接入的情况下应当采取两阶段提交协议(2PC)或者其他补偿措施来规避潜在风险点保证最终状态达成一致目标[^2]. #### 3. 组件间通讯方式探讨 考虑到实际生产环境下的复杂性我们往往还需要借助消息队列中间件Kafka/RabbitMQ之类的产品来进行异步解耦优化整体吞吐量水平同时也利于后期运维监控告警等功能拓展实施[^3]. --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值