ruoyi的spring cloud项目详解(十一)

 接着之前的继续学习

ruoyi的spring cloud项目详解(十)-CSDN博客

咱们研究研究这个com/ruoyi/common/utils/AddressUtils.java

package com.ruoyi.common.utils;

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

import com.ruoyi.common.json.JSON;
import com.ruoyi.common.json.JSONObject;
import com.ruoyi.common.utils.http.HttpUtils;

/**
 * 获取地址类
 * 
 * @author ruoyi
 */
public class AddressUtils
{
    private static final Logger log    = LoggerFactory.getLogger(AddressUtils.class);

    public static final String  IP_URL = "http://region.zmrit.com";

    public static String getRealAddressByIP(String ip)
    {
        String address = "XX XX";
        // 内网不查询
        if (IpUtils.internalIp(ip))
        {
            return "内网IP";
        }
        String rspStr = HttpUtils.sendPost(IP_URL, "ip=" + ip);
        if (StringUtils.isEmpty(rspStr))
        {
            log.error("获取地理位置异常 {}", ip);
            return address;
        }
        JSONObject obj;
        try
        {
            obj = JSON.unmarshal(rspStr, JSONObject.class);
            JSONObject data = obj.getObj("data");
            address = data.getStr("address");
        }
        catch (Exception e)
        {
            log.error("获取地理位置异常 {}", ip);
        }
        return address;
    }
}

以下是对这段 Java 代码的分析,以代码块形式呈现:

一、导入依赖部分

package com.ruoyi.common.utils;

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

import com.ruoyi.common.json.JSON;
import com.ruoyi.common.json.JSONObject;
import com.ruoyi.common.utils.http.HttpUtils;

这里导入了必要的类,包括用于日志记录的LoggerLoggerFactory,以及自定义的 JSON 处理类JSONJSONObject,还有自定义的 HTTP 工具类HttpUtils

二、类定义和变量声明部分

public class AddressUtils {
    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
    public static final String IP_URL = "http://region.zmrit.com";

定义了一个名为AddressUtils的类。log是一个日志记录器,用于记录这个类中的操作日志。IP_URL是一个常量,指定了获取 IP 地址对应的实际地址信息的服务 URL。

三、获取实际地址方法部分

public static String getRealAddressByIP(String ip) {
    String address = "XX XX";
    // 内网不查询
    if (IpUtils.internalIp(ip)) {
        return "内网IP";
    }
    String rspStr = HttpUtils.sendPost(IP_URL, "ip=" + ip);
    if (StringUtils.isEmpty(rspStr)) {
        log.error("获取地理位置异常 {}", ip);
        return address;
    }
    JSONObject obj;
    try {
        obj = JSON.unmarshal(rspStr, JSONObject.class);
        JSONObject data = obj.getObj("data");
        address = data.getStr("address");
    } catch (Exception e) {
        log.error("获取地理位置异常 {}", ip);
    }
    return address;
}

这个方法用于根据给定的 IP 地址获取实际地址。首先初始化一个默认地址为 “XX XX”。如果 IP 是内网 IP(通过调用IpUtils.internalIp(ip)判断),则直接返回 “内网 IP”。如果不是内网 IP,就使用HttpUtils.sendPost向指定的 URL 发送包含 IP 的 POST 请求,并获取响应字符串。如果响应为空,记录错误日志并返回默认地址。如果响应不为空,尝试将其解析为JSONObject,然后从解析后的对象中提取出包含实际地址的信息。如果在解析过程中出现异常,也记录错误日志并返回默认地址。

一、功能概述

这段代码定义了一个工具类AddressUtils,用于根据 IP 地址获取对应的实际地址信息。如果是内网 IP 则直接返回 “内网 IP”,否则通过向指定的IP_URL发送包含 IP 地址的 POST 请求来获取地理位置信息,并解析返回的 JSON 数据提取地址。

二、代码详解

  1. 导入依赖:

    • 导入了org.slf4j.Loggerorg.slf4j.LoggerFactory用于日志记录。
    • 导入了自定义的com.ruoyi.common.json.JSONcom.ruoyi.common.json.JSONObject以及com.ruoyi.common.utils.http.HttpUtils类。
  2. 定义变量和常量:

    • log:使用LoggerFactory创建一个与当前类相关联的日志记录器。
    • IP_URL:一个常量字符串,指定了获取 IP 地址对应的地理位置信息的服务 URL。
  3. getRealAddressByIP方法:

    • 接收一个 IP 地址作为参数,用于获取该 IP 对应的实际地址。
    • 首先判断传入的 IP 是否为内网 IP,如果是,则直接返回 “内网 IP”。这是通过调用IpUtils.internalIp(ip)方法来判断的,具体的判断逻辑应该在IpUtils类中实现。
    • 如果不是内网 IP,则使用HttpUtils.sendPost方法向IP_URL发送一个 POST 请求,请求参数为 “ip=” 加上传入的 IP 地址。这个方法应该会返回一个字符串,表示服务器的响应内容。
    • 如果响应内容为空,则记录错误日志并返回默认的地址 “XX XX”。
    • 如果响应内容不为空,则尝试将其解析为JSONObject对象,然后从解析后的 JSON 对象中提取出名为 “data” 的子对象,再从这个子对象中获取名为 “address” 的字符串属性,这个属性应该包含实际的地址信息。如果在解析过程中出现异常,也会记录错误日志并返回默认地址。

三、可能的改进点

