其他常用类

back2 专题

Enum

返回顶部

一般使用方法

public enum DeviceType {
     Firecontrolhost(
            "消控主机",
            getTableName(com.faith.mvc.entity.TsBiFirecontrolhost.class),
            getTableName(com.faith.mvc.entity.TsDataFirecontrolhost.class),
            Lists.newArrayList(
                    WarningProcessType.Misinformation,
                    WarningProcessType.Fault,
//                    WarningProcessType.Abnormal,
                    WarningProcessType.Fire,
                    WarningProcessType.Other
            ),
            "T.EQUIPNO,T.EQUIPNAME"
    ),
    OtherDevice("其它设备", getTableName(com.faith.mvc.entity.TsBiOtherDevice.class), null,
            Lists.newArrayList(WarningProcessType.Misinformation, WarningProcessType.Fault,   WarningProcessType.Other),
            "");
    private String typeName;
    private String busiTable;
    private String dataTable;
    private List<WarningProcessType> warningProcessTypes;
    private Map<String, String> processStatusMap;
    private String specialFields;
    /*
     * @param typeName            类型名称
     * @param busiTable           基础表名
     * @param dataTable           数据表名
     * @param warningProcessTypes 拥有的告警类型
     */
    DeviceType(String typeName, String busiTable, String dataTable, List<WarningProcessType> warningProcessTypes,String specialFields) {
        this.typeName = typeName;
        this.busiTable = busiTable;
        this.dataTable = dataTable;
        this.warningProcessTypes = warningProcessTypes;
        this.specialFields=specialFields;

        processStatusMap = new HashMap<>();
        for (WarningProcessType warningProcessType : warningProcessTypes) {
            processStatusMap.put(warningProcessType.getStatus(), warningProcessType.getStatusName());
        }
    }
public static DeviceType getByTable(String table) {
    if (StringUtils.isBlank(table)) {
        return null;
    }

    for (DeviceType deviceType : DeviceType.values()) {
        if (StringUtils.equals(deviceType.getBusiTable(), table)
                || StringUtils.equals(deviceType.getDataTable(), table)) {
            return deviceType;
        }
    }
    return null;
}

FTP

返回顶部

package com.faith.utils;

import com.faith.exception.BusinessException;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.log4j.Logger;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class FtpUtil {
    private static Logger log = Logger.getLogger(FtpUtil.class);

    private FTPClient ftpClient;
    public static final int BINARY_FILE_TYPE = FTP.BINARY_FILE_TYPE;
    public static final int ASCII_FILE_TYPE = FTP.ASCII_FILE_TYPE;

    /**
     * 每次Ftp操作前,先获取连接
     *
     * @param server   Ftp服务器地址,IP
     * @param port     Ftp端口
     * @param user     用户名
     * @param password 密码
     * @param path     工作间
     * @return void 返回类型
     * @throws SocketException
     * @throws IOException     设定文件
     * @Title: connectServer
     * @author zhuyj
     */
    private void connectServer(String server, int port, String user,
                              String password, String path) throws SocketException, IOException {
        ftpClient = new FTPClient();
        ftpClient.setDataTimeout(120000);       //设置传输超时时间为60秒
        ftpClient.setConnectTimeout(120000);       //连接超时为60秒

//        ftpClient.setFileType(BINARY_FILE_TYPE);
        /**
         * 解决中文文件名乱码问题
         */
        ftpClient.setControlEncoding("GBK");
        ftpClient.connect(server, port);
        log.info("Connected to " + server + ".");
        log.info(ftpClient.getReplyCode());
        /**
         * 登陆Ftp
         */
        ftpClient.login(user, password);

        //进入多级目录,若不存在则创建
        createAndChangeDirs(path);
//        /**
//         * 如果Ftp中不存在此目录则创建
//         */
//        if (path.length() != 0 && !existDirectory(path)) {
//            ftpClient.makeDirectory(path);
//        }
//        /**
//         * 设置此目录为工作
//         */
//        if (path.length() != 0) {
//            ftpClient.changeWorkingDirectory(path);
//        }

    }

    /**
     * FTP.BINARY_FILE_TYPE | FTP.ASCII_FILE_TYPE
     * 设置传输文件格式
     *
     * @author zhuyj
     */
    public void setFileType(int fileType) throws IOException {
        ftpClient.setFileType(fileType);
    }

    /**
     * 每次Ftp时必须获取异常,在finally块中关闭连接
     *
     * @throws IOException
     * @author zhuyj
     */
    public void closeServer() throws IOException {
        try {
            /**
             * 关闭连接前先退出登陆
             *
             */
            ftpClient.logout();
        } catch (RuntimeException e) {
            log.error("关闭Ftp连接错误:" + e.getMessage());
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                ftpClient.disconnect();
            }
        }
    }

    /**
     * 更改工作间
     *
     * @param path
     * @return boolean 返回类型
     * @throws IOException 设定文件
     * @Title: changeDirectory
     * @Description: TODO(这里用一句话描述这个方法的作用)
     * @author zhuyj
     */
    public boolean changeDirectory(String path) throws IOException {
        return ftpClient.changeWorkingDirectory(path);
    }

