servlets - pattern - xml servlet java
Diferencia entre/y/* en el patrĂ³n de url de mapeo de servlets (5)
<url-pattern>/*</url-pattern>
El /*
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 dispare, terminará en ese servlet. Este es, por lo tanto, un patrón de URL incorrecto para los servlets. Generalmente, 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 a FilterChain#doFilter()
.
<url-pattern>/</url-pattern>
El /
no anula ningún otro servlet. Solo reemplaza el servlet por defecto incorporado de servletcontainer para todas las solicitudes que no coincide con ningún otro servlet registrado. Normalmente, esto solo se invoca en recursos estáticos (CSS / JS / image / etc) y listados de directorios. El servlet por defecto incorporado de 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 sobrescribir el servlet predeterminado ya que de lo contrario tendría que encargarse de todas sus tareas, lo que no es exactamente trivial (la biblioteca de utilidades JSF OmniFaces tiene un example 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, se debe a que se invocará el servlet JSP incorporado de servletcontainer, que ya está mapeado por defecto en el patrón de URL más específico *.jsp
.
<url-pattern></url-pattern>
Luego, también está el patrón de URL de cadena vacía . Esto se invocará cuando se solicite la raíz de contexto. Esto es diferente del enfoque
<welcome-file>
que no se invoca cuando se solicita una subcarpeta. Es muy probable que sea el patrón de URL que realmente está buscando en caso de que desee un " servlet de página de inicio ". Solo tengo que admitir que esperaría intuitivamente el patrón de URL de cadena vacía y el patrón de URL de barra
/
se define exactamente al revés, por lo que puedo entender que muchos principiantes se confundieron al respecto. Pero es lo que es.
Controlador frontal
En caso de que realmente pretenda tener un servlet de controlador frontal, será mejor que lo asigne en un patrón de URL más específico como *.html
, *.do
, /pages/*
, /app/*
, etc. Puede esconderse el patrón de URL del controlador frontal y cubre recursos estáticos en un patrón de URL común como /resources/*
, /static/*
, etc. con la ayuda de un filtro de servlet. Consulte también Cómo evitar que los recursos estáticos sean manejados por el servlet del controlador frontal que está mapeado en / * . Se debe tener en cuenta que Spring MVC tiene un servlet de recursos estáticos integrado, por lo que es posible que pueda asignar su controlador frontal en /
si configura un patrón de URL común para los recursos estáticos en Spring. Consulte también ¿Cómo manejar el contenido estático en Spring MVC?
El código familiar:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Tengo entendido que /*
asigna a http://host:port/context/*
.
¿Qué tal /
? Seguro que no se asigna a http://host:port/context
raíz de http://host:port/context
solamente. De hecho, aceptará http://host:port/context/hello
, pero rechazará http://host:port/context/hello.jsp
.
¿Alguien puede explicar cómo se mapea http://host:port/context/hello
?
Creo que la respuesta de Candy es en su mayoría correcta. Hay una pequeña parte, creo que de lo contrario.
Para asignar el host: puerto / contexto / hello.jsp
- No hay servlets URL exactos instalados, a continuación.
- Se han encontrado servlets de rutas comodín , return.
Creo que por qué "/ *" no coincide con host: port / context / hello porque trata a "/ hello" como una ruta en lugar de un archivo (ya que no tiene una extensión).
La diferencia esencial entre /*
y /
es que un servlet con mapeo /*
se seleccionará antes de cualquier servlet con una asignación de extensión (como *.html
), mientras que un servlet con mapeo /
se seleccionará solo después de considerar las asignaciones de extensión (y se usará para cualquier solicitud que no concuerde con ninguna otra cosa --- es el "servlet predeterminado").
En particular, siempre se seleccionará un mapeo a /*
antes de un /
mapping. Tener bien impide que cualquier solicitud llegue al propio servlet predeterminado del contenedor.
O bien se seleccionarán solo después de las asignaciones de servlets que sean coincidencias exactas (como /foo/bar
) y aquellas que sean mapeos de ruta más largos que /*
(como /foo/*
). Tenga en cuenta que la asignación de cadena vacía es una coincidencia exacta para la raíz de contexto ( http://host:port/context/
).
Consulte el Capítulo 12 de la Especificación del Servlet de Java, disponible en la versión 3.1 en http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html .
Me gustaría complementar la respuesta de BalusC con las reglas de mapeo y un ejemplo.
Reglas de mapeo de la especificación de Servlet 2.5:
- Calcular URL exacta
- Asignar rutas de comodines
- Extensiones de mapa
- Mapa del servlet predeterminado
En nuestro ejemplo, hay tres servlets. / es el servlet predeterminado instalado por nosotros. Tomcat instala dos servlets para servir jsp y jspx. Así que para mapear http://host:port/context/hello
- No hay servlets URL exactos instalados, a continuación.
- No hay servlets de rutas comodín instaladas, a continuación.
- No coincide con ninguna extensión, a continuación.
- Mapa para el servlet predeterminado, return.
Para mapear http://host:port/context/hello.jsp
- No hay servlets URL exactos instalados, a continuación.
- No hay servlets de rutas comodín instaladas, a continuación.
- Se encontró el servlet de extensión, return.
Quizás necesite saber cómo se mapean también las URL, ya que sufrí 404
durante 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 manejadores comparten una propiedad común llamada alwaysUseFullPath
que por defecto es false
.
false
aquí significa que Spring no usará la ruta completa para aplicar una url a un controlador. Qué significa eso? Significa cuando defines un servlet-mapping
:
<servlet-mapping>
<servlet-name>viewServlet</servlet-name>
<url-pattern>/perfix/*</url-pattern>
</servlet-mapping>
el controlador realmente usará la parte *
para encontrar el controlador. Por ejemplo, el siguiente controlador enfrentará un error 404
cuando lo solicite 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 falso, lo que significa que en su solicitud, solo /api/feature/doSomething
se usa para encontrar un Controller correspondiente, pero no hay ningún controlador que se preocupe por esa ruta. /perfix/perfix/api/feature/doSomething
cambiar su URL a /perfix/perfix/api/feature/doSomething
o eliminar perfix
de MyController base @RequestingMapping
.