Embedded Jetty Pass Параметр класса [duplicate]

Проще всего вычислить нужные вам величины за пределами ggplot, так как трудно отслеживать, что вычисляет ggplot и где эти величины хранятся и доступны.

Сначала суммируем ваши данные:

library(dplyr)

mtcars %>% count(cyl = factor(cyl), gear = factor(gear)) %>% 
    ungroup() %>%    # drop if you want percentages per cylinder
    mutate(pct = prop.table(n) * 100)

## # A tibble: 8 × 4
##      cyl   gear     n    pct
##       
## 1      4      3     1  3.125
## 2      4      4     8 25.000
## 3      4      5     2  6.250
## 4      6      3     2  6.250
## 5      6      4     4 12.500
## 6      6      5     1  3.125
## 7      8      3    12 37.500
## 8      8      5     2  6.250

Сохраните это, если хотите, или прямо в ggplot:

mtcars %>% count(cyl = factor(cyl), gear = factor(gear)) %>% 
    ungroup() %>%
    mutate(pct = prop.table(n) * 100) %>% 
    ggplot(aes(x = cyl, y = pct, fill = gear)) + 
    geom_bar(stat = 'identity', position = 'dodge') + 
    geom_text(aes(y = pct + .5,    # nudge above top of bar
                  label = paste0(pct, '%')),    # prettify
              position = position_dodge(width = .9), 
              size = 3)

Если вы действительно хотите его сохранить все внутренние по отношению к ggplot, вы можете использовать geom_text с stat = 'count' (или stat_count с geom = "text", если хотите):

ggplot(data = mtcars, aes(x = factor(cyl), fill = factor(gear))) +
    geom_bar(aes(y = prop.table(..count..) * 100),
             position = "dodge") + 
    geom_text(aes(y = prop.table(..count..) * 100 + 0.5, 
                  label = paste0(prop.table(..count..) * 100, '%')), 
              stat = 'count', 
              position = position_dodge(.9), 
              size = 3) + 
    labs(x = 'cyl', y = 'pct', fill = 'gear')

, который изображает одно и то же.

2
задан Freddy 10 September 2016 в 01:38
поделиться

3 ответа

Embedded Jetty настолько замечателен здесь.

У вас есть несколько общих опций:

  1. Прямая инстанция сервлета, использование конструкторов или сеттеров, а затем передать его Jetty через ServletHolder (может быть любое значение или тип объекта)
  2. Добавьте его в ServletContext в своей основной папке, а затем получите доступ к нему через ServletContext в вашем приложении (может быть любое значение или тип объекта).

Примеры:

package jetty;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

public class ObjectPassingExample
{
    public static void main(String args[]) throws Exception
    {
        Server server = new Server(8080);

        ServletContextHandler context = new ServletContextHandler();
        context.setContextPath("/");

        // Option 1: Direct servlet instantiation and ServletHolder
        HelloServlet hello = new HelloServlet("everyone");
        ServletHolder helloHolder = new ServletHolder(hello);
        context.addServlet(helloHolder, "/hello/*");

        // Option 2: Using ServletContext attribute
        context.setAttribute("my.greeting", "you");
        context.addServlet(GreetingServlet.class, "/greetings/*");

        server.setHandler(context);
        server.start();
        server.join();
    }

    public static class HelloServlet extends HttpServlet
    {
        private final String hello;

        public HelloServlet(String greeting)
        {
            this.hello = greeting;
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
        {
            resp.setContentType("text/plain");
            resp.getWriter().println("Hello " + this.hello);
        }
    }

    public static class GreetingServlet extends HttpServlet
    {
        private String greeting;

