Arhn - архитектура программирования

Встроенный сервер Jetty, не видит веб-страницы в корневом контексте

Я использую причал v9.2.10.v20150310 с версией java "1.8.0_45" на Linux-сервере с ядром 3.18.9.

Проблема в том, что если я установил для пути контекста значение, отличное от корневого; т.е. / embed Я могу получить доступ к своей веб-странице на моем встроенном сервере причала. Однако, если я установил контекстный путь как root; т.е. "/" Я не могу получить доступ к странице. Интересно, что эта проблема не проявляется, когда я взаимодействую с сервлетом через curl.

Вот код:

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

final String servletWebDir = "/";
servletHandler.setContextPath( servletWebDir );

final customServlet iass = new customServlet();

final ServletHolder servletHolder = new ServletHolder( iass );
servletHolder.setInitOrder(0);
servletHandler.addServlet( servletHolder, "/customServlet" );

final ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setDirectoriesListed(false);
resourceHandler.setResourceBase(".");

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ servletHandler, resourceHandler } );

server.setHandler( handlers );

Если я изменю servletWebDir с «/» на «/ embed», все будет работать как надо. Если нет, я получаю 404.

Я могу успешно взаимодействовать с сервлетом с помощью следующих команд curl:

curl http://host:8080/customServlet?command=exp

Если я попытаюсь использовать http://host:8080/customServlet в firefox или chrome с servletWebDir, установленным на "/ "Я получаю 404. Обратите внимание, что этот код отлично работает под причалом v8.1.16.v20140903.

Что я делаю неправильно? Что я упустил в Jetty v9.x?

Обновленный код, который использует setBaseResource и удаляет ResourceHandler:

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
final String servletWebDir = "/";
final String theBaseResourceDir = "/aa/bb/cc";
Resource theBaseResource = null;
try{
    theBaseResource = Resource.newResource( theBaseResourceDir );
}
catch( MalformedURLException e ){
    System.err.println( "setup failed on newResource with the exception " + e.toString() );
    System.exit(0);
}

servletHandler.setBaseResource( theBaseResource );
System.err.println("Class path->" + servletHandler.getClassPath() );

final customServlet iass = new customServlet();
final ServletHolder servletHolder = new ServletHolder( iass );
servletHolder.setInitOrder(0);
servletHandler.addServlet( servletHolder, "/customServlet" );
final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ servletHandler } );
server.setHandler( handlers );

Этот новый код больше не обслуживает статическую страницу в веб-браузере независимо от значения servletWebDir. Взаимодействие с настраиваемым сервлетом через curl по-прежнему работает. Если приведенный выше новый код верен, я что-то пропустил? Путь к классу отображается в журналах ошибок как null. Что я могу попробовать дальше?

Иоаким:

Я попробовал предложенный вами код. Я очень ценю время и усилия, которые вы потратили на подготовку образца кода. Однако код не работает во время выполнения. В журнале ошибок указано:

STDERR: 2015-05-09 15: 51: 32.278: WARN: / embed: main: unavailable java.lang.IllegalAccessException: Class org.eclipse.jetty.server.handler.ContextHandler $ Context не может получить доступ к члену класса customServlet с модификаторы "private" в sun.reflect.Reflection.ensureMemberAccess (Reflection.java:102)

Исключение не указывает точного члена, который должен быть обнародован. Мой обновленный код действительно работает, и мне не нужно менять целую кучу методов с частных на общедоступные.

Йоаким, не могли бы вы объяснить преимущества вашего решения, которое, если я не ошибаюсь, требует изменения частных методов и элементов данных на элементы и методы общедоступных данных и, следовательно, теряет некоторые преимущества инкапсуляции.

Обновленный код, устраняющий эту проблему:

server = new Server();
final ServerConnector connector = getConnector( server );
connector.setReuseAddress(false);
connector.setSoLingerTime(0);

final int port = 8080;
connector.setHost( theHostName );
connector.setPort( port );

server.addConnector(connector);

final String theRootContextDir = "/";
final ContextHandler rootContext = new ContextHandler(theRootContextDir);
final String theBaseResourceDir = ".";
rootContext.setResourceBase( theBaseResourceDir );

final ResourceHandler rhx = new ResourceHandler();
rootContext.setHandler( rhx );

