Доступ к файлам / каталогам в папке webapp в Spring - PullRequest
15 голосов
/ 06 февраля 2012

Я неопытный в Spring, и все, что мне нужно сейчас сделать, - это получить доступ и получить ссылку на файлы и папки в папке веб-приложения. Вот моя соответствующая иерархия проектов:

-src
--main
---java (marked as source root)
----my
-----package
------controller
-------Home.java
---webapp
----images
-----avatars

Мой код в Home.java:

@Controller
@RequestMapping("/")
public class Home
{
    @RequestMapping(method = RequestMethod.GET)
    public String index(Model model,
                        HttpServletRequest request) throws Exception
    {
        String test1 = request.getSession().getServletContext().getRealPath("");
        String test2 = request.getSession().getServletContext().getRealPath("/");
        String test3 = request.getRealPath("");
        String test4 = request.getRealPath("/");
        String test5 = request.getSession().getServletContext().getRealPath(request.getServletPath());

        return "index";
    }
}

Все 5 запросов возвращают ноль. Я что-то не так делаю?

web.xml:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <display-name>Test</display-name>

    <servlet>
        <servlet-name>test</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>test</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <session-config>
        <session-timeout>10</session-timeout>
    </session-config>
</web-app>

То, чего я пытаюсь достичь (не показано в этом примере), - это написать код контроллера, отвечающего за масштабирование изображения. По этой причине мне потребуется доступ к папке src / main / webapp / _images.

Спасибо!

Обновление: упрощен пример для лучшего понимания.

Обновление2: Благодаря предложению @gigadot я развернул приложение в виде развернутой WAR, и проблема частично решена. Может кто-нибудь сказать мне, в чем разница в развертывании WAR в разобранном виде? Это не рекомендуется делать на производственном сервере? Преимущества / недостатки?

Я думаю, что стоит объяснить ситуацию на примере. Допустим, я кодирую социальную сеть и у меня есть возможность загрузить свою личную фотографию профиля. Это изображение будет загружено в папку src/main/webapp/_images/avatars/[myid].jpg. Рекомендуется ли загружать изображения в папку webapp? Или есть лучшее решение? Я хотел бы иметь возможность вернуть масштабированный экземпляр изображения при доступе к URL /images/[width]x[height]/[userid].jpg.

Развернув WAR в разобранном виде и внедрив ResourceLoaderAware (спасибо @KevinSchmidt), я могу заставить его работать, используя это:

resourceLoader.getResource("file:" + request.getSession().getServletContext().getRealPath("/") + "_images/avatars/");

Для меня это выглядит довольно грязно, это хорошая идея для производственного сервера? Есть ли лучшее решение?

Ответы [ 6 ]

16 голосов
/ 21 февраля 2012

Как именно вы развернули свое приложение?

ServletContext().getRealPath("/") может возвращать ноль, если он не развернут как взорванный. Прочитайте ссылку ниже для получения дополнительной информации. Однако способ настройки этого может не совпадать с вашим контейнером сервлета.

http://ananthkannan.blogspot.com/2009/12/servletcontextgetrealpath-returns-null.html

Обновление

Может кто-нибудь сказать мне, в чем разница в развертывании WAR как взорвалось?

Когда вы развертываете файл войны в разобранном виде, контейнер сервлетов, например, Tomcat извлекает содержимое файла war во временную папку и запускает все из этой папки, так что {WEB_ROOT]/_images/avatars/[myid].jpg фактически существует в файловой системе (жестком диске). Следовательно, вы можете получить реальный путь (как уже сказано в названии метода). Однако, если ваш контейнер сервлетов не извлекает файл war, папка, которую вы ищете, находится внутри файла war, и к ней нет реального пути, поэтому он вернет null.

Что-то не рекомендуется делать на производственном сервере? Преимущества / недостатки?