    /**
     * 创建目录
     *
     * @param pathName
     * @return boolean 返回类型
     * @throws IOException 设定文件
     * @throws
     * @Title: createDirectory
     * @Description: TODO(这里用一句话描述这个方法的作用)
     * @author zhuyj
     */
    public boolean createDirectory(String pathName) throws IOException {
        return ftpClient.makeDirectory(pathName);
    }

    /**
     * 创建多级目录
     * @param remote
     * @throws UnsupportedEncodingException
     * @throws IOException
     */
    public void createAndChangeDirs(String remote)throws UnsupportedEncodingException, IOException {

        //以/结尾,确保最后一个目录被创建
        if(!remote.endsWith("/")){
            remote += "/";
        }

        String directory = remote.substring(0, remote.lastIndexOf("/") + 1);

        if (!directory.equals("/") && !ftpClient.changeWorkingDirectory(

                new String(directory.getBytes("GBK"), "iso-8859-1"))) {

            // 如果远程目录不存在,则递归创建远程服务器目录
            int start = 0;
            int end = 0;
            if (directory.startsWith("/")) {
                start = 1;
            } else {
                start = 0;
            }

            end = directory.indexOf("/", start);

            while (true) {

                String subDirectory = new String(remote.substring(start, end).getBytes("GBK"),"iso-8859-1");

                if (!ftpClient.changeWorkingDirectory(subDirectory)) {

                    if (ftpClient.makeDirectory(subDirectory)) {

                        ftpClient.changeWorkingDirectory(subDirectory);
                    } else {
                        throw new BusinessException("01", "目录创建失败");
                    }
                }

                start = end + 1;

                end = directory.indexOf("/", start);

                // 检查所有目录是否创建完毕
                if (end <= start ) {
                    break;
                }
            }
        }
    }

    /**
     * 删除目录
     *
     * @param path
     * @return boolean 返回类型
     * @throws IOException 设定文件
     * @throws
     * @Title: removeDirectory
     * @Description: TODO(这里用一句话描述这个方法的作用)
     * @author zhuyj
     */
    public boolean removeDirectory(String path) throws IOException {
        return ftpClient.removeDirectory(path);
    }

    /**
     * @param path
     * @param isAll
     * @return boolean 返回类型
     * @throws IOException 设定文件
     * @Title: removeDirectory
     * @Description: 删除Ftp目录
     * @author zhuyj
     */
    public boolean removeDirectory(String path, boolean isAll)
            throws IOException {
        if (!isAll) {
            return removeDirectory(path);
        }

        FTPFile[] ftpFileArr = ftpClient.listFiles(path);
        if (ftpFileArr == null || ftpFileArr.length == 0) {
            return removeDirectory(path);
        }

        for (FTPFile ftpFile : ftpFileArr) {
            String name = ftpFile.getName();
            if (ftpFile.isDirectory()) {
                /**
                 * 去掉.和..,否则死循环了
                 */
                if (!ftpFile.getName().equals(".") && (!ftpFile.getName().equals(".."))) {
                    System.out.println("* 删除子目录 [" + path + "/" + name + "]");
                    removeDirectory(path + "/" + name, true);
                }
            } else if (ftpFile.isFile()) {
                System.out.println("* 删除文件 [" + path + "/" + name + "]");
                deleteFile(path + "/" + name);
            } else if (ftpFile.isSymbolicLink()) {

            } else if (ftpFile.isUnknown()) {

            }
        }
        return ftpClient.removeDirectory(path);
    }

    /**
     * 检查当前路径是否存在目录?存在返回true,否则返回false
     */
    public boolean existDirectory(String path) throws IOException {
        boolean flag = false;
        FTPFile[] ftpFileArr = ftpClient.listFiles();
        for (FTPFile ftpFile : ftpFileArr) {
            if (ftpFile.isDirectory()
                    && ftpFile.getName().equalsIgnoreCase(path)) {
                flag = true;
                break;
            }
        }
        return flag;
    }

    /**
     * 检查当前路径是否存在文件?存在返回true,否则返回false
     */
    public boolean existFile(String path) throws IOException {
        boolean flag = false;
        FTPFile[] ftpFileArr = ftpClient.listFiles();
        for (FTPFile ftpFile : ftpFileArr) {
            if (ftpFile.isFile()
                    && ftpFile.getName().equalsIgnoreCase(path)) {
                flag = true;
                break;
            }
        }
        return flag;
    }

    /**
     * 检查当前路径是否存在文件?存在返回true,否则返回false
     */
    public boolean existFile(String path, String fileName) throws IOException {
        boolean flag = false;
        System.out.println(flag);
        System.out.println(ftpClient);

        FTPFile[] ftpFileArr = ftpClient.listFiles(path);
        for (FTPFile ftpFile : ftpFileArr) {
            if (ftpFile.isFile() && ftpFile.getName().equalsIgnoreCase(fileName)) {
                flag = true;
                break;
            }
        }

        return flag;
    }