        @Override
        public void init() throws ServletException
        {
            this.greeting = (String) getServletContext().getAttribute("my.greeting");
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
        {
            resp.setContentType("text/plain");
            resp.getWriter().println("Greetings to " + this.greeting);
        }
    }
}
6
ответ дан Joakim Erdfelt 18 August 2018 в 22:14
поделиться
  • 1
    Переопределенный метод init работает отлично! Благодарю. – Freddy 12 September 2016 в 23:38
  • 2
    Что делать, если я использую WebAppProvider? Как я могу получить ServletContext в основном методе? – Ben 27 April 2018 в 14:30
  • 3
    @Ben, это вне сферы действия этого вопроса. Задайте новый вопрос (я отвечу на него, если увижу это) – Joakim Erdfelt 27 April 2018 в 15:37

Singleton

Вы хотите передать один и тот же единственный экземпляр каждому сервлету?

Используйте шаблон Singleton , чтобы создать единый экземпляр, доступный во всем мире.

Простейшим способом сделать это на Java является Enum . См. Учебник Oracle . Также см. эту статью и книгу Эффективное Java: Руководство по языку программирования, второе издание (ISBN 978-0-321-35668-0, 2008) by Dr. Джошуа Блох .

Так что не нужно передавать объект. Каждый сервлет может получить доступ к одному и тому же экземпляру через enum.

Для веб-приложения

Если вы хотите выполнить некоторую работу, когда ваше веб-приложение запускается первым, но перед любым сервлетом в этой сети приложение обработало любой запрос, напишите класс, который реализует интерфейс ServletContextListener .

Отметьте свой класс аннотацией @WebListener , чтобы ваш веб-контейнер автоматически создавал экземпляр и вызывал.

1
ответ дан Basil Bourque 18 August 2018 в 22:14
поделиться

У меня была аналогичная ситуация, но мне нужно было предоставить один сингл с сервлетом, развернутым через войну, с помощью горячего (повторного) развертывания в контейнере Jetty. Принятый ответ был не совсем тем, что мне нужно в моем случае, так как сервлет имеет жизненный цикл и контекст, управляемые установщиком.

Я закончил с применением грубой силы, добавив объект в server, который сохраняется для жизни контейнера, а затем извлекает объект из сервлета (ов). Это потребовало загрузки класса объекта в родительский (системный) загрузчик классов, чтобы war Webapp не загружал свою собственную версию класса в свой собственный загрузчик классов, что вызвало бы исключение литья, как описано здесь здесь .

Код сервера Embedded Jetty:

    Server server = new Server(8090);

    // Add all classes related to the object(s) you want to share here.
    WebAppContext.addSystemClasses(server, "my.package.MyFineClass", ...);

    // Handler config
    ContextHandlerCollection contexts = new ContextHandlerCollection();
    HandlerCollection handlers = new HandlerCollection();
    handlers.setHandlers(new Handler[] { contexts });
    server.setHandler(handlers);

    // Deployer config (hot deploy)
    DeploymentManager deployer = new DeploymentManager();
    DebugListener debug = new DebugListener(System.err,true,true,true);
    server.addBean(debug);
    deployer.addLifeCycleBinding(new DebugListenerBinding(debug));
    deployer.setContexts(contexts);
    deployer.setContextAttribute(
            "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
            ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$");

    WebAppProvider webapp_provider = new WebAppProvider();
    webapp_provider.setMonitoredDirName("/.../webapps");
    webapp_provider.setScanInterval(1);
    webapp_provider.setExtractWars(true);
    webapp_provider.setConfigurationManager(new PropertiesConfigurationManager());

    deployer.addAppProvider(webapp_provider);
    server.addBean(deployer);

    // Other config...

    // Tuck any objects/data you want into the root server object.
    server.setAttribute("my.package.MyFineClass", myFineSingleton);

    server.start();
    server.join();

Пример сервлета:

public class MyFineServlet extends HttpServlet
{
    MyFineClass myFineSingleton;

    @Override
    public void init() throws ServletException
    {
        // Sneak access to the root server object (non-portable).
        // Not possible to cast this to `Server` because of classloader restrictions in Jetty.
        Object server = request.getAttribute("org.eclipse.jetty.server.Server");

        // Because we cannot cast to `Server`, use reflection to access the object we tucked away there.
        try {
            myFineSingleton = (MyFineClass) server.getClass().getMethod("getAttribute", String.class).invoke(server, "my.package.MyFineClass");
        } catch (Exception ex) {
            throw new ServletException("Unable to reflect MyFineClass instance via Jetty Server", ex);
        }
    }

    @Override
    protected void doGet( HttpServletRequest request,
            HttpServletResponse response ) throws ServletException, IOException
    {
        response.setContentType("text/html");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().println("<h1>Hello from MyFineServlet</h1>");
        response.getWriter().println("Here's: " + myFineSingleton.toString());
    }
}

Мой файл сборки для сервлета (sbt) помещал my.package.MyFineClass в «предоставленный» объем, чтобы он не попал в войну, поскольку он уже будет загружен на сервер Jetty.

0
ответ дан Reed Sandberg 18 August 2018 в 22:14
поделиться
  • 1
    Для меня контекст сервлета не имеет атрибута для «org.eclipse.jetty.server.Server», когда в методе init сервлета. Вам нужно сделать что-то особенное, чтобы получить это? – Ben 27 April 2018 в 15:30
  • 2
    @Ben, вы используете причал или другой контейнер? Как уже упоминалось, это не переносится в другие контейнеры сервлетов, по крайней мере, как есть, вам нужно будет использовать точное полное имя класса Server, которое реализует ваш контейнер, и, возможно, это может измениться для Jetty также в разных версиях. – Reed Sandberg 13 June 2018 в 23:57
Другие вопросы по тегам:

Похожие вопросы: