Доступ к ресурсам из Spring

Автор PremaServices - Пятница, 21 Июнь 2013. В рубриках: Spring

Работа с файловой системой

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

В контексте обычного сервлета Java мы привыкли делать это таким образом:

public void init (ServletConfig conf) throws ServletException {
	InputStream in = conf.getServletContext().getResourceAsStream(path);
	
}

В Spring все делается также просто, но немного иначе. Для начала необходимо создать класс, который будет отвечать за загрузку ресурсов, и унаследовать его от org.springframework.context.ResourceLoaderAware.


ResourceLoader

package ru.premaservices.koladwip.controller;
 
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
 
@Service
public class ResourceLoaderService implements ResourceLoaderAware {
	
	private ResourceLoader resourceLoader;
	 
	public void setResourceLoader(ResourceLoader resourceLoader) {
		this.resourceLoader = resourceLoader;
	}
 
	public Resource getResource(String location) {
		return resourceLoader.getResource(location);
	}
}

И затем вызывать из приложения обычным способом (например, из контроллера):

package ru.premaservices.koladwip.controller;
...
@Controller
public class ExerciseController {
	
	@Autowired
	private ResourceLoaderService resourceLoader;
	
	...
	
	@RequestMapping(value = YOGA_EX_IMAGE_REQUEST)
	public ResponseEntity<byte[]> getImage (@RequestParam("id") Integer id, @RequestParam("t") Character type) {
	   byte[] content = null;
	   
	   if (type == FOTO_TYPE) 
		   content = exerciseManager.getExerciseFoto(id);
	   else if (type == PREVIEW_TYPE) 
		   content = exerciseManager.getExercisePreview(id);
	   
	   if (content == null) {
		   try {
			   //load standard pictures
			   String path = "classpath:ru/premaservices/koladwip/view/";
			   if (type == FOTO_TYPE) path += "lotos.png";
			   else if (type == PREVIEW_TYPE) path += "lotos_preview.png";
			   Resource resource = resourceLoader.getResource(path);
			   content = FileUtil.getImage(resource.getInputStream());
		   }
		   catch (IOException e) {
			   e.printStackTrace();
			   content = new byte[0];
		   }
	   }
	   
	   HttpHeaders headers = new HttpHeaders();
	   headers.setContentType(MediaType.IMAGE_PNG);
	   return new ResponseEntity<byte[]>(content, headers, HttpStatus.OK);
	}
	...
}

Вот и всё. В вышеприведенном примере мы выгружаем PNG-картинку по ее ID. Если она не найдена в базе, тогда ищем картинку по умолчанию в classpath проекта.


ServletContext

Для некоторых случаев можно организовать доступ к контексту сервлета. Тогда необходимо унаследовать класс от org.springframework.web.context.ServletContextAware.

package ru.premaservices.koladwip.controller;
 
import java.io.FileNotFoundException;
import java.io.InputStream;
import javax.servlet.ServletContext;
import org.springframework.stereotype.Service;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.util.WebUtils;
 
@Service
public class ServletContextService implements ServletContextAware {
	
	private ServletContext servletContext;
 
	@Override
	public void setServletContext(ServletContext context) {
		this.servletContext = context;
	}
	
	public String getRealPath (String path) throws FileNotFoundException {
		return WebUtils.getRealPath(servletContext, path);
	}
	
	public InputStream getResourceAsStream (String name) {
		return servletContext.getResourceAsStream(name);
	}
}

И затем вызывать эти знакомые методы аналогично тому, как это делается в обычном сервлете.

@Autowired
private ServletContextService contextService;
...
String fullname = contextService.getRealPath("our_file.xml");


MessageSource

Как мы знаем, в Spring есть замечательный способ управлять локализацией сообщений через определение в конфигурации специального файла свойств.

	<!-- Messages -->
	<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>/WEB-INF/classes/messages</value>
            </list>
        </property>
        <property name="defaultEncoding" value="utf-8"/>
        <property name="fallbackToSystemLocale" value="true"/>
 	</bean>

В этом случае в JSP все значения свойств, определенные в файле messages.properties станут доступны через директиву spring:message. Однако, иногда необходимо сделать этот файл доступным не только в JSP, но и в контексте приложения. Для этого мы последуем все тому же способу: сначала определим специальный класс.

package ru.premaservices.astroved.student.service;
 
import java.util.Properties;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.context.support.MessageSourceAccessor;
 
@Service
public class ApplicationMessageSource extends ApplicationObjectSupport {
	
	public String getMessage(String key) {  
		
        MessageSourceAccessor messageSourceAccessor = this.getMessageSourceAccessor();   
        return messageSourceAccessor.getMessage(key);  
    }  
	
	public Properties getMessages (String keys[]) {
		
		MessageSourceAccessor messageSourceAccessor = this.getMessageSourceAccessor(); 
		Properties p = new Properties();
		if (keys != null) {
			for (String key : keys) {
				p.put(key, messageSourceAccessor.getMessage(key));
			}
		}
		return p;
	}
}

Он позволит нам получать как текст отдельного сообщения по его ID, так и набор сообщений из файла. область применения: ну, например, нам нужно получить русские названия для значений перечисления.

package ru.premaservices.astroved.student.pojo;
public enum Course {
	NONE, ABITURIENT, FIRST, SECOND, THIRD, FORTH, GRADUATE
	
}

 

package ru.premaservices.astroved.student.controller;
...
@Controller
public class StudentController {
 
	@Autowired
	ApplicationMessageSource messageSource;
	
	...
	
	private HashMap<String, String> getCourseMap () {
		Course[] courses = Course.values();
		HashMap<String, String> cMap = new HashMap<String, String>(courses.length);
		for (Course t : courses) {
			if (t != Course.NONE) {
				String key = t.toString();
				String value = messageSource.getMessage("str.enum.Course." + key);
				cMap.put(key, value);
			}
		}
		return cMap;
	}
}

На этом пока всё.

Об авторе

Комментарии (0)

Оставить комментарий

Вы комментируете как Гость.