同一URL下不同HTTP动词配置独立Grizzly HttpHandler的实现问题
问题解答
核心原因
Grizzly HTTP Server的路由规则为:同路径下绑定的多个HttpHandler仅会按注册顺序调用第一个匹配到路径的Handler,不会自动降级触发后续注册的Handler,这是你当前POST请求也会触发GetHandler返回错误内容的根本原因。
方案选择
你提到的两种实现思路都可行,可根据场景选择:
- 轻量场景推荐单Handler内部判断方法:代码更简洁,无额外路由开销,适合单路径下处理方法不多的场景
- 若不同方法的处理逻辑复杂,想要拆分独立类维护,可以自行实现一个调度Handler,统一路由到对应子Handler
修正代码示例
方案1:单Handler内部判断方法
import java.net.URI; import javax.ws.rs.client.ClientBuilder; import org.glassfish.grizzly.http.Method; import org.glassfish.grizzly.http.server.HttpHandler; import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.grizzly.http.server.Request; import org.glassfish.grizzly.http.server.Response; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; public class HttpHandlerTest { private static final URI BASE_URI = URI.create("http://localhost:8081"); private static final String MAPPING = "/test"; public static void main(String[] args) { HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, (GrizzlyHttpContainer) null, false, null, true); // 仅注册一个统一处理Handler server.getServerConfiguration().addHttpHandler(new UnifiedHandler(), MAPPING); javax.ws.rs.core.Response getResponse = ClientBuilder.newClient().target(BASE_URI + MAPPING).request().get(); System.out.println(getResponse.readEntity(String.class)); // 输出 GET response javax.ws.rs.core.Response postResponse = ClientBuilder.newClient().target(BASE_URI + MAPPING).request().post(null); System.out.println(postResponse.readEntity(String.class)); // 输出 POST response server.shutdown(); } public static class UnifiedHandler extends HttpHandler{ @Override public void service(Request request, Response response) throws Exception{ if (request.getMethod() == Method.GET){ response.getWriter().write("GET response"); } else if (request.getMethod() == Method.POST) { response.getWriter().write("POST response"); } else { response.setStatus(405); response.getWriter().write("Method Not Allowed"); } } } }
方案2:多Handler拆分+调度转发
如果需要将不同方法的处理逻辑拆分为独立类,加一层调度Handler即可:
import java.net.URI; import javax.ws.rs.client.ClientBuilder; import org.glassfish.grizzly.http.Method; import org.glassfish.grizzly.http.server.HttpHandler; import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.grizzly.http.server.Request; import org.glassfish.grizzly.http.server.Response; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; public class HttpHandlerTest { private static final URI BASE_URI = URI.create("http://localhost:8081"); private static final String MAPPING = "/test"; public static void main(String[] args) { HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, (GrizzlyHttpContainer) null, false, null, true); // 仅注册调度Handler server.getServerConfiguration().addHttpHandler(new DispatchHandler(), MAPPING); javax.ws.rs.core.Response getResponse = ClientBuilder.newClient().target(BASE_URI + MAPPING).request().get(); System.out.println(getResponse.readEntity(String.class)); javax.ws.rs.core.Response postResponse = ClientBuilder.newClient().target(BASE_URI + MAPPING).request().post(null); System.out.println(postResponse.readEntity(String.class)); server.shutdown(); } // 统一调度Handler public static class DispatchHandler extends HttpHandler{ private final GetHandler getHandler = new GetHandler(); private final PostHandler postHandler = new PostHandler(); @Override public void service(Request request, Response response) throws Exception{ if (request.getMethod() == Method.GET){ getHandler.service(request, response); } else if (request.getMethod() == Method.POST) { postHandler.service(request, response); } else { response.setStatus(405); response.getWriter().write("Method Not Allowed"); } } } public static class GetHandler extends HttpHandler{ @Override public void service(Request request, Response response) throws Exception{ response.getWriter().write("GET response"); } } public static class PostHandler extends HttpHandler{ @Override public void service(Request request, Response response) throws Exception{ response.getWriter().write("POST response"); } } }
补充说明
不需要引入额外的上层组件,上述两种方案都可基于Grizzly原生能力实现,你之前的思路问题在于对Grizzly的路由匹配规则不熟悉,误以为同路径下多个Handler会依次触发,实际框架没有内置该逻辑,需要自行实现调度。
内容的提问来源于stack exchange,提问作者Amber
相关产品推荐
相关产品推荐

