调试

Java调试

直接调用 JVM 中的实例方法,传入调试参数并查看执行结果。

Java 调试用于直接调用当前 JVM 中已经存在的实例方法。无需通过 HTTP、Dubbo 等入口构造完整链路,即可在 IDE 中选择目标方法、填写参数并查看返回值,适合快速验证业务逻辑、复现问题和调试定时任务。

视频加载中

适用场景

  • 调用 Spring、Solon 等容器中的 Bean 实例方法。
  • 调用普通 Java 对象、代理对象或原始对象上的方法。
  • 调试 Controller、Service、定时任务、监听器等不方便直接发起请求的代码。
  • 在不改业务代码的情况下,临时构造参数并查看方法执行结果。

调用 JVM 实例方法

在 Java 方法上使用 Call This Method 后,Cool Request 会识别当前 JVM 中可调用的对象实例,并根据方法签名生成参数输入区域。点击执行后,插件会在运行中的 JVM 内完成方法调用,并在响应区域展示返回值、异常信息和执行耗时。

提示

如果方法所在类由框架代理,调用时可根据需要选择代理对象或原对象,便于分别验证切面、事务、缓存等框架逻辑是否生效。

参数支持

方法参数可以直接在界面中填写,支持常见 Java 类型和复杂对象参数。填写完成后,插件会按方法签名将文本内容转换为对应类型再发起调用。

常用参数类型包括:

  • 基础类型与包装类型,例如 intlongbooleanIntegerLongBoolean
  • 字符串、枚举、日期时间等类型,例如 StringEnumDateLocalDateTime
  • 数组、集合与 Map,例如 List<T>Set<T>Map<K,V>
  • Java Bean、DTO、VO 等对象类型,可通过 JSON 结构填写字段。
  • 嵌套对象、对象列表、Map 对象等组合参数。

对象参数示例:

{
  "userId": 10001,
  "userName": "Tom",
  "roles": ["admin", "operator"],
  "enabled": true
}

集合参数示例:

[
  {
    "sku": "A100",
    "count": 2
  },
  {
    "sku": "B200",
    "count": 1
  }
]

前/后置脚本

Java 方法调用支持前置脚本和后置脚本。前置脚本会在方法执行前运行,可用于动态生成参数、读取环境变量、准备上下文数据或取消本次调用;后置脚本会在方法执行后运行,可用于处理返回结果、输出日志或提取数据给后续调试使用。

调用方法时可以选择事先配置好的脚本。在调用界面的 Script 下拉框中选择目标脚本后,本次调用会按该脚本中的 beforeCallafterCall 逻辑执行。

典型用途:

  • 从环境变量中读取 token、用户 ID、租户 ID 等调试数据。
  • 在调用前动态修改参数,避免每次手动填写。
  • 在调用后格式化返回值,提取关键字段并打印日志。
  • 根据返回结果写入环境变量,供其他 HTTP 请求或方法调用复用。

注意

脚本中的方法名、返回值、参数列表通常由插件生成。编辑脚本时只修改方法体内容,避免改动函数签名导致编译失败。

脚本模板

Java 方法调用脚本使用 dev.coolrequest.function.CoolRequestMethodCall 类。插件会在调用前执行 beforeCall,在调用结束后执行 afterCall

package dev.coolrequest.function;

import org.springframework.context.ApplicationContext;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Map;

public class CoolRequestMethodCall {

    /**
     * Before calling the method
     *
     * @param applicationContext SpringBoot ApplicationContext
     * @param method             Target method
     * @param parameterValueMap  Parameter Value Map, You can modify this object
     */
    public void beforeCall(ApplicationContext applicationContext, Method method, Map<Parameter, Object> parameterValueMap) {

    }

    /**
     * After method call
     *
     * @param applicationContext SpringBoot ApplicationContext
     * @param method             Target method
     * @param result             Result value
     */
    public void afterCall(ApplicationContext applicationContext, Method method, Object result) {

    }

