Подтвердить что ты не робот

Доступ к файлам/каталогам в папке webapp в Spring

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

-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 запросов возвращают null. Я что-то не так?

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.

Спасибо!

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

Update2:, благодаря предложению @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/");

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

4b9b3361

Ответ 1

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

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

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

Обновление

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

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

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

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

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

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

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

Ответ 2

Учитывая расположение файла, вы должны изучить 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;
    }
}

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

Ответ 3

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

Я запускаю JDK 1.7_02 Tomcat 7.0.25 Spring 3.1.1

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

    @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";
        }
    }

Ответ 4

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

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

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

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

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

Ответ 5

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

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

Ответ 6

вы можете попробовать следующее:

@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("/");
       //...
    }
}