java swing根据url生成截图

时间:2021-10-11 15:22:12
上一周,由于公司业务需求,需要根据表中的url生成图片,翻阅了一天资料之后,发现只有一篇博文基本可以参考:http://blog.csdn.net/cping1982/article/details/5353049/,其他博文,大部分都是和该篇博文大差不差。该篇博文中,很显然,只有第三种合适。所以我也模仿写了一个根据url截图的,写完测试后,10条之内的截图还可以,但我数据库中数据量过大,根据该方法生成截图效率很低,经不起大数据的考验。所以就又写了一 个根据swingworker生成截图的,该方法在速度上有明显的提升,上代码:

1、TestSwingWorker是入口类

方法

package com;

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

import com.demo.EagleBrowser;
import com.mysql.jdbc.PreparedStatement;

public class TestSwingWorker extends JFrame implements ActionListener {

private static final long serialVersionUID = -6147740041804837545L;

public static void main(String[] args) {
try {
ConstantsUtils.init();
TestSwingWorker main = new TestSwingWorker();
main.setVisible(true); // 设置窗体可见
} catch (Exception e) {
e.printStackTrace();
}
}

Container p = getContentPane();
public static JButton updateButton;
public static JTextField draftIdTextField;
public static JLabel infoLable;
public static JLabel infoLable1;
public static JLabel infoLable2;
public static int totalCount;

public TestSwingWorker() {
super();
this.setTitle("更新截图");
this.setBounds(200, 200, 350, 260); // setSize(int width,int
// hight);setBounds(x,y,width,hight);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p.setLayout(null);

JLabel label1 = new JLabel("稿件ID");
label1.setBounds(80, 10, 80, 30);
p.add(label1);

draftIdTextField = new JTextField();
draftIdTextField.setBounds(130, 10, 120, 30);
p.add(draftIdTextField);

updateButton = new JButton("更新");
updateButton.setBounds(80, 48, 180, 30);
updateButton.addActionListener(this); // 添加鼠标响应事件
p.add(updateButton);

infoLable = new JLabel();
p.add(infoLable);
infoLable.setBounds(100, 100, 300, 30);

infoLable1 = new JLabel();
p.add(infoLable1);
infoLable1.setBounds(100, 125, 300, 30);
}

public void actionPerformed(ActionEvent e) {
JButton jb = (JButton) e.getSource();
if (jb == updateButton) {
String id = draftIdTextField.getText();
if(null == id || "".equals(id)){
infoLable.setText("稿件ID不能为空!");
}else{
try {
updateShortCutImgURL(id);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

}

/**
* 更新大数据表中的截图url
*
* @param draftPublishedList
*/
private void updateShortCutImgURL(String draftId) throws Exception {
Connection conn = DBUtil.getConnection();
String sql = "select id,url from tb_draft_published_list where draft_id = "
+ Integer.parseInt(draftId)
+ " and short_cut_Img is null and url is not null";
PreparedStatement stmt = (PreparedStatement) conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery(sql);

//计算该稿件在大数据表中的个数
String countSql = "select count(*) as rowCount from tb_draft_published_list where draft_id = "
+ Integer.parseInt(draftId)
+ " and short_cut_Img is null and url is not null";
PreparedStatement stmt2 = (PreparedStatement) conn.prepareStatement(sql);
ResultSet r2 = stmt2.executeQuery(countSql);
r2.next();

List<String> urls = new ArrayList<String>();
List<String> paths = new ArrayList<String>();
while (rs.next()) {
Integer id = Integer.parseInt(rs.getString(1));
final String url = rs.getString(2);
final String path = initPath(draftId);
urls.add(url);
paths.add(path);
String updateSql = "update tb_draft_published_list set short_cut_Img = '"
+ path + "' where id = " + id;
PreparedStatement stmt1 = null;
try {
stmt1 = (PreparedStatement) conn
.prepareStatement(updateSql);
stmt1.executeUpdate(updateSql);
} catch (SQLException e) {
e.printStackTrace();
}
}

infoLable.setText("共:" + urls.size() + "张");
EagleBrowser.main1(urls, paths);

}

private static String initPath(String draftId) {
Calendar cal = Calendar.getInstance();
String year = String.valueOf(cal.get(Calendar.YEAR));
String month = String.valueOf(cal.get(Calendar.MONTH) + 1);
String path = year + "/" + month + "/" + draftId + "/";
String s_save = ConstantsUtils.IMG_WRITE_PATH + ConstantsUtils.FILE_SHORTCUT_URL + "/" + path;
String randomFile = UUID.randomUUID().toString().concat(".jpg");
File file = new File(s_save);
if (!file.exists()) {
file.mkdirs();
}
return s_save.concat(randomFile);
}

}
2、ConstantsUtils类是我初始化时加载的配置信息:

package com;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ConstantsUtils {


public static String IMG_WRITE_PATH = ""; //图片写入路径

public static String DRIVER_URL = "";

public static String USERNAME = "";

public static String PASSWORD = "";

public static final String FILE_SHORTCUT_URL = "shortCut";// 根据大数据返回来的稿件URL保存截图


/**
* 静态变量初始化方法
*/
public static void init() throws Exception {
//String filePath = ConstantsUtils.class.getResource("/").getPath().concat("screen_short.xml");
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("com/screen_short.xml");
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>();

SAXReader reader = new SAXReader();
Document document = reader.read(is);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
@SuppressWarnings("unchecked")
List<Element> elementList = root.elements();

// 遍历所有子节点
for (Element e : elementList)
map.put(e.getName(), e.getText());

//获取配置文件中的值
IMG_WRITE_PATH = map.get("IMG_WRITE_PATH");
DRIVER_URL = map.get("DRIVER_URL");
USERNAME = map.get("USERNAME");
PASSWORD = map.get("PASSWORD");
}

public static void main(String[] args) {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("com/screen_short.xml");
System.out.println(ConstantsUtils.class.getResource("/").getPath());
System.out.println(is);
}

}

3、DBUtil是连接数据库的类

<span style="color:#000000;">package com;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;


public class DBUtil {

public static Connection getConnection() throws SQLException {
Connection conn = null;
String url = ConstantsUtils.DRIVER_URL + "user=" + ConstantsUtils.USERNAME + "&password=" + ConstantsUtils.PASSWORD + "&useUnicode=true&characterEncoding=UTF8";
try {
Class.forName("com.mysql.jdbc.Driver");// 动态加载mysql驱动
System.out.println("成功加载MySQL驱动程序");
conn = DriverManager.getConnection(url);
} catch (SQLException e) {
System.out.println("MySQL操作错误");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
}</span>
4、EagleBrowser是swingworker主要截图的类

package com.demo;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.Executors;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

import com.TestSwingWorker;

import chrriis.dj.nativeswing.swtimpl.NativeComponent;
import chrriis.dj.nativeswing.swtimpl.NativeInterface;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserAdapter;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserEvent;

public class EagleBrowser extends JPanel {

/**
*
*/
private static final long serialVersionUID = 1L;

public static Integer pic_nums = 0;//记录已完成数量

private String url;

JWebBrowser webBrowser;

public EagleBrowser(String url) {
super(new BorderLayout());
this.url = url;
JPanel webBrowserPanel;
webBrowserPanel = new JPanel(new BorderLayout());
webBrowser = new JWebBrowser();
webBrowser.navigate(url);
webBrowser.setButtonBarVisible(false);
webBrowser.setMenuBarVisible(false);
webBrowser.setBarsVisible(false);
webBrowser.setStatusBarVisible(false);
webBrowserPanel.add(webBrowser, BorderLayout.CENTER);
add(webBrowserPanel, BorderLayout.CENTER);
}
final static public String LS = System.getProperty("line.separator", "\n");
// 文件分割符
final static public String FS = System.getProperty("file.separator", "\\");
// 以javascript脚本获得网页全屏后大小
final static StringBuffer jsDimension;
static {
jsDimension = new StringBuffer();
jsDimension.append("var width = 0;").append(LS);
jsDimension.append("var height = 0;").append(LS);
jsDimension.append("if(document.documentElement) {").append(LS);
jsDimension
.append(" width = Math.max(width, document.documentElement.scrollWidth);")
.append(LS);
jsDimension
.append(" height = Math.max(height, document.documentElement.scrollHeight);")
.append(LS);
jsDimension.append("}").append(LS);
jsDimension.append("if(self.innerWidth) {").append(LS);
jsDimension.append(" width = Math.max(width, self.innerWidth);")
.append(LS);
jsDimension.append(" height = Math.max(height, self.innerHeight);")
.append(LS);
jsDimension.append("}").append(LS);
jsDimension.append("if(document.body.scrollWidth) {").append(LS);
jsDimension.append(
" width = Math.max(width, document.body.scrollWidth);")
.append(LS);
jsDimension.append(
" height = Math.max(height, document.body.scrollHeight);")
.append(LS);
jsDimension.append("}").append(LS);
jsDimension.append("return width + ':' + height;");
}


public static void main1(final List<String> urls, final List<String> paths) {
final String title = "";
// UIUtils.setPreferredLookAndFeel();
NativeInterface.open();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
for(int i = 0; i < urls.size(); i++){
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
EagleBrowser eb = new EagleBrowser(urls.get(i));
frame.getContentPane().add(eb, BorderLayout.CENTER);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setLocationByPlatform(true);
frame.invalidate();
frame.pack();
frame.setVisible(false);

swingWorker(eb.webBrowser, urls.get(i), frame, urls.size(), paths.get(i));
}
}
});
NativeInterface.runEventPump();
}

public static void swingWorker(final JWebBrowser webBrowser, final String url, final JFrame frame , final int nums, final String path){

sun.awt.AppContext.getAppContext().put(SwingWorker.class, Executors.newFixedThreadPool(5));

SwingWorker<Integer, String> sw = new SwingWorker<Integer, String>(){

protected Integer doInBackground() throws Exception {
editJpg(webBrowser, url, frame, path);
publish(url);
return pic_nums;
}

@Override
// This will be called if you call publish() from doInBackground()
// Can safely update the GUI here.
protected void process(List<String> chunks) {
// Thread.sleep(100);
// TestSwingWorker.infoLable1.setText("地址:" + url);
}

@Override
// This is called when the thread finishes.
// Can safely update GUI here.
protected void done() {
/* try {
Integer status = get();
TestSwingWorker.infoLable1.setText("Completed with status: " + status);
}
catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}*/
}
};
sw.execute();
}

public static void editJpg(final JWebBrowser webBrowser, final String url, final JFrame frame, final String path){
//截取图片
webBrowser.addWebBrowserListener(new WebBrowserAdapter() {
// 监听加载进度
public void loadingProgressChanged(WebBrowserEvent e) {
// 当加载完毕时
if (e.getWebBrowser().getLoadingProgress() == 100) {
String result = (String) webBrowser.executeJavascriptWithResult(jsDimension.toString());
if(null != result && result.indexOf(":") > 0){
int index = result.indexOf(":");
NativeComponent nativeComponent = webBrowser.getNativeComponent();
Dimension originalSize = nativeComponent.getSize();
Dimension imageSize = new Dimension(Integer.parseInt(result.substring(0, index)), Integer.parseInt(result.substring(index + 1)));
imageSize.width = Math.max(originalSize.width, imageSize.width + 50);
imageSize.height = Math.max(originalSize.height, imageSize.height + 50);
nativeComponent.setSize(imageSize);
BufferedImage image = new BufferedImage(imageSize.width,
imageSize.height, BufferedImage.TYPE_INT_RGB);
nativeComponent.paintComponent(image);
nativeComponent.setSize(originalSize);

// 当网页超出目标大小时
// 此部分为使用缩略图
AffineTransform tx = new AffineTransform();
tx.scale(0.8d, 0.9d);
//int width = image.getWidth(), height = image.getHeight();
// AffineTransformOp op = new AffineTransformOp(tx,
// AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
// //缩小
// image = op.filter(image, null);

BufferedImage outputImage = new BufferedImage(
(int) (imageSize.width * 0.8),
(int) (imageSize.height * 0.9),
BufferedImage.TYPE_INT_RGB);
Graphics2D gd2 = outputImage.createGraphics();
gd2.drawImage(image, tx, null);
gd2.dispose();
try {
// 输出图像
ImageIO.write(image, "jpg", new File(path));
} catch (IOException ex) {
ex.printStackTrace();
}

// 如果加载完毕之后就关闭掉该监听事件,this为当前new的webBrowserListener
// Main.infoLable.setText("剩余(" + --Main.totalCount + ")个");
e.getWebBrowser().removeWebBrowserListener(this);
// webBrowser.removeWebBrowserListener(this);
if(null != image){
image = null;
System.gc();
}
if(null != outputImage){
outputImage = null;
System.gc();
}
if(null != frame){
frame.dispose();
}
synchronized (pic_nums)
{
pic_nums = pic_nums + 1;
System.out.println("已完成:" + pic_nums );
TestSwingWorker.infoLable1.setText("已完成:" + pic_nums + "张");
}
}
}
}
});

}

}