    //-----------------------------Assist in dynamically modifying parameter values-----------------------------
    private void setParameterByIndex(Map<Parameter, Object> parameterValueMap, Method method, int index, Object value) {
        if (index < 0 || index >= method.getParameterCount()) return;
        parameterValueMap.put(method.getParameters()[index], value);
    }

    private void setParameterByName(Map<Parameter, Object> parameterValueMap, String name, Object value) {
        for (Parameter parameter : parameterValueMap.keySet()) {
            if (parameter.getName().equals(name)) {
                parameterValueMap.put(parameter, value);
                return;
            }
        }
    }

    private Object findParameterValueByIndex(Method method, int index, Map<Parameter, Object> parameterValueMap) {
        if (index < 0 || index >= method.getParameterCount()) return null;
        return parameterValueMap.get(method.getParameters()[index]);
    }

    private Object findParameterValueByName(Map<Parameter, Object> parameterValueMap, String name) {
        for (Parameter parameter : parameterValueMap.keySet()) {
            if (parameter.getName().equals(name)) {
                return parameterValueMap.get(parameter);
            }
        }
        return null;
    }
}

beforeCall

beforeCall 在目标方法执行前调用,可读取 Spring ApplicationContext、目标 Method 和参数 Map。parameterValueMap 中保存了本次调用的参数值,脚本可以直接修改它,从而动态调整最终传入目标方法的参数。

常见用法:

  • 按参数下标修改入参。
  • 按参数名修改入参。
  • 从 Spring 容器中获取 Bean,用 Bean 生成或补全参数。
  • 根据当前方法名、参数类型等信息决定是否修改参数。

按下标修改第一个参数:

public void beforeCall(ApplicationContext applicationContext, Method method, Map<Parameter, Object> parameterValueMap) {
    setParameterByIndex(parameterValueMap, method, 0, 10001L);
}

按参数名修改参数:

public void beforeCall(ApplicationContext applicationContext, Method method, Map<Parameter, Object> parameterValueMap) {
    setParameterByName(parameterValueMap, "userId", 10001L);
}

读取原始参数后再修改:

public void beforeCall(ApplicationContext applicationContext, Method method, Map<Parameter, Object> parameterValueMap) {
    Object oldValue = findParameterValueByIndex(method, 0, parameterValueMap);
    if (oldValue == null) {
        setParameterByIndex(parameterValueMap, method, 0, 10001L);
    }
}

提示

如果需要按参数名读取或修改参数,请确认项目编译时保留了方法参数名,否则运行时参数名可能是 arg0arg1 这类名称。

afterCall

afterCall 在目标方法执行完成后调用,可读取目标方法和返回值。它适合用于记录调试日志、检查返回结果、提取关键字段,或根据结果执行后续辅助逻辑。

public void afterCall(ApplicationContext applicationContext, Method method, Object result) {
    System.out.println("method: " + method.getName());
    System.out.println("result: " + result);
}

注意

afterCall 中的 result 是目标方法的返回值。对于返回 void 的方法,result 通常为空。

XXL-JOB 参数

当目标方法用于 XXL-JOB 调度任务时,可在调用界面设置 XXL-JOB 参数。执行时插件会把填写的任务参数注入到调度上下文中,使本地直接调用能够模拟线上调度入参。

适合调试以下场景:

  • 任务方法依赖 XxlJobHelper.getJobParam() 获取参数。
  • 需要复现线上 XXL-JOB 调度时传入的字符串参数。
  • 同一个任务根据不同参数执行不同业务分支。

XXL-JOB 参数示例:

{"startDate":"2026-06-01","endDate":"2026-06-05","tenantId":"demo"}

调试建议

  • 优先使用接近真实业务的数据,避免参数缺失导致调试结果失真。
  • 对有副作用的方法,例如写库、发消息、调用外部系统,先确认当前环境和参数。
  • 如果方法依赖登录态、租户、线程上下文或调度上下文,可通过前置脚本或 XXL-JOB 参数补齐。
  • 如果返回值较复杂,可使用后置脚本打印关键字段,减少排查成本。