beanshell 处理返回Base64解码例子

import java.util.Base64
import groovy.json.JsonSlurper
import groovy.json.JsonOutput

// =============================================================
// ✅ 环境兼容:本地调试可运行(无 JMeter 环境时)
// =============================================================
if (!binding.hasVariable("vars")) {
    vars = new HashMap()
    prev = [ getResponseDataAsString: { -> vars.get("mockResponse") ?: "" } ] as Object
    log = [ info : {msg -> println "[INFO ] $msg"},
            warn : {msg -> println "[WARN ] $msg"},
            error: {msg -> println "[ERROR] $msg"} ] as Object
}

// =============================================================
// Step 1️⃣ 获取HTTP响应数据
// =============================================================
def responseBody = prev.getResponseDataAsString()?.trim()
if (!responseBody) {
    log.warn("❗未检测到响应内容,请检查接口返回或Sampler配置。")
    return
}
log.info("====== 🌐【原始接口返回】======\n" + responseBody)

// =============================================================
// Step 2️⃣ 尝试解析最外层JSON
// =============================================================
def json
try {
    json = new JsonSlurper().parseText(responseBody)
} catch (e) {
    log.error("❌ 响应体不是合法JSON,原文:\n${responseBody}")
    return
}

// =============================================================
// Step 3️⃣ 提取 payload 字段
// =============================================================
def base64Payload = json.payload
if (!base64Payload) {
    log.info("⚠️ 未找到 payload 字段,可能无需解码,直接解析。")
}

// =============================================================
// Step 4️⃣ Base64 解码(第一层)
// =============================================================
def decodedStr1 = responseBody
if (base64Payload) {
    try {
        decodedStr1 = new String(Base64.getDecoder().decode(base64Payload), "UTF-8")
        log.info("====== 🔍【第一层Base64解码结果】======\n" + decodedStr1)
    } catch (e) {
        log.error("❌ 第一层Base64解码失败:" + e.getMessage())
        return
    }
}

// =============================================================
// Step 5️⃣ 检查是否还有嵌套payload(第二层)
// =============================================================
def decodedStr = decodedStr1
try {
    def inner = new JsonSlurper().parseText(decodedStr1)
    if (inner.payload) {
        decodedStr = new String(Base64.getDecoder().decode(inner.payload), "UTF-8")
        log.info("====== 🔄【检测到第二层payload,继续解码】======\n" + decodedStr)
    }
} catch (ignore) {}

// =============================================================
// Step 6️⃣ 尝试转为JSON对象(若可能)
// =============================================================
def decodedObj
try {
    decodedObj = new JsonSlurper().parseText(decodedStr)
} catch (e) {
    log.warn("⚠️ 解码结果不是标准JSON字符串:\n${decodedStr}")
}

// =============================================================
// Step 7️⃣ 输出到日志和JMeter变量(增强版)
// =============================================================
if (decodedObj) {
    vars.put("decodedJsonStr", decodedStr)
    vars.put("decodedJsonPretty", JsonOutput.prettyPrint(JsonOutput.toJson(decodedObj)))
    log.info("====== ✅【最终解码JSON】======\n" + JsonOutput.prettyPrint(JsonOutput.toJson(decodedObj)))

    // 自动提取一级字段
    decodedObj.each { k, v ->
        if (v instanceof String || v instanceof Number) {
            vars.put("decoded_" + k, v.toString())
        }
    }

    // =============================================================
    // ✅ 递归查找 变量
    // =============================================================
    def foundIds = [:]

    def findIds
    findIds = { obj ->
        if (obj instanceof Map) {
            obj.each { k, v ->
                if (k.toLowerCase() in ["token", "code"]) {
                    foundIds[k] = v?.toString()
                }
                findIds(v)
            }
        } else if (obj instanceof List) {
            obj.each { item -> findIds(item) }
        }
    }

    findIds(decodedObj)

    if (!foundIds.isEmpty()) {
        foundIds.each { k, v ->
            vars.put(k, v)
            log.info("📦 已提取 ${k} = ${v}")
        }
    } else {
        log.info("(未检测到 pushId 或 publishId 字段)")
    }

} else {
    vars.put("decodedRaw", decodedStr)
    log.info("====== ✅【最终解码字符串】======\n${decodedStr}")
}

// =============================================================
// Step 8️⃣ (可选)用于本地调试
// =============================================================
// vars.put("mockResponse", '{"to":{"client":{"pushId":"66A058DA-41EF-36B4-80A3-FC17FE3DDBF1"}}}')

BeanShell 后置处理程序在 JMeter 中是一个功能强大的组件,广泛用于接口性能测试中,以提升测试脚本的灵活性和数据处理能力。其主要用途包括响应数据的解析、变量的提取与存储、断言逻辑的实现以及测试流程的动态控制。 ### 用途 1. **响应数据处理与变量提取** BeanShell 后置处理程序可以在 HTTP 请求执行后,对接收到的响应数据进行解析,例如从 JSON 或 XML 响应中提取特定字段,并将这些字段存储为 JMeter 变量,供后续请求使用。通过 `vars.put()` 和 `vars.get()` 方法实现变量的存储与获取,使得测试脚本能够动态传递参数[^3]。 2. **自定义断言逻辑** BeanShell 后置处理程序可以用于实现复杂的断言逻辑。通过编写 Java 代码,可以对接口响应进行深度验证,并根据验证结果设置 `Failure` 和 `FailureMessage` 标志,以控制测试是否失败及其原因描述[^4]。 3. **流程控制与数据转换** 在性能测试中,BeanShell 后置处理程序还可用于实现条件判断、数据转换等操作,从而增强测试脚本的灵活性和适应性。 ### 实现方法 BeanShell 后置处理程序的实现主要依赖于 Java 语言编写脚本,通常包括以下几个步骤: 1. **添加 BeanShell 后置处理程序** 在 JMeter 的测试计划中,选中需要处理响应数据的 HTTP 请求,右键选择“添加 > 后置处理器 > BeanShell 后置处理程序”。 2. **编写脚本提取与处理数据** 在 BeanShell 脚本中,使用 `prev` 对象获取当前请求的响应数据,结合 `ResponseData` 方法提取响应内容。例如,以下代码展示了如何从 JSON 响应中提取字段并存储为变量: ```java import org.json.JSONObject; String response = new String(prev.getResponseData()); JSONObject json = new JSONObject(response); String message = json.getString("message"); vars.put("message", message); ``` 3. **实现断言逻辑** 通过判断提取到的变量值,设置断言结果。例如,以下代码展示了如何实现自定义断言: ```java String message = vars.get("message"); if (!message.equals("success")) { Failure = true; FailureMessage = "规则解析失败"; } else { FailureMessage = "规则解析成功"; } ``` 通过上述方法,BeanShell 后置处理程序能够有效增强 JMeter 测试脚本的功能,满足复杂的测试需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值