一、文件上传与下载
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>
- 在application.yml文件中配置(如果是properties记得要改名)
server:
port: 8082
spring:
servlet:
multipart:
enabled: true
#最大支持文件大小
max-file-size: 100MB
#最大支持请求大小
max-request-size: 100MB
- 创建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 "上传失败";
}
}
- 访问localhost:8082/upload.html进行访问测试
2、多文件上传
- 在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>
- 在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、文件下载
- 在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();
}
- 在E盘新建file文件夹,并在file文件夹中新建a.txt文本文件
- 输入localhost:8082/file/download,然后就可以发现浏览器弹出下载框
二、定时器
1、Task
Task是Spring自带的定时器,使用方便,简单
- 在启动类(即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);
}
}
- 创建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());
}
}
- 查看控制台
这里面出现了一个cronExpression表达式,简单解释一下
"[秒] [分] [时] [日] [月] [周] [年]"
年可以省略,还有周的1表示星期天,也即一个星期的第一天
- *字符表示指定所有的值
- -表示一个范围
- ?表示指定非明确的值,只在日期和周期域中使用,举个例子:指定星期几但是不确定是什么日期时就可以使用
- /表示每多少分钟/秒触发一次
“ 0 15 10 ? * 6 ”:表示每个星期五的上午10:15触发
“ 0 0/5 14 * * * ”:表示下午14:00到14:59没五分钟触发一次
2、Quartz
Quartz框架的核心组件包括调度器、触发器、作业等
Quartz介绍
- Job表示一个任务,要执行的具体内容
- JobDetail表示一个具体的可执行的调度程序,包含了Job的调度方案和策略
- Trigger是一个类,描述触发Job执行的时间及触发规则
- Scheduler代表一个调度容器,用于将Trigger和JobDetail绑定
使用Quartz
- 在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>
- 编写任务执行类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()));
}
}
若报红就按照提示安装相应依赖
- 详细配置类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;
}
}