Spring Загрузка нестатического статического содержимого
Я ударяю головой о стену в течение нескольких часов. Мой проект почти закончен, но я не могу заставить его обслуживать статический контент.
Я разместил папку под static
под src/main/resources
. Внутри у меня есть папка с именем images
. Когда я упаковываю приложение и запускаю его, он не может найти изображения, которые я разместил в этой папке.
Я попытался поместить статические файлы в public
, resources
и META-INF/resources
, но ничего не работает.
Если я jar -tvf app.jar, я вижу, что файлы находятся внутри jar в правой папке:
/static/images/head.png
например, но вызов: http://localhost:8080/images/head.png
, все, что я получаю, это 404
Любые идеи, почему spring -boot не находит это? (Я использую 1.1.4 BTW)
Ответы
Ответ 1
Не поднимать мертвых после более чем года, но все предыдущие ответы пропускают некоторые важные моменты:
-
@EnableWebMvc
на вашем классе отключит org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration
. Это прекрасно, если вы хотите полного контроля, но в противном случае это проблема.
-
Нет необходимости писать код, чтобы добавить другое место для статических ресурсов в дополнение к тому, что уже предусмотрено. Посмотрев org.springframework.boot.autoconfigure.web.ResourceProperties
с v1.3.0.RELEASE, я вижу поле staticLocations
, которое можно настроить в application.properties
. Вот фрагмент из источника:
/**
* Locations of static resources. Defaults to classpath:[/META-INF/resources/,
* /resources/, /static/, /public/] plus context:/ (the root of the servlet context).
*/
private String[] staticLocations = RESOURCE_LOCATIONS;
-
Как упоминалось ранее, URL-адрес запроса будет разрешен относительный для этих местоположений. Таким образом, src/main/resources/static/index.html
будет использоваться, когда URL-адрес запроса /index.html
. Класс, который отвечает за разрешение пути, как Spring 4.1, org.springframework.web.servlet.resource.PathResourceResolver
.
-
Согласование шаблонов суффикса включено по умолчанию, что означает URL-адрес запроса /index.html
, Spring будет искать обработчики, соответствующие /index.html
. Это проблема, если целью является статический контент. Чтобы отключить это, расширьте WebMvcConfigurerAdapter
(но не используйте @EnableWebMvc
) и переопределите configurePathMatch
, как показано ниже:
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
super.configurePathMatch(configurer);
configurer.setUseSuffixPatternMatch(false);
}
IMHO, единственный способ уменьшить количество ошибок в вашем коде - это не писать код, когда это возможно. Используйте то, что уже предоставлено, даже если это требует некоторых исследований, возврат стоит того.
Ответ 2
В отличие от состояния spring -boot, чтобы получить мой spring -boot jar для обслуживания содержимого:
Мне пришлось добавить специально зарегистрировать мой src/main/resources/static content через этот класс конфигурации:
@Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/" };
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
}
}
Ответ 3
У меня была аналогичная проблема, и оказалось, что простым решением было расширение класса конфигурации WebMvcAutoConfiguration
:
@Configuration
@EnableWebMvc
@ComponentScan
public class ServerConfiguration extends WebMvcAutoConfiguration{
}
Мне не нужен какой-либо другой код, чтобы разрешить мой статический контент, но я поместил каталог под public
под src/main/webapp
и настроил maven для указания на src/main/webapp
в качестве каталога ресурсов. Это означает, что public
копируется в target/classes
и поэтому находится на пути к классам во время выполнения для spring -boot/tomcat, чтобы найти.
Ответ 4
Посмотрите на контроллеры, сопоставленные с "/" или без отображения пути.
У меня была такая проблема, получилось 405 ошибок, и я долго бил головой. Проблема оказалась аннотированным контроллером @RestController
, который я забыл аннотировать с аннотацией @RequestMapping
. Я предполагаю, что этот сопоставленный путь по умолчанию был "/" и заблокировал сопоставление ресурса статического содержимого.
Ответ 5
Конфигурация может быть выполнена следующим образом:
@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcAutoConfigurationAdapter {
// specific project configuration
}
Важно, чтобы ваш WebMvcConfig
мог переопределить addResourceHandlers
метод, и поэтому вам нужно явно вызвать super.addResourceHandlers(registry)
(это правда, что если вас устраивают местоположения ресурсов по умолчанию, не нужно переопределять какой-либо метод).
Еще одна вещь, которая должна быть прокомментирована здесь, заключается в том, что эти местоположения ресурсов по умолчанию (/static
, /public
, /resources
и /META-INF/resources
) будут зарегистрированы только в том случае, если еще не обработчик ресурсов, сопоставленный с /**
.
С этого момента, если у вас есть образ на src/main/resources/static/images
с именем image.jpg
, например, вы можете получить к нему доступ, используя следующий URL-адрес: http://localhost:8080/images/image.jpg
(будучи сервером, запущенным на порту 8080, и приложение развернуто в корневой контекст).
Ответ 6
Вы проверили Spring справочные документы загрузки?
По умолчанию Spring Boot будет обслуживать статический контент из папки с именем /static
(или /public
или /resources
или /META-INF/resources
) в пути к классам или из корня ServletContext.
Вы также можете сравнить свой проект с руководством Обслуживание веб-контента с помощью Spring MVC или проверить исходный код spring-boot-sample-web-ui.
Ответ 7
Я думаю, что предыдущие ответы очень хорошо затрагивают тему. Однако я бы добавил, что в одном случае, когда в вашем приложении включена защита Spring Безопасность, вам может потребоваться указать Spring, чтобы разрешать запросы в другие каталоги статических ресурсов, например, "/static/fonts" .
В моем случае у меня были "/static/css", "/static/js", "/static/images", разрешенные по умолчанию, но /static/fonts/ ** были заблокированы моей реализацией безопасности Spring.
Ниже приведен пример того, как я исправил это.
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.....
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/", "/fonts/**").permitAll().
//other security configuration rules
}
.....
}
Ответ 8
У меня была эта точная проблема, затем я понял, что я определил в своем приложении application.properties:
spring.resources.static-locations=file:/var/www/static
Это было все, что я пробовал. В моем случае я хотел сохранить оба, поэтому я просто сохранил свойство и добавил:
spring.resources.static-locations=file:/var/www/static,classpath:static
Какие файлы были отправлены из src/main/resources/static как localhost: {port}/file.html.
Ни одно из вышеперечисленных не работало для меня, потому что никто не упомянул об этом небольшом свойстве, которое можно было легко скопировать из Интернета, чтобы служить другой цели;)
Надеюсь, это поможет! Понял, что это хорошо впишется в этот длинный пост ответов для людей с этой проблемой.
Ответ 9
Это решение работает для меня:
Сначала поместите папку ресурсов в папку webapp/WEB-INF, следуя структуре
-- src
-- main
-- webapp
-- WEB-INF
-- resources
-- css
-- image
-- js
-- ...
Во-вторых, в spring файле конфигурации
@Configuration
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter{
@Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
return resolver;
}
@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resource/**").addResourceLocations("WEB-INF/resources/");
}
}
Затем вы можете получить доступ к своему ресурсу, например
http://localhost:8080/resource/image/yourimage.jpg
Ответ 10
Можно рассмотреть две вещи (Spring Boot v1.5.2.RELEASE) -
1) Проверьте все классы контроллера для аннотации @EnableWebMvc, удалите его, если есть
2) Проверьте классы контроллера, для которых используется аннотация - @RestController или @Controller. Не смешивайте поведение Rest API и поведение MVC в одном классе. Для MVC используйте @Controller и для REST API используйте @RestController
Выполнение выше 2 вещей разрешило мою проблему. Теперь моя загрузка spring загружает статические ресурсы без каких-либо проблем.
@Controller = > load index.html = > загружает статические файлы.
@Controller
public class WelcomeController {
// inject via application.properties
@Value("${welcome.message:Hello}")
private String message = "Hello World";
@RequestMapping("/")
public String home(Map<String, Object> model) {
model.put("message", this.message);
return "index";
}
}
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>index</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet/less" th:href="@{/webapp/assets/theme.siberia.less}"/>
<!-- The app logic -->
<script type="text/javascript" data-main="/webapp/app" th:src="@{/webapp/libs/require.js}"></script>
<script type="text/javascript">
require.config({
paths: { text:"/webapp/libs/text" }
});
</script>
<!-- Development only -->
<script type="text/javascript" th:src="@{/webapp/libs/less.min.js}"></script>
</head>
<body>
</body>
</html>
Ответ 11
Просто добавьте еще один ответ на старый вопрос... Люди упомянули, что @EnableWebMvc
предотвратит WebMvcAutoConfiguration
, что является кодом, ответственным за создание статических обработчиков ресурсов. Существуют и другие условия, которые также предотвратят WebMvcAutoConfiguration
. Самый простой способ увидеть это - посмотреть на источник:
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java # L139-L141
В моем случае я WebMvcConfigurationSupport
библиотеку, в которой был класс, который расширялся из WebMvcConfigurationSupport
что является условием, которое предотвратит автоконфигурацию:
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
Важно никогда не распространяться на WebMvcConfigurationSupport
. Вместо этого от WebMvcConfigurerAdapter
.
Ответ 12
В случае возникновения проблемы при запуске приложения из среды IDE (т.е. начиная с Eclipse или IntelliJ Idea) и использования Maven ключ к решению находится в Spring -boot Начало работы:
Если вы используете Maven, выполните:
mvn package && java -jar target/gs-spring-boot-0.1.0.jar
Важная часть которого заключается в добавлении цели package
, которая должна быть запущена до того, как приложение будет запущено. (Идея: Run
меню, Edit Configrations...
, Add
и выберите Run Maven Goal
и укажите цель package
в поле)
Ответ 13
Имела ту же проблему, используя gradle и затмение и потраченные часы, пытаясь понять это.
Нет необходимости в кодировании, трюк заключается в том, что вы должны использовать опцию меню New- > Source Folder (NOT New → Folder) для создания статической папки в src/main/resources. Не знаю, почему это работает, но в новой → исходной папке, тогда я назвал папку статичной (тогда в диалоговом окне исходной папки появляется ошибка, для которой вы должны проверить: обновите фильтры исключений в других папках источника для разрешения вложенности). В моей новой статической папке я добавил index.html, и теперь она работает.
Ответ 14
Я использую 1.3.5 и размещаю кучу REST-сервисов через реализацию Джерси. Это работало нормально, пока я не решил добавить пару файлов HTML + js.
Ни один из ответов на этом форуме не помог мне. Однако, когда я добавил следующую зависимость в моем pom.xml, все содержимое в src/main/resources/static окончательно показывалось через браузер:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<dependency>
Кажется, что spring -web/spring -webmvc - важная транзитивная зависимость, которая активирует автоматическую настройку загрузки spring.
Ответ 15
Ну, иногда стоит проверить, переопределили ли вы глобальные сопоставления каким-то контроллером отдыха. Простой пример ошибки (котлин):
@RestController("/foo")
class TrainingController {
@PostMapping
fun bazz(@RequestBody newBody: CommandDto): CommandDto = return commandDto
}
В приведенном выше случае вы получите, когда будете запрашивать статические ресурсы:
{
title: "Method Not Allowed",
status: 405,
detail: "Request method 'GET' not supported",
path: "/index.html"
}
Причина этого может быть то, что вы хотите отобразить @PostMapping
к /foo
, но забыть о @RequestMapping
аннотации на @RestController
уровне. В этом случае весь запрос сопоставляется с POST
и в этом случае вы не получите статического содержимого.
Ответ 16
Я в той же ситуации, когда мое приложение (интеграция) с пружинной загрузкой не поддерживает статическое содержимое папки, чтобы показать интерфейс на localhost: 8080. Frontend разрабатывается в angular4, поэтому используется ng build
который генерирует файлы в выходном пути dir src/main/resources/static, но не показывает никакого содержимого. Я сделал контроллер специально для обслуживания index.html, но кажется, что что-то отключено для весенней загрузки, чтобы понять, что такое угловая информация о маршрутизации и localhost: 8080 просто отображает возвращаемую строку из моего метода контроллера "index.html" на веб-странице. Ниже index.html (я изменил тег селектора по умолчанию в теле, так как компонент входа - тот, который я создал, и мой главный угловой компонент для пользовательского интерфейса, но все еще не работает, будь то корневой или корневой):
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hello Test App</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-login></app-login>
<script type="text/javascript" src="runtime.js"></script><script type="text/javascript" src="polyfills.js"></script><script type="text/javascript" src="styles.js"></script><script type="text/javascript" src="vendor.js"></script><script type="text/javascript" src="main.js"></script></body>
</html>
Код контроллера:
@RequestMapping("/")
public String userInterface() {
return "index.html";
}
Не уверен, имеет ли это значение, но это проект, основанный на градле, разработанный в IntellijIdea, а весенняя версия загрузки - org.springframework.boot:spring-boot-starter-web:2.0.2.RELEASE
.
@Vizcaino - Как вы сказали, есть простой trick-, делает Intellijidea аналогичный вариант для создания исходного каталога/папки? Я создал из контекстного меню → Новый → каталог. Но не уверен, что это то же самое, задаваясь вопросом, не станет ли это причиной моей проблемы?
Ответ 17
FYI: Я также заметил, что могу испортить отлично работающее приложение для загрузки весны и не позволять ему обслуживать содержимое из статической папки, если я добавлю плохой контроллер отдыха, например,
@RestController
public class BadController {
@RequestMapping(method= RequestMethod.POST)
public String someMethod(@RequestParam(value="date", required=false)String dateString, Model model){
return "foo";
}
}
В этом примере после добавления плохого контроллера в проект, когда браузер запрашивает файл, доступный в статической папке, ответ об ошибке "405 Method Not Allowed".
В примере плохого контроллера отсутствуют сопоставления уведомлений.
Ответ 18
Как указано выше, файл должен находиться в $ClassPath/static/images/name.png
, (/static или /public или/resources или /META -INF/resources). Этот класс $ClassPath означает main/resources
или main/java
dir.
Если ваши файлы не находятся в стандартном каталоге, вы можете добавить следующую конфигурацию:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/lib/**"); // like this
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// ... etc.
}
...
}