Say Goodbye to Hand-Written HTTP Code: Run Your curl Command Directly in Java with JQuickCurl
Every backend engineer knows the drill: you spend ten minutes in Postman or the browser DevTools crafting the perfect request, click "Copy as cURL", and then… stare at the screen. You have to manually translate headers, query strings, JSON bodies, and timeouts into OkHttp builders, RestTemplate exchanges, or HttpClient request objects. Translation bugs sneak in, the code balloons, and nobody wants to maintain it.
JQuickCurl (a Dromara open-source project) takes the opposite approach: the curl command itself becomes your request definition. You paste curl syntax into a Java annotation, declare an interface, and call it like a local method. The library parses your curl command with ANTLR4, executes it over the battle-tested OkHttp transport layer, and converts the response into whatever Java type you ask for.
In this first post of the series you will:
- Learn what JQuickCurl is and when it shines.
- Add the dependency with Maven.
- Write a complete Hello-World example.
- Understand what happens behind the scenes (spoiler: no system curl binary is ever spawned).
What Exactly Is JQuickCurl?
JQuickCurl is a curl-command-driven HTTP client framework for Java, licensed under Apache-2.0. Its core idea: reuse the same curl snippets your frontend, QA, and API docs already share.
| Layer | Technology |
|---|---|
| curl syntax parsing | ANTLR4 (in-process, no ProcessBuilder) |
| HTTP transport | OkHttp 4.x (connection pool, HTTP/2, interceptors) |
| Request definition |
@JCurlCommand annotation and XML files |
| Dynamic behavior |
${...} variable substitution, XML <if> conditions |
| Extra features | file upload/download, batch execution, retry, timeouts, interceptors, dynamic proxy |
Because parsing happens inside the JVM, JQuickCurl never calls the system curl binary. That means the same Java code works on Windows, Linux, and macOS, needs no external installation, and keeps full programmatic control over the request lifecycle.
Step 1: Add the Maven Dependency
Add this to your pom.xml (check Maven Central for the newest release; the examples here use 2.5.0):
<dependency>
<groupId>io.github.paohaijiao</groupId>
<artifactId>jquick-curl</artifactId>
<version>2.5.0</version>
</dependency>
Step 2: Declare Your First curl-Powered API
Create an interface and put a raw curl command inside @JCurlCommand. The only "parameter convention" you need today is a JQuickCurlReq — a simple HashMap<String, Object> that carries variables for the command (more on that in a later post).
import com.github.paohaijiao.anno.JCurlCommand;
import com.github.paohaijiao.domain.req.JQuickCurlReq;
public interface EchoApi {
// Any curl command starting with "curl" works as the annotation value.
@JCurlCommand("curl -X GET https://httpbin.org/get")
String get(JQuickCurlReq request);
}
Step 3: Run It from a main Method
JCurlInvoker.createProxy(Class) builds a JDK dynamic proxy for your interface. Every call on that proxy parses the annotation's curl command, executes it, and converts the HTTP response body into the method's return type.
import com.github.paohaijiao.domain.req.JQuickCurlReq;
import com.github.paohaijiao.executor.JCurlInvoker;
public class HelloCurl {
public static void main(String[] args) {
// 1. Create the proxy once — it is cheap and reusable.
EchoApi api = JCurlInvoker.createProxy(EchoApi.class);
// 2. An empty request map for a command without variables.
JQuickCurlReq request = new JQuickCurlReq();
// 3. Call your interface method like a local Java method.
String body = api.get(request);
System.out.println("HTTP response body:");
System.out.println(body);
}
}
Compile and run:
mvn compile exec:java -Dexec.mainClass=HelloCurl
You will see httpbin's JSON echo — the args, headers, and url that your request actually sent:
{
"args": {},
"headers": {
"Accept-Encoding": "gzip",
"Host": "httpbin.org",
"User-Agent": "okhttp/4.10.0"
},
"url": "https://httpbin.org/get"
}
That's the whole point: the request was described by curl syntax, yet executed by OkHttp in-process.
What Just Happened Under the Hood?
Three stages, all inside your JVM:
-
Parse — ANTLR4 lexes and parses the annotation string
curl -X GET https://httpbin.org/getinto an abstract syntax tree of HTTP method, URL, headers, data, and options. -
Build & execute — a visitor walks the tree and produces a real OkHttp
Request; the executor sends it through OkHttp's client (connection pool, timeouts, retries, and interceptors included). -
Convert — the raw response body is converted to the declared return type. Here it's
String, butbyte[],InputStream, custom POJOs, collections,JResult, and rawJQuickCurlResponseBodyare all supported.
No curl process, no shell, no command injection risk.
Why Backend Teams Care
- Zero translation bugs: the command in your code is byte-for-byte the one you tested in Postman.
- One format for everyone: product docs, curl examples, and Java code stay in sync.
- Configurable where it counts: timeouts, proxies, and retries can be layered on top without rewriting the request.
- Lightweight: Apache-2.0, pure Java, no external runtime.
Summary
JQuickCurl lets you declare HTTP calls the way you already think about them — as curl commands. In roughly ten lines of Java you have a typed, proxy-based HTTP client with no request-building boilerplate. The Hello-World example above is the smallest building block of a much larger toolkit: dynamic variables, XML API catalogs, conditional rendering, file transfer, batch runs, interceptors, and authentication are all covered in the upcoming posts of this series.
Bookmark the repository — dromara/jquick-curl — and stay tuned for Post 2, where we wire this into a real Spring Boot application.
Top comments (0)