Java Html转图片示例
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.w3c.dom.Document;
import org.xhtmlrenderer.swing.Java2DRenderer;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public abstract class Poster {

    private static String IMG_POSTER_PATH = "d://poster/"; // 海报生成后存放的文件夹

    protected String shortUrl;
    protected String attrUrl;
    protected Object paramObject; // 主要携带参数的对象
    protected Map<String,Object> paramMap; // 一些个性化的数据,比如生成的二维码路径等
    protected ShareProductMode shareProductMode;

    // 冗余字段
    protected String attr01;
    protected String attr02;

    private final static int POSTER_WIDTH = 750; // 海报宽度
    private final static int POSTER_HEIGHT = -1; // 海报高度-1自适应

    private volatile static Configuration configuration = null;

    private String url;

    public String getUrl() {
        return url;
    }
    public String getFullUrl() {
        if (url != null && url != ""){
            return attrUrl+url;
        }
        return null;
    }

    public void setParamMap(Map<String, Object> paramMap) {
        this.paramMap = paramMap;
    }

    static {
        configuration = initConfiguration();
    }

    private synchronized static Configuration initConfiguration(){
        try {
            if (configuration == null){
                configuration = new Configuration();
                configuration.setDirectoryForTemplateLoading(new File(Global.getUserfilesBaseDir()+"posterTemplate"));
                configuration.setDefaultEncoding("UTF-8");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return configuration;
    }

    public static String getAttrUrl(HttpServletRequest request){
        return getAttrUrl(request, OsGlobal.ATTR_PATH_SHARE);
    }

    /**
     * 获取服务器文件接口地址
     * @param request
     * @param url 参考ATTR_PATH属性,示例:
     * @return
     */
    public static String getAttrUrl(HttpServletRequest request, String url){
        String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
        return basePath+url;
    }

    public Poster(ShareProductMode shareProductMode, ShareProduct shareProduct, String shortUrl, String attrUrl){
        this.shareProductMode = shareProductMode;
        this.paramObject = shareProduct;
        this.shortUrl = shortUrl;
        this.attrUrl = attrUrl;
    }

    /**
     * 获取模版html文件以及商品的内容
     * @return
     */
    private Map<String, String> genderContent() {
        Map<String,String> resMap = new HashMap();
        resMap.put("flag","false");
        Template template = null;
        try {
            template = configuration.getTemplate("demo.html");// 海报模板文件名
            // 生成邀请码
            String qrCodeUrl = OsGlobal.SHORT_QR_CODE_PATH + IdGen.uuid() +".png"; // 前面一个参数是存放二维码图片的文件夹
            QRCodeEncoder.createQRCode(shortUrl,qrCodeUrl,"png");
            // 携带参数的map
            HashMap<Object, Object> root = new HashMap<>();
            // 携带自定义参数的map
            if (paramMap == null){
                paramMap = new HashMap<>();
            }
            paramMap.put("qrCodeUrl",attrUrl + qrCodeUrl);

            root.put("param",paramObject);
            root.put("personalized",paramMap);
            StringWriter writer = new StringWriter();
            template.process(root, writer);
            resMap.put("flag","true");
            resMap.put("res",writer.toString());
            writer.close();
        }catch (IOException e) {
            e.printStackTrace();
            resMap.put("msg","海报模板文件不存在");
            return resMap;
        }catch (TemplateException e) {
            e.printStackTrace();
        }
        return resMap;
    }

    /**
     * 生成海报前的接口(可以用来加一些自定义参数等)
     */
    protected abstract void before();

    /**
     * 提供给用户调用的生成海报的接口
     * @return
     */
    public Map<String, String> drawPoster() {
        before();
        Map<String,String> contentMap = genderContent();
        if (!Objects.equals(contentMap.get("flag"),"true")){
            return contentMap;
        }
        String content = contentMap.get("res");
        System.out.println(content);
        Map<String,String> resMap = new HashMap();
        url = genderImg(content);

        resMap.put("flag","true");
        return resMap;
    }

    /**
     * 最终生成海报
     * @param content html内容
     * @return
     */
    private String genderImg(String content){
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setNamespaceAware(true);

        String fileName = IdGen.uuid()+".png";
        String fullOutPath = IMG_POSTER_PATH + fileName;

        Document document = null;
        StringReader reader = null;
        try {
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            reader = new StringReader(content);
            InputSource inputSource = new InputSource(reader);
            document = documentBuilder.parse(inputSource);
            Java2DRenderer renderer = new Java2DRenderer(document, POSTER_WIDTH, POSTER_HEIGHT);
            BufferedImage img = renderer.getImage();
            ImageIO.write(img, "png", new File(fullOutPath));
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (reader != null){
                reader.close();
            }
        }
        return fullOutPath;
    }

}