封装爬取到的页面信息为Java对象,Java反射应用,java工作中函数式接口用法,实际封装函数式传值方法

本文介绍了一种方法,通过引入函数式接口BiConsumer来简化HTML页面表格数据解析的过程。原有的代码通过反射和循环遍历表格单元格来填充SelectMemberResult和SelectRingResult实体类,现在通过新定义的getDataList方法,将数据处理逻辑封装成函数式参数,使得代码更加简洁易读。此优化适用于处理类似结构的HTML表格数据。
摘要由CSDN通过智能技术生成

该功能为解析html页面上的表格
代码中用到的相关反射工具类为: Hutool
原方法:

private List<String> getFieldName(Class clazz)
{
    // 通过反射获取 clazz 中的所有属性名称
    return Stream.of(ReflectUtil.getFields(clazz)).map(Field::getName).collect(Collectors.toList())      
}
private Elements getElements(String html)
{
    // 获取数据列表
    Element tbody = Jsoup.parse(html).getElementsByTag("tbody").get(0);
    // 每个tr
    return tbody.getElementsByTag("tr")  
}
public List<SelectMemberResult> selectMemberResult(String phone, String type)
{
    // 通过反射获取 SelectMemberResult 类中的所有属性名称
    List<String> selectMemberProperty = this.getFieldName(SelectMemberResult.class);
    // 获取用户列表
    String userInfoHtml = this.getUserInfo(phone, type);
    // 获取号码列表中的每个tr
    Elements trs = this.getElements(userInfoHtml);
    // 创建商户列表集合
    List<SelectMemberResult> selectMembers = new ArrayList<>();
    trs.forEach(tr ->
    {
        // 获取详细信息
        Elements tds = tr.getElementsByTag("td");
        SelectMemberResult selectMember = new SelectMemberResult();
        for (int i = 0; i < tds.size(); i++)
        {
            // 序号	姓名	用户号码	省份	所属商户	彩铃名称	彩铃功能	业务状态	设置状态	创建时间	 操作  多选框
            if (i < tds.size() - 2)
            {
                // 通过反射,设置对应字段的信息
                ReflectUtil.setFieldValue(selectMember, selectMemberProperty.get(i), tds.get(i).text());
                continue;
            }
            // 忽略操作
            if (i == tds.size() - 2)
            {
                continue;
            }
            // 设置最后一个多选框的值
            ReflectUtil.setFieldValue(selectMember, selectMemberProperty.get(i), tds.get(i).childNode(0).attr("value"));
        }
        selectMembers.add(selectMember);
    });
    return selectMembers;
}
public List<SelectRingResult> selectRingResult(String type)
{
    // 获取铃音列表
    String ringHtml = this.getRingInfo(type);
    // 通过反射获取 SelectRingResult 类中的所有属性名称
    List<String> selectRingProperty = this.getFieldName(SelectRingResult.class);
    // 每个tr
    Elements trs = this.getElements(ringHtml);
    // 创建商户列表集合
    List<SelectRingResult> selectRings = new ArrayList<>();
    trs.forEach(tr ->
    {
        // 获取详细信息
        Elements tds = tr.getElementsByTag("td");
        SelectRingResult selectRing = new SelectRingResult();
        for (int i = 0; i < tds.size(); i++)
        {
            // 序号 彩铃名称	制作类型	支付状态	审核状态	创建时间	操作
            if (i < tds.size() - 1)
            {

                // 通过反射,设置对应字段的信息
                ReflectUtil.setFieldValue(selectRing, selectRingProperty.get(i), tds.get(i).text());
                continue;
            }
            // οnclick="deleRing(4513649,'淮安祥通汽车服务有限公司208904');"
            Elements elements = tds.get(i).getElementsByTag("i");
            String onclick = elements.get(elements.size() - 1).attr("onclick");
            // deleRing(4513649,'淮安祥通汽车服务有限公司208904');
            ReflectUtil.setFieldValue(selectRing, selectRingProperty.get(i), StringUtils.substringBetween(onclick, "(", ","));
        }
        selectRings.add(selectRing);
    });
    return selectRings;
}

实体类:

public class SelectRingResult implements Serializable
{
    // 序号 彩铃名称	制作类型	支付状态	审核状态	创建时间	操作
    /** 序号*/
    private Integer serialNumber;
    /** 彩铃名称*/
    private String ringName;
    /** 制作类型*/
    private String productionType;
    /** 支付状态*/
    private String paymentStatus;
    /** 审核状态*/
    private String auditStatus;
    /** 创建时间*/
    private String creationTime;
    /** 操作(铃音id)*/
    private String ringId;
}

public class SelectMemberResult implements Serializable
{
    // 序号	姓名	用户号码	省份	所属商户	彩铃名称	彩铃功能	业务状态	设置状态	创建时间	 操作  多选框
    /** 序号*/
    private String serialNumber;
    /** 姓名*/
    private String userName;
    /** 用户号码*/
    private String phone;
    /** 省份*/
    private String province;
    /** 所属商户*/
    private String groupName;
    /** 彩铃名称*/
    private String ringName;
    /** 彩铃功能*/
    private String ringStatus;
    /** 业务状态*/
    private String isOpenImusic;
    /** 设置状态*/
    private String setStatus;
    /** 创建时间*/
    private String creationTime;
    /** 操作*/
    private String operate;
    /** 成员id*/
    private String userId;
}

现方法:

/**增加一个函数式接口*/
@FunctionalInterface
public interface BiConsumer<T,U,P>
{
    void accept(T t, U u, P p);
}

封装的函数式参数方法:

private  <T> List<T> getDataList(String html, Class<T> clazz, BiConsumer<Elements, List<String>, T> function)
{
    // 通过反射获取类中的所有属性名称
    List<String> property = Stream.of(ReflectUtil.getFields(clazz)).map(Field::getName).collect(Collectors.toList());
    // 获取号码列表中的每个tr
    Element tbody = Jsoup.parse(html).getElementsByTag("tbody").get(0);
    Elements trs =tbody.getElementsByTag("tr");
    // 创建列表集合
    List<T> result = new ArrayList<>();
    trs.forEach(tr ->
    {
        // 获取详细信息
        Elements tds = tr.getElementsByTag("td");
        // 反射创建对象
        T obj= ReflectUtil.newInstance( clazz);
        // 执行对象设置值的,函数式逻辑
        function.accept(tds, property, obj);
        // 添加到集合中
        result.add(t);
    });
    return result;
}

这里以上面的获取用户列表为例:

public List<SelectMemberResult> selectMemberResult(String phone, String type)
{
    // 获取用户列表
    String userInfoHtml = this.getUserInfo(phone, type);
    // 处理数据返回结果
    return this.getDataList(userInfoHtml,SelectMemberResult.class, (tds, property, obj) -> 
    {
        for (int i = 0; i < tds.size(); i++)
        {
            // 序号	姓名	用户号码	省份	所属商户	彩铃名称	彩铃功能	业务状态	设置状态	创建时间	 操作  多选框
            if (i < tds.size() - 2)
            {
                // 通过反射,设置对应字段的信息
                ReflectUtil.setFieldValue(obj, property.get(i), tds.get(i).text());
                continue;
            }
            // 忽略操作
            if (i == tds.size() - 2)
            {
                continue;
            }
            // 设置最后一个多选框的值
            ReflectUtil.setFieldValue(obj, property.get(i), tds.get(i).childNode(0).attr("value"));
        }
    });
}

现在只需要关心for循环的操作就好了,开心的一天从学到了新知识开始吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值