概述
功能概述:使用多线程下载图片,消息code,直接下载图片,消息code,打包输出到相应文件夹中
实现效果
库表设计
类设计
主要的类是TaskManagerThread类,它做了两件事情,一个是初始化数据,另一个是通过表中的HandlerName取到相应的类做具体处理
代码如下,我们可以看到TaskManagerThread继承了Thread类,
@Slf4j
public class TaskManagerThread extends Thread{
private HttpConnectionManager httpConnectionManager;
private ExecutorService executorService;
private MessageInfo messageInfo;
public TaskManagerThread(MessageInfo messageInfo){
this.executorService = new ThreadPoolExecutor(5,10,1000,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());
this.httpConnectionManager = SpringContextUtil.getBean("httpConnectionManager");
this.messageInfo = messageInfo;
}
@Override
public void run() {
DownBaseHandler downBaseHandler = SpringContextUtil.getBean(messageInfo.getHandlerName());
downBaseHandler.init(httpConnectionManager);
downBaseHandler.handler(messageInfo);
}
这样设计的意义在于每有一个过来的请求,都交给线程池去处理,能够极大的提程序的处理效率
@RestController
@RequestMapping("/down")
public class ThreadDownController {
/*
功能概述:
使用多线程下载图片,
消息种类,类型1,直接下载图片,
消息种类,类型2,打包输出到相应文件夹中
*/
@Autowired
private MessageInfoService messageInfoService;
private ExecutorService executorService =
new ThreadPoolExecutor(5, 10, 1000,TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());
@GetMapping
public void test(@RequestParam String code){
MessageInfo one =
messageInfoService.getOne(new QueryWrapper<MessageInfo>().lambda().eq(MessageInfo::getCode, code));
executorService.execute(new TaskManagerThread(one));
}
}
DownBaseHandler
public abstract class DownBaseHandler{
protected HttpConnectionManager manager;
abstract public void handler(MessageInfo messageInfo);
public void init(HttpConnectionManager manager){
this.manager = manager;
}
}
SingleDownHandler
@Component("DownBaseHandler.single")
@Slf4j
public class SingleDownHandler extends DownBaseHandler {
@Override
public void handler(MessageInfo messageInfo) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (!manager.copyStream(messageInfo.getImageUrl(), baos)) {
throw new TaskException(messageInfo);
}
log.info("下载图片成功");
byte[] bytes = baos.toByteArray();
File file = new File(messageInfo.getPath(),new Date().getTime()+".jpg");
try {
OutputStream outputStream = new FileOutputStream(file);
outputStream.write(bytes);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
MultiDownHadnler
@Component("DownBaseHandler.multi")
public class MultiDownHadnler extends DownBaseHandler {
@Override
public void handler(MessageInfo messageInfo) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (!manager.copyStream(messageInfo.getImageUrl(), baos)) {
throw new TaskException(messageInfo);
}
byte[] bytes = baos.toByteArray();
try {
ZipOutputStream zos = new ZipOutputStream(baos);
ZipEntry zipEntry = new ZipEntry(String.format("%s.%s",new Date().getTime()+"","jpg"));
zos.putNextEntry(zipEntry);
zos.write(bytes);
zos.closeEntry();
zos.close();
baos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
bytes = baos.toByteArray();
File file = new File(messageInfo.getPath(),new Date().getTime()+".zip");
try {
OutputStream outputStream = new FileOutputStream(file);
outputStream.write(bytes);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
我们大概的把结构搭好,在结构下做具体的代码填充也就比较方便了,TaskManagerThread是方法的主入口,继承Thread类,在run方法中通过,SpringContextUtil.getBean()找到具体的实现类做具体处理,基本一系列的工作也就完成了,剩下的就是如何在SingleDownHandler、MultiDownHadnler中实现具体功能的事情了
来看看,在SingleDownHandler中,使用了httpclient发送请求,得到结果,而handler
则是将数据写到磁盘中
MultiDownHadnler基本类型,只不过增加了ZipOutputStream,将数据写出zip流并输出,所以最后也就能得到相应的压缩文件了
学两个组件,一个用于HTTP连接,一个用于流输出
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
</dependency>
获取ApplicationContext应用上下文,可实现ApplicationContextAware接口
项目地址如下,有需要的可以参考
项目地址