/**
  * I want to replace the default jetty error handler with my
  * custom error handler. However I have not figured out how
  * to do it under jetty v9.x, yet-(May.08.2015,W.S.)
  * final ErrorHandler uiErrHandler = new userInputErrorHandler( logger );
  * rootContext.setErrorHandler( uiErrHandler );
  ***/

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

final String theServletContextPath = "/";
servletHandler.setContextPath( theServletContextPath );
servletHandler.setResourceBase( "." );

final customServlet iass = new customServlet();
final ServletHolder servletHolder = new ServletHolder( iass );
final MultipartConfigElement mce = new MultipartConfigElement( fileUploadTmpDir );
servletHolder.getRegistration().setMultipartConfig( mce );
servletHolder.setInitOrder(0);
final String theServletName = "/customServlet";
servletHandler.addServlet( servletHolder, theServletName );

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ rootContext, servletHandler } );

server.setHandler( handlers );
06.05.2015

Ответы:


1

Вы используете ServletContextHandler, вы не можете смешивать это с ResourceHandler, поскольку встроенный DefaultServlet ServletContextHandler будет обслуживать файлы (или давать ответ об ошибке), оставляя ResourceHandler никогда не запускаться.

Чтобы исправить:

Отбросьте ResourceHandler (в любом случае он намного уступает DefaultServlet).

Установите _ 8_ в корневой каталог вашего веб-приложения (где находятся ваши статические файлы). Это может быть URL-адрес, URI или ссылка на путь к файловой системе.

Примеры:

// As a file system reference
servletHandler.setBaseResource(Resource.newResource("/path/to/res"));

// or URL
servletHandler.setBaseResource(Resource.newResource("jar:file://tmp/b.jar!/webroot"));

Путь к ресурсу должен указывать на каталог, а не на конкретный файл.

Дополнительные сведения см. В предыдущем ответе по этому поводу.

Пример:

package jetty;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.nio.file.Path;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.resource.Resource;

public class SimpleServletExample
{
    public static void main(String[] args)
    {
        try
        {
            Server server = new Server(8080);

            // Find the full path to the webroot.
            // Use the real path, with real file system case for all parts of the path
            // Otherwise we fall afoul of alias checking.
            // (esp on OSX and Windows. Unix and Linux do not have this issue)
            Path webrootPath = new File("src/test/resources/sample-files").toPath().toRealPath();

            URI webrootUri = webrootPath.toUri();

            System.err.println("webroot uri: " + webrootUri);

            Resource webroot = Resource.newResource(webrootUri);
            if (!webroot.exists())
            {
                System.err.println("Resource does not exist: " + webroot);
                System.exit(-1);
            }

            if (!webroot.isDirectory())
            {
                System.err.println("Resource is not a directory: " + webroot);
                System.exit(-1);
            }

            // Establish ServletContext for all servlets
            ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
            context.setContextPath("/");
            context.setBaseResource(webroot);
            // What file(s) should be used when client requests a directory
            context.setWelcomeFiles(new String[] { "index.html" });
            server.setHandler(context);

            // Add a servlet (technique #1)
            ServletHolder holderHello = context.addServlet(HelloServlet.class,"/hello");
            holderHello.setInitOrder(0);

            // Add default servlet last (always last) (technique #2)
            // Must be named "default", must be on path mapping "/"
            ServletHolder holderDef = new ServletHolder("default",DefaultServlet.class);
            holderDef.setInitParameter("dirAllowed","true");
            context.addServlet(holderDef,"/");

            // Start server
            server.start();
        }
        catch (MalformedURLException e)
        {
            System.err.println("Unable to establish webroot");
            e.printStackTrace(System.err);
        }
        catch (Throwable t)
        {
            t.printStackTrace(System.err);
        }
    }
}
06.05.2015
  • Привет: Я сделал, как вы предложили. Я использовал setBaseResource и удалил ResourceHandler. Однако это не работает, даже если я установил для servletWebDir значение / embed. Не могли бы вы сделать еще одно предложение. Спасибо за уделенное время. 07.05.2015
  • @westsuhanic в плохой форме, чтобы отредактировать чей-то ответ с дополнительными вопросами, используйте свой собственный исходный вопрос, чтобы опубликовать обновление вопроса. (пошел вперед и сделал это за вас) 07.05.2015
  • Этот ответ не приводит к тому, что server обслуживает статические ресурсы для меня. 07.03.2017
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..