How do I override all 404 pages without defining d

2019-07-31 23:59发布

问题:

In my Dropwizard project, I'm defining a generic ExceptionMapper<WebApplicationException>:

environment.jersey().register(new WebApplicationExceptionMapper());

...but this doesn't seem to catch any of the 404 errors for unmatched paths.

Without defining five defaultHandler() methods for every single resource, how do I catch all 404s so I can return my own error page or some JSON?

So, if I had a service with one resrouce, say, /docs, this is the situtation:

  • /myservice/docs/helloworld doesn't match any @Path defined in my DocsResource. It returns a generic Jetty 404 page (not what I want)

  • /myservice/doesntexist returns my own error resource with the exception mapper (this is what I want everywhere)

回答1:

what you need to do is to set a different Error handler. The 404's you are seeing when hitting a non-existing path, are not handled by jersey. Jersey maps exceptions for resources, but you in fact never hit the resource in the first place. This is where you will need to define an error handler:

In DefaultServerFactory, you need to overwrite:

protected Server buildServer(LifecycleEnvironment lifecycle,
                                 ThreadPool threadPool) {
        final Server server = new Server(threadPool);
        server.addLifeCycleListener(buildSetUIDListener());
        lifecycle.attach(server);
        final ErrorHandler errorHandler = new ErrorHandler();
        errorHandler.setServer(server);
        errorHandler.setShowStacks(false);
        server.addBean(errorHandler);
        server.setStopAtShutdown(true);
        server.setStopTimeout(shutdownGracePeriod.toMilliseconds());
        return server;
    }

(This class is in AbstractServerFactory).

You then can implement your own ErrorHandler and make it do whatever it is you want it to do.

For testing, open org.eclipse.jetty.server.handler.ErrorHandler and set a breakpoint, then try and hit a non-existing URL. It will stop there and you can see how jetty handles this sort of thing.

I hope that helps.

If you need help overwriting default DW functionality, you can look at a similar post where I described how to overwrite loggers:

Dropwizard doesn't log custom loggers to file

Cheers, Artur