    /**
     * @param path
     * @return List<String> 返回类型
     * @throws IOException 设定文件
     * @throws
     * @Title: 获取ftp目录所有文件
     * @Description: TODO(这里用一句话描述这个方法的作用)
     * @author zhuyj
     */
    public List<String> getFileList(String path) throws IOException {

        FTPFile[] ftpFiles = ftpClient.listFiles(path);

        List<String> retList = new ArrayList<String>();
        if (ftpFiles == null || ftpFiles.length == 0) {
            return retList;
        }
        for (FTPFile ftpFile : ftpFiles) {
            if (ftpFile.isFile()) {
                retList.add(ftpFile.getName());
            } else {
                retList.add(ftpFile.getName());
            }
        }
        return retList;
    }

    /**
     * @param pathName
     * @return boolean 返回类型
     * @throws IOException 设定文件
     * @throws
     * @Title: 删除ftp文件
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public boolean deleteFile(String pathName) throws IOException {
        boolean flag = ftpClient.deleteFile(pathName);
        return flag;
    }

    /**
     * 文件上传
     *
     * @param fileName
     * @param newName
     * @return
     * @throws IOException
     */
    public boolean uploadFile(String fileName, String newName)
            throws IOException {
        boolean flag = false;
        InputStream iStream = null;
        try {
            iStream = new FileInputStream(fileName);
            int i = iStream.available();
            if (i > 0) {
                flag = ftpClient.storeFile(newName, iStream);
            }

        } catch (IOException e) {
            log.error("上传服务器文件到Ftp错误:" + e.getMessage());
            e.printStackTrace();
            flag = false;
            return flag;
        } finally {
            if (iStream != null) {
                iStream.close();
            }
        }
        return flag;
    }

    /**
     * @param fileName
     * @return boolean 返回类型
     * @throws IOException 设定文件
     * @throws
     * @Title: uploadFile
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public boolean uploadFile(String fileName) throws IOException {
        int i = fileName.lastIndexOf("/");
        log.debug("fileName:" + fileName);
        log.debug("newName:" + fileName.substring(i).replaceAll("/", ""));
        return uploadFile(fileName, fileName.substring(i).replaceAll("/", ""));
    }

    /**
     * FTP文件上传方法
     *
     * @param file   上传的文件
     * @param folder 上传到的具体的目录,可根据业务场景自行定义,比如富琦维保项目的项目合同: fqwbht
     * @return 返回文件值对象,含文件的原始名称,新名称,最终的访问地址,文件类型,后缀等
     * @throws IOException
     */
    public static FileVO uploadFile(MultipartFile file, String folder) {

        try {
            FileVO fileVO = uploadFile(file.getOriginalFilename(), file.getInputStream(), folder);
            return fileVO;
        } catch (IOException e) {
            log.error("上传文件到Ftp错误:", e);
            throw new BusinessException("01", "文件上传失败");
        }
    }

    /**
     * FTP文件上传方法
     *
     * @param fileName   上传的文件名
     * @param inputStream   文件流
     * @param folder 上传到的具体的目录,可根据业务场景自行定义,比如富琦维保项目的项目合同: fqwbht
     * @return 返回文件值对象,含文件的原始名称,新名称,最终的访问地址,文件类型,后缀等
     * @throws IOException
     */
    public static FileVO uploadFile(String fileName, InputStream inputStream, String folder) {
        boolean flag = false;
        FtpUtil ftp = null;
        try {
            //String fileName = file.getOriginalFilename();
            int index = fileName.lastIndexOf(".");
            // 后缀
            String ext = fileName.substring(index + 1);
            // 保前缀
            String qz = fileName.substring(0, index);
            String id = UUID.randomUUID().toString();
            // 图片新名称
            String fileNewName = id + "." + ext;
            ftp = FtpUtil.getFtpUtil(folder);
            flag = ftp.ftpClient.storeFile(fileNewName, inputStream);
            //上传成功,返回文件对象
            if (!flag) {
                throw new BusinessException("01", "文件上传失败");
            }

            String filePath = folder + "/" + fileNewName;
            FileVO fileVO = new FileVO(fileName, fileNewName, filePath, Constants.getFtpFullImageUrl(filePath), ext);
            return fileVO;
        } catch (IOException e) {
            log.error("上传文件到Ftp错误:", e);
            throw new BusinessException("01", "文件上传失败");
        } finally {
            try {
                if (ftp != null)
                    ftp.closeServer();
            } catch (IOException e) {
                log.error("Ftp流关闭错误:", e);
            }
        }
    }