Вы не должны хранить динамическое содержимое в исходной папке или в папке webroot (webapp), поскольку контейнер сервлета будет использовать его временно и удалять или переходить в новую папку при повторном развертывании веб-приложения. Вероятно, вы потеряете динамические данные, которые вы поместили в эти папки. Корневая веб-папка обычно предназначена для хранения статического содержимого, то есть содержимого, которое вы не хотите изменять, например графических изображений для вашего веб-компонента, таких как фоновые изображения, CSS и т. Д.

Обычный метод хранения пользовательских данных - каким-то образом создать папку в пользовательском пространстве и поместить туда ваши динамические данные. Однако вы не сможете обслуживать содержимое папки за пределами webroot. Вам нужно будет написать свой собственный статический сервлет для передачи данных по запросу. Это довольно сложно для новичка.

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

Поскольку вы собираетесь предоставить REST-интерфейс для изменения размера изображений, вы можете создать контроллер, который будет считывать исходные изображения из папки динамического содержимого, выполнять изменение размера, сохранять его как временный файл или очищать содержимое HttpResponse.

5 голосов
/ 23 февраля 2012

Учитывая расположение файла, вы должны посмотреть на Spring ResourceLoader , например так:

public class ArbitraryResourceLoader implements ResourceLoaderAware {
    private ResourceLoader resourceLoader;

    public void test() {
        Resource resource = resourceLoader.getResource("file:webapp/images/avatars/avatar.jpg");
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}

Помните, что вашему контейнеру необходимо разрешение на доступ к файлу.

4 голосов
/ 19 февраля 2012

Это мой код и он работает Я не получаю ноль.

Я использую JDK 1.7_02 Tomcat 7.0.25 Весна 3.1.1

И я не получаю нули

    @Controller
    public class IndexController {

        @RequestMapping("/index")
        public String go(HttpServletRequest request, HttpServletResponse response) {
            HttpSession session = request.getSession();
            ServletContext sc = session.getServletContext();
            String x = sc.getRealPath("/");
            System.out.println(x);
            return "index";
        }
    }
0 голосов
/ 19 февраля 2012

Вы можете попробовать это:

@Controller
@RequestMapping("/")
public class Home implements ServletContextAware
{
    private ServletContext servletContext;
    public void setServletContext(ServletContext servletCtx){
       this.servletContext=servletCtx;
    }

    @RequestMapping(method=RequestMethod.GET)
    public String index(Model model,HttpServletRequest) throws Exception{
       String rootPath = servletContext.getRealPath("/");
       //...
    }
}
0 голосов
/ 19 февраля 2012

Посмотрите на использование <mvc:resources> в справочнике Spring, раздел 16.14.5 Настройка обслуживания ресурсов .Я использую этот метод для моих JavaScript / CSS / изображений, и он прекрасно работает - мне просто нужно было добавить одну строку в мой application-context.xml файл.Документация гласит:

Это обеспечивает удобный способ обслуживания статических ресурсов из расположений, отличных от корня веб-приложения, включая местоположения на пути к классам.

0 голосов
/ 06 февраля 2012

ClassPathResource может помочь вместо.Ваш способ доступа к ресурсу в classpath, если категорически неверен.

Что касается расположения веб-ресурсов, то те, которые хранятся в src / main / resources, будут развернуты в папке WEB-INF / classes, поэтомуэто явно не идти.Вместо этого пользователь webapp.

Обновление: теперь я вижу, откуда вы.Я не вижу в этом ничего плохого, хотя и чрезвычайно экзотическогоСкорее всего, отображение DispatcherServlet не покрывает папку images (т. Е. Это не /*).

Что касается открытия файла, каталог webapp не виден из загрузчика классов, за исключением папки WEB-INF.Таким образом, вам нужно будет вызывать метод HttpServletRequest.getRealPath(), чтобы получить реальный путь к изображению.

Обратите внимание, что, хотя это маловероятно, в вашем случае усиленные Java JVM (то есть JVM с политиками безопасности)) может потребовать дополнительных привилегий, чтобы сервлет мог открыть файл из произвольного местоположения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...