Differenza tra / e / * nel pattern url di mappatura servlet


175

Il codice familiare:

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

La mia comprensione è che /*mappe per http://host:port/context/*.

Che ne dici /? Di certo non è http://host:port/contextmappato solo al root. In realtà, accetterà http://host:port/context/hello, ma rifiuterà http://host:port/context/hello.jsp.

Qualcuno può spiegare come è http://host:port/context/hellomappato?

Risposte:


268

<url-pattern>/*</url-pattern>

L' /*on su un servlet sostituisce tutti gli altri servlet, inclusi tutti i servlet forniti dal servletcontainer come il servlet predefinito e il servlet JSP. Qualunque richiesta tu spari, finirà in quel servlet. Questo è quindi un modello URL errato per i servlet. Di solito, si desidera utilizzare /*su un Filtersolo. È in grado di lasciare che la richiesta continui a uno dei servlet in ascolto su un pattern URL più specifico chiamando FilterChain#doFilter().

<url-pattern>/</url-pattern>

Il /non ignora qualsiasi altro servlet. Sostituisce solo il servlet predefinito incorporato del servletcontainer per tutte le richieste che non corrispondono a nessun altro servlet registrato. Questo è normalmente invocato solo su risorse statiche (CSS / JS / image / etc) ed elenchi di directory. Il servlet predefinito incorporato del servletcontainer è anche in grado di gestire richieste di cache HTTP, streaming di file multimediali (audio / video) e download di file. Di solito, non si desidera sovrascrivere il servlet predefinito in quanto altrimenti ci si dovrebbe occupare di tutte le sue attività, il che non è esattamente banale (la libreria di utilità JSF OmniFaces ha un esempio open source ). Questo è quindi anche un modello URL non valido per i servlet. Il motivo per cui le pagine JSP non raggiungono questo servlet, è perché verrà richiamato il servlet JSP incorporato del servletcontainer, che è già mappato di default sul pattern URL più specifico *.jsp.

<url-pattern></url-pattern>

Quindi c'è anche il pattern URL stringa vuoto . Questo verrà invocato quando viene richiesta la root di contesto. Questo è diverso <welcome-file>dall'approccio che non viene invocato quando viene richiesta una sottocartella. Questo è molto probabilmente il pattern URL che stai effettivamente cercando nel caso in cui desideri un " servlet home page ". Devo solo ammettere che mi aspetterei intuitivamente che il pattern URL stringa vuoto e il pattern URL slash /siano definiti esattamente al contrario, quindi posso capire che molti antipasti si sono confusi su questo. Ma è quello che è.

Front Controller

Nel caso in cui in realtà intenzione di avere un servlet front controller, allora si sarebbe meglio mappa su un modello di URL più specifico come *.html, *.do, /pages/*, /app/*, ecc È possibile nascondere le risorse statiche fronte del modello di controllo URL e coperchio di un modello comune URL come /resources/*, /static/*ecc. con l'aiuto di un filtro servlet. Vedi anche Come impedire che le risorse statiche vengano gestite dal servlet del front controller che è mappato su / * . Va notato che Spring MVC ha un servlet di risorse statiche incorporato, quindi è possibile mappare il suo front controller /se si configura un pattern URL comune per risorse statiche in Spring. Vedi anche Come gestire il contenuto statico in Spring MVC?


9
Grazie. Dopo alcune ricerche, vorrei chiarire un punto sottile. / sovrascrive il servlet predefinito installato dal server Web. Ad esempio, Tomcat installa un DefaultServlet che serve risorse statiche. L'uso / elimina il servlet predefinito come effetto collaterale (molto probabilmente indesiderabile).
Candy Chiu,

Bene, non lo definirei "sovrascrittura", ma "sostituzione". Può essere utile sostituire il servlet predefinito in questo modo.
BalusC,

1
<url-pattern> </url-pattern> genera un errore: <url-pattern> non valido nella mappatura servlet
slim

Il messaggio di errore proveniva da Tomcat, non dal mio IDE; tuttavia, sto usando Tomcat 6, quindi questo è probabilmente il problema;)
slim

2
@ BalusC, puoi dirmi quale /**motivo indica?
Sajib Acharya,

45

Vorrei integrare la risposta di BalusC con le regole di mappatura e un esempio.

Regole di mappatura dalla specifica Servlet 2.5:

  1. URL esatto della mappa
  2. Mappa percorsi jolly
  3. Estensioni della mappa
  4. Mappa sul servlet predefinito

Nel nostro esempio, ci sono tre servlet. / è il servlet predefinito installato da noi. Tomcat installa due servlet per servire jsp e jspx. Quindi per mapparehttp://host:port/context/hello

  1. Nessun servlet URL esatto installato, successivo.
  2. Nessun servlet di percorsi jolly installati, successivo.
  3. Successivamente, non corrisponde ad alcuna estensione.
  4. Mappa sul servlet predefinito, ritorna.

Mappare http://host:port/context/hello.jsp

  1. Nessun servlet URL esatto installato, successivo.
  2. Nessun servlet di percorsi jolly installati, successivo.
  3. Servlet estensione trovato, ritorno.

25

Forse devi sapere anche come sono mappati gli URL, dal momento che ho sofferto 404per ore. Esistono due tipi di gestori che gestiscono le richieste. BeanNameUrlHandlerMappinge SimpleUrlHandlerMapping. Quando abbiamo definito un servlet-mapping, stiamo usando SimpleUrlHandlerMapping. Una cosa che dobbiamo sapere è che questi due gestori condividono una proprietà comune denominata alwaysUseFullPathpredefinita false.

falsequi significa che Spring non utilizzerà l'intero percorso per mappare un URL a un controller. Cosa significa? Significa quando si definisce un servlet-mapping:

<servlet-mapping>
    <servlet-name>viewServlet</servlet-name>
    <url-pattern>/perfix/*</url-pattern>
</servlet-mapping>

il gestore utilizzerà effettivamente la *parte per trovare il controller. Ad esempio, il controller seguente riscontrerà un 404errore quando lo si richiede utilizzando/perfix/api/feature/doSomething

@Controller()
@RequestMapping("/perfix/api/feature")
public class MyController {
    @RequestMapping(value = "/doSomething", method = RequestMethod.GET) 
    @ResponseBody
    public String doSomething(HttpServletRequest request) {
        ....
    }
}

È una partita perfetta, vero? Ma perché 404. Come accennato in precedenza, il valore predefinito di alwaysUseFullPathè falso, il che significa che nella tua richiesta, /api/feature/doSomethingviene utilizzato solo per trovare un controller corrispondente, ma non esiste un controller che si preoccupi di quel percorso. Devi modificare l'URL /perfix/perfix/api/feature/doSomethingo rimuoverlo perfixdalla base di MyController @RequestingMapping.


8

Penso che la risposta di Candy sia per lo più corretta. C'è una piccola parte che penso diversamente.

Per mappare l'host: port / context / hello.jsp

  1. Nessun servlet URL esatto installato, successivo.
  2. Trovati servlet percorsi jolly , ritorno.

Credo che il motivo per cui "/ *" non corrisponde a host: port / context / hello perché tratta "/ hello" come un percorso anziché come un file (poiché non ha estensione).


2

La differenza essenziale tra /*e /è che un servlet con mapping /*verrà selezionato prima di qualsiasi servlet con un mapping di estensione (come *.html), mentre un servlet con mapping /verrà selezionato solo dopo aver considerato i mapping di estensione (e verrà utilizzato per qualsiasi richiesta che non corrisponde a qualsiasi altra cosa --- è il "servlet predefinito").

In particolare, una /*mappatura verrà sempre selezionata prima di una /mappatura. Avere impedisce a qualsiasi richiesta di raggiungere il servlet predefinito del contenitore.

Entrambi saranno selezionati solo dopo le mappature servlet che corrispondono esattamente (come /foo/bar) e quelle che sono mappature del percorso più lunghe di /*(simili /foo/*). Si noti che il mapping di stringhe vuote è una corrispondenza esatta per il contesto root ( http://host:port/context/).

Vedere il capitolo 12 delle specifiche del servlet Java, disponibile nella versione 3.1 all'indirizzo http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.