Esta es la solución más correcta que te podemos compartir, sin embargo obsérvala detenidamente y analiza si se puede adaptar a tu trabajo.
Solución:
/*
los /*
en un servlet anula todos los demás servlets, incluidos todos los servlets proporcionados por el servletcontainer, como el servlet predeterminado y el servlet JSP. Cualquiera que sea la solicitud que envíe, terminará en ese servlet. Por lo tanto, este es un patrón de URL incorrecto para los servlets. Por lo general, le gustaría usar /*
en un Filter
solamente. Puede permitir que la solicitud continúe a cualquiera de los servlets que escuchan en un patrón de URL más específico llamando FilterChain#doFilter()
.
/
los /
no anula ningún otro servlet. Solo reemplaza el servlet predeterminado incorporado del servletcontainer para todas las solicitudes que no coincidan con ningún otro servlet registrado. Esto normalmente solo se invoca en static recursos (CSS/JS/image/etc) y listados de directorios. El servlet predeterminado incorporado del servletcontainer también es capaz de manejar solicitudes de caché HTTP, transmisión de medios (audio/video) y reanudaciones de descarga de archivos. Por lo general, no desea anular el servlet predeterminado, ya que de lo contrario tendría que encargarse de todas sus tareas, lo cual no es exactamente trivial (la biblioteca de utilidades JSF OmniFaces tiene un ejemplo de código abierto). Por lo tanto, este también es un patrón de URL incorrecto para los servlets. En cuanto a por qué las páginas JSP no llegan a este servlet, es porque se invocará el servlet JSP integrado del servletcontainer, que ya está asignado de forma predeterminada en el patrón de URL más específico. *.jsp
.
Luego también está el vacío string patrón de URL . Esto se invocará cuando se solicite la raíz de contexto. Esto es diferente de la
enfoque que no se invoca cuando se solicita cualquier subcarpeta. Lo más probable es que este sea el patrón de URL que está buscando en caso de que desee un “servlet de página de inicio”. Solo tengo que admitir que intuitivamente esperaría el vacío string patrón de URL y el patrón de URL de barra oblicua
/
definirse exactamente al revés, por lo que puedo entender que muchos principiantes se confundieron con esto. Pero es lo que es.
Controlador frontal
En el caso que tú Realmente tiene la intención de tener un servlet de controlador frontal, entonces será mejor que lo mapee en un patrón de URL más específico como *.html
, *.do
, /pages/*
, /app/*
etc. Puede ocultar el patrón de URL del controlador frontal y cubrir static recursos en un patrón de URL común como /resources/*
, /static/*
, etc. con la ayuda de un filtro de servlet. Ver también Cómo prevenir static los recursos sean manejados por el servlet del controlador frontal que está mapeado en /*. Se debe tener en cuenta que Spring MVC tiene un incorporado static servlet de recursos, por eso podría mapear su controlador frontal en /
si configura un patrón de URL común para static recursos en primavera. Ver también Cómo manejar static contenido en Spring MVC?
Me gustaría complementar la respuesta de BalusC con las reglas de mapeo y un ejemplo.
Reglas de mapeo de la especificación Servlet 2.5:
- Asignar URL exacta
- Asignar rutas comodín
- Extensiones de mapa
- Asignar al servlet predeterminado
En nuestro ejemplo, hay tres servlets. / es el servlet predeterminado que instalamos. Tomcat instala dos servlets para servir jsp y jspx. Entonces para mapear http://host:port/context/hello
- No hay servlets de URL exactos instalados, a continuación.
- No hay servlets de rutas comodín instalados, a continuación.
- No coincide con ninguna extensión, siguiente.
- Asignar al servlet predeterminado, volver.
Para asignar http://host:port/context/hello.jsp
- No hay servlets de URL exactos instalados, a continuación.
- No hay servlets de rutas comodín instalados, a continuación.
- Servlet de extensión encontrado, retorno.
Tal vez también necesite saber cómo se mapean las URL, ya que sufrí 404
por horas. Hay dos tipos de controladores que manejan las solicitudes. BeanNameUrlHandlerMapping
y SimpleUrlHandlerMapping
. Cuando definimos un servlet-mapping
estamos usando SimpleUrlHandlerMapping
. Una cosa que debemos saber es que estos dos controladores comparten una propiedad común llamada alwaysUseFullPath
que por defecto es false
.
false
aquí significa que Spring no usará la ruta completa para asignar una URL a un controlador. ¿Qué significa? Significa que cuando defines un servlet-mapping
:
viewServlet
/perfix/*
el controlador realmente usará el *
parte para encontrar el controlador. Por ejemplo, el siguiente controlador se enfrentará a un 404
error cuando lo solicitas usando /perfix/api/feature/doSomething
@Controller()
@RequestMapping("/perfix/api/feature")
public class MyController
@RequestMapping(value = "/doSomething", method = RequestMethod.GET)
@ResponseBody
public String doSomething(HttpServletRequest request)
....
Es una combinación perfecta, ¿verdad? Pero por qué 404
. Como se mencionó anteriormente, el valor predeterminado de alwaysUseFullPath
es falselo que significa que en su solicitud, solo /api/feature/doSomething
se utiliza para encontrar un controlador correspondiente, pero no hay controlador que se preocupe por esa ruta. Necesitas cambiar tu URL a /perfix/perfix/api/feature/doSomething
o eliminar perfix
desde la base de MyController @RequestingMapping
.