Java构建静态html片段工具类

package cn.wangjiahang.record.util.html;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * Created on 2022/10/23.
 *
 * @author jh.wang
 */
public class HtmlUtil implements StrPool {
    private static final String startTag = "startTag";
    private static final String aloneTagContent = "aloneTagContent";
    private static final String style = "style";
    private static final String clazz = "class";
    private static final String content = "content";
    private static final String extra = "extra";

    //---------------------------------
    public static HtmlStyle style() {
        return new HtmlStyle(MapUtil.newHashMap());
    }
    //---------------------------------


    public static class HtmlTag {
        private final String tag;
        private String template;

        public HtmlTag(boolean nonStyle, String htmlOrTag) {
            this.tag = htmlOrTag;
            this.template = nonStyle ? htmlOrTag : tagTemplate(htmlOrTag, null, false);
        }

        public HtmlTag(String tag) {
            this.tag = tag;
            this.template = tagTemplate(tag, null, false);
        }

        public HtmlTag(String tag, String extra) {
            this.tag = tag;
            this.template = tagTemplate(tag, extra, false);
        }

        public HtmlTag(String tag, boolean aloneTag) {
            this.tag = tag;
            this.template = tagTemplate(tag, null, aloneTag);
        }

        public HtmlTag(String tag, String extra, boolean aloneTag) {
            this.tag = tag;
            this.template = tagTemplate(tag, extra, aloneTag);
        }

        private static String tagTemplate(String tag, String extra, boolean aloneTag) {
            // <{startTag} style='{style}' class='{class}' {extra}{aloneTagContent}
            return StrUtil.format("<{startTag} style='{style}' class='{class}' {extra}{aloneTagContent}",
                    MapUtil.builder(HtmlUtil.startTag, tag)
                            .put(HtmlUtil.extra, extra)
                            .put(HtmlUtil.aloneTagContent, aloneTag ? "/>" : String.format(">{content}</%s>", tag))
                            .build(),
                    false);
        }

        public HtmlTag appendContent(HtmlTag htmlTag) {
            return appendContent(htmlTag.build());
        }

        public HtmlTag appendContent(String customTag, Consumer<HtmlTag> htmlTag) {
            final HtmlTag custom = HtmlUtil.custom(customTag);
            htmlTag.accept(custom);
            return appendContent(custom);
        }

        public HtmlTag appendContent(String customTag, String customExtra, Consumer<HtmlTag> htmlTag) {
            final HtmlTag custom = HtmlUtil.custom(customTag, customExtra);
            htmlTag.accept(custom);
            return appendContent(custom);
        }

        public HtmlTag appendContent(String content) {
            this.template = StrUtil.format(this.template, MapUtil.builder(HtmlUtil.content, content + String.format("{%s}", HtmlUtil.content)).build());
            return this;
        }

        public String content(HtmlTag htmlTag) {
            return content(htmlTag.ignore());
        }

        public String content(String customTag, Consumer<HtmlTag> htmlTag) {
            final HtmlTag custom = HtmlUtil.custom(customTag);
            htmlTag.accept(custom);
            return content(custom);
        }

        public String content(String customTag, String customExtra, Consumer<HtmlTag> htmlTag) {
            final HtmlTag custom = HtmlUtil.custom(customTag, customExtra);
            htmlTag.accept(custom);
            return content(custom);
        }


        public String content(String content) {
            this.template = StrUtil.format(this.template, MapUtil.builder(HtmlUtil.content, content).build());
            return build();
        }

        public HtmlTag style(String style) {
            this.template = StrUtil.format(this.template, MapUtil.builder(HtmlUtil.style, style).build());
            return this;
        }

        public HtmlTag style(HtmlStyle htmlStyle) {
            return style(htmlStyle.build());
        }

        public HtmlTag style(Consumer<HtmlStyle> htmlTag) {
            final HtmlStyle htmlStyle = HtmlUtil.style();
            htmlTag.accept(htmlStyle);
            return style(htmlStyle);
        }

