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.
}
...

}