程序员蜗牛
1 year ago
9 changed files with 383 additions and 0 deletions
@ -0,0 +1,77 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
<parent> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-parent</artifactId> |
||||
|
<version>2.7.4</version> |
||||
|
<relativePath/> <!-- lookup parent from repository --> |
||||
|
</parent> |
||||
|
<groupId>com.example</groupId> |
||||
|
<artifactId>demo-request-scope</artifactId> |
||||
|
<version>0.0.1-SNAPSHOT</version> |
||||
|
<name>demo-request-scope</name> |
||||
|
<description>Demo project for Spring Boot</description> |
||||
|
<properties> |
||||
|
<java.version>8</java.version> |
||||
|
</properties> |
||||
|
|
||||
|
|
||||
|
<dependencies> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.google.guava</groupId> |
||||
|
<artifactId>guava</artifactId> |
||||
|
<version>30.1-jre</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-aop</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-data-redis</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-web</artifactId> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>cn.hutool</groupId> |
||||
|
<artifactId>hutool-all</artifactId> |
||||
|
<version>5.8.16</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>com.alibaba</groupId> |
||||
|
<artifactId>easyexcel</artifactId> |
||||
|
<version>3.3.2</version> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-test</artifactId> |
||||
|
<scope>test</scope> |
||||
|
</dependency> |
||||
|
|
||||
|
<dependency> |
||||
|
<groupId>org.projectlombok</groupId> |
||||
|
<artifactId>lombok</artifactId> |
||||
|
<optional>true</optional> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
|
||||
|
<build> |
||||
|
<plugins> |
||||
|
<plugin> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
|
</plugin> |
||||
|
</plugins> |
||||
|
</build> |
||||
|
|
||||
|
</project> |
@ -0,0 +1,14 @@ |
|||||
|
package com.example.demo; |
||||
|
|
||||
|
import org.springframework.boot.SpringApplication; |
||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
|
||||
|
|
||||
|
@SpringBootApplication |
||||
|
public class DemoRequestScopeApplication { |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
SpringApplication.run(DemoRequestScopeApplication.class, args); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
package com.example.demo.config; |
||||
|
|
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
|
||||
|
import java.util.concurrent.ArrayBlockingQueue; |
||||
|
import java.util.concurrent.ThreadPoolExecutor; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
@Configuration |
||||
|
public class ThreadPoolConfig { |
||||
|
|
||||
|
private static final int corePoolSize = 10; // 核心线程数
|
||||
|
private static final int maximumPoolSize = 20; // 最大线程数
|
||||
|
private static final long keepAliveTime = 60L; // 空闲线程存活时间
|
||||
|
private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; |
||||
|
|
||||
|
@Bean |
||||
|
public ThreadPoolExecutor getThreadPoolExecutor() { |
||||
|
return new ThreadPoolExecutor( |
||||
|
corePoolSize, |
||||
|
maximumPoolSize, |
||||
|
keepAliveTime, |
||||
|
TIME_UNIT, |
||||
|
new ArrayBlockingQueue<>(2000), |
||||
|
new ThreadPoolExecutor.AbortPolicy() |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,93 @@ |
|||||
|
package com.example.demo.export; |
||||
|
|
||||
|
|
||||
|
|
||||
|
import cn.hutool.core.bean.BeanUtil; |
||||
|
import cn.hutool.core.util.PageUtil; |
||||
|
import com.alibaba.excel.EasyExcel; |
||||
|
import com.alibaba.excel.ExcelWriter; |
||||
|
import com.alibaba.excel.write.metadata.WriteSheet; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
|
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
import java.net.URLEncoder; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Slf4j |
||||
|
public abstract class AbstractExport<T, K> { |
||||
|
|
||||
|
|
||||
|
public abstract void export(ExportUser sysUser) throws InterruptedException; |
||||
|
|
||||
|
/** |
||||
|
* 导出 |
||||
|
* @param response 输出流 |
||||
|
* @param pageSize 每页大小 |
||||
|
* @param t 导出条件 |
||||
|
* @param k Excel内容实体类 |
||||
|
* @param fileName 文件名称 |
||||
|
*/ |
||||
|
public void export(HttpServletResponse response, int pageSize, T t, Class<K> k, String fileName) throws Exception { |
||||
|
ExcelWriter writer = null; |
||||
|
try { |
||||
|
writer = getExcelWriter(response, fileName); |
||||
|
//查询导出总条数
|
||||
|
int total = this.countExport(t); |
||||
|
//页数
|
||||
|
int loopCount = PageUtil.totalPage(total, pageSize); |
||||
|
BeanUtil.setProperty(t, "pageSize", pageSize); |
||||
|
for (int i = 0; i < loopCount; i++) { |
||||
|
//开始页
|
||||
|
BeanUtil.setProperty(t, "pageNum", PageUtil.getStart(i + 1, pageSize)); |
||||
|
//获取Excel导出信息
|
||||
|
List<K> kList = this.getExportDetail(t); |
||||
|
WriteSheet writeSheet = EasyExcel.writerSheet(fileName).head(k).build(); |
||||
|
writer.write(kList, writeSheet); |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
String msg = "导出" + fileName + "异常"; |
||||
|
log.error(msg, e); |
||||
|
throw new Exception(msg + e); |
||||
|
} finally { |
||||
|
if (writer != null) { |
||||
|
writer.finish(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ExcelWriter getExcelWriter(HttpServletResponse response, String fileName) throws IOException { |
||||
|
response.setContentType("application/vnd.ms-excel"); |
||||
|
response.setCharacterEncoding("utf-8"); |
||||
|
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
|
||||
|
String fileNameUtf = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); |
||||
|
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameUtf + ".xlsx"); |
||||
|
return EasyExcel.write(response.getOutputStream()).build(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* (模版导出) |
||||
|
* |
||||
|
* @param t |
||||
|
* @param fileName |
||||
|
* @param response |
||||
|
*/ |
||||
|
public abstract void complexFillWithTable(T t, String fileName, HttpServletResponse response); |
||||
|
|
||||
|
/** |
||||
|
* 查询导出总条数 |
||||
|
* |
||||
|
* @param t |
||||
|
* @return |
||||
|
*/ |
||||
|
public abstract int countExport(T t); |
||||
|
|
||||
|
/** |
||||
|
* 查询导出数据 |
||||
|
* |
||||
|
* @param t |
||||
|
* @return |
||||
|
*/ |
||||
|
public abstract List<K> getExportDetail(T t); |
||||
|
} |
@ -0,0 +1,40 @@ |
|||||
|
package com.example.demo.export; |
||||
|
|
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.web.bind.annotation.PostMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RestController; |
||||
|
|
||||
|
import java.util.concurrent.ThreadPoolExecutor; |
||||
|
|
||||
|
@RestController |
||||
|
@RequestMapping("/export") |
||||
|
@Slf4j |
||||
|
public class ExportController { |
||||
|
|
||||
|
@Autowired |
||||
|
private ExportImpl export; |
||||
|
|
||||
|
@Autowired |
||||
|
private ThreadPoolExecutor threadPoolExecutor; |
||||
|
|
||||
|
/** |
||||
|
* 实现一个排队导出功能 |
||||
|
*/ |
||||
|
@PostMapping("/exportFile") |
||||
|
public void exportFile() { |
||||
|
log.info("提交线程池任务"); |
||||
|
threadPoolExecutor.execute(() -> { |
||||
|
ExportUser sysUser = new ExportUser(); |
||||
|
sysUser.setUserName(Thread.currentThread().getName()); |
||||
|
try { |
||||
|
export.export(sysUser); |
||||
|
} catch (InterruptedException e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} |
||||
|
} |
||||
|
); |
||||
|
log.info("提交线程池任务结束"); |
||||
|
} |
||||
|
} |
@ -0,0 +1,58 @@ |
|||||
|
package com.example.demo.export; |
||||
|
|
||||
|
import com.alibaba.excel.ExcelWriter; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
import java.util.LinkedList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Service |
||||
|
@Slf4j |
||||
|
public class ExportImpl extends AbstractExport { |
||||
|
|
||||
|
@Autowired |
||||
|
private ExportQueue exportQueue; |
||||
|
|
||||
|
@Override |
||||
|
public void export(ExportUser sysUser) throws InterruptedException { |
||||
|
//导出
|
||||
|
log.info("导出文件方法执行~~~~~~~~~"); |
||||
|
LinkedList<ExportUser> queue = exportQueue.add(sysUser); |
||||
|
//可以考虑把队列进行持久化
|
||||
|
log.info("导出队列:" + queue); |
||||
|
//export(response,pageSize,t,k,fileName);
|
||||
|
//导出成功后移除当前导出用户
|
||||
|
ExportUser nextSysUser = exportQueue.getNextSysUser(); |
||||
|
log.info("移除后获取下一个排队的用户: " + nextSysUser.getUserName()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void export(HttpServletResponse response, int pageSize, Object o, Class k, String fileName) throws Exception { |
||||
|
super.export(response, pageSize, o, k, fileName); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ExcelWriter getExcelWriter(HttpServletResponse response, String fileName) throws IOException { |
||||
|
return super.getExcelWriter(response, fileName); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void complexFillWithTable(Object o, String fileName, HttpServletResponse response) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int countExport(Object o) { |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List getExportDetail(Object o) { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
@ -0,0 +1,60 @@ |
|||||
|
package com.example.demo.export; |
||||
|
|
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import java.util.LinkedList; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Component |
||||
|
public class ExportQueue { |
||||
|
|
||||
|
|
||||
|
private final int MAX_CAPACITY = 10; // 队列最大容量
|
||||
|
private LinkedList<ExportUser> queue; // 用户队列 或者阻塞队列 或者 直接消息队列
|
||||
|
|
||||
|
public ExportQueue(LinkedList<ExportUser> queue) { |
||||
|
this.queue = new LinkedList<>(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 排队队列添加 |
||||
|
* |
||||
|
* @param sysUser |
||||
|
*/ |
||||
|
public synchronized LinkedList<ExportUser> add(ExportUser sysUser) { |
||||
|
while (queue.size() >= MAX_CAPACITY) { |
||||
|
try { |
||||
|
log.info("当前排队人已满,请等待"); |
||||
|
wait(); |
||||
|
} catch (InterruptedException e) { |
||||
|
e.getMessage(); |
||||
|
} |
||||
|
} |
||||
|
queue.add(sysUser); |
||||
|
log.info("目前导出队列排队人数:" + queue.size()); |
||||
|
notifyAll(); |
||||
|
return queue; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 获取排队队列下一个人 |
||||
|
* |
||||
|
* @return |
||||
|
*/ |
||||
|
public synchronized ExportUser getNextSysUser() { |
||||
|
while (queue.isEmpty()) { |
||||
|
try { |
||||
|
wait(); |
||||
|
} catch (InterruptedException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
ExportUser sysUser = queue.remove(); |
||||
|
notifyAll(); //唤醒
|
||||
|
return sysUser; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
@ -0,0 +1,8 @@ |
|||||
|
package com.example.demo.export; |
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
@Data |
||||
|
public class ExportUser { |
||||
|
private String userName; |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
|
||||
|
spring.redis.host=192.168.56.10 |
||||
|
spring.redis.password=123456 |
Loading…
Reference in new issue