web.xml
<servlet>
<servlet-name>dispatcherservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherservlet-name>
<url-pattern>/*url-pattern>
servlet-mapping>
dispatcher-servlet.xml
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
bean>
控制器代码如下:
@RequestMapping("/")
public String index()
{
return "hello";
}
浏览器URL:http://localhost:8080/
控制台报错提示:
org.springframework.web.servlet.PageNotFound.noHandlerFound No mapping found for HTTP request with URI [/WEB-INF/jsp/hello.jsp] in DispatcherServlet with name 'dispatcher'
不用怀疑,我的项目下肯定有/WEB-INF/jsp/hello.jsp
这个jsp文件,并不是路径的问题。
真正的原因是,控制器返回"hello"
后,视图解析器会去寻找/WEB-INF/jsp/hello.jsp
这个文件,根据web.xml
中的配置,无疑这个文件会被上面配置的名为dispatcher
的servlet
拦截,然后交给相应的控制器进行处理,但:
1、
我们并没有配置相应的处理代码,我们只写了@RequestMapping("/")
这一句;
2、
我们也不应该去进行处理,这是视图解析器该做的事情,不是控制器应该做的。
所以,不要尝试去写/*
,当然学习除外,学的时候要充分理解,很有必要试一下。
在web.xml中添加如下配置:
<<servlet>
<servlet-name>servletTestservlet-name>
<servlet-class>servlet.ServletTestservlet-class>
servlet>
<servlet-mapping>
<servlet-name>servletTestservlet-name>
<url-pattern>/WEB-INF/*url-pattern>
servlet-mapping>
src文件夹下新建package:servlet
,新建java类:ServletTest
ServletTest类代码如下:
package servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletTest extends HttpServlet {
public void init() throws ServletException {
System.out.println("ServletTest init");
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("come into ServletTest");
System.out.println(request.getServletPath());
System.out.println(request.getServletPath());
}
public void destroy() {
System.out.println("ServletTest destroy");
}
}
浏览器URLhttp://localhost:8080/
控制台输出:
come into ServletTest
/WEB-INF
/jsp/hello.jsp
说明
当浏览器发出请求后,服务器收到请求,根据URL交给dispatcher
处理,dispatcher
会进行处理器映射,交给控制器方法index
处理,index
方法返回字符串hello
,视图解析器根据配置获得jsp
路径/WEB-INF/jsp/hello.jsp
,然后又进行服务器处理,服务器根据长路径原则,选择/WEB-INF/*
的servlet而不是/*
,即交给我们后面添加的名为servletTest
的servlet进行处理,servletTest
初始化调用init
方法,控制台输出come into ServletTest
,然后因为请求被doGet方法处理,依次输出/WEB-INF
和 /jsp/hello.jsp
。后面的两句输出也可以说明确实视图解析器重新进行了请求,因为ServletPath输出的是/WEB-INF
,即上下文为/WEB-INF
。
为什么写/
时没有问题,而/*
就发生了错误。
这是servlet的url-pattern匹配规则的原因
/
是url-pattern匹配的最低级,而web.xml中虽然没有写,但有一些默认的servlet,比如jsp类型的就会被存在的servlet匹配到(虽然不知道是一个还是几个,但肯定是有的),扩展名匹配高于/
,也就是说jsp请求根本不会被/
的servlet处理,自然对于/WEB-INF/jsp/hello.jsp
这样的也会被默认的servlet处理,而且会被正确处理,得到正确地结果。
出现错误的原因:
1、视图解析器会重新向服务器发送请求处理jsp
2、写/*
时匹配优先级高于扩展名匹配,jsp请求会被我们添加的servlet处理,我们并没有正确处理jsp渲染。
第一次写这个。 暑假学习spring mvc,/*
的问题一直没有解决,项目要做完的时候再来试了,最终发现了原因。以前在CSDN上也查到了很多问题,还是很有帮助的。反正暑假时间多,就把这个问题写了出来,分享一下。