對(duì)于springmvc中前端控制器url-pattern配置, 看了很多博客, 發(fā)現(xiàn)好多人理解都是錯(cuò)誤, 并不清楚會(huì)攔截什么路徑的請(qǐng)求, 有點(diǎn)小的細(xì)節(jié)并不被大家所關(guān)注.
<servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- contextConfigLocation配置springmvc加載的配置文件(配置處理器映射器,適配器等等) 如果不配置,默認(rèn)加載的是/WEB-INF/[DispatcherServlet 的Servlet 名字]-servlet.xml(springmvc-servlet.xml) --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
'*.xxx'
, 以指定后綴結(jié)尾的請(qǐng)求都交由DispatcherServlet處理'/'
將會(huì)覆蓋容器的default servlet, 凡是在web.xml文件中找不到匹配的URL,它們的訪問(wèn)請(qǐng)求都將交給該Servlet處理(靜態(tài)資源也將會(huì)攔截). 所以web.xml沒(méi)有配置其他特殊路徑的servlet, 基本上所有的請(qǐng)求都交由DispatcherServlet處理.關(guān)于什么是default servlet, 可以參考我之前的博文.
'/*'
錯(cuò)誤的配置,會(huì)攔截*.jsp, *.jspx
的請(qǐng)求, 使用這種配置最終要轉(zhuǎn)發(fā)到一個(gè)JSP頁(yè)面,仍然會(huì)由DispatcherServlet, 解析jsp地址, 不能根據(jù)jsp頁(yè)面找到handler, 會(huì)報(bào)錯(cuò)對(duì)于第一種擴(kuò)展匹配, 是最簡(jiǎn)單的. 也是使用最簡(jiǎn)單的了.但是現(xiàn)在如此流行restful風(fēng)格的URL, 這種帶小尾巴的URL, 還是有點(diǎn)low的.
第二種配置使用/
, 通過(guò)該配置是可以實(shí)現(xiàn)rustful風(fēng)格的URL的.
為了驗(yàn)證這種配置, 我做了一個(gè)簡(jiǎn)單的測(cè)試
在webapp/WEB-INF/jsp下新建test.jsp, controller中只做轉(zhuǎn)發(fā).
@Controller@RequestMapping("")public class Test { @RequestMapping("/test") public String test() { return "test"; }}
測(cè)試請(qǐng)求路徑: /test
結(jié)果: 執(zhí)行該請(qǐng)求后404
console打印如下日志:
DispatcherServlet with name ‘taotao-sso’ processing GET request for [/test]
RequestMappingHandlerMapping]-[DEBUG] Looking up handler method for path /test
RequestMappingHandlerMapping]-[DEBUG] Returning handler method [public java.lang.String com.taotao.sso.controller.Test.test()]
DispatcherServlet]-[DEBUG] Rendering view [org.springframework.web.servlet.view.InternalResourceView: name ‘test’; URL [/WEB-INF/jsp/test.jsp]] in DispatcherServlet with name ‘taotao-sso’
InternalResourceView]-[DEBUG] Forwarding to resource [/WEB-INF/jsp/test.jsp] in InternalResourceView ‘test’
DispatcherServlet]-[DEBUG] DispatcherServlet with name ‘taotao-sso’ processing GET request for [/WEB-INF/jsp/test.jsp]
RequestMappingHandlerMapping]-[DEBUG] Looking up handler method for path /WEB-INF/jsp/test.jsp
RequestMappingHandlerMapping]-[DEBUG] Did not find handler method for [/WEB-INF/jsp/test.jsp]
PageNotFound]-[WARN] No mapping found for HTTP request with URI [/WEB-INF/jsp/test.jsp] in DispatcherServlet with name ‘taotao-sso’
DispatcherServlet]-[DEBUG] Successfully completed request
從日志可以清晰的看出, springmvc可以找到請(qǐng)求/test的handler, 之后springmvc轉(zhuǎn)發(fā)請(qǐng)求’/WEB-INF/jsp/test.jsp’, 同樣被DispatcherServlet處理, 之后就發(fā)出了/WEB-INF/jsp/test.jsp這樣的轉(zhuǎn)發(fā)請(qǐng)求, 自然會(huì)找不到handler, No mapping. 所以這樣的請(qǐng)求會(huì)一直為404.
這里DispatcherServlet配置為:
按照servlet的匹配規(guī)則,則路徑匹配(/*
)會(huì)優(yōu)先于擴(kuò)展匹配(*.jsp, *.jspx
),導(dǎo)致對(duì)jsp的請(qǐng)求會(huì)被DispatcherServlet攔截掉。
*.jsp, *.jspx
所對(duì)應(yīng)的servlet為org.apache.jasper.servlet.JspServlet
, 位于tomcat_home/conf/web.xml中, 下文會(huì)講到.
對(duì)于servlet的匹配規(guī)則和順序不清楚的同學(xué), 可以參看這篇博文
請(qǐng)求路徑為: /test
結(jié)果: 正確找到view, 并進(jìn)行渲染.
DispatcherServlet]-[DEBUG] DispatcherServlet with name ‘springmvc’ processing GET request for [/test]
RequestMappingHandlerMapping]-[DEBUG] Looking up handler method for path /test
RequestMappingHandlerMapping]-[DEBUG] Returning handler method [public java.lang.String com.taotao.sso.controller.Test.test()]
DefaultListableBeanFactory]-[DEBUG] Invoking afterPropertiesSet() on bean with name ‘test’
DispatcherServlet]-[DEBUG] Rendering view [org.springframework.web.servlet.view.InternalResourceView: name ‘test’; URL [/WEB-INF/jsp/test.jsp]] in DispatcherServlet with name ‘springmvc’
InternalResourceView]-[DEBUG] Forwarding to resource [/WEB-INF/jsp/test.jsp] in InternalResourceView ‘test’
DispatcherServlet]-[DEBUG] Successfully completed request
看到這里的日志, 很多同學(xué)就奇怪了, 這里DispatcherServlet并不攔截轉(zhuǎn)發(fā)的請(qǐng)求[/WEB-INF/jsp/test.jsp], 就直接找到了view.
前面說(shuō)的當(dāng)DispatcherServlet配置為’/’, 將會(huì)覆蓋default servlet
, 將會(huì)處理所有其他Servlet都不處理的訪問(wèn)請(qǐng)求. 所以這里不攔截?cái)r截.jsp, .jspx.的請(qǐng)求, 一定有其他地方攔截了該請(qǐng)求, 但是仔細(xì)查找web.xml并沒(méi)有發(fā)現(xiàn)其他的servlet啊!那一定是在容器中定義的啦~
果不其然, 在%TOMCAT_HOME%/conf/web.xml中繼承過(guò)來(lái)的JspServlet會(huì)處理該請(qǐng)求.
<servlet> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> <init-param> <param-name>fork</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>xpoweredBy</param-name> <param-value>false</param-value> </init-param> <load-on-startup>3</load-on-startup> </servlet> <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.jspx</url-pattern> </servlet-mapping>
從該web.xml也看到DefaultServlet
的定義了(文件中總共就定義了這兩個(gè)servlet)
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
這也就是為什么我們直接訪問(wèn)不在WEB-INF的jsp, 可以直接找到并解析的原因了.
我們將test.jsp拷貝一份到webapp下, 直接訪問(wèn)/test.jsp, 訪問(wèn)到j(luò)sp中的內(nèi)容了.并未出現(xiàn)404, 從而驗(yàn)證了我們的猜想.
聯(lián)系客服