一些方法

自定义类加载器

import javassist.ClassPool;

/**
 * @author 99013
 * @ClassName MyClassLoader
 * @Description 自定义类加载器
 * 作者:99013
 * 创建时间:2022年02月17日 15:36:54
 * @Version 1.0
 **/
public class MyClassLoader extends ClassLoader {

    // 类池
    private static ClassPool pool;

    /**
     * 利用子类池覆盖默认类池,从而防止ClassPool中类越来越多的情况
     * @return javassist.ClassPool
     * <br><br><b>作者: 990130556 <a class=b href="https://blog.csdn.net/lingdu_dou">lingdu</a></b><br>
     * 创建时间: 2022年05月24日 14:33:11
     */
    public static ClassPool getClassPool() {
        return new ClassPool(getPool());
    }

    /**
     * 初始默认类池
     * @return javassist.ClassPool
     * <br><br><b>作者: 990130556 <a class=b href="https://blog.csdn.net/lingdu_dou">lingdu</a></b><br>
     * 创建时间: 2022年05月24日 14:35:01
     */
    private static ClassPool getPool() {
        if (pool == null) {
            pool = ClassPool.getDefault();
        }
        return pool;
    }

    public Class<?> defineClass(String name, byte[] b) {
        // ClassLoader是个抽象类,而ClassLoader.defineClass 方法是protected的
        // 所以我们需要定义一个子类将这个方法暴露出来
        return super.defineClass(name, b, 0, b.length);
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        // 根据类的全类名进行加锁操作,也就是保证了线程安全
        synchronized (getClassLoadingLock(name)) {
            Class<?> klass = findLoadedClass(name);
            // 到已经加载的缓存中查看是否已经被加载了如果是则直接返回,如果没有就需要进行加载
            if (klass == null) {
                // 如果缓存中没有,则表示这个类是第一次被加载,对于类进行判断操作
                if (name.startsWith("java.") || name.startsWith("javax.")) {
                    try {
                        klass = getSystemClassLoader().loadClass(name);
                    } catch (Exception e) {
                        throw e;
                    }
                    // 如果不满足要求则表示使用自定义的类加载器进行加载操作。
                } else {
                    try {
                        klass = this.findClass(name);
                    } catch (Exception ignored) {
                    }
                    // 如果自定义加载器没有完成则需要交给父类加载器去进行加载操作
                    if (klass == null) {
                        if (getParent() != null) {
                            klass = getParent().loadClass(name);
                        } else {
                            klass = getSystemClassLoader().loadClass(name);
                        }
                    }
                }
            }
            // 如果加载不成功的话就抛出异常。
            if (null == klass) {
                throw new ClassNotFoundException("The class " + name + " not found.");
            }
            if (resolve) {
                resolveClass(klass);
            }
            return klass;
        }
    }
}

自定义线程池

import java.util.concurrent.*;

/**
 * 自定义线程池
 * 描述:TODO
 * @作者 <b><a class=b href="https://blog.csdn.net/lingdu_dou" color="red">⭕°</a></b>
 * @创建时间 2022-08-26 11:01
 */
public class MyThreadPool {

    public static ExecutorService threadPool;

    static {
        newThreadPool();
    }


    /**
     * 1⚫corePoolSize线程池的核心线程数
     *      线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,
     *      除非设置了allowCoreThreadTimeOut。这里的最小线程数量即是corePoolSize。
     * 2⚫maximumPoolSize能容纳的最大线程数
     *      一个任务被提交到线程池以后,首先会找有没有空闲存活线程,如果有则直接将任务交给这个空闲线程来执行,
     *      如果没有则会缓存到工作队列(后面会介绍)中,如果工作队列满了,才会创建一个新线程,
     *      然后从工作队列的头部取出一个任务交由新线程来处理,而将刚提交的任务放入工作队列尾部。
     *      线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定。
     * 3⚫keepAliveTime空闲线程存活时间
     *      一个线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,
     *      这里的指定时间由keepAliveTime来设定
     * 4⚫unit 空闲线程存活时间单位
     * 5⚫workQueue 存放提交但未执行任务的队列
     *      新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。jdk中提供了四种工作队列:
     *      ArrayBlockingQueue
     *      基于数组的有界阻塞队列,按FIFO排序。新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。
     *      当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。
     *      如果队列已经是满的,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。
     *      LinkedBlockingQuene
     *      基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序。由于该队列的近似无界性,
     *      当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而不会去创建新线程直到maxPoolSize,
     *      因此使用该工作队列时,参数maxPoolSize其实是不起作用的。
     *      SynchronousQuene
     *      一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。也就是说新任务进来时,不会缓存,
     *      而是直接被调度执行该任务,如果没有可用线程,则创建新线程,如果线程数量达到maxPoolSize,则执行拒绝策略。
     *      PriorityBlockingQueue
     *      具有优先级的无界阻塞队列,优先级通过参数Comparator实现。
     * 6⚫threadFactory 创建线程的工厂类
     *      创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等
     * 7⚫handler 等待队列满后的拒绝策略
     *      当工作队列中的任务已到达最大限制,并且线程池中的线程数量也达到最大限制,这时如果有新任务提交进来,
     *      该如何处理呢。这里的拒绝策略,就是解决这个问题的,jdk中提供了4中拒绝策略:
     *      CallerRunsPolicy
     *      该策略下,在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务
     *      AbortPolicy
     *      该策略下,直接丢弃任务,并抛出RejectedExecutionException异常
     *      DiscardPolicy
     *      该策略下,直接丢弃任务,什么都不做
     *      DiscardOldestPolicy
     *      该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列
     */
    private static void newThreadPool() {
        threadPool = new ThreadPoolExecutor(10, 50,
                1L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(50),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());
    }
}

