1:List转数组
1.1:工具类
org.springframework.util.StringUtils
。
1.2:使用实例
private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
...
String[] candidates = StringUtils.toStringArray(configurations);
}
2:加载META-INF/spring.factories
数据
SpringFactoriesLoader.loadFactoryNames({class 全限定名}, {类加载器});
,如:
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
3:List去重
protected final <T> List<T> removeDuplicates(List<T> list) {
return new ArrayList<>(new LinkedHashSet<>(list));
}
4:获取classpath是否存在某类
4.1:工具类
org.springframework.util.ClassUtils
。
4.2:使用实例
ClassUtils.isPresent("org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration", getClass().getClassLoader())
5:逗号分割字符串转换为数组
5.1:工具类
org.springframework.util.StringUtils
。
5.2:使用实例
// javax.servlet.Servlet,org.springframework.web.servlet.config.annotation.WebMvcConfigurer,org.springframework.web.servlet.DispatcherServlet
for (String candidate : StringUtils.commaDelimitedListToStringArray(candidates)) {
ConditionOutcome outcome = getOutcome(candidate, this.beanClassLoader);
if (outcome != null) {
return outcome;
}
}
6:获取当前使用的类加载器
6.1:工具类
org.springframework.util.ClassUtils
。
6.2:使用实例
public static boolean isPresent(String className, ClassLoader classLoader) {
if (classLoader == null) {
classLoader = ClassUtils.getDefaultClassLoader();
}
try {
forName(className, classLoader);
return true;
}
catch (Throwable ex) {
return false;
}
}
7:数组转换为逗号分割字符串
7.1:工具类
org.springframework.util.StringUtils#arrayToDelimitedString
。
7.2:使用实例
public Builder andCondition(String condition, Object... details) {
Assert.notNull(condition, "Condition must not be null");
String detail = StringUtils.arrayToDelimitedString(details, " ");
if (StringUtils.hasLength(detail)) {
return new Builder(condition + " " + detail);
}
return new Builder(condition);
}
8:数组拷贝
8.1:工具类
java.lang.System#arraycopy
。
8.2:使用实例
ConditionOutcome[] secondHalf = secondHalfResolver.resolveOutcomes();
ConditionOutcome[] firstHalf = firstHalfResolver.resolveOutcomes();
ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
System.arraycopy(firstHalf, 0, outcomes, 0, firstHalf.length);
System.arraycopy(secondHalf, 0, outcomes, split, secondHalf.length);
附源码:
/*
src:源数组
srcPos:源数组拷贝的开始位置
dest:目标数组
destPos:拷贝到目标数组的开始位置
length:拷贝源数组的元素的个数
*/
public static native void arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length);
9:根据class创建对象
9.1:工具类
org.springframework.beans.BeanUtils#instantiateClass(java.lang.Class<T>)
。
9.2:使用实例
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
10:URL转URI
10.1:工具类
org.springframework.util.ResourceUtils
。
10.2:使用实例
org.springframework.core.io.AbstractResource#getURI
@Override
publicURI getURI() throws IOException {
URL url = getURL();
try {
return ResourceUtils.toURI(url);
}
catch (URISyntaxException ex) {
throw new NestedIOException("Invalid URI [" + url + "]", ex);
}
}
11:处理路径为标准格式
11.1:作用说明
处理相对路径..
,.
等信息,如下去除..
:
处理斜杠:
11.2:工具类
org.springframework.util.StringUtils#cleanPath
。
11.3:使用实例
org.springframework.core.io.FileSystemResource#FileSystemResource(java.lang.String)
public FileSystemResource(String path) {
Assert.notNull(path, "Path must not be null");
this.path = StringUtils.cleanPath(path);
this.file = new File(path);
this.filePath = this.file.toPath();
}
12:通过file:
协议文件URL获取File对象
12.1:工具类
org.springframework.util.ResourceUtils#getFile(java.net.URL, java.lang.String)
。
12.2:使用实例
org.springframework.core.io.AbstractFileResolvingResource#getFile()
@Override
public File getFile() throws IOException {
URL url = getURL();
if (url.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
return VfsResourceDelegate.getResource(url).getFile();
}
return ResourceUtils.getFile(url, getDescription());
}
13:判断路径是否包含通配符
13.1:工具类
org.springframework.util.AntPathMatcher#isPattern
。
13.1:使用实例
new AntPathMatcher().isPattern("yudaosourcecode/spring/*.class")
14:加载.properties文件
14.1:工具类
org.springframework.core.io.support.PropertiesLoaderUtils
。
14.2:使用实例
// META-INF/spring.schemas
Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation, this.classLoader);
schemaMappings = new ConcurrentHashMap<>(mappings.size());
// 合并properties内容到map中
CollectionUtils.mergePropertiesIntoMap(mappings, schemaMappings);
this.schemaMappings = schemaMappings;
15:合并.properties到map中
15.1:工具类
org.springframework.util.CollectionUtils
。
15.2:使用实例
// META-INF/spring.schemas
Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation, this.classLoader);
schemaMappings = new ConcurrentHashMap<>(mappings.size());
// 合并properties内容到map中
CollectionUtils.mergePropertiesIntoMap(mappings, schemaMappings);
16:从一个集合查找在另一个集合中存在的第一个元素
16.1:工具类
org.springframework.util.CollectionUtils#findFirstMatch
。
16.2:使用实例
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#checkNameUniqueness
protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {
String foundName = null;
if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) {
foundName = beanName;
}
if (foundName == null) {
foundName = CollectionUtils.findFirstMatch(this.usedNames, aliases);
}
if (foundName != null) {
error("Bean name '" + foundName + "' is already used in this <beans> element", beanElement);
}
this.usedNames.add(beanName);
this.usedNames.addAll(aliases);
}
17:获取某class的Method对象
17.1:工具类
org.springframework.beans.BeanUtils
,org.springframework.util.ClassUtils
。
17.2:使用实例
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeCustomInitMethod
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
String initMethodName = mbd.getInitMethodName();
Assert.state(initMethodName != null, "No init method set");
Method initMethod = (mbd.isNonPublicAccessAllowed() ?
BeanUtils.findMethod(bean.getClass(), initMethodName) :
ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
...snip...
}
18:去除集合中所有元素的空格
18.1:工具类
org.springframework.util.StringUtils
。
18.2:使用实例
org.springframework.core.env.AbstractEnvironment#doGetActiveProfiles
protected Set<String> doGetActiveProfiles() {
synchronized (this.activeProfiles) {
// 为空
if (this.activeProfiles.isEmpty()) {
// 从属性源中获取属性名称为ACTIVE_PROFILES_PROPERTY_NAME
// 的激活profiles(,分割)
String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
// 如果是在属性源中设置了
if (StringUtils.hasText(profiles)) {
// 去除空格,并转换为数组,设置到激活的profiles中
// 这里的代码说明,我们只需要设置到环境中如"-Dspring.profiles.active=aa,bb"
// 这里就会自动set了
setActiveProfiles(StringUtils.commaDelimitedListToStringArray(
StringUtils.trimAllWhitespace(profiles)));
}
}
return this.activeProfiles;
}
}
19:将类转换为类名+内存地址字符串
19.1:工具类
org.springframework.util.ObjectUtils
。
19.2:使用实例
private String id = ObjectUtils.identityToString(this);
20:获取类所在的完整包名
20.1:工具类
org.springframework.util.ClassUtils
。
20.2:源码
org.springframework.util.ClassUtils#getPackageName(java.lang.String)
// 通过给定的全限定类名称获取包名,比如全限定类名称是"java.lang.String",则包名就是"java.lang",
// 如果是默认包的话,则返回空字符串
public static String getPackageName(String fqClassName) {
Assert.notNull(fqClassName, "Class name must not be null");
int lastDotIndex = fqClassName.lastIndexOf(PACKAGE_SEPARATOR);
return (lastDotIndex != -1 ? fqClassName.substring(0, lastDotIndex) : "");
}
21:转换json字符串为map
21.1:工具类
org.springframework.boot.json.JsonParser
。
21.2:源码
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor#processJson
private void processJson(ConfigurableEnvironment environment, JsonPropertyValue propertyValue) {
JsonParser parser = JsonParserFactory.getJsonParser();
Map<String, Object> map = parser.parseMap(propertyValue.getJson());
if (!map.isEmpty()) {
addJsonPropertySource(environment, new JsonPropertySource(propertyValue, flatten(map)));
}
}
22:获取文件扩展名
22.1:工具类
org.springframework.util.StringUtils#getFilenameExtension
。
22.2:实例
org.springframework.boot.logging.AbstractLoggingSystem#getSpringConfigLocations
protected String[] getSpringConfigLocations() {
String[] locations = getStandardConfigLocations();
for (int i = 0; i < locations.length; i++) {
String extension = StringUtils.getFilenameExtension(locations[i]);
locations[i] = locations[i].substring(0, locations[i].length() - extension.length() - 1) + "-spring."
+ extension;
}
return locations;
}
23:通过class获取指定类型的注解对象
23.1:工具类
org.springframework.core.annotation.AnnotationUtils#findAnnotation(java.lang.Class<?>, java.lang.Class<A>)
。
23.2:实例
org.springframework.boot.context.properties.EnableConfigurationPropertiesImportSelector.ConfigurationPropertiesBeanRegistrar#getName
private String getName(Class<?> type) {
ConfigurationProperties annotation = AnnotationUtils.findAnnotation(type, ConfigurationProperties.class);
String prefix = (annotation != null) ? annotation.prefix() : "";
return (StringUtils.hasText(prefix) ? prefix + "-" + type.getName() : type.getName());
}
24:StringTokenizer
24.1:作用和源码
作用是按照指定的分隔符对字符串进行分割,并提供API返回分割后的每个元素。
主要源码如下:
java.util.StringTokenizer
public class StringTokenizer implements Enumeration<Object> {
public StringTokenizer(String str) {
this(str, " \t\n\r\f", false);
}
public StringTokenizer(String str, String delim) {
this(str, delim, false);
}
// str:要分割的字符串
// delim:可能的分割字符,可指定多个,连着写即可
// returnDelim:是否需要返回分割符
public StringTokenizer(String str, String delim, boolean returnDelims) {
currentPosition = 0;
newPosition = -1;
delimsChanged = false;
this.str = str;
maxPosition = str.length();
delimiters = delim;
retDelims = returnDelims;
setMaxDelimCodePoint();
}
// 是否还有下一个元素
public boolean hasMoreTokens() {
newPosition = skipDelimiters(currentPosition);
return (newPosition < maxPosition);
}
}
// 返回下一个元素
public String nextToken() {
currentPosition = (newPosition >= 0 && !delimsChanged) ?
newPosition : skipDelimiters(currentPosition);
delimsChanged = false;
newPosition = -1;
if (currentPosition >= maxPosition)
throw new NoSuchElementException();
int start = currentPosition;
currentPosition = scanToken(currentPosition);
return str.substring(start, currentPosition);
}
24.2:实例
如有字符串{name=jack, age=90}
,要解析出姓名和年龄,代码如下:
public static void main(String[] args) throws Exception {
Stringmystr = "{name=jack, age=90}";
// 使用{ } = ,作为分隔符进行分割,并且不返回分割符,当然如果有特殊需求也可以选择返回
StringTokenizer stringTokenizer = new StringTokenizer(mystr, "{}=, ", false);
while (stringTokenizer.hasMoreTokens()) {
String key = stringTokenizer.nextToken();
String value = stringTokenizer.nextToken();
System.out.println("key: " + key);
System.out.println("value: " + value);
}
}
运行:
key: name
value: jack
key: age
value: 90
Process finished with exit code 0
简单修改程序,看下返回分割符的情况,修改代码如下:
public static void main(String[] args) throws Exception {
String mystr = "{name=jack, age=90}";
// 使用{ } = ,作为分隔符进行分割,并且不返回分割符,当然如果有特殊需求也可以选择返回
StringTokenizer stringTokenizer = new StringTokenizer(mystr, "{}=, ", true);
while (stringTokenizer.hasMoreTokens()) {
// 注意:前后拼接-的原因是看出空格的效果
System.out.println("-" + stringTokenizer.nextToken() + "-");
}
}
输出:
-{-
-name-
-=-
-jack-
-,-
- -
-age-
-=-
-90-
-}-
Process finished with exit code 0
25:判断方法是否为getter,setter,废弃
相关代码复制自org.apache.dubbo.common.utils.MethodUtils
。
public static boolean isSetter(Method method) {
return method.getName().startsWith("set")
&& !"set".equals(method.getName())
&& Modifier.isPublic(method.getModifiers())
&& method.getParameterCount() == 1
&& ClassUtils.isPrimitive(method.getParameterTypes()[0]);
}
public static boolean isGetter(Method method) {
String name = method.getName();
return (name.startsWith("get") || name.startsWith("is"))
&& !"get".equals(name) && !"is".equals(name)
&& !"getClass".equals(name) && !"getObject".equals(name)
&& Modifier.isPublic(method.getModifiers())
&& method.getParameterTypes().length == 0
/*&& ClassUtils.isPrimitive(method.getReturnType()*/
method.getReturnType() != null);
}
public static boolean isDeprecated(Method method) {
return method.getAnnotation(Deprecated.class) != null;
}
26:根据getter获取属性名称
相关代码复制自org.apache.dubbo.config.AbstractConfig#calculatePropertyFromGetter
:
private static String calculatePropertyFromGetter(String name) {
// get开头或者是is开头
int i = name.startsWith("get") ? 3 : 2;
return camelToSplitName(name.substring(i, i + 1).toLowerCase() + name.substring(i + 1), ".");
}
public static String camelToSplitName(String camelName, String split) {
if (isEmpty(camelName)) {
return camelName;
}
StringBuilder buf = null;
for (int i = 0; i < camelName.length(); i++) {
char ch = camelName.charAt(i);
if (ch >= 'A' && ch <= 'Z') {
if (buf == null) {
buf = new StringBuilder();
if (i > 0) {
buf.append(camelName, 0, i);
}
}
if (i > 0) {
buf.append(split);
}
buf.append(Character.toLowerCase(ch));
} else if (buf != null) {
buf.append(ch);
}
}
return buf == null ? camelName : buf.toString();
}
入参和返回值实例isOk->ok
,getName->name
。
27:根据类名称获取Class对象
相关代码复制自com.alibaba.dubbo.common.utils.ClassHelper
。
27.1:代码
public class ClassHelper {
private static final Map<String, Class<?>> primitiveTypeNameMap = new HashMap<String, Class<?>>(16);
private static final Map<Class<?>, Class<?>> primitiveWrapperTypeMap = new HashMap<Class<?>, Class<?>>(8);
static {
primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
primitiveWrapperTypeMap.put(Byte.class, byte.class);
primitiveWrapperTypeMap.put(Character.class, char.class);
primitiveWrapperTypeMap.put(Double.class, double.class);
primitiveWrapperTypeMap.put(Float.class, float.class);
primitiveWrapperTypeMap.put(Integer.class, int.class);
primitiveWrapperTypeMap.put(Long.class, long.class);
primitiveWrapperTypeMap.put(Short.class, short.class);
Set<Class<?>> primitiveTypeNames = new HashSet<Class<?>>(16);
primitiveTypeNames.addAll(primitiveWrapperTypeMap.values());
primitiveTypeNames.addAll(Arrays
.asList(new Class<?>[]{boolean[].class, byte[].class, char[].class, double[].class,
float[].class, int[].class, long[].class, short[].class}));
for (Iterator<Class<?>> it = primitiveTypeNames.iterator(); it.hasNext(); ) {
Class<?> primitiveClass = (Class<?>) it.next();
primitiveTypeNameMap.put(primitiveClass.getName(), primitiveClass);
}
}
public static Class<?> forNameWithThreadContextClassLoader(String name)
throws ClassNotFoundException {
return forName(name, Thread.currentThread().getContextClassLoader());
}
/**
* Suffix for array class names: "[]"
*/
public static final String ARRAY_SUFFIX = "[]";
/**
* Prefix for internal array class names: "[L"
*/
private static final String INTERNAL_ARRAY_PREFIX = "[L";
public static Class<?> forName(String name, ClassLoader classLoader)
throws ClassNotFoundException, LinkageError {
Class<?> clazz = resolvePrimitiveClassName(name);
if (clazz != null) {
return clazz;
}
// "java.lang.String[]" style arrays
if (name.endsWith(ARRAY_SUFFIX)) {
String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length());
Class<?> elementClass = forName(elementClassName, classLoader);
return Array.newInstance(elementClass, 0).getClass();
}
// "[Ljava.lang.String;" style arrays
int internalArrayMarker = name.indexOf(INTERNAL_ARRAY_PREFIX);
if (internalArrayMarker != -1 && name.endsWith(";")) {
String elementClassName = null;
if (internalArrayMarker == 0) {
elementClassName = name
.substring(INTERNAL_ARRAY_PREFIX.length(), name.length() - 1);
} else if (name.startsWith("[")) {
elementClassName = name.substring(1);
}
Class<?> elementClass = forName(elementClassName, classLoader);
return Array.newInstance(elementClass, 0).getClass();
}
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = getClassLoader();
}
return classLoaderToUse.loadClass(name);
}
public static Class<?> resolvePrimitiveClassName(String name) {
Class<?> result = null;
// Most class names will be quite long, considering that they
// SHOULD sit in a package, so a length check is worthwhile.
if (name != null && name.length() <= 8) {
// Could be a primitive - likely.
result = (Class<?>) primitiveTypeNameMap.get(name);
}
return result;
}
public static ClassLoader getClassLoader() {
return getClassLoader();
}
}
27.2:测试
public static void main(String[] args) throws Exception {
System.out.println(ClassHelper.forNameWithThreadContextClassLoader("java.lang.String"));
System.out.println(ClassHelper.forNameWithThreadContextClassLoader("java.util.HashMap"));
System.out.println(ClassHelper.forNameWithThreadContextClassLoader("java.lang.String[]"));
System.out.println(ClassHelper.forNameWithThreadContextClassLoader("[Ljava.lang.String;"));
System.out.println(ClassHelper.forNameWithThreadContextClassLoader("java.util.Collection"));
}
运行:
class java.lang.String
class java.util.HashMap
class [Ljava.lang.String;
class [Ljava.lang.String;
interface java.util.Collection
Process finished with exit code 0
28:从classpath下获取properties文件
相关代码复制自com.alibaba.dubbo.common.utils.ConfigUtils#loadProperties(java.lang.String, boolean, boolean)
。
28.1:代码
public class ConfigUtils {
private static Logger logger = LoggerFactory.getLogger(ConfigUtils.class);
public static Properties loadProperties(String fileName, boolean allowMultiFile, boolean optional) {
Properties properties = new Properties();
if (checkFileNameExist(fileName)) {
try {
FileInputStream input = new FileInputStream(fileName);
try {
properties.load(input);
} finally {
input.close();
}
} catch (Throwable e) {
logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e);
}
return properties;
}
List<URL> list = new ArrayList<URL>();
try {
// Enumeration<URL> urls = com.alibaba.dubbo.common.utils.ClassHelper.getClassLoader().getResources(fileName);
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(fileName);
list = new ArrayList<java.net.URL>();
while (urls.hasMoreElements()) {
list.add(urls.nextElement());
}
} catch (Throwable t) {
logger.warn("Fail to load " + fileName + " file: " + t.getMessage(), t);
}
if (list.isEmpty()) {
if (!optional) {
logger.warn("No " + fileName + " found on the class path.");
}
return properties;
}
if (!allowMultiFile) {
if (list.size() > 1) {
String errMsg = String.format("only 1 %s file is expected, but %d dubbo.properties files found on class path: %s",
fileName, list.size(), list.toString());
logger.warn(errMsg);
// throw new IllegalStateException(errMsg); // see http://code.alibabatech.com/jira/browse/DUBBO-133
}
// fall back to use method getResourceAsStream
try {
// properties.load(ClassHelper.getClassLoader().getResourceAsStream(fileName));
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));
} catch (Throwable e) {
logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e);
}
return properties;
}
return properties;
}
/**
* check if the fileName can be found in filesystem
* @param fileName
* @return
*/
private static boolean checkFileNameExist(String fileName) {
File file = new File(fileName);
return file != null && file.exists() ? true : false;
}
}
28.2:测试
public static void main(String[] args) throws Exception {
Properties properties = ConfigUtils.loadProperties("myproperties/a.properties", false, true);
System.out.println(properties);
Properties properties1
= ConfigUtils.loadProperties("E:\\workspace-idea\\java-life\\src\\main\\resources\\myproperties\\a.properties",
false,
true);
System.out.println(properties1);
}
输出:
{aKey=aVal}
{aKey=aVal}
Process finished with exit code 0
29:判断某个类是否有指定参数的构造函数
相关代码复制自com.alibaba.dubbo.common.utils.ReflectUtils
。
public static Constructor<?> findConstructor(Class<?> clazz, Class<?> paramType) throws NoSuchMethodException {
Constructor<?> targetConstructor;
try {
targetConstructor = clazz.getConstructor(new Class<?>[]{paramType});
} catch (NoSuchMethodException e) {
targetConstructor = null;
Constructor<?>[] constructors = clazz.getConstructors();
for (Constructor<?> constructor : constructors) {
if (Modifier.isPublic(constructor.getModifiers())
&& constructor.getParameterTypes().length == 1
&& constructor.getParameterTypes()[0].isAssignableFrom(paramType)) {
targetConstructor = constructor;
break;
}
}
if (targetConstructor == null) {
throw e;
}
}
return targetConstructor;
}
30:获取Java进程号
private static int PID = -1;
public static int getPid() {
if (PID < 0) {
try {
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
String name = runtime.getName(); // format: "pid@hostname"
PID = Integer.parseInt(name.substring(0, name.indexOf('@')));
} catch (Throwable e) {
PID = 0;
}
}
return PID;
}
31:获取IP地址
public static InetAddress fetchLocalAddress() {
InetAddress localAddress = null;
try {
localAddress = InetAddress.getLocalHost();
if (isValidAddress(localAddress)) {
return localAddress;
}
} catch (Throwable e) {
// logger.warn(e);
}
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
if (interfaces != null) {
while (interfaces.hasMoreElements()) {
try {
NetworkInterface network = interfaces.nextElement();
Enumeration<InetAddress> addresses = network.getInetAddresses();
if (addresses != null) {
while (addresses.hasMoreElements()) {
try {
InetAddress address = addresses.nextElement();
if (isValidAddress(address)) {
return address;
}
} catch (Throwable e) {
// logger.warn(e);
}
}
}
} catch (Throwable e) {
// logger.warn(e);
}
}
}
} catch (Throwable e) {
// logger.warn(e);
}
return localAddress;
}
public static final String LOCALHOST = "127.0.0.1";
public static final String ANYHOST = "0.0.0.0";
private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$");
private static boolean isValidAddress(InetAddress address) {
if (address == null || address.isLoopbackAddress())
return false;
String name = address.getHostAddress();
return (name != null
&& !ANYHOST.equals(name)
&& !LOCALHOST.equals(name)
&& IP_PATTERN.matcher(name).matches());
}
32:日期相关
32.1:当前日期加减指定天数
/**
* 当前日期加上指定的天数,并转换为YYYY-MM-dd格式的字符串
* @return
*/
public static String addDayToDateStr(int day) {
Date date = addOrMinusDays(new Date().getTime(), day);
String s = dateToString(date, "yyyy-MM-dd");
return s;
}
// 在一个日期上加或者减去指定天数
public static Date addOrMinusDays(long ti, int i) {
Date rtn = null;
final GregorianCalendar cal = new GregorianCalendar();
final Date date = new Date(ti);
cal.setTime(date);
cal.add(Calendar.DAY_OF_MONTH, i);
rtn = cal.getTime();
return rtn;
}
/**
* 根据时间变量返回时间字符串
*
* @return 返回时间字符串
* @param pattern
* 时间字符串样式
* @param date
* 时间变量
*/
public static String dateToString(Date date, String pattern) {
if (date == null) {
return null;
}
try {
SimpleDateFormat sfDate = new SimpleDateFormat(pattern);
sfDate.setLenient(false);
return sfDate.format(date);
} catch (Exception e) {
return null;
}
}
32.2:获取两个日期间隔的所有日期
/**
* 获取格式为yyyy-MM-dd的两个日期之间,格式都是yyyy-MM-dd,注意结果包括开始时间和结束时间
* @param startTime 开始时间
* @param endTime 结束时间
* @return
*/
public static List<String> queryDayListBetweenDate(String startTime, String endTime) {
List<String> days = new ArrayList<>();
// 返回的日期集合
// if (StringUtil.isEmpty(startTime) || StringUtil.isEmpty(endTime)) {
if (startTime == null || startTime.trim() == "" || endTime == null || endTime.trim() == "") {
return days;
}
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
Date start = dateFormat.parse(startTime);
Date end = dateFormat.parse(endTime);
Calendar tempStart = Calendar.getInstance();
tempStart.setTime(start);
Calendar tempEnd = Calendar.getInstance();
tempEnd.setTime(end);
tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)
while (tempStart.before(tempEnd)) {
days.add(dateFormat.format(tempStart.getTime()));
tempStart.add(Calendar.DAY_OF_YEAR, 1);
}
} catch (ParseException e) {
e.printStackTrace();
}
return days;
}
33:生成二维码
参考这篇文章 。
34:获取包下所有的class
参考 org.apache.ibatis.binding.MapperRegistry#addMappers(java.lang.String, java.lang.Class<?>)
。
35:判断class是否为接口,抽象类,某类子类等
35.1:判断是否为接口
waiClass.isInterface()
35.2:判断是否为抽象类
Modifier.isAbstract(waiClass.getModifiers())
35.3:判断是否为某类子类
WebApplicationInitializer.class.isAssignableFrom(waiClass)
这里就是判断waiClass是否为WebApplicationInitializer子类的class。
36:根据class创建实例对象
org.springframework.util.ReflectionUtils.accessibleConstructor(waiClass).newInstance());
37:获取接口的一组实现类
37.1:jdk SPI
参考SPI的简单介绍 。
37.1:springboot SPI(推荐
)
首先在META-INF/spring.factories
,定义,如下:
然后如下方式获取:
// public void setListeners(Collection<? extends ApplicationListener<?>> listeners)
// org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class<T>)
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
38:获取指定包下的类
源码如下:
// org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClients
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(false, this.environment) {
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
boolean isCandidate = false;
if (beanDefinition.getMetadata().isIndependent()) {
if (!beanDefinition.getMetadata().isAnnotation()) {
isCandidate = true;
}
}
return isCandidate;
}
};
// 这里this.resourceLoader就是applicationcontext,可以很容易的通过ApplicationContextAware获取
scanner.setResourceLoader(this.resourceLoader);
// 按照注解过滤
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
Set<String> basePackages = getBasePackages(metadata);
for (String basePackage : basePackages) {
// 如:
// 0 = {ScannedGenericBeanDefinition@5659} "Generic bean: class [dongshi.daddy.feign.rpc.CalculationService]; "
// 1 = {ScannedGenericBeanDefinition@5728} "Generic bean: class [dongshi.daddy.feign.rpc.TemplateService]; "
candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
}