    /**
     * 从远程下载文件到应用服务器
     *
     * @param remoteFileName
     * @param localFileName
     * @return
     * @throws IOException
     * @author zhuyj
     */
    public boolean download(String remoteFileName, String localFileName)
            throws IOException {
        boolean flag = false;
        File outfile = new File(localFileName);
        OutputStream oStream = null;
        try {
            oStream = new FileOutputStream(outfile);
            flag = ftpClient.retrieveFile(remoteFileName, oStream);
        } catch (IOException e) {
            log.error("下载Ftp文件到服务器错误:" + e.getMessage());
            flag = false;
            return flag;
        } finally {
            if (oStream != null) {
                oStream.close();
            }
        }
        return flag;
    }

    /**
     * 从远程下载文件
     *
     * @param filePath
     * @param localFileName
     * @return
     * @throws IOException
     * @author zhuyj
     */
    public static void download(String filePath, OutputStream outputStream) {

        try {

            int index = filePath.lastIndexOf("/");
            String folder = filePath.substring(0, index);
            String fileName = filePath.substring(index + 1);

            FtpUtil.getFtpUtil(folder).ftpClient.retrieveFile(fileName, outputStream);
        } catch (IOException e) {
            log.error("下载文件错误:", e);
            throw new BusinessException("01", "文件下载失败");
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch (IOException e) {
                    log.error("文件输出流关闭失败", e);
                }
            }
        }
    }


    /**
     * 批量从FTP下载文件到应用服务器
     *
     * @param remotePath ftp文件路径
     * @param localPath  应用服务器文件路径
     * @param fileNames  需要下载的文件名称
     * @return void 返回类型
     * @throws IOException 设定文件
     * @throws
     * @Title: download
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public void download(String remotePath, String localPath, List<String> fileNames)
            throws IOException {
        for (String name : fileNames) {
            /*
             * 应用服务器文件
             */
            String localFileName = localPath + "/" + name;
            /*
             * ftp文件
             */
            String remoteFileName = remotePath + name;
            File outfile = new File(localFileName);
            OutputStream oStream = null;
            try {
                oStream = new FileOutputStream(outfile);
                ftpClient.retrieveFile(remoteFileName, oStream);
            } catch (IOException e) {
                log.error("下载Ftp文件到服务器错误:" + e.getMessage());
            } finally {
                if (oStream != null) {
                    oStream.close();
                }
            }
        }
    }

    /**
     * 从Ftp中获取文件输入流
     *
     * @param sourceFileName
     * @return
     * @throws IOException
     * @author zhuyj
     */
    public InputStream downFile(String sourceFileName) throws IOException {
        return ftpClient.retrieveFileStream(sourceFileName);
    }

    public static FtpUtil getFtpUtil(String path) throws IOException {
        FtpUtil ftp = new FtpUtil();
        try {
            String ftpurl = Constants.getFtpUrl();
            String port = Constants.getFtpPort();
            String user = Constants.getFtpUser();
            String pws = Constants.getFtpPass();
            ftp.connectServer(ftpurl, 21, user, pws, path);
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ftp;

    }


    public static void main(String[] args) {
        FtpUtil ftp = new FtpUtil();
        try {
            ftp.connectServer(Constants.getFtpUrl(), Integer.parseInt(Constants.getFtpPort()), Constants.getFtpUser(), Constants.getFtpPass(), "image");
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            boolean uploadFlag = ftp.uploadFile("d:/test.jpg");
            System.out.println("uploadFlag:" + uploadFlag);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                ftp.closeServer();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }

}

FileUpload

返回顶部

package com.faith.utils;

import com.faith.exception.BusinessException;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;
import java.util.function.Function;

public class FileUploadUtil {

   private static final Logger logger = Logger.getLogger(FileUploadUtil.class);

   /**
    *  将图片文件转化为字节数组字符串,并对其进行Base64编码处理
    * @param imgFilePath 路径
    * @return
    */
   public static String ImgToBase(String imgFilePath) {
      byte[] data = null;

      // 读取图片字节数组
      try {
         InputStream in = new FileInputStream(imgFilePath);
         data = new byte[in.available()];
         in.read(data);
         in.close();
      } catch (IOException e) {
         e.printStackTrace();
      }

      // 对字节数组Base64编码
      BASE64Encoder encoder = new BASE64Encoder();
      if(null != data){
         return encoder.encode(data);// 返回Base64编码过的字节数组字符串
      }
      return null;
   }

   /**
    *  Base64字符串解码并生成图片
    * @param imgStr 字符串
    * @param imgFilePath 路径
    * @return
    */
   public static boolean BaseToImg(String imgStr, String imgFilePath,String imgName) {
      if (imgStr == null) // 图像数据为空
         return false;
      File file =new File(imgFilePath);
      if(!file.exists()){
         file.mkdirs();
      }
      BASE64Decoder decoder = new BASE64Decoder();
      try {
         // Base64解码
         byte[] bytes = decoder.decodeBuffer(imgStr);
         for (int i = 0; i < bytes.length; ++i) {
            if (bytes[i] < 0) {// 调整异常数据
               bytes[i] += 256;
            }
         }
         // 生成jpeg图片
         OutputStream out = new FileOutputStream(imgFilePath+"\\"+imgName);
         out.write(bytes);
         out.flush();
         out.close();
         return true;
      } catch (Exception e) {
         return false;
      }
   }

   public static <T> List<T> upload(HttpServletRequest request, Function<FileMap, T> fun,Long maxSize){

      if (!ServletFileUpload.isMultipartContent(request)) {
         throw new BusinessException("01", "没有待上传的文件");
      }

      try {
         // 1. 创建DiskFileItemFactory对象,设置缓冲区大小和临时文件目录
         DiskFileItemFactory factory = new DiskFileItemFactory();
         // 2. 创建ServletFileUpload对象,并设置上传文件的大小限制。
         ServletFileUpload sfu = new ServletFileUpload(factory);
         //限制大小
         if(null != maxSize && maxSize > 0){
            sfu.setSizeMax(maxSize);
         }
         sfu.setHeaderEncoding("utf-8");

         // 3.
         // 调用ServletFileUpload.parseRequest方法解析request对象,得到一个保存了所有上传内容的List对象。
         List<FileItem> fileItemList = sfu.parseRequest(request);
         Iterator<FileItem> fileItems = fileItemList.iterator();

         //提取请求参数
         Map<String, String> params = new HashMap<>();

         List<FileItem> fileList = new ArrayList<>();

         // 4. 遍历list,每迭代一个FileItem对象,调用其isFormField方法判断是否是上传文件
         while (fileItems.hasNext()) {
            FileItem fileItem = fileItems.next();
            // 普通表单元素
            if (fileItem.isFormField()) {

               String name = fileItem.getFieldName();// name属性值
               String value = fileItem.getString("utf-8");// name对应的value值
               params.put(name, value);

            } else { // <input type="file">的上传文件的元素

               fileList.add(fileItem);
            }
         }

         FileMap fileMap = new FileMap();
         fileMap.setParams(params);

         List<T> list = new ArrayList<>();
         for (FileItem fileItem : fileList) {

            fileMap.setFileItem(fileItem);

            T t = fun.apply(fileMap);
            list.add(t);

            // 6. 调用FileItem的delete()方法,删除临时文件
            fileItem.delete();
         }

         return list;

      } catch (UnsupportedEncodingException e) {
         logger.error("文件上传-参数编码解析异常", e);
         throw new BusinessException("01", "参数解析失败");
      } catch (FileUploadException e) {
         logger.error("文件上传异常", e);
         throw new BusinessException("01", "文件上传失败");
      }
   }

   /**
    * 文件上传MAP
    */
   public static class FileMap{
      private FileItem fileItem;
      private Map<String, String> params;

      public FileItem getFileItem() {
         return fileItem;
      }

      public void setFileItem(FileItem fileItem) {
         this.fileItem = fileItem;
      }

      public Map<String, String> getParams() {
         return params;
      }

      public void setParams(Map<String, String> params) {
         this.params = params;
      }
   }
}

反射

返回顶部

Java 中的反射机制

back

反射中常见的类

  • Class 类

Class 类实例表示正在运行的 Java 应用程序中的类和接口。Class 是普通类、接口、枚举类、数组等的抽象,即它们的类型就是 Class,它们是 Class 的实例。
既然 Class 代表着类和接口,那么我们可以通过他的实例(字节码文件)来获取对应类或接口的信息,如:注解、修饰符、类型、类的名称、属性、方法、构造方法、直接父类和子类等,还有可以创建它的实例,但只能调用无参构造方法来创建

  • Field 类

Field 表示类的属性,属性含有修饰符、类型、属性名称和值。所以可以通过 Field 的实例获取属性的修饰符、类型、属性名称,并且可以修改属性的值。

  • Method 类

Method 表示类的成员方法,方法包括注解、修饰符、返回类型、方法名,参数等。所以可以通过 Method 的实例获取方法的的信息,如,注解、修饰符、返回类型、方法名并且可以调用所表示的方法。

  • Constructor 类

Constructor 表示构造方法,可以通过 Constructor 的实例获取构造方法的信息,如,修饰符等,并且可以通过它来创建它所在类的的实例。

  • Modifier 类

Modifier 表示修饰符,可通过它来获取修饰符的信息,例如何种修饰符等

  • Annotation

Annotation 代表注解

以上类都位于 java.lang 中

获取 Class 对象的方法

首先要获取 Class 对象吧,因为 Class 对象是代表着各种类,有了它之后才可以得到类的各种信息。获取方法如下:

  • 1)通过 object.getClass()