调用

class A {
    public void start() {
        MyThreadPool.threadPool.execute(this::init);
    }

    public void init() {
        // 业务逻辑
    }
}


class B {
    private void addDataSource(SysDatabase d) {
        MyThreadPool.threadPool.execute(() -> addDataSource(d, false));
    }

    public boolean addDataSource(SysDatabase d, boolean test) {
        // 业务逻辑
    }
}



class C {
    private void c(int a, int b) {
        if(a>b){
            MyThreadPool.threadPool.execute(() -> {
                // 存量推送处理
                stockPush(kds);
                // 更新启动线程列表和版本号
                updateDataVersion(RedisDataVersion.KAFKA_CONSUMER_THREAD_NAMES, keySet);
            });
            return;
        }
        if(a<b){
            // ............
        }
    }
}


Java代码中验证IP地址是否可访问【Linux和windows环境下】

说明

我的需求场景是尝试连接数据源,数据库地址有不同网络环境下的地址{生产、内网、局域网等},所以在连接数据源之前判断一下url中的ip是否可访问,然后决定是否执行下一步操作。

  • 提取字符串中的IP

class A {
    /**
     * 提取字符串中的IP集合
     * @param line 目标字符
     * @return 返回所有发现的IP
     * @作者 <b><a class=b href="https://blog.csdn.net/lingdu_dou" color="red">⭕°</a></b>
     * @创建时间 2022-08-30 11:20     */
    public static List<String> extractIp(String line) {
        List<String> ips = new ArrayList<>();
        if (line != null) {
            String regex = "(^|[^\\d])(((2[0-4]\\d|25[0-5]|1\\d\\d|\\d\\d?)\\.){3}(2[0-4]\\d|25\\d|1\\d\\d|\\d\\d?))";
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(line);
            while (m.find()) {
                ips.add(m.group(2));
            }
        }
        return ips;
    }
}

  • 检查是否可访问

class A {
    /**
     * 测试网址是否可访问
     * @param ip ip地址
     * @return 返回true可访问 返回false不可访问
     * @作者 <b><a class=b href="https://blog.csdn.net/lingdu_dou" color="red">⭕°</a></b>
     * @创建时间 2022-08-31 9:05     */
    public static boolean ping(String ip) {
        //获取操作系统类型
        String osName = System.getProperty("os.name");
        log.info("操作系统:" + osName);
        String command = "";
        if (osName.contains("Linux")) {
            command = "ping -c 1 -w 1 " + ip;
        } else if (osName.contains("Windows")) {
            command = "ping -n 1 -w 1000 " + ip;
        } else {
            log.error("未知系统 执行ping命令失败");
            return false;
        }
        try {
            Process p = Runtime.getRuntime().exec(command);
            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream(), "GBK"));
            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
                if (line.contains("来自") || line.contains("1 received")) {
                    log.info(ip + " 连接成功");
                    return true;
                }
                if (line.contains("请求超时") || line.contains("0 received")) {
                    log.info(ip + " 连接失败");
                    return false;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
}

java模拟HTTP请求工具


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

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;

/**
 * java模拟HTTP请求工具
 *
 * @author 99013
 * @ClassName HttpRequestUtil
 * @Description TODO
 * 作者:99013
 * 创建时间:2020年12月03日 14:07:35
 * @Version 2.0
 **/
public class HttpRequestUtil {
    private static final Logger log = LoggerFactory.getLogger(HttpRequestUtil.class);
    /**
     * POST请求
     */
    public static final String POST = "POST";
    /**
     * PUT请求
     */
    public static final String PUT = "PUT";
    /**
     * GET请求
     */
    public static final String GET = "GET";
    /**
     * DELETE请求
     */
    public static final String DELETE = "DELETE";
    /**
     * utf-8
     */
    public static final String CHARSET_UTF8 = "UTF-8";
    /**
     * 请求内容类型
     */
    public static final String CONTENT_TYPE = "Content-type";
    /**
     * 请求通用格式
     */
    public static final String CONTENT_TYPE_JSON = "application/json";
    /**
     * multipart/form-data类型
     */
    public static final String CONTENT_TYPE_FORMDATA = "multipart/form-data";