  1. 错误处理可以更加详细,比如在记录错误日志时可以打印更多的异常信息,以便于排查问题。
  2. 可以考虑对HttpUtils.sendPost方法的调用进行超时设置,以防止在网络不稳定的情况下长时间等待响应。
  3. 如果获取地址的服务不稳定,可以考虑添加缓存机制,避免频繁地向服务发送请求

com/ruoyi/common/utils/Arith.java

package com.ruoyi.common.utils;

import java.math.BigDecimal;

/**
 * 精确的浮点数运算
 * 
 * @author ruoyi
 */
public class Arith
{

    /** 默认除法运算精度 */
    private static final int DEF_DIV_SCALE = 10;

    /** 这个类不能实例化 */
    private Arith()
    {
    }

    /**
     * 提供精确的加法运算。
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    /**
     * 提供精确的减法运算。
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 提供精确的乘法运算。
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mul(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
     * 小数点以后10位,以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static double div(double v1, double v2)
    {
        return div(v1, v2, DEF_DIV_SCALE);
    }

    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
     * 定精度,以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1, double v2, int scale)
    {
        if (scale < 0)
        {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        if (b1.compareTo(BigDecimal.ZERO) == 0)
        {
            return BigDecimal.ZERO.doubleValue();
        }
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供精确的小数位四舍五入处理。
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v, int scale)
    {
        if (scale < 0)
        {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
}

以下是对这段 Java 代码的逐块解析:

package com.ruoyi.common.utils;

import java.math.BigDecimal;

这部分代码声明了包名,并导入了java.math.BigDecimal类,这个类用于进行高精度的数值计算。

/**
 * 精确的浮点数运算
 * 
 * @author ruoyi
 */
public class Arith {

这是一个名为Arith的公共类的开始,带有一个 JavaDoc 注释,表明这个类用于精确的浮点数运算,作者是 “ruoyi”。

    /** 默认除法运算精度 */
    private static final int DEF_DIV_SCALE = 10;

定义了一个私有静态常量DEF_DIV_SCALE,表示默认的除法运算精度为 10。

    /** 这个类不能实例化 */
    private Arith() {
    }

定义了一个私有的构造函数,使得这个类不能被实例化。