public static void main(String[] args) {
 Car car = new Car();
 Class clazz = car.getClass();
 }

注意:此方法不适用于 int、float 等基本类型

  • 2)通过(类型名).class、包装类.Type
public static void main(String[] args) {
 Class clazz = Car.class;
 Class cls1 = int.class;
 Class cls2 = String.class;
 Class cls3=Iteger.Type
 }
  • 3)通过 Class.forClass(String 类的全限定名)
try {
 Class clz = Class.forName("com.frank.test.Car");
} catch (ClassNotFoundException e) {
 e.printStackTrace();
}

采用哪种方法来获取,看实际情况而定。

获取类信息

有了 Class 对象后,就可以获取类的成员(方法+属性)注解类的修饰符等。上面也说了,java 中方法用 Method 类表示、属性用 Field 类表示、注解用 Annotation 类来表示、修饰符用 Modifier 类表示。Class 类中有对应的方法来获取他们。如下:

  • 获取属性 Field 的对象
//获取所有的属性,但不包括从父类继承下来的属性
public Field[] getDeclaredFields() throws SecurityException
//获取自身的所有的 public 属性,包括从父类继承下来的。
public Field[] getFields() throws SecurityException
//获取在本类中声明的指定的属性,参数为属性的名称
public Field getDeclaredField(String name)
//获取指定的公有属性,包括父类的,参数为属性的名称
public Field getField(String name)
  • 获取方法 Method 对象