        public HtmlTag style(String name, String value) {
            return style(MapUtil.builder(name, value).build());
        }

        public HtmlTag style(Map<String, String> mapStyle) {
            return style(MapUtil.joinIgnoreNull(mapStyle, ";", ": "));
        }

        public HtmlTag clazz(String... clazz) {
            this.template = StrUtil.format(this.template, MapUtil.builder(HtmlUtil.clazz, CollUtil.join(Convert.toList(String.class, clazz), " ")).build());
            return this;
        }

        public HtmlTag clazz(List<String> clazzs) {
            return clazz(CollUtil.join(clazzs, " "));
        }

        public HtmlTag extraTag(String extraTag, String value) {
            return this.extraTag(MapUtil.builder(extraTag, value).build());
        }

        public HtmlTag extraTag(Map<String, String> value) {
            for (Map.Entry<String, String> entry : value.entrySet()) {
                entry.setValue(String.format("%s=\"%s\"", entry.getKey(), entry.getValue()));
            }
            this.template = StrUtil.format(this.template, value);
            return this;
        }

        public HtmlTag extraTag(Consumer<Map<String, String>> htmlTag) {
            final HashMap<String, String> map = MapUtil.newHashMap();
            htmlTag.accept(map);
            return extraTag(map);
        }

        private String ignore() {
            String temp = this.template.replaceAll(" style='\\{style}'", "").replaceAll(" class='\\{class}'", "");
            return ReUtil.replaceAll(temp, String.format("<%s.*?>", this.tag), str -> ReUtil.replaceAll(str.group(0), "(\\{[^\\}]+\\})", ""));
        }

        public String build() {
            return ignore().replaceAll("\\{content}", "");
        }
    }


    public static class HtmlStyle {
        private final Map<String, String> styles;

        private HtmlStyle(Map<String, String> styles) {
            this.styles = styles;
        }

        public HtmlStyle append(String name, String value) {
            styles.put(name, value);
            return this;
        }

        public String build() {
            return MapUtil.joinIgnoreNull(styles, ";", ": ");
        }
    }


    //---------------------------------

    public static HtmlTag custom(String tag) {
        return new HtmlTag(tag);
    }

    public static HtmlTag custom(String tag, String extra) {
        return new HtmlTag(tag, extra);
    }

    public static HtmlTag custom(String tag, boolean aloneTag) {
        return new HtmlTag(tag, aloneTag);
    }

    public static HtmlTag custom(String tag, String extra, boolean aloneTag) {
        return new HtmlTag(tag, extra, aloneTag);
    }

    public static HtmlTag custom(boolean nonStyle, String html, int repeatCount) {
        return new HtmlTag(nonStyle, StrUtil.repeat(html, repeatCount));
    }

    public static HtmlTag div() {
        return custom("div");
    }

    public static HtmlTag span() {
        return custom("span");
    }

    public static HtmlTag p() {
        return custom("p");
    }

    public static HtmlTag img() {
        return custom("img", "{src} {alt} {width}", true);
    }

    public static HtmlTag H(int level) {
        return custom(String.format("h%s", level));
    }

    public static HtmlTag br() {
        return br(0);
    }

    public static HtmlTag br(int count) {
        return custom(true, "<br>", count);
    }

    public static HtmlTag hr() {
        return br(0);
    }

    public static HtmlTag hr(int count) {
        return custom(true, "<hr>", count);
    }

    public static HtmlTag i() {
        return custom("i");
    }

    public static HtmlTag a() {
        return custom("a", "{href}");
    }

    public static HtmlTag table() {
        return custom("table", "{width} {align} {height} {border}", false);
    }

    public static HtmlTag thead() {
        return custom("thead");
    }

    public static HtmlTag tfoot() {
        return custom("tfoot");
    }

    public static HtmlTag tbody() {
        return custom("tbody");
    }

    public static HtmlTag tr() {
        return custom("tr");
    }

    public static HtmlTag th() {
        return custom("th");
    }

