一、文件上传与下载

1、单文件上传

  1. 在static目录下创建upload.html文件
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
    <title>单文件上传</title>
</head>
<body>
<!--
enctype就是encodetype就是编码类型的意思。
multipart/form-data是指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思。
需要注意的是:默认情况下,enctype的值是application/x-www-form-urlencoded,不能用于文件上传,只有使用了multipart/form-data,才能完整的传递文件数据。
application/x-www-form-urlencoded不是不能上传文件,是只能上传文本格式的文件,multipart/form-data是将文件以二进制的形式上传,这样可以实现多种类型的文件上传。
-->
<form method="post" action="/file/upload" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="提交">
</form>

</body>
</html>
  1. 在application.yml文件中配置(如果是properties记得要改名)
server:
    port: 8082

spring:
    servlet:
        multipart:
            enabled: true
            #最大支持文件大小
            max-file-size: 100MB
            #最大支持请求大小
            max-request-size: 100MB
  1. 创建Controller目录,并创建FileController类
package com.example.demo7load.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.UUID;

@Controller
@RequestMapping("/file/")
public class FileController {
    /*单文件上传*/
    @RequestMapping("upload")
    @ResponseBody
    public String upload (@RequestParam("file") MultipartFile file) {
        // 获取原始名字
        String fileName = file.getOriginalFilename();
        // 文件保存路径
        String filePath = "E:/file/";
        // 文件重命名,防止重复
        fileName = filePath + UUID.randomUUID() + fileName;
        // 文件对象
        File dest = new File(fileName);
        // 判断路径是否存在,如果不存在则创建
        if(!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            // 保存到服务器中
            file.transferTo(dest);
            return "上传成功";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "上传失败";
    }
}
  1. 访问localhost:8082/upload.html进行访问测试

2、多文件上传

  1. 在upload.html文件中添加代码
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
    <title>单文件上传</title>
</head>
<body>
<!--
enctype就是encodetype就是编码类型的意思。
multipart/form-data是指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思。
需要注意的是:默认情况下,enctype的值是application/x-www-form-urlencoded,不能用于文件上传,只有使用了multipart/form-data,才能完整的传递文件数据。
application/x-www-form-urlencoded不是不能上传文件,是只能上传文本格式的文件,multipart/form-data是将文件以二进制的形式上传,这样可以实现多种类型的文件上传。
-->
<form method="post" action="/file/upload" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="提交">
</form>

<p>多文件上传</p>
<form method="POST" enctype="multipart/form-data" action="/file/uploads">
    <!--
    添加multiple属性,可以按住ctrl多选文件
    multiple 属性规定输入字段可选择多个值,在这里即输入多个文件
    -->
    <p>文件:<input type="file" multiple name="file" /></p>
    <p><input type="submit" value="上传" /></p>
</form>
</body>
</html>
  1. 在FileController类中添加代码
package com.example.demo7load.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.UUID;

@Controller
@RequestMapping("/file/")
public class FileController {
    /*单文件上传*/
    @RequestMapping("upload")
    @ResponseBody
    public String upload (@RequestParam("file") MultipartFile file) {
        // 获取原始名字
        String fileName = file.getOriginalFilename();
        // 文件保存路径
        String filePath = "E:/file/";
        // 文件重命名,防止重复
        fileName = filePath + UUID.randomUUID() + fileName;
        // 文件对象
        File dest = new File(fileName);
        // 判断路径是否存在,如果不存在则创建
        if(!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            // 保存到服务器中
            file.transferTo(dest);
            return "上传成功";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "上传失败";
    }
    /*多文件上传*/
    @PostMapping("/uploads")
    @ResponseBody
    public String handleFileUpload(HttpServletRequest request) {
        List<MultipartFile> files = ((MultipartHttpServletRequest) request)
                .getFiles("file");
        MultipartFile file = null;
        for (int i = 0; i < files.size(); ++i) {
            file = files.get(i);
            if (!file.isEmpty()) {
                try {
                    // 获取原始名字
                    String fileName = file.getOriginalFilename();
                    // 文件保存路径
                    String filePath = "E:/file/";
                    // 文件重命名,防止重复
                    fileName = filePath + UUID.randomUUID() + fileName;
                    // 文件对象
                    File dest = new File(fileName);
                    // 保存到服务器中
                    file.transferTo(dest);
                } catch (Exception e) {
                    e.printStackTrace();
                    return "上传失败";
                }
            }else {
                return "上传失败";
            }
        }
        return "上传成功";
    }
}

3、文件下载

  1. 在FileController中添加代码
@RequestMapping("download")
    public void download(HttpServletResponse response) throws Exception {
        // 文件地址,真实环境是存放在数据库中的
        String filename="a.txt";
        String filePath = "E:/file" ;
        File file = new File(filePath + "/" + filename);
        // 创建输入对象
        FileInputStream fis = new FileInputStream(file);
        // 设置相关格式
        response.setContentType("application/force-download");
        // 设置下载后的文件名以及header
        response.setHeader("Content-Disposition", "attachment;fileName=" +filename);
        // 创建输出对象
        OutputStream os = response.getOutputStream();
        // 常规操作,把文件里的内容写上
        byte[] buf = new byte[1024];
        int len = 0;
        while((len = fis.read(buf)) != -1) {
            os.write(buf, 0, len);
        }
        fis.close();
    }
  1. 在E盘新建file文件夹,并在file文件夹中新建a.txt文本文件
  2. 输入localhost:8082/file/download,然后就可以发现浏览器弹出下载框

二、定时器

1、Task

Task是Spring自带的定时器,使用方便,简单