//获取本类声明指定的的方法,第一个参数是方法的名称,后面的参数是方法参数类型的类,
//如获取setName(String name)方法,getDeclareMethod(“setName”,String.Class)
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
//获取公有的方法,包括父类的
public Method getMethod(String name, Class<?>... parameterTypes)
//获取本类中声明的所有方法
public Method[] getDeclaredMethods()
//获取所有的公有方法,包括父类的
public Method[] getMethods()
  • 获取构造器 Constructor 对象
//获取本类中指定的构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
//获取指定的公有构造方法
public Constructor<T> getConstructor(Class<?>... parameterTypes)
//获取本类中所有的构造方法
public Constructor<?>[] getDeclaredConstructors() throws SecurityException
//获取本类中所有的公有构造方法
public Constructor<?>[] getConstructors()

构造方法的获取与普通方法的获取大致是一样的。

获取类成员信息

上面只是获取了类的成员所代表类的对象,我们还要使用他们或者获取成员的信息(名称、修饰符等)。因为有了代表成员的对象,使用对象调用实例方法就可以了。

Field 类

Field 类的方法大概可以分为两种,一种是获取属性的信息,另外一种是设置属性的值。

  • 第一种
//返回由此 Field对象表示的字段的名称
 String getName()
//返回一个 类对象标识了此表示的字段的声明类型 Field对象。
Class<?> getType()
//返回由该 Field对象表示的字段的Java语言修饰符,作为整数。把整数作为Modifier的构造方法的参数,就可以获取该整数代表的修饰符类的对象了
int getModifiers()
// ----------------------------------------------------------------
//获取类型为 int的静态或实例字段的值,或通过扩展转换转换为类型 int的另一个原始类型的值。
int getInt(Object obj)
//获取类型为 long的静态或实例字段的值,或通过扩大转换获得可转换为类型 long的另一个基本类型的值。
long getLong(Object obj)

......此处省略一堆 get**(Object obj)的方法,属性是什么基本类型,就 get 什么就行了

14 属性是引用类型,那么就调用以下方法 //返回该所表示的字段的 Field ,指定的对象上。 16 Object get(Object obj)

  • 第二种
//设置作为一个字段的值 double指定的对象上。
void setDouble(Object obj, double d)
//设置作为一个字段的值 float指定的对象上。
void setFloat(Object obj, float f)
//设置作为一个字段的值 int指定的对象上。
void setInt(Object obj, int i)

........此处省略一堆 set\*\*()方法,属性是什么基本类型就 set 什么就行了

  • 属性是引用类型,那么就调用以下方法
//将指定对象参数上的此 Field对象表示的字段设置为指定的新值。
void set(Object obj, Object value)

注意啦:如果没有访问权限的话,默认是不能设置属性值的,那怎么办呢?

这时我们调用 Class 对象的setAccessible(true)方法就可以了!

Method 类

Method 类的方法主要是获取方法的信息

部分方法:

int getModifiers() //返回由该对象表示的可执行文件的Java语言modifiers 。
String getName() //返回由此 方法对象表示的方法的名称,作为 String 。
Annotation[][] getParameterAnnotations() //返回一个 Annotation s的数组数组,表示由该对象表示的Executable的形式参数的声明顺序的 Executable 。
int getParameterCount() //返回由此对象表示的可执行文件的形式参数(无论是显式声明还是隐式声明)的数量。
Class<?>[] getParameterTypes() //返回一个 类对象的数组, 类以声明顺序表示由该对象表示的可执行文件的形式参数类型。

Constructor 类

Constructor 类的方法主要是获取构方法的信息和创建对象

获取方法信息:

int getModifiers() //返回由该对象表示的可执行文件的Java语言modifiers 。
String getName() //以字符串形式返回此构造函数的名称。
Annotation[][] getParameterAnnotations() //返回的数组的数组 Annotation表示的形参进行注释s时,声明顺序的的 Executable该对象表示。
int getParameterCount() //返回由此对象表示的可执行文件的形式参数(无论是显式声明还是隐式声明)的数量。
Class<?>[] getParameterTypes() //返回一个 类对象的数组, 类以声明顺序表示由该对象表示的可执行文件的形式参数类型。

