Dropwizard: новый ресурс администратора

Я использую Drowpizard 0.7.1, но, возможно, я скоро перейду к 0.8.4.

Кто-нибудь знает, как добавить ресурс администратора в dropwizard, который показан в рабочем меню, как пример ниже?

Operational Menu

    Metrics
    Ping
    Threads
    Healthcheck
    CustomAdminXy

Ответ 1

Я не думаю, что вы можете сделать это легко.

AdminServlet создается при создании ServerFactory. Возможно, можно расширить DefaultServerFactory и переопределить createAdminServlet создать настраиваемый сервлет администрирования с вашими ссылками и т.д. (тогда вам нужно будет установить ваш сервер factory через конфигурацию.)

Кажется, что это приведет к некоторому дублированию кода и может быть довольно хрупким.

Возможно, вам будет проще просто зарегистрировать собственный сервлет администратора (в дополнение к обычному), например:

environment.admin().addServlet("custom-admin", new CustomAdminServlet())
    .addMapping("/custom-admin");

Вероятно, тоже не идеальный.

Ответ 2

Использование .addMapping("") с Dropwizard версии 0.9.1 позволяет переопределить меню, не противоречая сопоставлению AdminServlet по умолчанию в "/*".

В приложении:

public void run(final NetworkModelApplicationConfiguration configuration, final Environment environment) {
    environment.admin().addServlet("my-admin-menu", new MyAdminServlet()).addMapping("");
    environment.admin().addServlet("my-admin-feature", new MyAdminFeatureServlet()).addMapping("/myAdminFeature");
}

Расширение AdminServlet не очень полезно, поскольку все свойства являются закрытыми. Я построил HTTPServlet, который читает ресурс как шаблон:

public class MyAdminServlet extends HttpServlet {
  private String serviceName;

  @Override
  public void init(ServletConfig config) throws ServletException {
    super.init(config);
    this.serviceName = config.getInitParameter("service-name");
  }

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String path = req.getContextPath() + req.getServletPath();
    resp.setStatus(200);
    resp.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
    resp.setContentType("text/html");
    PrintWriter writer = resp.getWriter();

    try {
      String template = getResourceAsString("/admin.html", "UTF-8");
      String serviceName = this.serviceName == null?"":" (" + this.serviceName + ")";

      writer.println(MessageFormat.format(template, new Object[] { path, serviceName }));
    } finally {
      writer.close();
    }
  }

  String getResourceAsString(String resource, String charSet) throws IOException {
    InputStream in = this.getClass().getResourceAsStream(resource);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    while ((len = in.read(buffer)) != -1) {
      out.write(buffer, 0, len);
    }
    return out.toString(charSet);
  }
}

Мой ресурс /admin.html выглядит следующим образом:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Operational Menu{1}</title>
  </head>
  <body>
    <h1>Operational Menu{1}</h1>
    <ul>
      <li><a href="{0}/metrics?pretty=true">Metrics</a></li>
      <li><a href="{0}/ping">Ping</a></li>
      <li><a href="{0}/threads">Threads</a></li>
      <li><a href="{0}/healthcheck?pretty=true">Healthcheck</a></li>
      <li><a href="{0}/myAdminFeature">My Admin Feature</a></li>
    </ul>
  </body>
</html>