    /**
     * 提供精确的加法运算。
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

这是一个静态方法add,用于进行精确的加法运算。它接受两个 double 类型的参数v1v2,将它们转换为BigDecimal类型进行加法运算,然后再转换回 double 类型返回结果。

    /**
     * 提供精确的减法运算。
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

静态方法sub用于进行精确的减法运算,原理与加法类似。

    /**
     * 提供精确的乘法运算。
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mul(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

静态方法mul用于进行精确的乘法运算。

    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
     * 小数点以后 10 位,以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static double div(double v1, double v2) {
        return div(v1, v2, DEF_DIV_SCALE);
    }

静态方法div是一个重载方法,它调用另一个带有精度参数的div方法,并使用默认精度DEF_DIV_SCALE

    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由 scale 参数指
     * 定精度,以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        if (b1.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO.doubleValue();
        }
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

这个div方法接受三个参数,用于进行精确的除法运算。它首先检查精度参数是否合法,如果被除数为 0,则直接返回 0,否则使用BigDecimal进行除法运算并根据指定的精度和舍入模式进行四舍五入后返回结果。

    /**
     * 提供精确的小数位四舍五入处理。
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
}

静态方法round用于对一个数字进行精确的四舍五入处理,它接受一个数字和小数点后保留的位数作为参数,同样先检查精度参数的合法性,然后使用BigDecimal进行四舍五入操作并返回结果。

以下是对这段 Java 代码的分析:

一、功能概述

这个名为Arith的类提供了精确的浮点数运算方法,包括加法、减法、乘法、除法和四舍五入。它通过使用BigDecimal类来避免浮点数运算中的精度损失问题。

二、代码详解

  1. 常量定义

    • DEF_DIV_SCALE:定义了默认的除法运算精度为 10,表示在进行除法运算且没有指定精度时,结果将精确到小数点后 10 位。
  2. 构造函数私有化

    • private Arith():将类的构造函数设为私有,确保这个类不能被实例化,只能通过静态方法来使用其提供的运算功能。
  3. 加法运算方法

    • public static double add(double v1, double v2):接受两个 double 类型的参数v1v2,将它们转换为BigDecimal类型进行加法运算,然后再转换回 double 类型返回结果。这样可以避免浮点数加法可能出现的精度问题。
  4. 减法运算方法

    • public static double sub(double v1, double v2):与加法类似,对两个参数进行减法运算。
  5. 乘法运算方法

    • public static double mul(double v1, double v2):执行乘法运算。
  6. 除法运算方法

    • public static double div(double v1, double v2):调用另一个带精度参数的除法方法,使用默认精度DEF_DIV_SCALE进行除法运算。
    • public static double div(double v1, double v2, int scale):接受三个参数,包括被除数v1、除数v2和精度参数scale。在进行除法运算前,先检查精度参数是否合法(不能为负数),然后将参数转换为BigDecimal类型进行除法运算,并根据指定的精度和舍入模式进行四舍五入,最后返回结果。如果被除数为 0,则直接返回 0。
  7. 四舍五入方法

    • public static double round(double v, int scale):接受一个需要进行四舍五入的数字v和小数点后保留的位数scale。同样先检查精度参数的合法性,然后使用BigDecimal进行四舍五入操作并返回结果。

三、使用场景和注意事项

  • 使用场景:在需要进行精确的浮点数运算时,特别是在金融、科学计算等对精度要求较高的领域,可以使用这个类的方法来确保结果的准确性。

  • 注意事项:

    • 虽然这个类提供了精确的运算方法,但在使用时仍然需要注意传入的参数是否合法,特别是精度参数不能为负数。
    • 由于使用了BigDecimal进行运算,可能会有一定的性能开销,在对性能要求非常高的场景下需要考虑这一点。

com/ruoyi/common/utils/DateUtils.java

package com.ruoyi.common.utils;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;

/**
 * 时间工具类
 * 
 * @author ruoyi
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    
    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * 获取当前Date型日期
     * 
     * @return Date() 当前日期
     */
    public static Date getNowDate()
    {
        return new Date();
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     * 
     * @return String
     */
    public static String getDate()
    {
        return dateTimeNow(YYYY_MM_DD);
    }

    public static final String getTime()
    {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static final String dateTimeNow()
    {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

    public static final String dateTimeNow(final String format)
    {
        return parseDateToStr(format, new Date());
    }

    public static final String dateTime(final Date date)
    {
        return parseDateToStr(YYYY_MM_DD, date);
    }

    public static final String parseDateToStr(final String format, final Date date)
    {
        return new SimpleDateFormat(format).format(date);
    }

    public static final Date dateTime(final String format, final String ts)
    {
        try
        {
            return new SimpleDateFormat(format).parse(ts);
        }
        catch (ParseException e)
        {
            throw new RuntimeException(e);
        }
    }

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static final String datePath()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static final String dateTime()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str)
    {
        if (str == null)
        {
            return null;
        }
        try
        {
            return parseDate(str.toString(), parsePatterns);
        }
        catch (ParseException e)
        {
            return null;
        }
    }
    
    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate()
    {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate)
    {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }
}

以下是对这段 Java 代码的逐块分析:

package com.ruoyi.common.utils;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang3.time.DateUtils;

这部分代码声明了包名,并导入了必要的类,包括用于管理 Java 虚拟机的java.lang.management.ManagementFactory,用于处理日期和时间的java.text.SimpleDateFormatjava.util.Date,以及来自 Apache Commons Lang 库的org.apache.commons.lang3.time.DateUtils,这个类可能提供了一些额外的日期处理功能。

/**
 * 时间工具类
 * 
 * @author ruoyi
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

这是一个名为DateUtils的公共类的开始,带有一个 JavaDoc 注释,表明这个类是一个时间工具类,作者是 “ruoyi”。这个类继承自 Apache Commons Lang 库中的DateUtils类。

    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

定义了一些常量字符串,分别表示不同的日期时间格式。

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

定义了一个字符串数组parsePatterns,包含了多种可能的日期时间格式,用于在解析日期字符串时尝试不同的格式。

    /**
     * 获取当前Date型日期
     * 
     * @return Date() 当前日期
     */
    public static Date getNowDate() {
        return new Date();
    }

这是一个静态方法,用于获取当前的Date对象,表示当前日期和时间。

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     * 
     * @return String
     */
    public static String getDate() {
        return dateTimeNow(YYYY_MM_DD);
    }

静态方法,以默认格式yyyy-MM-dd获取当前日期的字符串表示,它调用了另一个方法dateTimeNow并传入指定的格式参数。

    public static final String getTime() {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

静态方法,以yyyy-MM-dd HH:mm:ss格式获取当前日期和时间的字符串表示,同样调用了dateTimeNow方法。

    public static final String dateTimeNow() {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

静态方法,以yyyyMMddHHmmss格式获取当前日期和时间的字符串表示,调用了另一个重载的dateTimeNow方法。

    public static final String dateTimeNow(final String format) {
        return parseDateToStr(format, new Date());
    }

静态方法,根据指定的格式获取当前日期和时间的字符串表示。它调用了另一个方法parseDateToStr,传入指定的格式和当前日期。

    public static final String dateTime(final Date date) {
        return parseDateToStr(YYYY_MM_DD, date);
    }

静态方法,根据默认格式yyyy-MM-dd将给定的Date对象转换为字符串表示,调用了parseDateToStr方法。

    public static final String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }

静态方法,根据指定的格式将给定的Date对象转换为字符串表示,使用SimpleDateFormat进行格式化。

    public static final Date dateTime(final String format, final String ts) {
        try {
            return new SimpleDateFormat(format).parse(ts);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

静态方法,根据指定的格式将日期时间字符串解析为Date对象,如果解析失败则抛出运行时异常。

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static final String datePath() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

静态方法,以yyyy/MM/dd格式返回当前日期的路径表示,例如2018/08/08,使用了DateFormatUtils类进行格式化。

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static final String dateTime() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

另一个名为dateTime的静态方法,以yyyyMMdd格式返回当前日期的路径表示,例如20180808

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

静态方法,尝试使用多种预定义的格式将给定的对象(通常是字符串)解析为Date对象,如果解析失败则返回null

    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

静态方法,通过ManagementFactory.getRuntimeMXBean().getStartTime()获取服务器启动时间的毫秒值,并转换为Date对象返回。

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }
}

静态方法,计算两个日期之间的时间差,以 “天 小时 分钟” 的格式返回。它首先定义了不同时间单位的毫秒值常量,然后计算两个日期之间的毫秒差异,进而计算出天、小时和分钟的差值,并返回格式化后的字符串。

一、功能概述

这个类名为DateUtils,是一个时间工具类,提供了一系列与日期和时间处理相关的静态方法,包括获取当前日期和时间、格式化日期、解析日期字符串、获取服务器启动时间以及计算两个日期之间的时间差等功能。

二、代码详解

  1. 常量定义

    • YYYYYYYY_MMYYYY_MM_DDYYYYMMDDHHMMSSYYYY_MM_DD_HH_MM_SS:定义了不同的日期时间格式字符串常量,方便在其他方法中使用。

    • parsePatterns:一个字符串数组,包含了多种可能的日期时间格式,用于在解析日期字符串时尝试不同的格式。

  2. 获取当前日期和时间的方法

    • getNowDate():返回当前的Date对象,表示当前日期和时间。
    • getDate():以默认格式yyyy-MM-dd获取当前日期的字符串表示。
    • getTime()dateTimeNow():以不同的格式获取当前日期和时间的字符串表示。
    • dateTimeNow(final String format):根据指定的格式获取当前日期和时间的字符串表示。
    • dateTime(final Date date):根据默认格式yyyy-MM-dd将给定的Date对象转换为字符串表示。
    • parseDateToStr(final String format, final Date date):根据指定的格式将给定的Date对象转换为字符串表示。
    • dateTime(final String format, final String ts):根据指定的格式将日期时间字符串解析为Date对象,如果解析失败则抛出运行时异常。
  3. 日期路径相关方法

    • datePath():以yyyy/MM/dd格式返回当前日期的路径表示,例如2018/08/08
    • dateTime():以yyyyMMdd格式返回当前日期的路径表示,例如20180808
  4. 解析日期字符串方法

    • parseDate(Object str):尝试使用多种预定义的格式将给定的对象(通常是字符串)解析为Date对象,如果解析失败则返回null
  5. 获取服务器启动时间方法

    • getServerStartDate():通过ManagementFactory.getRuntimeMXBean().getStartTime()获取服务器启动时间的毫秒值,并转换为Date对象返回。
  6. 计算时间差方法

    • getDatePoor(Date endDate, Date nowDate):计算两个日期之间的时间差,以 “天 小时 分钟” 的格式返回。

三、使用场景和注意事项

  • 使用场景:

    • 在需要进行日期和时间处理的各种应用场景中,如日志记录、数据处理、定时任务等,可以使用这个工具类来方便地获取、格式化和解析日期时间信息,以及计算时间差。
  • 注意事项:

    • 在解析日期字符串时,如果输入的字符串格式不匹配预定义的任何一种格式,将返回null,需要注意处理这种情况。
    • 在计算时间差时,只计算了天、小时和分钟,没有考虑秒和更精确的时间单位,如果需要更精确的时间差计算,可能需要进行调整。

com/ruoyi/common/utils/ExceptionUtil.java

package com.ruoyi.common.utils;

import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.commons.lang3.exception.ExceptionUtils;

/**
 * 错误信息处理类。
 *
 * @author ruoyi
 */
public class ExceptionUtil
{
    /**
     * 获取exception的详细错误信息。
     */
    public static String getExceptionMessage(Throwable e)
    {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw, true));
        String str = sw.toString();
        return str;
    }

    public static String getRootErrorMseeage(Exception e)
    {
        Throwable root = ExceptionUtils.getRootCause(e);
        root = (root == null ? e : root);
        if (root == null)
        {
            return "";
        }
        String msg = root.getMessage();
        if (msg == null)
        {
            return "null";
        }
        return StringUtils.defaultString(msg);
    }
}

以下是对这段 Java 代码的逐块分析:

package com.ruoyi.common.utils;

import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.commons.lang3.exception.ExceptionUtils;

这部分代码声明了包名,并导入了必要的类。其中PrintWriter用于将文本输出到指定的输出流,StringWriter用于将输出内容收集到一个字符串中,ExceptionUtils来自 Apache Commons Lang 库,用于处理异常。

/**
 * 错误信息处理类。
 *
 * @author ruoyi
 */
public class ExceptionUtil {

这是一个名为ExceptionUtil的公共类的开始,带有一个 JavaDoc 注释,表明这个类是一个错误信息处理类,作者是 “ruoyi”。

