Servlet Spec 3.0 不呈现 JSP 包含



我尝试使用Tomcat 7和Tomcat 8 RC 5,但我的JSP包含没有渲染。

我正在使用Spring MVC(不过不要认为这很重要)。

我的 JSP 看起来像这样:

<jsp:include page="includes/header.jsp" />
It Worked!
<jsp:include page="includes/footer.jsp" />

当页面呈现时,它看起来像这样

<jsp:include page="includes/header.jsp" />
It Worked!
<jsp:include page="includes/footer.jsp" />

在我的Pom文件中,我包括:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>

我的网络.xml文件如下所示:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="Blog" version="3.0">
<display-name>Blog</display-name>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/error/404.html</location>
</error-page>

我的应用初始值设定项如下所示:

public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new     AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.package.to.AppConfig");
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic servlet = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
servlet.setLoadOnStartup(1);
servlet.addMapping("/*");
}

我做错了什么? 为什么我的包含无法正确呈现?

我也尝试了以下方法,结果相同:

<%@ include file="includes/header.jsp" %>
It Worked!
<%@ include file="includes/footer.jsp" %> 

控制器方法:

@Controller
public class PageController {
@Autowired
PageService pageService;
@RequestMapping(value = "/*", method = RequestMethod.GET)
public String index(HttpServletRequest request){
String path = request.getRequestURI().substring(request.getContextPath().length());
Page page = pageService.getPageByUrl(path);
if(page == null){
throw new ResourceNotFoundException();
}
return page.getTemplate().getPageTemplatePath();
}

}

应用配置

@Configuration
@ComponentScan({"package.to.scan"})
@EnableTransactionManagement
@EnableWebMvc
@PropertySource("/${env:prod}.properties")
@Import({DataSourceConfig.class})
public class AppConfig extends WebMvcConfigurerAdapter {
@Autowired
Environment environment;
@Bean
public InternalResourceViewResolver internalResourceViewResolver(){
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/styles/**").addResourceLocations("/styles/");
registry.addResourceHandler("/images/**").addResourceLocations("/images/");
registry.addResourceHandler("/scripts/**").addResourceLocations("/scripts/");
}
}

要快速修复,请将DispatcherServlet映射更改为/而不是/*

您有一个DispatcherServlet/*映射。换句话说,任何未命名的RequestDispatcherforwards 或includes 都将经历相同的Servlet

因此,当您InternalResourceViewResolver的已解析视图尝试转发到时,例如,

/WEB-INF/jsp/somepage.jsp

将选择DispatcherServlet来处理它。由于您没有处理对该 URL 的请求的@Controller方法,因此注册的SimpleUrlHandlerMapping

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}

将被使用。DefaultServletHandlerConfigurer注册一个DefaultServletHttpRequestHandler,该将请求发送到defaultServlet。它通过按名称获取defaultServlet来实现此目的

@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName);
if (rd == null) {
throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" +
this.defaultServletName +"'");
}
rd.forward(request, response);
}

对于Tomcat,这通常是org.apache.catalina.servlets.DefaultServlet

大多数 Web 应用程序的默认资源服务 Servlet,使用 提供静态资源,如 HTML 页面和图像。

换句话说,它不处理 jsp,它只是将它们直接馈送到HttpServletResponseOutputStream.

相反,如果您将DispatcherServleturl 映射更改为/,则Servlet容器将再次遍历匹配 url 的规则。这些在 Servlet 规范中进行了描述。第三个去

如果网址路径中的最后一个段包含扩展名(例如 .jsp), servlet 容器将尝试匹配处理的 servlet 请求延期。扩展被定义为 最后一个"."字符之后的最后一段

在这种情况下,默认情况下,Tomcat将找到映射到org.apache.jasper.servlet.JspServlet

<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>

此 url 映射与/WEB-INF/jsp/somepage.jsp匹配,因此被选中。JspServlet确实渲染 jsp,因此可以解决问题。


有点相关的说明,servlet-api应由Servlet容器提供,而不是由 Web 应用程序提供。

更改此内容

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>

对此

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>

无论这是否是原因,都应进行此更改。

最新更新