Commit cfe46864 by yangyang

人员数据导出提交

parent e38057d2
...@@ -70,6 +70,18 @@ ...@@ -70,6 +70,18 @@
<artifactId>spring-tx</artifactId> <artifactId>spring-tx</artifactId>
<version>4.3.9.RELEASE</version> <version>4.3.9.RELEASE</version>
</dependency> </dependency>
<!--xls-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<!--xlsx-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package com.exam.conf;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@EnableScheduling
//线程池配置类
@Configuration
public class TaskPoolConfig implements AsyncConfigurer {
//参数初始化
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//核心线程数量大小
private static final int corePoolSize = Math.max(2, Math.min(CPU_COUNT - 1, 4));
//线程池最大容纳线程数
private static final int maxPoolSize = CPU_COUNT * 2 + 1;
//阻塞队列
private static final int workQueue = 5;
//线程空闲后的存活时长
private static final int keepAliveTime = 30;
@Override
@Bean("ThreadPoolTaskExecutor")
public ThreadPoolTaskExecutor getAsyncExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
//核心线程数
threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
//最大线程数
threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
//等待队列
threadPoolTaskExecutor.setQueueCapacity(workQueue);
//线程前缀
threadPoolTaskExecutor.setThreadNamePrefix("taskExecutor-");
//线程池维护线程所允许的空闲时间,单位为秒
threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveTime);
// 线程池对拒绝任务(无线程可用)的处理策略
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler();
}
}
\ No newline at end of file
...@@ -5,9 +5,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; ...@@ -5,9 +5,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.exam.entity.*; import com.exam.entity.*;
import com.exam.serviceimpl.ScoreServiceImpl; import com.exam.serviceimpl.ScoreServiceImpl;
import com.exam.util.ApiResultHandler; import com.exam.util.ApiResultHandler;
import com.exam.util.ExportExcelUtil;
import org.apache.ibatis.annotations.Param;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -68,6 +72,16 @@ public class ScoreController { ...@@ -68,6 +72,16 @@ public class ScoreController {
return ApiResultHandler.buildApiResult(200, "根据单位查询每个人统计成绩", listResult); return ApiResultHandler.buildApiResult(200, "根据单位查询每个人统计成绩", listResult);
} }
// 全部人员统计导出
@GetMapping("/listAllStudentScoreTj/{clazz}")
public void listAllStudentScoreTj(@PathVariable("clazz") String clazz, HttpServletResponse response)throws Exception {
List<StudentScoreTj> list = scoreService.listAllStudentScoreTj(clazz);
ExportExcelUtil<StudentScoreTj> exportExcelUtil = new ExportExcelUtil<>();
String[] headersName = {"ip","姓名","答题次数","答题量","答题正确率","总成绩","单位"};
String[] headersField = {"studentId","studentName","count","dtcount","right","countsum","clazz"};
exportExcelUtil.exportExcel("DataStatistics", headersName, headersField, list, response,"人员答题统计");
}
@PostMapping("/score") @PostMapping("/score")
public ApiResult add(@RequestBody Score score) { public ApiResult add(@RequestBody Score score) {
int res = scoreService.add(score); int res = scoreService.add(score);
......
...@@ -15,4 +15,6 @@ public class StudentScoreTj { ...@@ -15,4 +15,6 @@ public class StudentScoreTj {
private Integer dtcount; private Integer dtcount;
private String right; private String right;
private String clazz;
} }
\ No newline at end of file
...@@ -48,4 +48,14 @@ public interface ScoreMapper { ...@@ -48,4 +48,14 @@ public interface ScoreMapper {
// 单位统计数据透视 // 单位统计数据透视
@Select("select t.studentId,t.studentName,count(s.studentId) as count,IFNULL(sum(etScore),0) as countsum from student t left join score s on s.studentId = t.studentId where t.clazz=#{clazz} GROUP BY t.studentId order by sum(etScore) desc") @Select("select t.studentId,t.studentName,count(s.studentId) as count,IFNULL(sum(etScore),0) as countsum from student t left join score s on s.studentId = t.studentId where t.clazz=#{clazz} GROUP BY t.studentId order by sum(etScore) desc")
IPage<StudentScoreTj> findTjTsDw(Page<?> page,@Param("clazz") String clazz); IPage<StudentScoreTj> findTjTsDw(Page<?> page,@Param("clazz") String clazz);
// 全部人员数据
@Select("<script> select t.studentId,t.studentName,t.clazz as clazz,count(s.studentId) as count,IFNULL(sum(etScore),0) as countsum from student t left join score s on s.studentId = t.studentId"
+"<if test='clazz != \"null\"'>"
+"where t.clazz=#{clazz}"
+ "</if>"
+"GROUP BY t.studentId order by sum(etScore) desc"
+"</script>")
List<StudentScoreTj> listAllStudentScoreTj(@Param("clazz") String clazz);
} }
...@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; ...@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.exam.entity.DwScoreTj; import com.exam.entity.DwScoreTj;
import com.exam.entity.Score; import com.exam.entity.Score;
import com.exam.entity.StudentScoreTj; import com.exam.entity.StudentScoreTj;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
...@@ -24,4 +25,6 @@ public interface ScoreService { ...@@ -24,4 +25,6 @@ public interface ScoreService {
List<DwScoreTj> findTjDw(); List<DwScoreTj> findTjDw();
IPage<StudentScoreTj> findTjTsDw(Page<StudentScoreTj> page,String clazz); IPage<StudentScoreTj> findTjTsDw(Page<StudentScoreTj> page,String clazz);
List<StudentScoreTj> listAllStudentScoreTj(@Param("clazz") String clazz);
} }
...@@ -9,13 +9,16 @@ import com.exam.entity.StudentScoreTj; ...@@ -9,13 +9,16 @@ import com.exam.entity.StudentScoreTj;
import com.exam.mapper.ScoreMapper; import com.exam.mapper.ScoreMapper;
import com.exam.service.ScoreService; import com.exam.service.ScoreService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.IOException;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.*;
import java.util.Comparator; import java.util.concurrent.CompletableFuture;
import java.util.List; import java.util.concurrent.CompletionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
...@@ -24,6 +27,9 @@ public class ScoreServiceImpl implements ScoreService { ...@@ -24,6 +27,9 @@ public class ScoreServiceImpl implements ScoreService {
@Autowired @Autowired
private ScoreMapper scoreMapper; private ScoreMapper scoreMapper;
@Qualifier("ThreadPoolTaskExecutor")
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Override @Override
public int add(Score score) { public int add(Score score) {
return scoreMapper.add(score); return scoreMapper.add(score);
...@@ -102,6 +108,37 @@ public class ScoreServiceImpl implements ScoreService { ...@@ -102,6 +108,37 @@ public class ScoreServiceImpl implements ScoreService {
} }
@Override @Override
public List<StudentScoreTj> listAllStudentScoreTj(String clazz) {
percentInstance.setMinimumFractionDigits(2);
List<StudentScoreTj> list = scoreMapper.listAllStudentScoreTj(clazz);
// 存储结果集
List<CompletableFuture<?>> futures = new ArrayList<>();
for(StudentScoreTj p:list) {
futures.add(
CompletableFuture.supplyAsync(() -> {
int dtcount = 0;
String right = "0%";
dtcount = p.getCount() * 1;
if(p.getCountsum()!=0&&dtcount!=0){
right = percentInstance.format((double) (p.getCountsum())/(dtcount));
}
p.setDtcount(dtcount);
p.setRight(right);
return p;
}, threadPoolTaskExecutor)
.whenComplete((r, e) -> {
}).exceptionally(e -> {
CompletionException ex = new CompletionException(e);
System.out.println(ex);
throw ex;
}));
}
// 等待全部完成
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
return list;
}
@Override
public List<Score> findByExamCode(Integer examCode) { public List<Score> findByExamCode(Integer examCode) {
return scoreMapper.findByExamCode(examCode); return scoreMapper.findByExamCode(examCode);
} }
......
package com.exam.util;
import org.apache.poi.hssf.usermodel.*;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 导出Excel工具类 admin 2018/10/11
* title 表名
* headersName 使用数组封装excel列名
* headersId 使用数组封装对应列名需要展示的列的属性名 (二者需要一一对应,顺序不能打乱)
* dtoList 对象结果集
* */
public class ExportExcelUtil<T> {
@SuppressWarnings("deprecation")
public void exportExcel(String title, String[] headersName,
String[] headersId, List<T> dtoList, HttpServletResponse response, String name)
throws Exception {
Map<Integer, String> headersNameMap = new HashMap<>();
int key = 0;
for (int i = 0; i < headersName.length; i++) {
if (!headersName[i].equals(null)) {
headersNameMap.put(key, headersName[i]);
key++;
}
}
Map<Integer, String> titleFieldMap = new HashMap<>();
int value = 0;
for (int i = 0; i < headersId.length; i++) {
if (!headersId[i].equals(null)) {
titleFieldMap.put(value, headersId[i]);
value++;
}
}
//创建Excel工作薄对象
HSSFWorkbook wb = new HSSFWorkbook();
//创建Excel工作表对象
HSSFSheet sheet = wb.createSheet(title);
// 设置列宽
sheet.setDefaultColumnWidth((short) 15);
//创建单元格样式
HSSFCellStyle style = wb.createCellStyle();
//创建Excel工作表的行
HSSFRow row = sheet.createRow(0);
System.out.println(HSSFWorkbook.class.getProtectionDomain().getCodeSource().getLocation());
HSSFCell cell;
// 拿到表格所有标题的value的集合
Collection<String> c = headersNameMap.values();
Iterator<String> it = c.iterator();// 表格标题的迭代器
// 根据选择的字段生成表头
int size = 0;
while (it.hasNext()) {
System.out.println(it);
String s = it.toString();
cell = row.createCell(size);
cell.setCellValue(it.next().toString());
cell.setCellStyle(style);
size++;
}
Collection<String> zdC = titleFieldMap.values();
Iterator<T> labIt = new ArrayList<T>().iterator();
if (dtoList != null) {
labIt = dtoList.iterator();
}
int zdRow = 0;
while (labIt.hasNext()) {// 记录的迭代器,遍历总记录
int zdCell = 0;
zdRow++;
row = sheet.createRow(zdRow);
T l = (T) labIt.next();
List<Field> fields = new ArrayList<>();
Class<?> tempClass = l.getClass();
while (tempClass != null) {
fields.addAll(Arrays.asList(tempClass.getDeclaredFields()));
tempClass = tempClass.getSuperclass();
}
Iterator<String> zdIt = zdC.iterator();
while (zdIt.hasNext()) {// 遍历要导出的字段集合
String next = zdIt.next();
for (short i = 0; i < fields.size(); i++) {// 遍历属性,比对
Field field = fields.get(i);
String fieldName = field.getName();// 属性名
if (next.equals(fieldName)) {
String getMethodName = "get"
+ fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);// 拿到属性的get方法
try {
Class<?> cls = l.getClass();
Method getMethod = cls.getMethod(getMethodName,
new Class[] {});
Object val = getMethod.invoke(l, new Object[] {});
String textVal = null;
if (val != null) {
// 如果是double类型则只保留两位小说
if (field.getGenericType().toString()
.equals("double")
|| field.getGenericType().toString()
.equals("Double")) {
DecimalFormat df = new DecimalFormat(
"#0.00");
String format = df.format(val);
textVal = String.valueOf(format);
} else {
textVal = String.valueOf(val);// 转化成String
}
} else {
textVal = null;
}
row.createCell( zdCell)
.setCellValue(textVal);
zdCell++;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
OutputStream out = response.getOutputStream();
try {
response.setContentType("application/x-download");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment;fileName="
+ new String((name).getBytes("gbk"), "iso8859-1")
+ new SimpleDateFormat("yyyy-MM-dd").format(new Date())
+ ".xls");
wb.write(out);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment