2013-12-05 4 views
3

У меня есть Spring webapp, чей файл .war был загружен на сервер Tomcat. Большинство основных функций работают по назначению - просмотры страниц и представления формы.Tomcat сервер абсолютный доступ к файлам в war webapp

Моя проблема в том, что мой webapp должен читать и писать файлы, и я не знаю, как я могу это достичь (вывод ввода/вывода файлов java.lang.NullPointerException).

Я использовал следующий code to get the absolute path of a given file предложенный Titi Wangsa Bin Damhore знать путь относительно сервера:

HttpSession session = request.getSession(); 
ServletContext sc = session.getServletContext(); 
String file = sc.getRealPath("src/test.arff"); 
logger.info("File path: " + file); 

Здесь есть выходной путь:

/home/username/tomcat/webapps/appname/src/test.arff 

Но когда я проверил файл каталога с помощью WinSCP , фактический путь файла:

/home/username/tomcat/webapps/appname/WEB-INF/classes/test.arff 

Вот мои вопросы:

  1. Как превратить эти пути в нечто вроде C:/Users/Workspace/appname/src/test.arff (исходного пути в моей локальной машине, которая прекрасно работает)? Это серверы Apache Tomcat 6.0.35 и Apache Tomcat 6.0.35.
  2. Почему код возвращает другой путь в отличие от фактического пути?
  3. Если файл ввода-вывода не применим, какие альтернативы я могу использовать?

PS мне просто нужно открыть два файла (< 1MB каждая), так что я не думаю, что, возможно, придется использовать базу данных, чтобы содержать их в соответствии с предложением minus в this thread.

File I/O

Ниже приведен код, который я использую для доступа к файлу мне нужно.

BufferedWriter writer; 
    try { 
     URI uri = new URI("/test.arff"); 
     writer = new BufferedWriter(new FileWriter(
      calcModelService.getAbsolutePath() + uri)); 

     writer.write(data.toString()); 
     writer.flush(); 
     writer.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (URISyntaxException e) { 
     e.printStackTrace(); 
    } 

ответ

3

Для чтения файлов:

ServletContext application = ...; 
InputStream in = null; 

try { 
    in = application.getResourceAtStream("/WEB-INF/web.xml"); // example 

    // read your file 
} finally { 
    if(null != in) try { in.close(); } 
    catch (IOException ioe) { /* log this */ } 
} 

для записи файлов:

ServletContext application = ...; 
File tmpdir = (File)application.getAttribute("javax.servlet.context.tempdir"); 

if(null == tmpdir) 
    throw new IllegalStateException("Container does not provide a temp dir"); // Or handle otherwise 

File targetFile = new File(tmpDir, "my-temp-filename.txt"); 
BufferedWriter out = null; 

try { 
    out = new BufferedWriter(new FileWriter(targetFile)); 

    // write to output stream 
} finally { 
    if(null != out) try { out.close(); } 
    catch (IOException ioe) { /* log this */ } 
} 

Если вы не хотите использовать TMPDIR предоставленный контейнер сервлетов, то вы должны использовать где-нибудь то есть полностью вне контекста контекста сервлета, например /path/to/temporary/files или что-то в этом роде. Вы определенно не хотите использовать временный каталог контейнера для чего-либо, кроме действительно временных файлов, которые можно удалить при повторном развертывании и т. Д.

+0

I Googled, как инициализировать 'ServletContext', но все они, похоже, создают для него новый класс. Как его инициализировать, если это только для этого класса? –

+2

«ServletContext» - это объект, который уже должен быть доступен вашему сервлету. Я оставлю это упражнением для вас, чтобы выяснить, где его взять. Подсказка: прочитайте javadocs API сервлета. –

2

Это война; вы не читаете/не записываете файлы внутри него.

Чтение тривиально; поместите файлы в путь к классам и прочитайте их как ресурс.

В любом случае вы не должны писать внутри веб-приложения, так как даже если он не был войной, вещи внутри контекста могли исчезнуть во время перераспределения, это может быть только на одном сервере, если вы кластеризованы и т. д. Файловые записи должны жить где-то настраиваемыми.

+0

Спасибо. Итак, файлы уже находятся в пути к классам ('/ root/src /'), но как я их читаю как ресурс *? Нужно ли объявлять их в файле 'xml'? –

+1

@thekalaban http://stackoverflow.com/q/1464291/438992 например, хотя это тривиально доступно для поиска на SO и в Интернете в целом. –

+0

Если вы вызываете 'getRealPath', вы делаете это неправильно. –

0

Если нет причин, то вам действительно нужен java.io.File, загрузите файл из classpath и не беспокойтесь о том, откуда он.

getClass().getClassLoader().getResourceAsStream("test.arff") 
+0

Хорошо, я получаю это, поэтому с 'test.arff' я просто создам и прочитаю его, используя этот код правильно? Что касается моего другого файла, который * только читается * и находится в '/ home/username/tomcat/webapps/appname/WEB-INF/classes/mlp.model'? Как мне получить к нему доступ? –

+0

Все, что попадает в 'classes /', я думаю, должно быть на пути к классам, поэтому вы можете использовать этот метод. Вы не можете писать файлы таким образом, и вы не должны действительно писать _ в 'WEB-INF'. –

+0

@ thekalaban Вы используете 'getServletContext(). GetResource ("/WEB-INF/classes/mlp.model ")'. Прочтите API некоторое время. Он будет творить чудеса для вашей производительности. –

0

Я использовал Spring Resource component to get my file path как предложено yawn, как это (NOTEtest.arff находится в root/src, прежде чем war развертывания):

Resource resource = new ClassPathResource("/test.arff"); 
String arffPathRaw = resource.getURI().toString(); // returns file:/path/to/file 
String arffPath = arffPathRaw.replace("file:/", ""); // pure file path 

Далее, я просто сцепляются arff к файлам, которые я хочу, как :

URI uri = new URI("test.arff"); 
BufferedWriter writer = new BufferedWriter(new FileWriter(
     arffPath + uri)); 

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

  1. Путь к файлу на самом деле /home/username/tomcat/webapps/bosom/WEB-INF/classes/test.arff, так что не бойтесь использовать это (как я сделал) только потому, что он не похож на C:/path/to/file LMAO

  2. Эти два пути файла одинаковы, если используемые для получения файла, не путайте.

+1

Это решение не будет работать, если ваш webapp не будет развернут как файл с расширенным WAR-файлом. Поэтому он является хрупким. Использование класса ClassLoader или ServletContext для получения ресурсов - более надежное решение. Это решение, как представляется, использует «ClassLoader», но затем управляет URL-адресом и загружает ресурс с помощью стандартного ввода-вывода файлов. :( –

+0

@ChristopherSchultz, не могли бы вы дать рабочий код, который я могу имитировать, пожалуйста? –

+0

Возможно, вы должны использовать атрибут «Файл», который можно найти в «ServletContext» под ключом «javax.servlet.context.tempdir». Или вы должны хранить ваши файлы в известном месте полностью за пределами веб-приложения (например, в '/ some/place/for/temp/files'). –