【问题标题】:Servlet Spec 3.0 not rendering JSP includeServlet Spec 3.0 不呈现 JSP 包括
【发布时间】:2014-01-10 15:13:29
【问题描述】:

我已尝试同时使用 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>

我的 web.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/");
}

}

【问题讨论】:

  • 你能显示转发到你的jsp的控制器方法吗?我想看看你的相关上下文配置。
  • 添加了控制器方法。
  • 你的上下文有一个InternalResourceViewResolver 或别的什么?
  • 我现在也发布了这个

标签: java spring jsp tomcat servlets


【解决方案1】:

为了快速解决问题,请将您的 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,它将请求分派给 default Servlet。它通过按名称获取default Servlet 来做到这一点

@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 页面和图像。

换句话说,它不处理jsps,它只是将它们直接提供给HttpServletResponseOutputStream

如果改为将 DispatcherServlet url-mapping 更改为 /Servlet 容器将再次通过匹配 url 的规则。这些在Servlet Specification 中有描述。第三个去

如果 URL 路径中的最后一段包含扩展名(例如 .jsp), 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 会渲染 jsps,这样就可以解决问题。


有点相关的说明,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>

不管是不是这个原因,你都应该做出这个改变。

【讨论】:

  • @user1304051 请查看完整答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-25
  • 2010-12-07
  • 2018-01-14
  • 2012-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多