  1. 在启动类(即main入口)添加@EnableScheduling注解
package com.example.demo7load;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class Demo7LoadApplication {

    public static void main(String[] args) {
        SpringApplication.run(Demo7LoadApplication.class, args);
    }

}
  1. 创建Time目录,并创建ScheduleedTask类(这里我打错了)
    定时任务主要靠@Scheduled注解来实现
package com.example.demo7load.time;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class ScheduleedTask {
    private Logger log= (Logger) LoggerFactory.getLogger(ScheduleedTask.class);

    //这里是cronExpression表达式,详情看后文介绍
    @Scheduled(cron="0/5 * * * * ?")
    public void testOne(){
        log.info("每5s执行一次");
    }

    @Scheduled(fixedRate = 3000)
    public void testTwo(){
        log.info("每3s执行一次");
    }

    @Scheduled(cron="0 0 14 * * ?")   //表示每天下午14点执行
    public void initTask(){
        log.info("执行任务"+new Date());
    }
}
  1. 查看控制台

    这里面出现了一个cronExpression表达式,简单解释一下
"[秒] [分] [时] [日] [月] [周] [年]"

年可以省略,还有周的1表示星期天,也即一个星期的第一天

  • *字符表示指定所有的值
  • -表示一个范围
  • ?表示指定非明确的值,只在日期和周期域中使用,举个例子:指定星期几但是不确定是什么日期时就可以使用
  • /表示每多少分钟/秒触发一次

“ 0 15 10 ? * 6 ”:表示每个星期五的上午10:15触发
“ 0 0/5 14 * * * ”:表示下午14:00到14:59没五分钟触发一次

2、Quartz

Quartz框架的核心组件包括调度器、触发器、作业等

Quartz介绍

springboot 二进制流分片返回 springboot接收二进制文件_spring boot

  1. Job表示一个任务,要执行的具体内容
  2. JobDetail表示一个具体的可执行的调度程序,包含了Job的调度方案和策略
  3. Trigger是一个类,描述触发Job执行的时间及触发规则
  4. Scheduler代表一个调度容器,用于将Trigger和JobDetail绑定

使用Quartz

  1. 在pom.xml中添加Quartz的依赖
<!--定时器依赖-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>
        <!-- 该依赖必加,里面有sping对schedule的支持 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>
        <!--必须添加,要不然会出错,项目无法启动-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>
  1. 编写任务执行类JobTask
package com.beixi.timer;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

@Configuration
@Component
@EnableScheduling
public class JobTask {
    public void start() throws InterruptedException {
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.err.println("定时任务开始执行。"+format.format(new Date()));

    }
}

若报红就按照提示安装相应依赖

  1. 详细配置类QuartzConfigration
package com.example.demo7load.time;

import org.quartz.Trigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

@Configuration
public class QuartzConfigration {
    @Bean(name = "jobDetail")
    public MethodInvokingJobDetailFactoryBean detailFactoryBean(JobTask task) {
        // ScheduleTask为需要执行的任务
        MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
        /*
         *  是否并发执行
         *  例如每3s执行一次任务,但是当前任务还没有执行完,就已经过了3s了.
         *  如果此处为true,则下一个任务会bing执行,如果此处为false,则下一个任务会等待上一个任务执行完后,再开始执行
         */
        jobDetail.setConcurrent(true);
        jobDetail.setName("scheduler");// 设置任务的名字
        jobDetail.setGroup("scheduler_group");// 设置任务的分组,这些属性都可以存储在数据库中,在多任务的时候使用

        /*
         * 这两行代码表示执行task对象中的scheduleTest方法。定时执行的逻辑都在scheduleTest。
         */
        jobDetail.setTargetObject(task);
        jobDetail.setTargetMethod("start");
        return jobDetail;
    }

    @Bean(name = "jobTrigger")
    public CronTriggerFactoryBean cronJobTrigger(MethodInvokingJobDetailFactoryBean jobDetail) {
        CronTriggerFactoryBean tigger = new CronTriggerFactoryBean();
        tigger.setJobDetail(jobDetail.getObject());
        tigger.setCronExpression("*/5 * * * * ?");//每五秒执行一次
        tigger.setName("myTigger");// trigger的name
        return tigger;
    }
    @Bean(name = "scheduler")
    public SchedulerFactoryBean schedulerFactory(Trigger cronJobTrigger) {
        SchedulerFactoryBean bean = new SchedulerFactoryBean();
        //设置是否任意一个已定义的Job会覆盖现在的Job。默认为false,即已定义的Job不会覆盖现有的Job。
        bean.setOverwriteExistingJobs(true);
        // 延时启动,应用启动5秒后  ,定时器才开始启动
        bean.setStartupDelay(5);
        // 注册定时触发器
        bean.setTriggers(cronJobTrigger);
        return bean;
    }
    //多任务时的Scheduler,动态设置Trigger。一个SchedulerFactoryBean可能会有多个Trigger
    @Bean(name = "multitaskScheduler")
    public SchedulerFactoryBean schedulerFactoryBean(){
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        return schedulerFactoryBean;
    }
}