    /**
     * 获取exception的详细错误信息。
     */
    public static String getExceptionMessage(Throwable e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw, true));
        String str = sw.toString();
        return str;
    }

这个静态方法getExceptionMessage接受一个Throwable类型的参数,表示要获取错误信息的异常对象。它创建一个StringWriter对象,然后使用PrintWriter将异常的堆栈跟踪信息输出到StringWriter中,最后将StringWriter中的内容转换为字符串并返回,这个字符串包含了异常的详细错误信息,包括异常类型、消息和堆栈跟踪。

    public static String getRootErrorMseeage(Exception e) {
        Throwable root = ExceptionUtils.getRootCause(e);
        root = (root == null? e : root);
        if (root == null) {
            return "";
        }
        String msg = root.getMessage();
        if (msg == null) {
            return "null";
        }
        return StringUtils.defaultString(msg);
    }
}

这个静态方法getRootErrorMseeage接受一个Exception类型的参数。它首先使用ExceptionUtils.getRootCause(e)尝试获取异常的根原因,如果根原因为空,则使用传入的异常本身。然后检查根异常是否为空,如果为空则返回空字符串。接着获取根异常的错误消息,如果消息为空则返回 “null”,否则使用StringUtils.defaultString(msg)进行处理(假设StringUtils是一个自定义的工具类,用于处理字符串,这里可能是确保返回一个非空字符串)。

以下是对这段 Java 代码的分析:

一、功能概述

这个类名为ExceptionUtil,主要用于处理异常信息。它提供了两个方法来获取异常的详细错误信息和根异常的错误消息。

二、代码详解