    public static String CONTENT_TYPE_WAY;
    /**
     * text/plain类型
     */
    public static final String CONTENT_TYPE_TEXT_PLAIN = "text/plain";
    /**
     * image/jpeg类型
     */
    public static final String MIME_TYPE_IMAGE_JPEG = "image/jpeg";
    /**
     * 边界
     */
    private static final String BOUNDARY = "----WebKitFormBoundary07I8UIuBx6LN2KyY";


    /**
     * Get请求
     *
     * @param url       请求路径
     * @param params    请求参数
     * @param cookie    Cookie
     * @param headerMap 请求头补充参数
     * @return java.lang.String
     * <br><br><b>作者: 990130556 <a class=b href="https://blog.csdn.net/lingdu_dou">lingdu</a></b><br>
     * 创建时间: 2021年08月26日 18:46:43
     */
    public static String sendGet(String url, Map<String, Object> params, String cookie, Map<String, Object> headerMap) {
        return send(GET, url, params, null, cookie, headerMap, null, null);
    }

    /**
     * Delete请求
     *
     * @param url       请求路径
     * @param params    请求参数
     * @param cookie    cookie
     * @param headerMap 请求头补充参数
     * @return java.lang.String
     * <br><br><b>作者: 990130556 <a class=b href="https://blog.csdn.net/lingdu_dou">lingdu</a></b><br>
     * 创建时间: 2021年08月26日 18:48:02
     */
    public static String sendDelete(String url, Map<String, Object> params, String cookie, Map<String, Object> headerMap) {
        return send(DELETE, url, params, null, cookie, headerMap, null, null);
    }

    /**
     * Post请求
     *
     * @param url    第三方接口地址
     * @param params 请求参数
     * @param pjson json方式传参
     * @param cookie cookie
     * @param headerMap 请求头补充参数
     * @return java.lang.String 返回信息
     * <br><br><b>作者: 990130556 <a class=b href="https://blog.csdn.net/lingdu_dou">lingdu</a></b><br>
     * 创建时间: 2020年12月03日 17:45:21
     */
    public static String sendPost(String url, Map<String, Object> params, String pjson, String cookie, Map<String, Object> headerMap) {
        return sendPostUplodFile(url, params, pjson, cookie, headerMap, null, null);
    }

    /**
     * 模拟http请求上传文件及相关参数
     *
     * @param url      第三方上传文件地址
     * @param fileName 文件名
     * @param params   请求参数
     * @param bytes    文件字节码
     * @param cookie   Cookie
     * @return java.lang.String
     */
    public static String sendPostUplodFile(String url, Map<String, Object> params, String pjson, String cookie, Map<String, Object> headerMap, String fileName, byte[] bytes) {
        return send(POST, url, params, pjson, cookie, headerMap, fileName, bytes);
    }

    /**
     * put请求方式
     *
     * @param url    请求路径
     * @param params 请求参数
     * @param cookie cookie
     * @return java.lang.String
     * 创建时间: 2021年03月07日 09:16:34
     */
    public static String sendPut(String url, Map<String, Object> params, String pjson, String cookie, Map<String, Object> headerMap) {
        return send(PUT, url, params, pjson, cookie, headerMap, null, null);
    }

    /**
     * put请求方式 上传文件
     *
     * @param url      请求路径
     * @param fileName 文件名
     * @param params   请求参数
     * @param pjson        json传参数
     * @param bytes    文件字节码
     * @param cookie   cookie
     * @return java.lang.String
     * 创建时间: 2021年03月07日 09:16:34
     */
    public static String sendPutUplodFile(String url, Map<String, Object> params, String pjson, String cookie, Map<String, Object> headerMap, String fileName, byte[] bytes) {
        return send(PUT, url, params, pjson, cookie, headerMap, fileName, bytes);
    }