反射创建对象和调用方法

创建普通类的对象

创建普通类的对象可以分为两种方法

  • 第一种:调用 Class 对象的方法
//首先获取Class对象
Class clazz=Class.forClass("test.Student");
//创建对象
Student stu=(Student)clazz.newInstance();

注:此方法只能创建无参构造函数的类的对象

  • 第二种:通过 Constructor 的 newInstance()方法
//首先创建Class对象
Class clazz=Class.forClass("test.Student");
//获取想调用的构造函数
Constructor constructor=clazz.getConstructor(String.class, int.class);
//调用Constructor的newInstance()方法
Student stu=(Student)constructor.newInstance("大王",20);

创建数组

数组本质上是一个 Class,而在 Class 中存在一个方法用来识别它是否为一个数组。
反射创建数组是通过 Array.newInstance(T.class,维数)这个方法。
第一个参数指定的是数组内的元素类型,后面的是可变参数,表示的是相应维度的数组长度限制。

比如,我要创建一个 int[2][3] 的数组。

Int[][] a=Array.newInstance(Integer.TYPE, 2, 3);

调用方法

用了上面的方法,就有 Class 对象,有方法 Method 对象,有实例,现在已经万事俱备,只欠东风了。
那我们怎么调用方法呢?在 Method 类有这么一个方法Object invoke(Object obj,Object... args),object 为实例对象,args 为调用方法的参数

来个栗子:

Class<?> c = Class.forName("com.kal01.reflect05.Person");//获取Class对象
Person p1 = (Person) c.newInstance();//获取实例
Method m3 = c.getDeclaredMethod("test");//获取方法
m3.setAccessible(true);//当没有访问权限时,设置一下就可以
m3.invoke(p1);//调用方法
m3.setAccessible(false);//修改了访问权限,记得修改回来

反射工具类

back

/**
 * Copyright (c) 2005-2012 springside.org.cn
 */
package com.faith.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import java.lang.reflect.*;

/**
 * 反射工具类.
 * 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
 * @author calvin
 * @version 2013-01-15
 */
@SuppressWarnings("rawtypes")
public class Reflections {
   private static final String SETTER_PREFIX = "set";

   private static final String GETTER_PREFIX = "get";

   private static final String CGLIB_CLASS_SEPARATOR = "$$";
   private static Logger logger = LoggerFactory.getLogger(Reflections.class);

   /**
    * 调用Getter方法.
    * 支持多级,如:对象名.对象名.方法
    */
   public static Object invokeGetter(Object obj, String propertyName) {
      Object object = obj;
      for (String name : StringUtils.split(propertyName, ".")){
         String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
         object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
      }
      return object;
   }

   /**
    * 调用Setter方法, 仅匹配方法名。
    * 支持多级,如:对象名.对象名.方法
    */
   public static void invokeSetter(Object obj, String propertyName, Object value) {
      Object object = obj;
      String[] names = StringUtils.split(propertyName, ".");
      for (int i=0; i<names.length; i++){
         if(i<names.length-1){
            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
            object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
         }else{
            String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
            invokeMethodByName(object, setterMethodName, new Object[] { value });
         }
      }
   }

   /**
    * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
    */
   public static Object getFieldValue(final Object obj, final String fieldName) {
      Field field = getAccessibleField(obj, fieldName);

      if (field == null) {
         throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
      }

      Object result = null;
      try {
         result = field.get(obj);
      } catch (IllegalAccessException e) {
         logger.error("不可能抛出的异常{}", e.getMessage());
      }
      return result;
   }

   /**
    * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
    */
   public static void setFieldValue(final Object obj, final String fieldName, final Object value) {
      Field field = getAccessibleField(obj, fieldName);

      if (field == null) {
         throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
      }

      try {
         field.set(obj, value);
      } catch (IllegalAccessException e) {
         logger.error("不可能抛出的异常:{}", e.getMessage());
      }
   }