  1. 导入依赖

    • import java.io.PrintWriter;:用于将文本输出到指定的输出流。
    • import java.io.StringWriter;:用于将输出内容收集到一个字符串中。
    • import org.apache.commons.lang3.exception.ExceptionUtils;:Apache Commons Lang 库中的类,提供了处理异常的实用方法。
  2. 类定义和方法

    • getExceptionMessage(Throwable e)方法:

      • 接受一个Throwable类型的参数,表示要获取错误信息的异常对象。
      • 创建一个StringWriter对象sw,用于收集输出内容。
      • 使用PrintWriter将异常的堆栈跟踪信息输出到StringWriter中。
      • StringWriter中的内容转换为字符串并返回,这个字符串包含了异常的详细错误信息,包括异常类型、消息和堆栈跟踪。
    • getRootErrorMseeage(Exception e)方法:

      • 接受一个Exception类型的参数。
      • 使用ExceptionUtils.getRootCause(e)尝试获取异常的根原因。如果根原因为空,则使用传入的异常本身。
      • 检查根异常是否为空,如果为空则返回空字符串。
      • 获取根异常的错误消息,如果消息为空则返回 “null”,否则使用StringUtils.defaultString(msg)进行处理(假设StringUtils是一个自定义的工具类,用于处理字符串,这里可能是确保返回一个非空字符串)。

三、使用场景和注意事项

  • 使用场景:

    • 在应用程序中,当需要记录或展示异常的详细信息时,可以使用这些方法来获取格式化的错误信息。
  • 注意事项:

    • 在使用getExceptionMessage方法时,由于它打印了异常的堆栈跟踪信息,可能会产生较多的输出,在某些情况下可能会影响性能或可读性。
    • getRootErrorMseeage方法依赖于ExceptionUtils.getRootCause的行为,如果异常的结构比较复杂,可能需要进一步分析以确保正确获取根异常的消息。

com/ruoyi/common/utils/IpUtils.java

package com.ruoyi.common.utils;

import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.servlet.http.HttpServletRequest;

/**
 * 获取IP方法
 * 
 * @author ruoyi
 */
public class IpUtils
{
    public static String getIpAddr(HttpServletRequest request)
    {
        if (request == null)
        {
            return "unknown";
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("X-Real-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getRemoteAddr();
        }

        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip.split(",")[0];
    }

    public static boolean internalIp(String ip)
    {
        byte[] addr = textToNumericFormatV4(ip);
        if (null != addr) {
            return internalIp(addr) || "127.0.0.1".equals(ip);
        }
        return false;
    }

    private static boolean internalIp(byte[] addr)
    {
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        // 10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        // 172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        // 192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0)
        {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4)
                {
                    return true;
                }
            case SECTION_5:
                switch (b1)
                {
                    case SECTION_6:
                        return true;
                }
            default:
                return false;
        }
    }

