1 实体

package com.company.common;

import java.io.Serializable;

/**
 * 用户信息实体
 * @author xindaqi
 * @since 2020-12-19
 */

public class UserInformationEntity implements Serializable {

//    private static final long serialVersionUID = 1547123013328323240L;

    public String nickname;

    private String address;

    public UserInformationEntity() {}

    public UserInformationEntity(String nickname, String address) {
        this.nickname = nickname;
        this.address = address;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

2 反射获取属性

获取类属性:共有属性和私有属性,通过getFields()方法获取公有属性,通过getDeclaredFields()方法获取所有属性,实现如下:

2.1 获取公共属性

package com.company.reflect;

import com.company.common.UserInformationEntity;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ReflectGetMethodAndProperties {

    public static void main(String[] args) throws ClassNotFoundException, IntrospectionException, IllegalAccessException, InvocationTargetException {

        Class<?> clzz = UserInformationEntity.class;
        UserInformationEntity userInformationEntity = new UserInformationEntity("xiaoxiao", "黑龙江");
        Class clzzUser = userInformationEntity.getClass();
        
        /**
         * 属性:公共
         */
        Field[] fields = clzz.getFields();
        for(Field field : fields) {
            System.out.println("类公共属性名称:" + field.getName());
        }    
}
  • 结果
类公共属性名称:nickname

2.2 获取所有属性

package com.company.reflect;

import com.company.common.UserInformationEntity;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ReflectGetMethodAndProperties {

    public static void main(String[] args) throws ClassNotFoundException, IntrospectionException, IllegalAccessException, InvocationTargetException {

        Class<?> clzz = UserInformationEntity.class;
        UserInformationEntity userInformationEntity = new UserInformationEntity("xiaoxiao", "黑龙江");
        Class clzzUser = userInformationEntity.getClass();

        /**
         * 属性: 所有
         */
        Field[] allFields = clzz.getDeclaredFields();
        for(Field field : allFields) {
            System.out.println("所有属性:" + field.getName());
        }      
}
  • 结果
所有属性:nickname
所有属性:address

3 反射获取属性值

package com.company.reflect;

import com.company.common.UserInformationEntity;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ReflectGetMethodAndProperties {

    public static void main(String[] args) throws ClassNotFoundException, IntrospectionException, IllegalAccessException, InvocationTargetException {

        Class<?> clzz = UserInformationEntity.class;
        UserInformationEntity userInformationEntity = new UserInformationEntity("xiaoxiao", "黑龙江");
        Class clzzUser = userInformationEntity.getClass();

        /**
         * 属性: 所有
         */
        Field[] allFields = clzz.getDeclaredFields();
        for(Field field : allFields) {
            System.out.println("所有属性:" + field.getName());
        }

        /**
         * 属性值
         */
        Field[] userFields = clzzUser.getDeclaredFields();
        for(Field field: allFields) {
            PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clzzUser);
            Method method = pd.getReadMethod();
            Object invoke = method.invoke(userInformationEntity);
            System.out.println(field.getName() + ":" + invoke);
        }
}
  • 结果
nickname:xiaoxiao
address:黑龙江

4 反射获取方法

package com.company.reflect;

import com.company.common.UserInformationEntity;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ReflectGetMethodAndProperties {

    public static void main(String[] args) throws ClassNotFoundException, IntrospectionException, IllegalAccessException, InvocationTargetException {

        Class<?> clzz = UserInformationEntity.class;
        UserInformationEntity userInformationEntity = new UserInformationEntity("xiaoxiao", "黑龙江");
        Class clzzUser = userInformationEntity.getClass();
        /**
         * 方法
         */
        Method[] methods = clzz.getMethods();
        for(Method method : methods) {
            System.out.println("类方法名称:" + method.getName());
        }
     
}
  • 结果
类方法名称:getNickname
类方法名称:setNickname
类方法名称:setAddress
类方法名称:getAddress
类方法名称:wait
类方法名称:wait
类方法名称:wait
类方法名称:equals
类方法名称:toString
类方法名称:hashCode
类方法名称:getClass
类方法名称:notify
类方法名称:notifyAll

5 反射遍历为Excel赋值

按行为Excel写入数据,Excel模板如图5.1

获取属性上的注解 java_方法


图5.1 Excel

Excel的每行(hang)为一个实体,通过遍历为Excel填充数据,使用反射机制,进行内层循环,即进行属性值遍历并填充,实现如下:

5.1 反射数据写入二维数组

package com.company.reflect;

import com.company.common.UserInformationEntity;
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ReflectGetMethodAndProperties {

    public static void main(String[] args) throws ClassNotFoundException, IntrospectionException, IllegalAccessException, InvocationTargetException {

        Class<?> clzz = UserInformationEntity.class;
        UserInformationEntity userInformationEntity = new UserInformationEntity("xiaoxiao", "黑龙江");
        Class clzzUser = userInformationEntity.getClass();

        /**
         * 属性: 所有
         */
        Field[] allFields = clzz.getDeclaredFields();
        for(Field field : allFields) {
            System.out.println("所有属性:" + field.getName());
        }
        /**
         * 反射为二维数据赋值
         * 用于Excel按行写入数据
         */
        List<UserInformationEntity> userInformationEntityList = new ArrayList<>();
        userInformationEntityList.add(userInformationEntity);
        UserInformationEntity userInformationEntity1 = new UserInformationEntity("dada", "安徽");
        userInformationEntityList.add(userInformationEntity1);
        UserInformationEntity userInformationEntity2 = new UserInformationEntity("haha", "辽宁");
        userInformationEntityList.add(userInformationEntity2);
        String[][] arrays = new String[3][2];
        for(int i = 0; i < userInformationEntityList.size(); i++) {
            for(int j = 0; j < allFields.length; j++) {
                PropertyDescriptor pd = new PropertyDescriptor(allFields[j].getName(), userInformationEntityList.get(i).getClass());
                Method method = pd.getReadMethod();
                String invoke = method.invoke(userInformationEntityList.get(i)).toString();
                arrays[i][j] = invoke;
            }
        }
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < 2; j++) {
                System.out.println(arrays[i][j] + "");
            }
        }
    }
}
  • 结果
xiaoxiao
黑龙江
dada
安徽
haha
辽宁

5.2 反射数据写入Excel

  • 实体
package com.company.microservicedata.vo;

/**
 * 用户详情
 * @author xindaqi
 * @since 2020-10-07
 */

public class UserDetailsVO {
    private Integer id;

    private String username;

    private String sex;

    private String address;

    public void setId(Integer id){
        this.id = id;
    }
    public Integer getId(){
        return id;
    }

    public void setUsername(String username){
        this.username = username;
    }
    public String getUsername(){
        return username;
    }

    public void setSex(String sex){
        this.sex = sex;
    }
    public String getSex(){
        return sex;
    }

    public void setAddress(String address){
        this.address = address;
    }
    public String getAddress(){
        return address;
    }

    @Override
    public String toString() {
        return "UserDetailsVO{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
  • 实现
package com.company.microservicedata.util;

import com.company.microservicedata.vo.UserDetailsVO;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.IntStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;

/**
 * Excel文件处理工具类
 * @author xindaqi
 * @since 2020-12-13
 */

@Component
public class ExcelProcessUtil {

    private static Logger logger = LoggerFactory.getLogger(ExcelProcessUtil.class);

    public void rawWrite(Class<?> clazz, String savePath, String fileName) {

        /**
         * 新建Excel文件和Sheet
         */
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet("原生POI生成Excel");
        List<String> titleList = Stream.of("序号", "姓名", "性别", "地址").collect(Collectors.toList());
        XSSFRow headRow = sheet.createRow(0);
        for(int i = 0; i < titleList.size(); i++) {
            headRow.createCell(i).setCellValue(titleList.get(i));
        }

        List<UserDetailsVO> userDetailsVOList = new ArrayList<>();
        UserDetailsVO u1 = new UserDetailsVO();
//        u1.setId(1);
        u1.setAddress("黑龙江");
        u1.setSex("male");
        u1.setUsername("xiaoxiao");
        userDetailsVOList.add(u1);
        UserDetailsVO u2 = new UserDetailsVO();
//        u2.setId(2);
        u2.setAddress("辽宁");
        u2.setSex("male");
        u2.setUsername("xiaohei");
        userDetailsVOList.add(u2);
        UserDetailsVO u3 = new UserDetailsVO();
//        u3.setId(3);
        u3.setAddress("广东");
        u3.setSex("male");
        u3.setUsername("xiaohua");
        userDetailsVOList.add(u3);
        logger.info("user list: {}", userDetailsVOList);
        Field[] fields = clazz.getDeclaredFields();
        FileOutputStream fos = null;
        try {
            for(int i = 0; i < userDetailsVOList.size(); i++) {
                // 每次遍历,重新生成行对象
                XSSFRow row = sheet.createRow(i+1);
                for(int j = 0; j < fields.length; j++) {
                    PropertyDescriptor pd = new PropertyDescriptor(fields[j].getName(), userDetailsVOList.get(i).getClass());
                    Method method = pd.getReadMethod();
                    // null置为空
                    String invoke = (null == method.invoke(userDetailsVOList.get(i))) ? "" : method.invoke(userDetailsVOList.get(i)).toString();
                    row.createCell(j).setCellValue(invoke);
                }
            }
            File file = new File(savePath + fileName);
            fos = new FileOutputStream(file);
            workbook.write(fos);
            logger.info("下载-完成写入");

        } catch(Exception e) {
            logger.error("下载异常:{}", e);
            logger.info("下载异常:{}", e);
        } finally {
            try {
                if(fos != null) {
                    fos.close();
                }
                logger.info("流关闭");
            } catch (Exception e) {
                logger.info("流关闭失败:{}", e);
            }
            try {
                workbook.close();
                logger.info("Workbook关闭");
            } catch (Exception e) {
                logger.info("Workbook关闭失败:{}", e);
            }
        }
    }
}
  • 调用方法
@Override
public String downloadExcel(HttpServletRequest request) {
    String savePath = "/Users/xindaqi/xinPrj/java/webStudy/microservice-book/microservice-data/src/main/resources/template/";
    String fileName = "下载-Excel.xlsx";
    excelProcessUtil.rawWrite(UserDetailsVO.class, savePath, fileName);
    String downloadLink = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getRequestURI() + "/" + fileName;
    return downloadLink;
}
  • 结果

获取属性上的注解 java_反射_02


图5.2 反射写入Excel

6 小结

  • 反射获取属性:公共属性:getFields(),所有属性:getDeclaredFields()
  • 反射属性值:PropertyDescriptor,getReadMethod()获取属性值的方法(get方法),获取值invoke()
  • 反射属性值会出现空指针,需要逻辑处理
  • Excel每次写入行,需要重新建立行对象