最近在学习SpringMVC,先跟着教程demo在类方法上使用RequestMapping()注解,完成了页面的跳转,先上代码吧。
HelloController类:
package com.itcast.zxw.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping(path = "/hello")
public String sayHello(){
System.out.println("Hello SpringMVC!");
return "success";
}
/**
* RequestMapping注解
* @return
*/
@RequestMapping(path = "/testRequestMapping")
public String testRequestMapping(){
System.out.println("测试RequestMapping注解!");
return "success";
}
}
index.jsp页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门程序</h3>
<a href="hello">入门程序</a><br/>
<a href="testRequestMapping">RequestMapping注解</a>
</body>
</html>
springmvc的配置文件:springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 开起注解扫描 -->
<context:component-scan base-package="com.itcast.zxw"/>
<!-- 视图解析器 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 开起SpringMVC框架注解支持 -->
<mvc:annotation-driven/>
</beans>
方法跳转成功的success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>入门成功!</h2>
</body>
</html>
所有文件的目录结构如下图:
这几个文件写好之后,启动TomCat完全没有问题,运行结果如下图:
这种情况呢,只是在方法前加@RequestMapping()注解的情况,真正出现问题的是在类前也加上@RequestMapping()的时候,这个时候的访问路径就相当于多了一个文件夹,先看代码,其中,只有index.jsp和Hellocontroller类的代码有变动,其它无变化。
类前加@RequestMapping()注解的Hellocontroller类:
package com.itcast.zxw.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(path = "/test")新加的一个@RequestMapping注解
public class HelloController {
@RequestMapping(path = "/hello")
public String sayHello(){
System.out.println("Hello SpringMVC!");
return "success";
}
/**
* RequestMapping注解
* @return
*/
@RequestMapping(path = "/testRequestMapping")
public String testRequestMapping(){
System.out.println("测试RequestMapping注解!");
return "success";
}
}
修改后的index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>入门程序</h3>
在访问路径前加了一个刚刚类里面加的test,如果继续直接访问hello,则会报404错误
<a href="test/hello">入门程序</a><br/>
<a href="test/testRequestMapping">RequestMapping注解</a>
</body>
</html>
新的index.jsp在访问路径前加了一个刚刚类里面加的test,如果继续直接访问hello,则会报404错误,但是这个404不是我们今天要说的404错误,因为这个不加是很明显的错误,我们要说的是加了之后还报404错误的情况:按照道理来讲,现在这代码也没什么问题了,index.jsp能正常访问,但是点击链接进入success的时候还是会报404错误的(但是控制台的打印没有问题)
这是为什么呢???
我们可以先来看一下报错的消息(红线框里的)
从这里我们可以清楚的看到程序去找这个success.jsp的时候,去找了一个test目录下的WEB-INF,然后再依次找pages目录,最后找success.jsp(springmvc_start是项目名称,也就是项目的根目录),然后我们可以看前面的目录结构,WEB-INF的上一层根本就没有test目录,test目录只是我们刚刚在映射注解的时候为那个类加上去的,这个路径有问题,而这个路径是我们在视图解析器配置中配置的,也就是springmvc.xml中配置的
<!-- 视图解析器 -->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
从404的消息中结合配置解析器的prefix属性的value值(value="WEB-INF/pages/")我们可以理解到,自动解析器会在当前同级目录下去寻找设定目录进而寻找跳转的页面,而当前的hello请求的目录是springmvc_start/test/hello,所以它的目录一个是springmvc_start/test下的hello请求,hello请求中又要去寻找一个叫success的文件,这个文件在视图配置器里可以看出来是个jsp文件(配置的后缀),前缀+名字+后缀可以解析出来这个文件的具体位置(WEB-INF/pages/success.jsp);然后我们前面又说到了value="WEB-INF/pages/"这句会在当前目录下去寻找,所以自然就得到了404报错消息中的springmvc_start/test/WEB-INF/pages/success.jsp这一句了,那肯定是找不到的,因为我们的WEB-INF文件夹在webapp下的,也就是说是属于项目文件的,并没有test这一层;所以我们只要把这个路径设置成项目下的WEB-INF就行了,即在value="WEB-INF/pages/"前面加一个/变成(value="/WEB-INF/pages/")
表示视图解析器在项目下的WEB-INF/pages去找对应名字的jsp,改掉之后demo也能正常运行,跟前面的结果一样了。
总结
其实这也是我自己的一个小失误,教程里面配置value的时候其实是有斜杠的,而我自己写的时候没有加,前面能正常运行也就没注意,后面报错了来找原因才发现的,因为一般都是把页面放在WEB-INF目录下的,所以这里设置就这样写(value="/WEB-INF/pages/")加斜杠就好了,表示在项目跟目录的WEB-INF/pages/这个路径。
而(value="WEB-INF/pages/")不加斜杠,就代表在当前路径去找对应的文件,如果类前加了一个@RequestMapping(path)注解的时候,就相当于多了一层路径,所以报错,而如果类前没有加@RequestMapping(path = "/test")注解的话,则表示方法的注解都在项目路径下去找,返回的结果呢找同级自然也是在项目路径下去找(这也是前面没问题的原因)。
但是为了方便肯定是推荐加斜杠,把视图解析的路径确定下来是最好的,也会少很多问题。