    /**
     * 执行请求
     *
     * @param type      请求类型
     * @param url       第三方请求地址
     * @param params    请求参数
     * @param pjson    json参数
     * @param cookie    Cookie
     * @param headerMap 补充请求头参数
     * @param fileName  文件名
     * @param bytes     文件字节码
     * @return java.lang.String
     * <br><br><b>作者: 990130556 <a class=b href="https://blog.csdn.net/lingdu_dou">lingdu</a></b><br>
     * 创建时间: 2021年08月26日 18:21:34
     */
    public static String send(String type, String url, Map<String, Object> params, String pjson, String cookie, Map<String, Object> headerMap, String fileName, byte[] bytes) {
        DataOutputStream out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try {
            // GET 和 DELETE 请求
            if (type.equals(GET) || type.equals(DELETE)) {
                if (params != null) {
                    StringBuilder urlBuilder = new StringBuilder(url + "?");
                    for (String s : params.keySet()) {
                        // 防     止     中     文     乱     码     ↓
                        urlBuilder.append(s).append("=").append(URLEncoder.encode(params.get(s).toString(), CHARSET_UTF8)).append("&");
                    }
                    url = urlBuilder.toString();
                }
            }
            // 默认表单提交
            CONTENT_TYPE_WAY = CONTENT_TYPE_FORMDATA;
            // 如果pjson不为空则使用json方式提交
            if (pjson != null) {
                CONTENT_TYPE_WAY = CONTENT_TYPE_JSON;
            }
            //打开和URL之间的连接
            HttpURLConnection conn = getHttpUrlConnection(url, type, cookie, headerMap);
            // POST 和 PUT 请求
            if (type.equals(POST) || type.equals(PUT)) {
                out = new DataOutputStream(conn.getOutputStream());
                //添加参数
                if (params != null) {
                    for (String key : params.keySet()) {
                        String sb = "--" +
                                BOUNDARY +
                                "\r\n" +
                                "Content-Disposition: form-data;name=\"" + key + "\"" +
                                "\r\n" +
                                "\r\n" +
                                params.get(key) +
//								URLEncoder.encode(params.get(key).toString(), "utf-8")+
                                "\r\n";
                        out.write(sb.getBytes());
                    }
                }

                // 传文件
                if (null != fileName && null != bytes) {
                    //添加参数file
                    String sb = "--" +
                            BOUNDARY +
                            "\r\n" +
                            "Content-Disposition: form-data;name=\"file\";filename=\"" + fileName + "\"" +
                            "\r\n" +
                            "Content-Type: " + MIME_TYPE_IMAGE_JPEG +
                            "\r\n" +
                            "\r\n";
                    out.write(sb.getBytes());
                    // TODO 写文件
                    out.write(bytes);
                    out.write("\r\n".getBytes());
                }
                if (pjson != null) {
                    out.writeBytes(pjson);
                } else {
                    byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
                    out.write(endData);
                }
                //flush输出流的缓冲
                out.flush();
            }
            //定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            log.error("发送请求出现异常:", e);
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return result.toString();
    }

    /**
     * 和URL之间建立连接
     *
     * @param url       请求路径
     * @param type      请求类型
     * @param cookie    cookie
     * @param headerMap 请求头补充参数
     * @return java.net.HttpURLConnection 返回连接信息
     * <br><br><b>作者: 990130556 <a class=b href="https://blog.csdn.net/lingdu_dou">lingdu</a></b><br>
     * 创建时间: 2021年09月02日 15:51:28
     */
    private static HttpURLConnection getHttpUrlConnection(String url, String type, String cookie, Map<String, Object> headerMap) throws IOException {
        URL realUrl = new URL(url);
        //打开和URL之间的连接
        HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
        if (POST.equals(type) || PUT.equals(type)) {
            //发送POST请求必须设置如下两行
            // 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true
            conn.setDoOutput(true);
            // 默认值为:true,当前向远程服务读取数据时,设置为true,该参数可有可无
            conn.setDoInput(true);
        }
        conn.setUseCaches(false);
        conn.setRequestMethod(type);

        // 设置连接主机服务器超时时间:15000毫秒
        conn.setConnectTimeout(15000);
        // 设置读取主机服务器返回数据超时时间:60000毫秒
        conn.setReadTimeout(60000);

        conn.setRequestProperty("connection", "Keep-Alive");
        conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36");
        conn.setRequestProperty("Charsert", CHARSET_UTF8);
        if (cookie != null) {
            conn.setRequestProperty("Cookie", cookie);
        }
        conn.setRequestProperty(CONTENT_TYPE, CONTENT_TYPE_WAY + "; boundary=" + BOUNDARY);
        //填充请求头
        if (headerMap != null && headerMap.keySet().size() != 0) {
            for (String s : headerMap.keySet()) {
                conn.setRequestProperty(s, headerMap.get(s).toString());
            }
        }
        conn.connect();
        return conn;
    }
}