异步导出excel表格(2)excel处理线程

        上一篇文章分享了用户下载任务的提交与下载,以及系统中对任务的保存方式,这篇文章,主要分享excel处理部分。excel处理基本流程如下:



异步导出excel表格(2)excel处理线程
 

        excel处理线程首先要获得生成excel表格的基本数据(其中不包括大的查询数据),保存到新创建的beansMap中;然后对于大的数据多次查询,将多次查询结果List统一保存到一个List中,最后保存到beansMap中,通过jxls生成excel报表。
 

	public void run() {
		if(orderViewService != null && pager != null) {
			if(beansMap == null)
				beansMap = new HashMap<String, Object>();
			// save query result list.
			List<OrderView> views = new LinkedList<OrderView>();
			// temp pager
			Pager tmpPager = new Pager();
			// copy pager to tmpPager
			try {
				BeanUtils.copyProperties(tmpPager, pager);
				tmpPager.setPage(1);
			} catch(InvocationTargetException e) {
				e.printStackTrace();
			} catch(IllegalAccessException e) {
				e.printStackTrace();
			}
			// query order view.
			tmpPager.setPage(1);
			tmpPager.setPageSize(SIZE_PER_PAGE);
			List<OrderView> orderViews = null;
			do {
				orderViews = orderViewService.find(tmpPager);
				tmpPager.setPage(tmpPager.getPage() + 1);
				views.addAll(orderViews);
			} while (ObjectUtil.isNotEmpty(orderViews) && orderViews.size() == 10);
			// order type
			beansMap.put("eshop", 0);
			beansMap.put("direct", 1);
			beansMap.put("distribution", 2);
			// shop list bean
			List<Eshop> shopList = eshopService.findAll();
			Map<Integer, String> shopMap = new HashMap<Integer, String>();
			for (Eshop shop : shopList) {
				shopMap.put(shop.getId(), shop.getName());
			}
			shopMap.put(-1, "-线下-");
			shopMap.put(null, "-空-");
			// logistic name map bean
			Map<Integer, String> logisticMap = new HashMap<Integer, String>();
			List<Logistic> logisticList = logisticService.findAll();
			for (Logistic logistic : logisticList) {
				logisticMap.put(logistic.getId(), logistic.getName());
			}
			// other beans
			beansMap.put("PayMode", Erp.PAYMODEMAP);
			beansMap.put("ShippingTypes", Erp.ShippingTypes.map);
			beansMap.put("OrderPayTypes", Erp.OrderPayTypes.map);
			beansMap.put("OrderStatus", Erp.OrderStatus.statusMap);
			beansMap.put("FLAGS", OrderViewServiceImpl.SELLERFLAGS);
			// current time.
			beansMap.put("CURRENT_TIME", new Date());
			beansMap.put("data", views);
			// generate excel.
			ExportResult exportResult = exportConfigService.createExportFile(jobParams.getTemplateFileCode(), jobParams.getGenerateExcelFilePath(), beansMap);
			// update job parameter.
			generateExportFile(jobParams, exportResult.getWorkBook());
		}
	}
	
	/**
	 * write <code>Workbook</code> object to file.
	 * @param jobParams job parameters
	 * @see AsynchronyExportJobParams
	 * @param workbook excel variable
	 * @see Workbook
	 * @return if success return true else return false
	 */
	private Boolean generateExportFile(AsynchronyExportJobParams jobParams, Workbook workbook) {
		// save excel into file.
		final String generateFilePrefix = Erp.contextPath + "/export/generate/";
		Boolean res = true;
		try {
			OutputStream os = new BufferedOutputStream(new FileOutputStream(generateFilePrefix + jobParams.getGenerateExcelFilePath()));
			workbook.write(os);
			os.flush();
			os.close();
		} catch(IOException e) {
			res = false;
		}
		// update job parameters in DB.
		if(res) {
			jobParams = asynchronyExportService.load(jobParams.getId());
			jobParams.setJobCurrentStatus(JobStatus.FINISHED);
			jobParams.setJobFinishTime(new Date());
			jobParams.setIsDeleteExportedFile(false);
			if(!asynchronyExportService.saveOrUpdate(jobParams))
				res = false;
		}
		return res;
	}

         对于excel的管理,我采用newSingleThreadExecutor管理,基本Service类如下:

public class ProcessOrderExportService {
	private static ExecutorService exec = Executors.newSingleThreadExecutor();
	
	/**
	 * add a job into executor queue.
	 */
	public static void pushJob(Runnable job) {
		exec.execute(job);
	}
	
	/**
	 * shutdown service.
	 */
	public static void shutdownService() {
		// interrupted all threads.
		exec.shutdown();
		// wait for two seconds.
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch(InterruptedException e) {
			e.printStackTrace();
		}
		// shutdown all threads now.
		if(!exec.isShutdown())
			exec.shutdownNow();
	}
	/**
	 * restart service.
	 */
	public static void restartService() {
		if(!exec.isTerminated())
			exec.shutdownNow();
		exec = Executors.newSingleThreadExecutor();
	}
}

 这样这完成了excel导出任务的处理。对于不同的导出方式,可以创建不同的Runnable线程。线程中常见的问题就是数据的传递方式,可以采用二种方法,第一是采用数据Map<String, Object>在线程的构造方法中传递,例如:public ProcessOrderExportJob(Map<String, Object> paramMap)。第二种,线程中数据传递spring注入的方式,基本采用ApplicationContext.getBean(SomeClass.class)方式获取各种类。当然,与可以两种方式混合使用。我做异步的系统中采用SpringMVC框架,上面的线程参数传递,我采用混合的方式,线程构造方法如下:

	/**
	 * query conditions.
	 */
	private Pager pager;
	/**
	 * beans map.
	 */
	private Map<String, Object> beansMap;
	/**
	 * order view service.
	 */
	private OrderViewService orderViewService;
	/**
	 * asynchrony export job parameters service.
	 */
	private AsynchronyExportJobParamsService asynchronyExportService;
	/**
	 * export configuration service.
	 */
	private ExportConfigService exportConfigService;
	/**
	 * eshop service.
	 */
	private EshopService eshopService;
	/**
	 * logistic service.
	 */
	private LogisticService logisticService;
	/**
	 * job parameters.
	 */
	private AsynchronyExportJobParams jobParams;
	/**
	 * the constant variable of a size per page.
	 */
	private final static int SIZE_PER_PAGE = 10;
	
	public ProcessOrderExportJob(Pager pager, Map<String, Object> beansMap, AsynchronyExportJobParams jobParams) {
		this.pager = pager;
		this.beansMap = beansMap;
		this.jobParams = jobParams;
		orderViewService = Erp.context.getBean(OrderViewService.class);
		asynchronyExportService = Erp.context.getBean(AsynchronyExportJobParamsService.class);
		exportConfigService = Erp.context.getBean(ExportConfigService.class);
		eshopService = Erp.context.getBean(EshopService.class);
		logisticService = Erp.context.getBean(LogisticService.class);
	}

 在线程的构造函数中,完成了参数的初始化。

 

你可能感兴趣的:(异步,Excel)