Как получить доступ к статическим ресурсам при отображении глобального сервлета фронтального контроллера на/*

Какую версию Node вы используете? Если имеется async / await, это очищает кучу.

const moveCsv = (file, dest) => {
    return new Promise((resolve, reject) => {
        //third
        file.mv(dest, function (err) {
            if (err) reject(err);
            resolve();
        });
    })
}

app.post('/', async(req, res) => {
    try {
        var filename = `outputs/${Date.now()}_output.json`;

        const {
            trainInput,
            trainOutput,
            testInput
        } = req.files;

        const prefix = `inputs/${req.body.caseName}`;
        await moveCsv(trainInput, `${prefix}/train_input.csv`);
        await moveCsv(trainOutput, `${prefix}/train_output.csv`);
        await moveCsv(testInput, `${prefix}/test_input.csv`);
        res.send('success');
    } catch(err) {
        res.status(500).send(err);
    }
});

Я также предполагаю, что ваши trainInput, trainOutput, testOutput не все должны были быть req.files.trainInput.

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

58
задан BalusC 6 June 2015 в 22:45
поделиться

8 ответов

Я тоже сталкивался с этим и так и не нашел отличного решения. В итоге я сопоставил свой сервлет на один уровень выше в иерархии URL:

<servlet-mapping>       
  <servlet-name>home</servlet-name>             
  <url-pattern>/app/*</url-pattern>     
</servlet-mapping>

И теперь все в базовом контексте (и в вашем каталоге / res) может обслуживаться вашим контейнером.

12
ответ дан 24 November 2019 в 18:38
поделиться

Я бы порекомендовал попробовать использовать фильтр вместо сервлета по умолчанию, когда это возможно.

Другие две возможности:

Напишите FileServlet самостоятельно. Вы найдете множество примеров, он должен просто открыть файл по URL-адресу и записать его содержимое в выходной поток. Затем используйте его для обслуживания запроса статического файла.

Создайте экземпляр класса FileServlet, используемого Google App Engine, и вызовите службу (запрос, ответ) на этом FileServlet, когда вам нужно обслужить статический файл по заданному URL-адресу.

Вы может отобразить / res / * на YourFileServlet или что-то еще, чтобы исключить его из обработки DispatcherServlets, или вызвать его непосредственно из DispatcherServlet.

И я должен спросить, что в документации Spring говорится об этом конфликте? Я никогда им не пользовался.

Я должен спросить, что в документации Spring говорится об этом столкновении? Я никогда им не пользовался.

Я должен спросить, что в документации Spring говорится об этом столкновении? Я никогда им не пользовался.

0
ответ дан 24 November 2019 в 18:38
поделиться

Если вы используете Tomcat, вы можете сопоставить ресурсы сервлету по умолчанию:

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
</servlet-mapping>

и получить доступ к своим ресурсам с помощью url http: // {context path} / static / res / ...

Также работает с Jetty, но не уверен в других контейнерах сервлетов.

17
ответ дан 24 November 2019 в 18:38
поделиться

«Статические» файлы в App Engine не доступны напрямую из вашего приложения. Вам нужно либо загрузить их дважды, либо обслуживать статические файлы самостоятельно, а не использовать статический обработчик.

3
ответ дан 24 November 2019 в 18:38
поделиться

Причина коллизии, по-видимому, в том, что по умолчанию корень контекста "/ ", должен обрабатываться org.apache.catalina.servlets.DefaultServlet. Этот сервлет предназначен для обработки запросов на статические ресурсы.

Если вы решите убрать его с пути с помощью собственного сервлета с целью обработки динамических запросов, этот сервлет верхнего уровня должен также выполнять любые задачи, выполняемые с помощью исходный обработчик "DefaultServlet" catalina.

Если вы прочитали документацию tomcat, они упоминают, что True Apache (httpd) лучше, чем Apache Tomcat для обработки статического контента, поскольку он специально создан для этого. Я предполагаю, что Tomcat по умолчанию использует org.apache.catalina.servlets.DefaultServlet для обработки статических запросов. Поскольку все это завернуто в JVM, а Tomcat предназначен как контейнер сервлета / JSP, они, вероятно, не писали этот класс как супероптимизированный обработчик статического содержимого. Это здесь. Он выполняет свою работу. Достаточно хорошо.

Но это то, что обрабатывает статический контент и находится в "/". Итак, если вы поместите туда что-нибудь еще, и эта штука не обрабатывает статические запросы, WHOOPS, туда уйдут ваши статические ресурсы.

Я много и мало искал один и тот же ответ, и везде получаю ответ: «Если вы этого не хотите,

5
ответ дан 24 November 2019 в 18:38
поделиться

Что вы делаете, так это добавляете приветственный файл в свой web.xml

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
</welcome-file-list>

, а затем добавляете его в свои сопоставления сервлетов, чтобы, когда кто-то заходит в корень вашего приложения, они отправлялись в index.html внутри, а затем отображение будет внутренне отправлять их сервлету, которому вы сопоставляете его

<servlet-mapping>
    <servlet-name>MainActions</servlet-name>
    <url-pattern>/main</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>MainActions</servlet-name>
    <url-pattern>/index.html</url-pattern>
</servlet-mapping>

. Конечный результат: вы посещаете / Application, но вам предоставляется сервлет / Application / MainActions, не прерывая никаких других корневых запросов.

Поняли? Таким образом, ваше приложение по-прежнему находится на дополнительном URL-адресе, но автоматически отображается, когда пользователь переходит в корень вашего сайта. Это позволяет вам, чтобы /images/bob.img все еще находился в обычном месте, но '/' - это ваше приложение.

19
ответ дан 24 November 2019 в 18:38
поделиться

Сопоставьте сервлет контроллера с более конкретным URL-шаблоном, например /pages/*, поместите статическое содержимое в определенную папку, например /static и создайте Filter, прослушивающий /*, который прозрачно продолжает цепочку для любого статического контента и отправляет запросы сервлету контроллера для другого контента.

В двух словах:

<filter>
    <filter-name>filter</filter-name>
    <filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
    <filter-name>filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
    <servlet-name>controller</servlet-name>
    <servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>controller</servlet-name>
    <url-pattern>/pages/*</url-pattern>
</servlet-mapping>

со следующим в фильтре doFilter():

HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());

if (path.startsWith("/static")) {
    chain.doFilter(request, response); // Goes to default servlet.
} else {
    request.getRequestDispatcher("/pages" + path).forward(request, response);
}

Нет, это не приводит к /pages в адресной строке браузера. Он полностью прозрачен. При необходимости вы можете сделать "/static" и/или "/pages" init-param фильтра.

71
ответ дан 24 November 2019 в 18:38
поделиться

Добавьте папки, которые не должны запускать обработку сервлета, в раздел вашего файла appengine-web.xml.

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

/

/pages/<.jsp files>

/css

Я добавил "/pages/**" и "/css/**" в < static-files> , и теперь я могу перенаправить файл .jsp из сервлета doGet, не вызывая бесконечного цикла.

1
ответ дан 24 November 2019 в 18:38
поделиться
Другие вопросы по тегам:

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