    /**
     * 将IPv4地址转换成字节
     * 
     * @param text IPv4地址
     * @return byte 字节
     */
    public static byte[] textToNumericFormatV4(String text)
    {
        if (text.length() == 0)
        {
            return null;
        }

        byte[] bytes = new byte[4];
        String[] elements = text.split("\\.", -1);
        try
        {
            long l;
            int i;
            switch (elements.length)
            {
                case 1:
                    l = Long.parseLong(elements[0]);
                    if ((l < 0L) || (l > 4294967295L))
                        return null;
                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 2:
                    l = Integer.parseInt(elements[0]);
                    if ((l < 0L) || (l > 255L))
                        return null;
                    bytes[0] = (byte) (int) (l & 0xFF);
                    l = Integer.parseInt(elements[1]);
                    if ((l < 0L) || (l > 16777215L))
                        return null;
                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 3:
                    for (i = 0; i < 2; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                            return null;
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    l = Integer.parseInt(elements[2]);
                    if ((l < 0L) || (l > 65535L))
                        return null;
                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 4:
                    for (i = 0; i < 4; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                            return null;
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    break;
                default:
                    return null;
            }
        }
        catch (NumberFormatException e)
        {
            return null;
        }
        return bytes;
    }

    public static String getHostIp()
    {
        try
        {
            return InetAddress.getLocalHost().getHostAddress();
        }
        catch (UnknownHostException e)
        {
        }
        return "127.0.0.1";
    }

    public static String getHostName()
    {
        try
        {
            return InetAddress.getLocalHost().getHostName();
        }
        catch (UnknownHostException e)
        {
        }
        return "未知";
    }
}

以下是对这段 Java 代码的逐块分析:

package com.ruoyi.common.utils;

import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.servlet.http.HttpServletRequest;

这部分代码声明了包名,并导入了必要的类。其中InetAddress用于获取本地主机的网络地址信息,UnknownHostException用于处理获取本地主机信息时可能出现的未知主机异常,HttpServletRequest用于获取 HTTP 请求对象,以便从中提取客户端 IP 地址。

/**
 * 获取IP方法
 * 
 * @author ruoyi
 */
public class IpUtils {

这是一个名为IpUtils的公共类的开始,带有一个 JavaDoc 注释,表明这个类用于获取 IP 地址,作者是 “ruoyi”。

    public static String getIpAddr(HttpServletRequest request) {
        if (request == null) {
            return "unknown";
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        return "0:0:0:0:0:0:0:1".equals(ip)? "127.0.0.1" : ip.split(",")[0];
    }

这个静态方法getIpAddr接受一个HttpServletRequest对象作为参数,用于从 HTTP 请求中获取客户端的 IP 地址。如果请求对象为null,则返回 “unknown”。然后依次尝试从请求头中的不同字段获取 IP 地址,如果都没有获取到,则使用request.getRemoteAddr()获取。最后,如果获取到的 IP 地址是 “0:0:0:0:0:0:0:1”,则将其转换为 “127.0.0.1”,并返回处理后的 IP 地址,如果有多个 IP 地址(以逗号分隔),则只取第一个。

    public static boolean internalIp(String ip) {
        byte[] addr = textToNumericFormatV4(ip);
        if (null!= addr) {
            return internalIp(addr) || "127.0.0.1".equals(ip);
        }
        return false;
    }

这个静态方法internalIp用于判断给定的 IP 地址是否为内网 IP 地址。首先调用textToNumericFormatV4(ip)将 IP 地址字符串转换为字节数组,如果转换结果不为null,则进一步判断该字节数组表示的 IP 地址是否为内网 IP 地址,或者判断 IP 地址是否为 “127.0.0.1”。如果转换结果为null,则直接返回false

    private static boolean internalIp(byte[] addr) {
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        // 10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        // 172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        // 192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0) {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4) {
                    return true;
                }
            case SECTION_5:
                switch (b1) {
                    case SECTION_6:
                        return true;
                }
            default:
                return false;
        }
    }

这个私有静态方法internalIp是判断字节数组表示的 IP 地址是否为内网 IP 地址的具体实现。根据不同的 IP 地址段进行判断,包括 “10.x.x.x/8”、“172.16.x.x/12” 和 “192.168.x.x/16” 等内网 IP 地址段。

    /**
     * 将IPv4地址转换成字节
     * 
     * @param text IPv4地址
     * @return byte 字节
     */
    public static byte[] textToNumericFormatV4(String text) {
        if (text.length() == 0) {
            return null;
        }

        byte[] bytes = new byte[4];
        String[] elements = text.split("\\.", -1);
        try {
            long l;
            int i;
            switch (elements.length) {
                case 1:
                    l = Long.parseLong(elements[0]);
                    if ((l < 0L) || (l > 4294967295L))
                        return null;
                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 2:
                    l = Integer.parseInt(elements[0]);
                    if ((l < 0L) || (l > 255L))
                        return null;
                    bytes[0] = (byte) (int) (l & 0xFF);
                    l = Integer.parseInt(elements[1]);
                    if ((l < 0L) || (l > 16777215L))
                        return null;
                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 3:
                    for (i = 0; i < 2; ++i) {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                            return null;
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    l = Integer.parseInt(elements[2]);
                    if ((l < 0L) || (l > 65535L))
                        return null;
                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 4:
                    for (i = 0; i < 4; ++i) {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                            return null;
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    break;
                default:
                    return null;
            }
        } catch (NumberFormatException e) {
            return null;
        }
        return bytes;
    }

这个静态方法textToNumericFormatV4将 IPv4 地址字符串转换为字节数组表示。如果输入的 IP 地址字符串为空,则返回null。然后根据 IP 地址字符串中 “.” 的数量进行不同的处理,将 IP 地址拆分为数字部分,并进行合法性检查。如果输入的 IP 地址字符串格式不正确或超出合法范围,则返回null

    public static String getHostIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
        }
        return "127.0.0.1";
    }

这个静态方法getHostIp尝试获取本地主机的 IP 地址,如果获取失败则返回 “127.0.0.1”。

    public static String getHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
        }
        return "未知";
    }
}

这个静态方法getHostName尝试获取本地主机的主机名,如果获取失败则返回 “未知”。

以下是对这段 Java 代码的分析:

一、功能概述

这个类IpUtils提供了一系列与 IP 地址处理相关的方法,包括从 HTTP 请求中获取客户端 IP 地址、判断 IP 地址是否为内网 IP、将 IP 地址字符串转换为字节数组、获取本地主机 IP 地址和主机名等功能。

二、代码详解

  1. 导入依赖

    • import java.net.InetAddress;:用于获取本地主机的网络地址信息。
    • import java.net.UnknownHostException;:用于处理获取本地主机信息时可能出现的未知主机异常。
    • import javax.servlet.http.HttpServletRequest;:用于获取 HTTP 请求对象,以便从中提取客户端 IP 地址。
  2. 方法分析

    • getIpAddr(HttpServletRequest request)

      • 这个方法接受一个HttpServletRequest对象作为参数,用于从 HTTP 请求中获取客户端的 IP 地址。
      • 如果请求对象为null,则返回 “unknown”。
      • 依次尝试从请求头中的 “x-forwarded-for”、“Proxy-Client-IP”、“X-Forwarded-For”、“WL-Proxy-Client-IP”、“X-Real-IP” 获取 IP 地址,如果都没有获取到,则使用request.getRemoteAddr()获取。
      • 如果获取到的 IP 地址是 “0:0:0:0:0:0:0:1”,则将其转换为 “127.0.0.1”,最后返回处理后的 IP 地址,并且如果有多个 IP 地址(以逗号分隔),则只取第一个。
    • internalIp(String ip)

      • 这个方法用于判断给定的 IP 地址是否为内网 IP 地址。
      • 首先调用textToNumericFormatV4(ip)将 IP 地址字符串转换为字节数组,如果转换结果为null,则返回false
      • 然后判断转换后的字节数组是否为内网 IP 地址,或者判断 IP 地址是否为 “127.0.0.1”。
    • internalIp(byte[] addr)

      • 这个私有方法是判断字节数组表示的 IP 地址是否为内网 IP 地址的具体实现。
      • 根据不同的 IP 地址段进行判断,包括 “10.x.x.x/8”、“172.16.x.x/12” 和 “192.168.x.x/16” 等内网 IP 地址段。
    • textToNumericFormatV4(String text)

      • 这个方法将 IPv4 地址字符串转换为字节数组表示。
      • 根据 IP 地址字符串中 “.” 的数量进行不同的处理,将 IP 地址拆分为数字部分,并进行合法性检查。
      • 如果输入的 IP 地址字符串格式不正确或超出合法范围,则返回null
    • getHostIp()

      • 尝试获取本地主机的 IP 地址,如果获取失败则返回 “127.0.0.1”。
    • getHostName()

      • 尝试获取本地主机的主机名,如果获取失败则返回 “未知”。