    public static HtmlTag td() {
        return custom("td");
    }

    public static HtmlTag ul() {
        return custom("ul");
    }

    public static HtmlTag ol() {
        return custom("ol");
    }

    public static HtmlTag dl() {
        return custom("dl");
    }

    public static HtmlTag li() {
        return custom("li");
    }
}

测试类

package cn.wangjiahang.record.util.html;

import cn.hutool.core.date.StopWatch;
import cn.hutool.core.lang.Console;
import org.junit.Test;

/**
 * @author jh.wang
 * @since 2022/10/30
 */
public class HtmlTest {
    @Test
    public void htmlBuildTest() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("测试1");

        final String build1 = HtmlUtil.custom("div").clazz("container", "kkk").style(HtmlUtil.style().append("color", "red")).build();
        stopWatch.stop();
        Console.log("{} 耗时:{} 内容:{}", stopWatch.getLastTaskName(), stopWatch.getTotalTimeMillis(), build1);


        stopWatch.start("测试2");
        final String build2 = HtmlUtil.div().style("position", "relative").appendContent(HtmlUtil.div().style("position: absolute; top: 0;right: 20;")).build();
        stopWatch.stop();
        Console.log("{} 耗时:{} 内容:{}", stopWatch.getLastTaskName(), stopWatch.getTotalTimeMillis(), build2);


        stopWatch.start("测试3");
        final String build3 = HtmlUtil.custom("div","{uu} {uu3}")
                .style(htmlStyle -> {
                    htmlStyle.append("yy", "90").append("ll", "99");
                }).extraTag(val -> {
                    val.put("uu", "88");
                    val.put("uu3", "88");
                }).appendContent("div", "{src}", tag -> {
                    tag.extraTag("src", "http:xxx/de/de12").content("p", inner1 -> {
                        inner1.clazz("aaaa").appendContent("a", "{alt} {src}", inner2 -> {
                            inner2.extraTag("src", "111")
                                    .extraTag("alt", "点击跳转")
                                    .style(style -> style.append("color", "#666"));
                        });
                    });
                })
                .content("来来来来来绿绿绿绿绿绿绿绿绿绿绿绿绿");
        stopWatch.stop();
        Console.log("{} 耗时:{} 内容:{}", stopWatch.getLastTaskName(), stopWatch.getTotalTimeMillis(), build3);


        stopWatch.start("测试4");
        for (int i = 0; i < 100; i++) {
            HtmlUtil.custom("div","{uu} {uu3}")
                    .style(htmlStyle -> {
                        htmlStyle.append("yy", "90").append("ll", "99");
                    }).extraTag(val -> {
                        val.put("uu", "88");
                        val.put("uu3", "88");
                    }).appendContent("div", "{src}", tag -> {
                        tag.extraTag("src", "http:xxx/de/de12").content("p", inner1 -> {
                            inner1.clazz("aaaa").appendContent("a", "{alt} {src}", inner2 -> {
                                inner2.extraTag("src", "111")
                                        .extraTag("alt", "点击跳转")
                                        .style(style -> style.append("color", "#666"));
                            });
                        });
                    })
                    .content("来来来来来绿绿绿绿绿绿绿绿绿绿绿绿绿");
        }
        stopWatch.stop();
        Console.log("{} 耗时:{}", stopWatch.getLastTaskName(), stopWatch.getTotalTimeMillis());
    }
}

// 测试1 耗时:68 内容:<div style='color: red' class='container kkk' ></div>
// 测试2 耗时:94 内容:<div style='position: relative' ><div style='position: absolute; top: 0;right: 20;' ></div></div>
// 测试3 耗时:98 内容:<div style='yy: 90;ll: 99' uu="88" uu3="88"><div src="http:xxx/de/de12"><p class='aaaa' ><a style='color: #666' alt="点击跳转" src="111"></a></p></div>来来来来来绿绿绿绿绿绿绿绿绿绿绿绿绿</div>
// 测试4 耗时:212

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值