Su aplicación Spring MVC estándar atenderá todas las solicitudes a través de una DispatcherServlet
que haya registrado con su contenedor Servlet.
El DispatcherServlet
mira su ApplicationContext
y, si está disponible, el ApplicationContext
registrado con un ContextLoaderListener
para beans especiales que necesita para configurar su lógica de servicio de solicitudes. Estos beans se describen en la documentación .
Posiblemente el HandlerMapping
mapa de beans de tipo más importante
solicitudes entrantes a los manejadores y una lista de pre y posprocesadores (interceptores de manejadores) basada en algunos criterios cuyos detalles varían según la HandlerMapping
implementación. La implementación más popular admite controladores anotados, pero también existen otras implementaciones.
El javadoc deHandlerMapping
describe además cómo deben comportarse las implementaciones.
El DispatcherServlet
busca todos los beans de este tipo y los registra en algún orden (se puede personalizar). Mientras atiende una solicitud, el DispatcherServlet
bucle recorre estos HandlerMapping
objetos y prueba cada uno de ellos getHandler
para encontrar uno que pueda manejar la solicitud entrante, representada como estándar HttpServletRequest
. A partir de 4.3.x, si no encuentra ninguno , registra la advertencia que ve
No se encontró el mapeo para la petición HTTP con URI [/some/path]
en DispatcherServlet
con el nombre somename
y ya sea tiros una NoHandlerFoundException
o inmediatamente compromete la respuesta con un código de estado 404 no encontrado.
¿Por qué no DispatcherServlet
encontré un HandlerMapping
que pudiera manejar mi solicitud?
La HandlerMapping
implementación más común es RequestMappingHandlerMapping
, que maneja el registro de @Controller
beans como manejadores (realmente sus @RequestMapping
métodos anotados). Se puede declarar ya sea un grano de este tipo a sí mismo (con @Bean
o <bean>
u otro mecanismo) o puede utilizar el incorporado en las opciones . Estos son:
- Anote su
@Configuration
clase con @EnableWebMvc
.
- Declare un
<mvc:annotation-driven />
miembro en su configuración XML.
Como se describe en el enlace anterior, ambos registrarán un RequestMappingHandlerMapping
bean (y muchas otras cosas). Sin embargo, a HandlerMapping
no es muy útil sin un controlador. RequestMappingHandlerMapping
espera algunos @Controller
beans, por lo que debe declararlos también, a través de @Bean
métodos en una configuración Java o <bean>
declaraciones en una configuración XML o mediante el escaneo de componentes de @Controller
clases anotadas en cualquiera de los dos. Asegúrese de que estos frijoles estén presentes.
Si recibe el mensaje de advertencia y un 404 y ha configurado todo lo anterior correctamente, entonces está enviando su solicitud al URI incorrecto , uno que no es manejado por un @RequestMapping
método de controlador anotado detectado .
La spring-webmvc
biblioteca ofrece otras HandlerMapping
implementaciones integradas . Por ejemplo, BeanNameUrlHandlerMapping
mapas
de URL a beans con nombres que comienzan con una barra ("/")
y siempre puedes escribir el tuyo. Obviamente, tendrá que asegurarse de que la solicitud que envía coincida con al menos uno de los HandlerMapping
controladores del objeto registrado .
Si no registra implícita o explícitamente ningún HandlerMapping
bean (o si lo detectAllHandlerMappings
es true
), el DispatcherServlet
registra algunos valores predeterminados . Estos se definen en DispatcherServlet.properties
el mismo paquete que la DispatcherServlet
clase. Son BeanNameUrlHandlerMapping
y DefaultAnnotationHandlerMapping
(que es similar RequestMappingHandlerMapping
pero obsoleto).
Depuración
Spring MVC registrará los controladores registrados a través de RequestMappingHandlerMapping
. Por ejemplo, un me @Controller
gusta
@Controller
public class ExampleController {
@RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom")
public String example() {
return "example-view-name";
}
}
registrará lo siguiente en el nivel INFO
Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example()
Esto describe el mapeo registrado. Cuando vea la advertencia de que no se encontró ningún controlador, compare el URI en el mensaje con la asignación que se muestra aquí. Todas las restricciones especificadas en @RequestMapping
deben coincidir para que Spring MVC seleccione el controlador.
Otras HandlerMapping
implementaciones registran sus propias declaraciones que deberían indicar sus asignaciones y sus correspondientes controladores.
De manera similar, habilite el registro de Spring en el nivel DEBUG para ver qué beans registra Spring. Debería informar qué clases anotadas encuentra, qué paquetes escanea y qué beans inicializa. Si los que esperaba no están presentes, revise su ApplicationContext
configuración.
Otros errores comunes
A DispatcherServlet
es solo un Java EE típico Servlet
. Lo registra con su declaración típica <web.xml>
<servlet-class>
y <servlet-mapping>
, o directamente a través ServletContext#addServlet
de a WebApplicationInitializer
, o con cualquier mecanismo que utilice Spring boot. Como tal, debe confiar en la lógica de mapeo de URL especificada en la especificación de Servlet , consulte el Capítulo 12. Consulte también
Teniendo esto en cuenta, un error común es registrar el DispatcherServlet
con una asignación de URL de /*
, devolver un nombre de vista de un @RequestMapping
método de controlador y esperar que se procese un JSP. Por ejemplo, considere un método de controlador como
@RequestMapping(path = "/example", method = RequestMethod.GET)
public String example() {
return "example-view-name";
}
con un InternalResourceViewResolver
@Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver vr = new InternalResourceViewResolver();
vr.setPrefix("/WEB-INF/jsps/");
vr.setSuffix(".jsp");
return vr;
}
puede esperar que la solicitud se reenvíe a un recurso JSP en la ruta /WEB-INF/jsps/example-view-name.jsp
. Esto no sucederá. En cambio, asumiendo un nombre de contexto de Example
, DisaptcherServlet
informará
No se encontró el mapeo para la petición HTTP con URI [/Example/WEB-INF/jsps/example-view-name.jsp]
en DispatcherServlet
con el nombre 'despachador'
Debido a que DispatcherServlet
se asigna /*
y /*
coincide con todo (excepto las coincidencias exactas, que tienen una prioridad más alta), DispatcherServlet
se elegiría para manejar el forward
de JstlView
(devuelto por InternalResourceViewResolver
). En casi todos los casos, DispatcherServlet
no se configurará para manejar dicha solicitud .
En cambio, en este caso simplista, debe registrar el DispatcherServlet
to /
, marcándolo como el servlet predeterminado. El servlet predeterminado es la última coincidencia de una solicitud. Esto permitirá que su contenedor de servlet típico elija una implementación de Servlet interna, asignada a *.jsp
, para manejar el recurso JSP (por ejemplo, Tomcat tiene JspServlet
), antes de intentar con el servlet predeterminado.
Eso es lo que está viendo en su ejemplo.
@EnableWebMvc
en una@Configuration
clase anotada no hace eso. Todo lo que hace es agregar una serie de beans de adaptadores / manejadores Spring MVC predeterminados al contexto de la aplicación. Registrar unDispatcherServlet
para servir/
es un proceso completamente independiente que se realiza de varias maneras que describo en la sección Otros errores comunes . Respondo a la pregunta formulada dos párrafos más abajo de lo que citó.Resolví mi problema cuando además de lo descrito anteriormente: `
@Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver vr = new InternalResourceViewResolver(); vr.setPrefix("/WEB-INF/jsps/"); vr.setSuffix(".jsp"); return vr; }
added tomcat-embed-jasper:
`from: El archivo JSP no se representa en la aplicación web Spring Boot
fuente
En mi caso, estaba siguiendo la documentación de Interceptors Spring para la versión 5.1.2 (mientras usaba Spring Boot v2.0.4.RELEASE ) y la
WebConfig
clase tenía la anotación@EnableWebMvc
, que parecía estar en conflicto con algo más en mi aplicación que impedía mi estática los activos se resuelvan correctamente (es decir, no se devolvieron archivos CSS o JS al cliente).Después de probar muchas cosas diferentes, intenté eliminar el
@EnableWebMvc
y funcionó.Editar: aquí está la documentación de referencia que dice que debe eliminar la
@EnableWebMvc
anotaciónAparentemente, al menos en mi caso, ya estoy configurando mi aplicación Spring (aunque no usando
web.xml
ningún otro archivo estático, definitivamente es programáticamente), así que hubo un conflicto allí.fuente
Intente modificar su código con el siguiente cambio en su archivo de configuración. Se usa la configuración de Java en lugar de
application.properties
. No olvide habilitar la configuración en elconfigureDefaultServletHandling
método.@Configuration @EnableWebMvc @ComponentScan public class WebConfig implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/WEB-INF/views/", ".jsp"); } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
Yo uso gradle, debes tener las siguientes dependencias en
pom.xml
:dependencies { compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.3.0.RELEASE' compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '9.0.35' }
fuente
Me encontré con otra razón para el mismo error. Esto también podría deberse a que los archivos de clase no se generaron para su archivo controller.java. Como resultado, el servlet del despachador mencionado en web.xml no puede asignarlo al método apropiado en la clase del controlador.
@Controller Class Controller{ @RequestMapping(value="/abc.html")//abc is the requesting page public void method() {.....} }
En eclipse, en Proyecto-> seleccione limpiar -> Crear proyecto. Compruebe si el archivo de clase se ha generado para el archivo del controlador en las compilaciones en su espacio de trabajo.
fuente
Para mí, descubrí que mis clases de destino se generaron en un patrón de carpeta que no es el mismo que el de origen. Esto posiblemente sea en eclipse. Agrego carpetas para contener mis controladores y no los agrego como paquetes. Así que terminé definiendo la ruta incorrecta en la configuración de primavera.
Mi clase objetivo estaba generando clases en la aplicación y me refería a com.happy.app
<context:annotation-config /> <context:component-scan base-package="com.happy.app"></context:component-scan>
Agregué paquetes (no carpetas) para com.happy.app y moví los archivos de las carpetas a los paquetes en eclipse y resolvió el problema.
fuente
Limpia tu servidor. Tal vez elimine el servidor y agregue el proyecto una vez más y Ejecute.
Detenga el servidor Tomcat
Haga clic derecho en el servidor y seleccione "Limpiar"
Haga clic derecho en el servidor nuevamente y seleccione "Limpiar directorio de trabajo de Tomcat"
fuente
En mi caso, estaba jugando con la importación de archivos de configuración de Java secundarios en un archivo de configuración de Java principal. Mientras creaba archivos de configuración secundarios, había cambiado el nombre de la clase de configuración principal, pero no había podido actualizar el nombre en web.xml. Entonces, cada vez que reiniciaba mi servidor tomcat, no veía los controladores de mapeo anotados en la consola del IDE de Eclipse, y cuando traté de navegar a mi página de inicio, veía este error:
La solución fue actualizar el archivo web.xml para que el nombre anterior "WebConfig" fuera "MainConfig", simplemente renombrándolo para reflejar el último nombre del archivo de configuración de Java principal (donde "MainConfig" es arbitrario y las palabras " Web "y" Main "utilizados aquí no son un requisito de sintaxis). MainConfig era importante, porque era el archivo que escaneaba el componente en busca de "WebController", mi clase de controlador Spring MVC que maneja mis solicitudes web.
@ComponentScan(basePackageClasses={WebController.class})
web.xml tenía esto:
El archivo web.xml ahora tiene:
Ahora veo el mapeo en la ventana de la consola:
Y mi página web se está cargando de nuevo.
fuente
Tuve el mismo problema que
**No mapping found for HTTP request with URI [/some/path] in DispatcherServlet with name SomeName**
Después de analizar durante 2 a 4 días, descubrí la causa raíz. Los archivos de clase no se generaron después de ejecutar el proyecto. Hice clic en la pestaña del proyecto.
Se han generado archivos de clase para el código fuente. Resolvió mi problema. Para verificar si los archivos de clase se han generado o no, verifique la carpeta de compilación en la carpeta de su proyecto.
fuente