三、使用场景和注意事项

  • 使用场景:

    • 在 Web 应用中,可以使用getIpAddr方法从 HTTP 请求中获取客户端的真实 IP 地址,用于日志记录、访问统计、安全控制等方面。
    • internalIp方法可以用于判断 IP 地址是否为内网 IP,以便进行不同的处理策略。
    • getHostIpgetHostName方法可以用于获取本地主机的网络信息。
  • 注意事项:

    • 在获取 IP 地址时,需要考虑代理服务器等因素可能导致的 IP 地址不准确问题。
    • 对于 IP 地址的合法性检查和内网 IP 的判断,需要根据实际需求进行适当的调整和验证。

com/ruoyi/common/utils/MapDataUtil.java

package com.ruoyi.common.utils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;

/**
 * Map通用处理方法
 * 
 * @author ruoyi
 */
public class MapDataUtil
{
    public static Map<String, Object> convertDataMap(HttpServletRequest request)
    {
        Map<String, String[]> properties = request.getParameterMap();
        Map<String, Object> returnMap = new HashMap<String, Object>();
        Iterator<?> entries = properties.entrySet().iterator();
        Map.Entry<?, ?> entry;
        String name = "";
        String value = "";
        while (entries.hasNext())
        {
            entry = (Entry<?, ?>) entries.next();
            name = (String) entry.getKey();
            Object valueObj = entry.getValue();
            if (null == valueObj)
            {
                value = "";
            }
            else if (valueObj instanceof String[])
            {
                String[] values = (String[]) valueObj;
                for (int i = 0; i < values.length; i++)
                {
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length() - 1);
            }
            else
            {
                value = valueObj.toString();
            }
            returnMap.put(name, value);
        }
        return returnMap;
    }
}

以下是对这段 Java 代码的逐块分析

package com.ruoyi.common.utils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;

这部分代码声明了包名,并导入了必要的类。其中HashMap用于创建一个新的Map对象,Iterator用于遍历Map中的元素,MapEntry用于定义方法的参数和返回类型,HttpServletRequest用于获取 HTTP 请求对象,以便从中提取参数。

/**
 * Map通用处理方法
 * 
 * @author ruoyi
 */
public class MapDataUtil {

这是一个名为MapDataUtil的公共类的开始,带有一个 JavaDoc 注释,表明这个类用于处理Map数据,作者是 “ruoyi”。

    public static Map<String, Object> convertDataMap(HttpServletRequest request) {
        Map<String, String[]> properties = request.getParameterMap();
        Map<String, Object> returnMap = new HashMap<String, Object>();
        Iterator<?> entries = properties.entrySet().iterator();
        Map.Entry<?,?> entry;
        String name = "";
        String value = "";
        while (entries.hasNext()) {
            entry = (Entry<?,?>) entries.next();
            name = (String) entry.getKey();
            Object valueObj = entry.getValue();
            if (null == valueObj) {
                value = "";
            } else if (valueObj instanceof String[]) {
                String[] values = (String[]) valueObj;
                for (int i = 0; i < values.length; i++) {
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length() - 1);
            } else {
                value = valueObj.toString();
            }
            returnMap.put(name, value);
        }
        return returnMap;
    }
}

这个静态方法convertDataMap接受一个HttpServletRequest对象作为参数,用于将请求中的参数转换为Map<String, Object>

首先,通过request.getParameterMap()获取请求中的所有参数,这将返回一个Map<String, String[]>,其中键是参数名,值是参数值的字符串数组(如果有多个值)。

然后,创建一个新的Map<String, Object>对象returnMap,用于存储转换后的参数。

接着,使用迭代器遍历参数Map中的键值对。对于每个键值对,提取参数名name和参数值valueObj。如果参数值为null,则将value设置为空字符串。如果参数值是一个字符串数组,则将数组中的值拼接成一个字符串,并用逗号分隔,最后去除末尾的逗号。如果参数值既不是null也不是字符串数组,则直接将其转换为字符串。

最后,将参数名和处理后的参数值放入returnMap中,并返回转换后的Map对象。

以下是对这段 Java 代码的分析:

一、功能概述

这个类MapDataUtil提供了一个将HttpServletRequest中的参数转换为Map<String, Object>的方法。它主要用于从 HTTP 请求中提取参数并以一种更方便的格式进行处理。

