英文:
@RequestMapping Couldn't find Jsp page
问题
我尝试在spring-boot中构建一个小应用程序,其结构如下所示。我在使用 @RequestMapping 时遇到了一个奇怪的问题,它可以找到除一个之外的所有资源。
以下是 `web.xml` 文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Step 2: 为 Spring MVC Dispatcher Servlet 设置 URL 映射 -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
以下是 `applicationContext.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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Step 3: 添加对组件扫描的支持 -->
<context:component-scan base-package="com.example.*" />
<!-- Step 4: 添加转换、格式化和验证支持 -->
<mvc:annotation-driven/>
<!-- Step 5: 定义 Spring MVC 视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
在 `com.example.controller` 包中,我有两个文件 `FrontController.java` 和 `FormController.java`。它们的外观如下所示。
`FrontController.java`
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class FrontController {
public FrontController() {
// TODO Auto-generated constructor stub
}
@RequestMapping("/")
public String showHomePage() {
System.out.println("Reached In");
return "home";
}
@RequestMapping("/spring")
public String spring() {
return "spring";
}
}
`FormController.java`
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class FormController {
public FormController() {
// TODO Auto-generated constructor stub
}
@RequestMapping("/showform")
public String showForm() {
return "showForm";
}
@RequestMapping("/formResp")
public String formResp() {
return "formResp";
}
}
现在,在服务器上加载项目后,我得到的默认页面是 `home.jsp`,它会成功显示,以下是相关的堆栈跟踪信息。
09:21:49.390 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.view.InternalResourceView - 视图名称 'home',模型 {}
09:21:49.392 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.view.InternalResourceView - 转发到 [/WEB-INF/views/home.jsp]
09:21:49.427 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.DispatcherServlet - 已完成 200 OK
`FormController.java` 中的 `showForm.jsp` 页面和 `formResp.jsp` 页面也是同样的情况,它们都能够成功显示。相关的堆栈跟踪信息如下所示。
09:21:57.107 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/WebAppDemo/showform",参数={}
09:21:57.107 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - 已映射至 com.example.controller.FormController#showForm()
09:21:57.108 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.view.InternalResourceView - 视图名称 'showForm',模型 {}
09:21:57.108 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.view.InternalResourceView - 转发到 [/WEB-INF/views/showForm.jsp]
09:21:57.302 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - 已完成 200 OK
09:22:02.378 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/WebAppDemo/formResp?name=jony",参数={masked}
09:22:02.379 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - 已映射至 com.example.controller.FormController#formResp()
09:22:02.380 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.view.InternalResourceView - 视图名称 'formResp',模型 {}
09:22:02.380 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.view.InternalResourceView - 转发到 [/WEB-INF/views/formResp.jsp]
09:22:02.621 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - 已完成 200 OK
但是,一旦我尝试在 `FrontController.java` 中显示 `spring.jsp` 页面,我遇到了 `404 错误`。相关的堆栈跟
<details>
<summary>英文:</summary>
I tried to build a small app in spring-boot, it's structure is given below. I am having a weird problem with @RequestMapping where it's able to find all the resources except one.
Here is the `web.xml` file
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Following is `applicationContext.xml` file
<?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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Step 3: Add support for component scanning -->
<context:component-scan base-package="com.example.*" />
<!-- Step 4: Add support for conversion, formatting and validation support -->
<mvc:annotation-driven/>
<!-- Step 5: Define Spring MVC view resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
in `com.example.controller` package I have two files `FrontController.java` and `FormController.java`.
This is how they look like.
`FrontController.java`
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class FrontController {
public FrontController() {
// TODO Auto-generated constructor stub
}
@RequestMapping("/")
public String showHomePage() {
System.out.println("Reached In");
return "home";
}
@RequestMapping("/spring")
public String spring() {
return "spring";
}
}
`FormController.java`
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class FormController {
public FormController() {
// TODO Auto-generated constructor stub
}
@RequestMapping("/showform")
public String showForm() {
return "showForm";
}
@RequestMapping("/formResp")
public String formResp() {
return "formResp";
}
}
Now on loading my project in the server the default page I get is `home.jsp` which get displayed successfully with the following stack trace.
09:21:49.390 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.view.InternalResourceView - View name 'home', model {}
09:21:49.392 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.view.InternalResourceView - Forwarding to [/WEB-INF/views/home.jsp]
09:21:49.427 [http-nio-8080-exec-3] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
Same thing happens with `showForm.jsp` page and `formResp.jsp` page in `FormController.java`, they get displayed successfully. Stacktrace below.
09:21:57.107 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/WebAppDemo/showform", parameters={}
09:21:57.107 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.example.controller.FormController#showForm()
09:21:57.108 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.view.InternalResourceView - View name 'showForm', model {}
09:21:57.108 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.view.InternalResourceView - Forwarding to [/WEB-INF/views/showForm.jsp]
09:21:57.302 [http-nio-8080-exec-4] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
09:22:02.378 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/WebAppDemo/formResp?name=jony", parameters={masked}
09:22:02.379 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to com.example.controller.FormController#formResp()
09:22:02.380 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.view.InternalResourceView - View name 'formResp', model {}
09:22:02.380 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.view.InternalResourceView - Forwarding to [/WEB-INF/views/formResp.jsp]
09:22:02.621 [http-nio-8080-exec-5] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK
But as soon as I try to display `spring.jsp` page in `FrontController.java` I run into `404 Error`. Stacktrace below.
09:22:09.179 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/WebAppDemo/spring", parameters={}
09:22:09.187 [http-nio-8080-exec-6] WARN org.springframework.web.servlet.PageNotFound - No mapping for GET /WebAppDemo/spring
09:22:09.187 [http-nio-8080-exec-6] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 404 NOT_FOUND
I don't know why is it not finding `spring.jsp` page when it's located in `WEB-INF/views` folder along with other JSP files. Will deeply appreciate some help on this. Thanks in Advance.
</details>
# 答案1
**得分**: 2
首先,我在项目中找到了许多配置问题和缺失的类,并进行了解决。
拉取新代码:https://github.com/anish-fullstack/WebDemoApp
更新的项目结构:
![项目结构][1]
从web.xml中移除了所有内容。更新后的web.xml:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<display-name>WebAppDemo</display-name>
</web-app>
添加了一个缺失的类,应用程序将从该类开始运行。
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("WEB-INF/applicationContext.xml")
public class WebAppDemoApplication {
public static void main(String[] args) {
SpringApplication.run(WebAppDemoApplication.class, args);
}
}
更新了application.properties文件。
spring.main.allow-bean-definition-overriding=true
您需要添加jasper和jstl依赖以支持jsp解析和jstl支持。更新后的pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>WebAppDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>WebAppDemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 其他依赖... -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<!-- 构建配置... -->
</project>
运行应用程序日志:
Spring Boot (v2.3.4.RELEASE)
2020-10-03 13:27:01.494 INFO 7738 --- [main] com.example.WebAppDemoApplication : Starting WebAppDemoApplication on Anishs-MacBook-Pro.local with PID 7738 (/Users/anish/Downloads/WebDemoApp-master/WebAppDemo/target/classes started by anish in /Users/anish/Downloads/WebDemoApp-master/WebAppDemo)
...
2020-10-03 13:27:02.309 INFO 7738 --- [main] com.example.WebAppDemoApplication : Started WebAppDemoApplication in 0.992 seconds (JVM running for 1.353)
...
此外,您正在访问错误的URL。映射的URL将如下所示:
http://localhost:8080/showform
- 这将打开 showForm.jsp。http://localhost:8080/formResp
- 这将打开 formResp.jsp。http://localhost:8080/
- 这将打开 home.jsp。http://localhost:8080/spring
- 这将打开 spring.jsp。
英文:
First of all, I found a lot of configuration issue and missing classes in the project that I resolved.
Take the pull of new code : https://github.com/anish-fullstack/WebDemoApp
Updated Project Structure :
Remove everything from web.xml. Updated web.xml :
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<display-name>WebAppDemo</display-name>
</web-app>
Added a missing class from where the application will start.
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("WEB-INF/applicationContext.xml")
public class WebAppDemoApplication {
public static void main(String[] args) {
SpringApplication.run(WebAppDemoApplication.class, args);
}
}
Update application.properties.
spring.main.allow-bean-definition-overriding=true
You need to jasper dependency and jstl to support jsp parsing and jstl support. Updated pom.xml :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>WebAppDemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>WebAppDemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Running application log :
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.4.RELEASE)
2020-10-03 13:27:01.494 INFO 7738 --- [ main] com.example.WebAppDemoApplication : Starting WebAppDemoApplication on Anishs-MacBook-Pro.local with PID 7738 (/Users/anish/Downloads/WebDemoApp-master/WebAppDemo/target/classes started by anish in /Users/anish/Downloads/WebDemoApp-master/WebAppDemo)
2020-10-03 13:27:01.495 INFO 7738 --- [ main] com.example.WebAppDemoApplication : No active profile set, falling back to default profiles: default
2020-10-03 13:27:01.955 INFO 7738 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2020-10-03 13:27:01.959 INFO 7738 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2020-10-03 13:27:01.959 INFO 7738 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.38]
2020-10-03 13:27:02.066 INFO 7738 --- [ main] org.apache.jasper.servlet.TldScanner : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
2020-10-03 13:27:02.071 INFO 7738 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-10-03 13:27:02.071 INFO 7738 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 553 ms
2020-10-03 13:27:02.242 INFO 7738 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2020-10-03 13:27:02.301 INFO 7738 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-10-03 13:27:02.309 INFO 7738 --- [ main] com.example.WebAppDemoApplication : Started WebAppDemoApplication in 0.992 seconds (JVM running for 1.353)
2020-10-03 13:27:11.354 INFO 7738 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-10-03 13:27:11.354 INFO 7738 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-10-03 13:27:11.358 INFO 7738 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 4 ms
Moreover, you are accessing wrong urls. The mapping urls will be as follows :
http://localhost:8080/showform
- this will open showForm.jsp.
http://localhost:8080/formResp
- this will open formResp.jsp.
http://localhost:8080/
- this will open home.jsp.
http://localhost:8080/spring
- /spring - this will open spring.jsp
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论