如何仅用Jetty 12 Handler.Abstract创建REST API
仅用Jetty 12 Handlers实现REST API
1. 核心逻辑:直接操作Jetty原生Request/Response
无需依赖Jersey或Servlet容器,直接通过Request解析请求的HTTP方法、路径、参数,通过Response构造响应,最终完成Callback即可实现REST接口。
2. 正确解析请求信息
你调用request.getComponents()得到的是通道状态对象,并非请求参数。以下是正确的解析方式:
获取HTTP方法
String method = request.getMethod(); // 得到GET/POST/PUT/DELETE等方法
获取请求路径
String path = request.getHttpURI().getPath(); // 提取如/shop/这类路径信息
解析URL查询参数
通过Request的getQueryParameters()方法直接获取已解码的参数:
MultiMap<String> queryParams = request.getQueryParameters(); String id = queryParams.getString("id"); // 取单个参数值 String city = queryParams.getString("city"); // 自动解码URL编码的内容(如new%20york转为new york) List<String> countryList = queryParams.get("country"); // 处理多值参数
解析POST/PUT请求体(如JSON)
若请求体是JSON格式,需读取输入流并解析:
if ("POST".equals(method)) { String requestBody = request.getReader().lines().collect(Collectors.joining()); // 可配合Jackson等JSON库转为实体类 // ObjectMapper mapper = new ObjectMapper(); // Shop shop = mapper.readValue(requestBody, Shop.class); }
3. 实现REST端点路由与处理
在handle方法中,根据请求路径和HTTP方法分支处理不同端点:
class RESTHandler extends Handler.Abstract { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @Override public boolean handle(Request request, Response response, Callback callback) { String method = request.getMethod(); String path = request.getHttpURI().getPath(); try { // 处理GET /shop/ 端点 if ("GET".equals(method) && "/shop/".equals(path)) { handleShopGet(request, response); } // 处理POST /shop/ 端点 else if ("POST".equals(method) && "/shop/".equals(path)) { handleShopPost(request, response); } // 404 未找到端点 else { response.setStatus(HttpStatus.NOT_FOUND_404); response.getWriter().write("Endpoint not found"); } } catch (IOException e) { response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500); try { response.getWriter().write("Server error: " + e.getMessage()); } catch (IOException ex) { // 忽略写入错误,确保后续回调执行 } } finally { // 必须调用callback,通知Jetty请求处理完成 callback.succeeded(); } return true; } private void handleShopGet(Request request, Response response) throws IOException { MultiMap<String> queryParams = request.getQueryParameters(); Shop shop = new Shop(queryParams.getString("id"), queryParams.getString("city"), queryParams.getString("country")); // 设置响应为JSON格式 response.getHeaders().add(HttpHeader.CONTENT_TYPE, "application/json"); OBJECT_MAPPER.writeValue(response.getOutputStream(), shop); } private void handleShopPost(Request request, Response response) throws IOException { Shop newShop = OBJECT_MAPPER.readValue(request.getInputStream(), Shop.class); // 此处可添加数据持久化逻辑 response.setStatus(HttpStatus.CREATED_201); response.getHeaders().add(HttpHeader.CONTENT_TYPE, "application/json"); OBJECT_MAPPER.writeValue(response.getOutputStream(), newShop); } // 模拟实体类 private static class Shop { public String id; public String city; public String country; public Shop() {} // Jackson解析需要无参构造 public Shop(String id, String city, String country) { this.id = id; this.city = city; this.country = country; } } }
4. 关键注意事项
- 必须完成Callback:无论请求成功或失败,都要调用
callback.succeeded()或callback.failed(Throwable),否则Jetty会一直等待请求结束,造成连接泄漏。 - 响应头配置:返回JSON时需设置
Content-Type: application/json,保证客户端正确解析响应。 - 异常捕获:处理IO异常并设置对应HTTP状态码,避免未处理异常导致请求挂起。
5. 注册Handler到Jetty服务器
最后将自定义的RESTHandler注册到Jetty服务:
public static void main(String[] args) throws Exception { Server server = new Server(8080); server.setHandler(new RESTHandler()); server.start(); server.join(); }
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