二、代码详解

  1. 导入依赖

    • import java.util.HashMap;:用于创建一个新的Map对象。
    • import java.util.Iterator;:用于遍历Map中的元素。
    • import java.util.Map;:用于定义方法的参数和返回类型。
    • import java.util.Map.Entry;:用于遍历Map中的键值对。
    • import javax.servlet.http.HttpServletRequest;:用于获取 HTTP 请求对象,以便从中提取参数。
  2. 方法分析

    • convertDataMap(HttpServletRequest request)
      • 这个方法接受一个HttpServletRequest对象作为参数,用于将请求中的参数转换为Map<String, Object>
      • 首先,通过request.getParameterMap()获取请求中的所有参数,这将返回一个Map<String, String[]>,其中键是参数名,值是参数值的字符串数组(如果有多个值)。
      • 创建一个新的Map<String, Object>对象returnMap,用于存储转换后的参数。
      • 使用迭代器遍历参数Map中的键值对。对于每个键值对,提取参数名name和参数值valueObj
      • 如果参数值为null,则将value设置为空字符串。如果参数值是一个字符串数组,则将数组中的值拼接成一个字符串,并用逗号分隔,最后去除末尾的逗号。如果参数值既不是null也不是字符串数组,则直接将其转换为字符串。
      • 将参数名和处理后的参数值放入returnMap中。
      • 最后,返回转换后的Map对象。

三、使用场景和注意事项

  • 使用场景:

    • 在 Web 应用中,可以使用这个方法将 HTTP 请求中的参数转换为更易于处理的Map格式,方便在业务逻辑中进行参数的读取和操作。
  • 注意事项:

    • 在处理参数值为字符串数组的情况时,需要注意拼接字符串的逻辑是否符合实际需求。
    • 如果请求中的参数可能包含特殊字符或需要进行进一步的验证和处理,可能需要在这个方法的基础上进行扩展。

com/ruoyi/common/utils/MessageUtils.java

package com.ruoyi.common.utils;

import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import com.ruoyi.common.utils.spring.SpringUtils;

/**
 * 获取i18n资源文件
 * 
 * @author ruoyi
 */
public class MessageUtils
{
    /**
     * 根据消息键和参数 获取消息 委托给spring messageSource
     *
     * @param code 消息键
     * @param args 参数
     * @return 获取国际化翻译值
     */
    public static String message(String code, Object... args)
    {
        MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
        return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
    }
}

以下是对这段 Java 代码的逐块分析:

package com.ruoyi.common.utils;

import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import com.ruoyi.common.utils.spring.SpringUtils;

这部分代码声明了包名,并导入了必要的类。其中MessageSource是 Spring 用于处理国际化消息的接口,LocaleContextHolder用于获取当前线程的本地化上下文信息,SpringUtils可能是自定义的工具类,用于获取 Spring 容器中的 bean。

/**
 * 获取i18n资源文件
 * 
 * @author ruoyi
 */
public class MessageUtils {

这是一个名为MessageUtils的公共类的开始,带有一个 JavaDoc 注释,表明这个类用于获取国际化资源文件,作者是 “ruoyi”。

    /**
     * 根据消息键和参数 获取消息 委托给spring messageSource
     *
     * @param code 消息键
     * @param args 参数
     * @return 获取国际化翻译值
     */
    public static String message(String code, Object... args) {
        MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
        return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
    }
}

这个静态方法message接受一个消息键code和可变参数args,用于在获取国际化消息时传入参数。

首先,通过SpringUtils.getBean(MessageSource.class)获取 Spring 容器中的MessageSource实例。

然后,调用messageSource.getMessage(code, args, LocaleContextHolder.getLocale())来获取国际化翻译后的消息。其中,code是消息键,args是参数列表,LocaleContextHolder.getLocale()用于获取当前线程的本地化信息,以确定使用哪种语言的资源文件进行翻译,并返回翻译后的消息字符串。

以下是对这段 Java 代码的分析:

一、功能概述

这个类MessageUtils用于获取国际化(i18n)资源文件中的消息。它通过依赖 Spring 的MessageSource来实现根据消息键和参数获取国际化翻译后的消息。

二、代码详解

  1. 导入依赖

    • import org.springframework.context.MessageSource;MessageSource是 Spring 用于处理国际化消息的接口。
    • import org.springframework.context.i18n.LocaleContextHolder;:用于获取当前线程的本地化上下文信息,以确定使用哪种语言的资源文件。
    • import com.ruoyi.common.utils.spring.SpringUtils;:可能是自定义的工具类,用于获取 Spring 容器中的 bean。
  2. 方法分析

    • message(String code, Object... args)
      • 这个方法接受一个消息键code和可变参数args,用于在获取国际化消息时传入参数。
      • 通过SpringUtils.getBean(MessageSource.class)获取 Spring 容器中的MessageSource实例。
      • 调用messageSource.getMessage(code, args, LocaleContextHolder.getLocale())来获取国际化翻译后的消息。其中,code是消息键,args是参数列表,LocaleContextHolder.getLocale()用于获取当前线程的本地化信息,以确定使用哪种语言的资源文件进行翻译。

三、使用场景和注意事项

  • 使用场景:

    • 在国际化的应用程序中,可以使用这个工具类方便地获取不同语言的消息。例如,在显示用户界面的文本、错误消息等场景中,可以根据消息键获取相应的国际化翻译后的文本。
  • 注意事项:

    • 确保SpringUtils.getBean(MessageSource.class)能够正确地获取到MessageSource实例,并且应用程序已经正确配置了国际化资源文件。
    • 在使用可变参数args时,要确保参数的类型和顺序与资源文件中的占位符匹配。
  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值