我尝试过使用 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 方法:
@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
的 /*
映射。换句话说,任何未命名的 RequestDispatcher
forward
或 include
都将通过同一个 Servlet
。
因此,例如,当您的 InternalResourceViewResolver
的解析 View 尝试转发到时,
/WEB-INF/jsp/somepage.jsp
将选择DispatcherServlet
来处理它。由于您没有处理对该 URL 的请求的 @Controller
方法,因此
SimpleUrlHandlerMapping
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
将使用。 DefaultServletHandlerConfigurer
注册一个 DefaultServletHttpRequestHandler
,它将请求分派(dispatch)给 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
这是
The default resource-serving servlet for most web applications, used to serve static resources such as HTML pages and images.
换句话说,它不处理 jsps,只是将它们直接提供给 HttpServletResponse
OutputStream
。
如果您将 DispatcherServlet
url 映射更改为 /
,则 Servlet
容器将再次运行通过匹配url的规则。这些在 Servlet Specification 中进行了描述。 。第三个去了
If the last segment in the URL path contains an extension (e.g. .jsp), the servlet container will try to match a servlet that handles requests for the extension. An extension is defined as the part of the last segment after the last ’.’ character
在这种情况下,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>
无论这是否是原因,您都应该进行此更改。
关于java - Servlet Spec 3.0 不渲染 JSP 包含,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20725961/