其他常用类
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 中的反射机制
反射中常见的类
- 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);//修改了访问权限,记得修改回来
反射工具类
/**
* 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));
}
}