tutorial - Spring Boot no sirve contenido estático
spring project (16)
Estoy golpeando mi cabeza contra la pared por un par de horas. Mi proyecto está casi terminado, pero no puedo obtener contenido estático.
He colocado una carpeta llamada static
en src/main/resources
. Dentro de él tengo una carpeta llamada images
. Cuando empaco la aplicación y la ejecuto, no puede encontrar las imágenes que he puesto en esa carpeta.
Intenté poner los archivos estáticos en public
, resources
y resources
META-INF/resources
pero nada funciona.
Si jar -tvf app.jar puedo ver que los archivos están dentro del /static/images/head.png
en la carpeta derecha: /static/images/head.png
por ejemplo, pero llamando a: http://localhost:8080/images/head.png
, todo lo que obtengo es un 404
¿Alguna idea de por qué Spring-Boot no está encontrando esto? (Estoy usando 1.1.4 por cierto)
¿Revisaste los documentos de referencia de Spring Boot ?
Por defecto Spring Boot servirá contenido estático desde una carpeta llamada
/static
(o/public
o/resources
o/META-INF/resources
) en classpath o desde la raíz de ServletContext.
También puede comparar su proyecto con la guía Servicio de contenido web con Spring MVC , o consulte el código fuente del proyecto spring-boot-sample-web-ui .
A diferencia de lo que dice la bota de resorte, para que mi contenedor de arranque de primavera sirva al contenido: tuve que agregar registrar específicamente mi contenido src / main / resources / static a través de esta clase de configuración:
@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);
}
}
Bueno, a veces vale la pena comprobar si anulaste las asignaciones globales mediante algún controlador de reposo. Error simple de ejemplo (kotlin):
@RestController("/foo")
class TrainingController {
@PostMapping
fun bazz(@RequestBody newBody: CommandDto): CommandDto = return commandDto
}
En el caso anterior, obtendrá cuando solicite recursos estáticos:
{
title: "Method Not Allowed",
status: 405,
detail: "Request method ''GET'' not supported",
path: "/index.html"
}
La razón de esto podría ser que quería asignar @PostMapping
a /foo
pero olvidarse de la anotación @RequestMapping
en el nivel @RestController
. En este caso, todas las solicitudes se asignan a POST
y no recibirá contenido estático en este caso.
Busque controladores asignados a "/" o sin ruta mapeada.
Tuve un problema como este, obtuve 405 errores y me golpeé la cabeza por días. El problema resultó ser un controlador anotado @RestController
que olvidé anotar con una anotación @RequestMapping
. Supongo que esta ruta mapeada dejó de forma predeterminada "/" y bloqueó la asignación de recursos de contenido estático.
Como se dijo anteriormente, el archivo debe estar en $ClassPath/static/images/name.png
, (/ static o / public o / resources o / META-INF / resources). Este $ ClassPath significa main/resources
o main/java
dir.
Si sus archivos no están en directorios estándar, puede agregar la siguiente configuración:
@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.
}
...
}
Creo que las respuestas anteriores abordan el tema muy bien. Sin embargo, agregaría que en un caso cuando tiene Spring Security habilitado en su aplicación, es posible que tenga que decirle específicamente a Spring que permita solicitudes a otros directorios de recursos estáticos como, por ejemplo, "/ static / fonts" .
En mi caso, tenía "/ static / css", "/ static / js", "/ static / images" permitido por defecto, pero / static / fonts / ** fue bloqueado por la implementación de Spring Security.
A continuación se muestra un ejemplo de cómo arreglé esto.
@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
}
.....
}
En caso de que surja un problema al iniciar la aplicación desde un IDE (es decir, desde Eclipse o IntelliJ Idea) y utilizando Maven, la clave de la solución se encuentra en la documentación de inicio de Spring-boot :
Si está utilizando Maven, ejecute:
mvn package && java -jar target/gs-spring-boot-0.1.0.jar
La parte importante de esto es agregar el objetivo del package
para que se ejecute antes de que realmente se inicie la aplicación. (Idea: menú Run
, Edit Configrations...
, Add
, y seleccione Run Maven Goal
y especifique el objetivo del package
en el campo)
Esta solución funciona para mí:
Primero, coloque una carpeta de recursos bajo webapp / WEB-INF, como sigue la estructura
-- src
-- main
-- webapp
-- WEB-INF
-- resources
-- css
-- image
-- js
-- ...
En segundo lugar, en el archivo de configuración de primavera
@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/");
}
}
Luego, puede acceder a su contenido de recursos, como http://localhost:8080/resource/image/yourimage.jpg
Estaba teniendo este problema exacto, luego me di cuenta de que lo había definido en mi application.properties:
spring.resources.static-locations=file:/var/www/static
Que estaba anulando todo lo demás que había intentado. En mi caso, quería conservar ambos, así que solo guardé la propiedad y agregué:
spring.resources.static-locations=file:/var/www/static,classpath:static
Que sirvió archivos desde src / main / resources / static como localhost: {port} /file.html.
Ninguno de los anteriores funcionó para mí porque nadie mencionó esta pequeña propiedad que podría haberse copiado fácilmente en línea para cumplir un propósito diferente;)
¡Espero eso ayude! Supuse que encajaría bien en este largo post de respuestas para las personas con este problema.
Estoy usando 1.3.5 y alojo un montón de servicios REST a través de la implementación de Jersey. Eso funcionó bien hasta que decidí agregar un par de archivos HTMLs + js. Ninguna de las respuestas dadas en este foro me ayudó. Sin embargo, cuando agregué la siguiente dependencia en mi pom.xml, todo el contenido en src / main / resources / static finalmente se mostraba a través del navegador:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<dependency>
Parece spring-web / spring-webmvc es la importante dependencia transitiva que hace que las configuraciones automáticas de arranque de primavera se enciendan.
Hay dos cosas a considerar (Spring Boot v1.5.2.RELEASE) - 1) Compruebe todas las clases de Controller para la anotación @EnableWebMvc, elimínelas si hay alguna 2) Compruebe las clases de Controller para las cuales se usa la anotación - @RestController o @Controller . No mezcle el comportamiento Rest API y MVC en una clase. Para MVC use @Controller y para API REST use @RestController
Hacer más de 2 cosas resolvió mi problema. Ahora mi arranque de primavera está cargando recursos estáticos sin ningún problema. @Controller => load index.html => carga archivos estáticos.
@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''s 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>
La configuración se puede hacer de la siguiente manera:
@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcAutoConfigurationAdapter {
// specific project configuration
}
Importante aquí es que su WebMvcConfig
puede anular el método addResourceHandlers
y, por lo tanto, debe invocar explícitamente super.addResourceHandlers(registry)
(es cierto que si está satisfecho con las ubicaciones de recursos predeterminadas, no es necesario que anule ningún método).
Otra cosa que debe comentarse aquí es que esas ubicaciones de recursos predeterminadas ( /static
, /public
, /resources
y /META-INF/resources
) se registrarán solo si no hay un manejador de recursos mapeado en /**
.
A partir de este momento, si tiene una imagen en src/main/resources/static/images
llamada image.jpg
por ejemplo, puede acceder a ella usando la siguiente URL: http://localhost:8080/images/image.jpg
( siendo el servidor iniciado en el puerto 8080 y la aplicación desplegada en el contexto raíz).
No para resucitar a los muertos después de más de un año, pero todas las respuestas anteriores omiten algunos puntos cruciales:
-
@EnableWebMvc
en su clase desactivaráorg.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration
. Eso está bien si quieres un control total, pero de lo contrario, es un problema. No es necesario escribir ningún código para agregar otra ubicación para recursos estáticos además de lo que ya está provisto. Mirando
org.springframework.boot.autoconfigure.web.ResourceProperties
desde v1.3.0.RELEASE, veo un campostaticLocations
que se puede configurar enapplication.properties
. Aquí hay un fragmento de la fuente:/** * 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;
Como se mencionó anteriormente, la URL de solicitud se resolverá en relación con estas ubicaciones. Por lo tanto
src/main/resources/static/index.html
se servirá cuando la URL de solicitud sea/index.html
. La clase que se encarga de resolver la ruta, a partir de Spring 4.1, esorg.springframework.web.servlet.resource.PathResourceResolver
.La coincidencia de patrón de sufijo está habilitada de manera predeterminada, lo que significa que para una URL de solicitud
/index.html
, Spring buscará los controladores correspondientes a/index.html
. Este es un problema si la intención es servir contenido estático. Para desactivar eso, extiendaWebMvcConfigurerAdapter
(pero no use@EnableWebMvc
) y anuleconfigurePathMatch
como se muestra a continuación:@Override public void configurePathMatch(PathMatchConfigurer configurer) { super.configurePathMatch(configurer); configurer.setUseSuffixPatternMatch(false); }
En mi humilde opinión, la única manera de tener menos errores en su código es no escribir código siempre que sea posible. Usa lo que ya está provisto, incluso si eso requiere un poco de investigación, el rendimiento vale la pena.
Por defecto Spring Boot sirve recursos estáticos definidos en las siguientes rutas:
- / META-INF / recursos /
- / recursos /
- /estático/
- /público/
Para cambiar las rutas predeterminadas de recursos estáticos, puede definir el atributo "spring.resources.static-locations" en application.properties como se muestra a continuación:
spring.resources.static-locations=/html/,/js/,/css/
En su caso, está utilizando las rutas predeterminadas leídas por Spring Boot, no debería obtener 404 al acceder / images / a menos que definiera explícitamente una ruta de contexto diferente para su aplicación o habilitó @EnableWebMvc que anula la configuración predeterminada de Spring Boot .
Para obtener más información sobre cómo servir y cargar recursos estáticos en Spring Boot, verifique esto: Sirva recursos estáticos con Spring Boot.
Tuve el mismo problema, usando gradle y eclipse y pasé horas intentando descubrirlo.
No se requiere codificación, el truco es que debe usar la opción de menú Nuevo-> Carpeta de origen (NO nueva -> Carpeta) para crear la carpeta estática en src / main / resources. No sé por qué funciona esto, pero hice una nueva -> carpeta de origen y luego nombré la carpeta como estática (luego el cuadro de diálogo de la carpeta de origen arroja un error que debe verificar: actualice los filtros de exclusión en otras carpetas de origen para solucionar el anidamiento). Mi nueva carpeta estática agregué index.html y ahora funciona.
Tuve un problema similar, y resultó que la solución simple era hacer que mi clase de configuración ampliara WebMvcAutoConfiguration
:
@Configuration
@EnableWebMvc
@ComponentScan
public class ServerConfiguration extends WebMvcAutoConfiguration{
}
No necesitaba ningún otro código para permitir que se sirviera mi contenido estático, sin embargo, puse un directorio llamado public
bajo src/main/webapp
y lo configuré para apuntar a src/main/webapp
como un directorio de recursos. Esto significa que public
se copia en target/classes
y, por lo tanto, está en el classpath en tiempo de ejecución para que spring-boot / tomcat lo encuentre.