启动浏览器
HTTP 控制浏览器
本文档介绍如何通过 HTTP 接口启动、导航及关闭 Playwright 浏览器实例,并提供完整的示例代码
一、前置条件
- JDK 8 及以上
- Playwright for Java 依赖:
- tio-boot 框架
二、核心数据结构:BrowserInstance
用于在内存中保存每个浏览器实例的上下文和页面引用。
package com.litongjava.ai.browser.service;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.Page;
public class BrowserInstance {
public final BrowserContext context;
public final Page page;
public BrowserInstance(BrowserContext ctx, Page pg) {
this.context = ctx;
this.page = pg;
}
}
三、服务层实现:PlaywrightService
负责启动、导航以及关闭浏览器实例,使用 ConcurrentHashMap
缓存所有活跃实例。
package com.litongjava.ai.browser.service;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ConcurrentHashMap;
import com.litongjava.model.body.RespBodyVo;
import com.litongjava.tio.utils.snowflake.SnowflakeIdUtils;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.BrowserType.LaunchPersistentContextOptions;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.Response;
public class PlaywrightService {
// 存储所有浏览器实例
private static final ConcurrentHashMap<Long, BrowserInstance> INSTANCES = new ConcurrentHashMap<>();
/**
* 启动或复用浏览器实例
* @param id 可选:传入已有实例 ID 则复用该实例,否则自动生成新 ID
* @param headless 是否以无头模式启动
* @return 浏览器实例 ID
*/
public long start(Long id, boolean headless) {
Playwright pw = Playwright.create();
BrowserType ct = pw.chromium();
LaunchPersistentContextOptions opts = new LaunchPersistentContextOptions().setHeadless(headless);
Path dir = Paths.get("user-data");
BrowserContext ctx = ct.launchPersistentContext(dir, opts);
// Playwright 会自动打开一个 about:blank 页,你可以立刻拿到它
Page firstPage = ctx.pages().get(0);
if (id == null) {
id = SnowflakeIdUtils.id();
}
INSTANCES.put(id, new BrowserInstance(ctx, firstPage));
return id;
}
/**
* 导航到指定 URL(复用同一个 Page 对象)
* @param browserId 浏览器实例 ID
* @param url 目标地址
* @return Playwright Response 对象,可获取状态码、Headers 等
*/
public Response navigate(Long browserId, String url) {
BrowserInstance inst = INSTANCES.get(browserId);
return inst.page.navigate(url);
}
/**
* 关闭并移除浏览器实例
* @param browserId 浏览器实例 ID
* @return 操作结果
*/
public RespBodyVo close(Long browserId) {
BrowserInstance instance = INSTANCES.remove(browserId);
if (instance != null && instance.context != null) {
instance.context.close();
return RespBodyVo.ok();
} else {
return RespBodyVo.fail("没有找到对应的浏览器实例:" + browserId);
}
}
}
四、控制层实现:PlaywrightController
通过 HTTP 接口暴露启动、导航和关闭功能。
package com.litongjava.ai.browser.controller;
import com.jfinal.kit.Kv;
import com.litongjava.ai.browser.service.PlaywrightService;
import com.litongjava.annotation.RequestPath;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.model.body.RespBodyVo;
import com.microsoft.playwright.Response;
@RequestPath("/api/v1/playwright")
public class PlaywrightController {
PlaywrightService playwrightService = Aop.get(PlaywrightService.class);
/**
* 启动或获取浏览器实例
* 调用示例:GET /api/v1/playwright/start?id=&headless=true
*/
@RequestPath("/start")
public RespBodyVo start(Long id, boolean headless) {
id = playwrightService.start(id, headless);
return RespBodyVo.ok(Kv.by("id", id));
}
/**
* 导航到指定 URL
* 调用示例:GET /api/v1/playwright/navigate?id=123&url=https://example.com
*/
@RequestPath("/navigate")
public RespBodyVo navigate(Long id, String url) {
Response response = playwrightService.navigate(id, url);
return RespBodyVo.ok(Kv.by("status", response.status()));
}
/**
* 关闭浏览器实例
* 调用示例:GET /api/v1/playwright/close?id=123
*/
@RequestPath("/close")
public RespBodyVo close(Long id) {
return playwrightService.close(id);
}
}
五、使用示例
启动浏览器(无头模式)
GET http://localhost:8080/api/v1/playwright/start?headless=true
响应:
{ "code": 0, "data": { "id": 1234567890123456 } }
导航到页面
GET http://localhost:8080/api/v1/playwright/navigate?id=1234567890123456&url=https://www.taobao.com
响应:
{ "code": 0, "data": { "status": 200 } }
关闭浏览器实例
GET http://localhost:8080/api/v1/playwright/close?id=1234567890123456
响应:
{ "code": 0 }
六、注意事项
LaunchPersistentContextOptions
会在本地user-data
目录中保存浏览器数据,如 cookies、LocalStorage 等;如需每次全新上下文,可改用browser.newContext()
。SnowflakeIdUtils
仅为示例 ID 生成方式,您可替换为任意唯一 ID 方案。