   /**
    * 直接调用对象方法, 无视private/protected修饰符.
    * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
    * 同时匹配方法名+参数类型,
    */
   public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
         final Object[] args) {
      Method method = getAccessibleMethod(obj, methodName, parameterTypes);
      if (method == null) {
         throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
      }

      try {
         return method.invoke(obj, args);
      } catch (Exception e) {
         throw convertReflectionExceptionToUnchecked(e);
      }
   }

   /**
    * 直接调用对象方法, 无视private/protected修饰符,
    * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
    * 只匹配函数名,如果有多个同名函数调用第一个。
    */
   public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
      Method method = getAccessibleMethodByName(obj, methodName);
      if (method == null) {
         throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
      }

      try {
         return method.invoke(obj, args);
      } catch (Exception e) {
         throw convertReflectionExceptionToUnchecked(e);
      }
   }

   /**
    * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
    *
    * 如向上转型到Object仍无法找到, 返回null.
    */
   public static Field getAccessibleField(final Object obj, final String fieldName) {
      Validate.notNull(obj, "object can't be null");
      Validate.notBlank(fieldName, "fieldName can't be blank");
      for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
         try {
            Field field = superClass.getDeclaredField(fieldName);
            makeAccessible(field);
            return field;
         } catch (NoSuchFieldException e) {//NOSONAR
            // Field不在当前类定义,继续向上转型
            continue;// new add
         }
      }
      return null;
   }

   /**
    * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
    * 如向上转型到Object仍无法找到, 返回null.
    * 匹配函数名+参数类型。
    *
    * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
    */
   public static Method getAccessibleMethod(final Object obj, final String methodName,
         final Class<?>... parameterTypes) {
      Validate.notNull(obj, "object can't be null");
      Validate.notBlank(methodName, "methodName can't be blank");

      for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
         try {
            Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
            makeAccessible(method);
            return method;
         } catch (NoSuchMethodException e) {
            // Method不在当前类定义,继续向上转型
            continue;// new add
         }
      }
      return null;
   }

   /**
    * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
    * 如向上转型到Object仍无法找到, 返回null.
    * 只匹配函数名。
    *
    * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
    */
   public static Method getAccessibleMethodByName(final Object obj, final String methodName) {
      Validate.notNull(obj, "object can't be null");
      Validate.notBlank(methodName, "methodName can't be blank");

      for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
         Method[] methods = searchType.getDeclaredMethods();
         for (Method method : methods) {
            if (method.getName().equals(methodName)) {
               makeAccessible(method);
               return method;
            }
         }
      }
      return null;
   }

   /**
    * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
    */
   public static void makeAccessible(Method method) {
      if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
            && !method.isAccessible()) {
         method.setAccessible(true);
      }
   }

   /**
    * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
    */
   public static void makeAccessible(Field field) {
      if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
            .isFinal(field.getModifiers())) && !field.isAccessible()) {
         field.setAccessible(true);
      }
   }

   /**
    * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
    * 如无法找到, 返回Object.class.
    * eg.
    * public UserDao extends HibernateDao<User>
    *
    * @param clazz The class to introspect
    * @return the first generic declaration, or Object.class if cannot be determined
    */
   @SuppressWarnings("unchecked")
   public static <T> Class<T> getClassGenricType(final Class clazz) {
      return getClassGenricType(clazz, 0);
   }

   /**
    * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
    * 如无法找到, 返回Object.class.
    *
    * 如public UserDao extends HibernateDao<User,Long>
    *
    * @param clazz clazz The class to introspect
    * @param index the Index of the generic ddeclaration,start from 0.
    * @return the index generic declaration, or Object.class if cannot be determined
    */
   public static Class getClassGenricType(final Class clazz, final int index) {

      Type genType = clazz.getGenericSuperclass();

      if (!(genType instanceof ParameterizedType)) {
         logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
         return Object.class;
      }

      Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

      if (index >= params.length || index < 0) {
         logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
               + params.length);
         return Object.class;
      }
      if (!(params[index] instanceof Class)) {
         logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
         return Object.class;
      }

      return (Class) params[index];
   }

   public static Class<?> getUserClass(Object instance) {
      Assert.notNull(instance, "Instance must not be null");
      Class clazz = instance.getClass();
      if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
         Class<?> superClass = clazz.getSuperclass();
         if (superClass != null && !Object.class.equals(superClass)) {
            return superClass;
         }
      }
      return clazz;

   }

   /**
    * 将反射时的checked exception转换为unchecked exception.
    */
   public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
      if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
            || e instanceof NoSuchMethodException) {
         return new IllegalArgumentException(e);
      } else if (e instanceof InvocationTargetException) {
         return new RuntimeException(((InvocationTargetException) e).getTargetException());
      } else if (e instanceof RuntimeException) {
         return (RuntimeException) e;
      }
      return new RuntimeException("Unexpected Checked Exception.", e);
   }
}

断言

返回顶部

org.springframework.util.Assert

public static void state(boolean expression, String message) {
    if (!expression) {
        throw new IllegalStateException(message);
    }
}

public static void state(boolean expression, Supplier<String> messageSupplier) {
    if (!expression) {
        throw new IllegalStateException(nullSafeGet(messageSupplier));
    }
}

@Nullable
private static String nullSafeGet(@Nullable Supplier<String> messageSupplier) {
    return (messageSupplier != null ? messageSupplier.get() : null);
}

public static void isTrue(boolean expression, Supplier<String> messageSupplier) {
    if (!expression) {
        throw new IllegalArgumentException(nullSafeGet(messageSupplier));
    }
}

public static void isNull(@Nullable Object object, Supplier<String> messageSupplier) {
    if (object != null) {
        throw new IllegalArgumentException(nullSafeGet(messageSupplier));
    }
}

public static void notNull(@Nullable Object object, Supplier<String> messageSupplier) {
    if (object == null) {
        throw new IllegalArgumentException(nullSafeGet(messageSupplier));
    }
}