我设置了一个Java配置Spring MVC Web应用程序,但是当我导航到主页时,它会输出原始页面源。
例如,我希望看到
Hello World!
但我明白了:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<html>
<body>Hello World!</body>
</html>
直接在浏览器中显示。
查看响应,看起来没有发送响应标头。
任何人都知道为什么?
public class WebInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext sc) throws ServletException {
WebApplicationContext context = getContext();
sc.addListener(new ContextLoaderListener(context)); // attach WebApplicationContext to ServletContext life cycle
ServletRegistration.Dynamic dispatcher = sc.addServlet("DispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1); // positive value means eagerly load on start up
dispatcher.addMapping("/*"); // map DispatcherServlet to /* URL
}
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.example.app.config"); // package containing @Configuration object
return context;
}
}
@EnableWebMvc
@ComponentScan(basePackages = "com.example.app") // base package to search for @Component / @Controller
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
// set default servlet handler.
// equivalent to <mvc:default-servlet-handler/>
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
final InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
}
@Controller
public class MainController {
@RequestMapping(value = "/", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
public String main() {
return "index";
}
}
修改
看起来当我从.jsp中删除<%@page ...>
行时,HTML会正确显示。但这意味着这个JSP不会被解析为JSP,而是直接输出到浏览器......?
答案 0 :(得分:0)
这里涉及一些概念。
首先,我们需要了解Servlet Specification关于订单网址模式匹配的内容
- 容器会尝试找到路径的完全匹配 请求servlet的路径。成功匹配选择servlet。
- 容器将递归尝试匹配最长的路径前缀。 这是通过使用一次逐步降低路径树的目录来完成的 '/'字符作为路径分隔符。最长的比赛决定了 选择了servlet。
- 如果网址路径中的最后一段包含扩展名(例如.jsp), servlet容器将尝试匹配处理请求的servlet 对于扩展名。扩展名被定义为最后一部分 最后一个'。'字符后的段。
- 如果前三个规则都没有导致servlet匹配,那么 容器将尝试提供适合的内容 资源要求。 如果为。定义了“默认”servlet 应用程序,将使用。许多容器提供隐式 用于提供内容的默认servlet 。
醇>
您的DispatcherServlet
已映射到
dispatcher.addMapping("/*");
。因此,它声明将在步骤2中使用的路径映射。此DispatcherServlet
基本上处理所有请求。
假设您将请求发送至
http://yourhost.com/context/
您的MainController
及其main()
处理程序方法将用于处理请求。该方法返回视图名称index
。您的InternalResourceViewResolver
会将该视图名称解析为
/WEB-INF/jsp/index.jsp
该路径将获得RequestDispatcher
,forward
将获得enables。由于您的DispatcherServlet
已映射到/*
,因此选择Servlet
来处理内部forward
。通常,它没有任何方法来处理它,因为您没有映射到该路径的@Controller
处理程序方法。但是,你确实有
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
DefaultServletHttpRequestHandler
{{3}}配置。
启用转发到“默认”Servlet。使用此方法时 DefaultServletHttpRequestHandler将尝试自动检测 “默认”Servlet名称。或者,您可以指定名称 默认Servlet通过enable(String)。
此DefaultServletHttpRequestHandler
已注册并用于尝试处理@Controller
中DispatcherServlet
个实例未处理的任何请求。
因此DispatcherServlet
用于处理
/WEB-INF/jsp/index.jsp
但它没有@Controller
,所以它使用DefaultServletHttpRequestHandler
。这个HttpRequestHandler
找到Servlet容器的默认Servlet
并委托处理请求。
通常,Servlet容器具有默认的Servlet
实现,只需将所请求资源的内容写入HttpServletResponse
OutputStream
即可。我相信Tomcat,你必须检查其他容器。
所以这个默认的Servlet会看到
/WEB-INF/jsp/index.jsp
然后找到此资源并将其直接流式传输到响应OutputStream
,编写JSP内容而不是呈现的HTML。
简单的解决方案是将您的servlet映射到\
。如果您这样做,RequestDispatcher
使用的InternalResourceViewResolver
将再次转发到
/WEB-INF/jsp/index.jsp
但该路径不会与DispatcherServlet
匹配,因为它是默认的Servlet(步骤4)。它将由用于处理JSP的容器Servlet
匹配。 Tomcat有JspServlet
。
答案 1 :(得分:-1)
我们最近提出的解决方案是您被迫使用web.xml配置您的Web应用程序(特别是DispatcherServlet):
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>webapp.config.WebAppConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
完美无缺。我知道。遗憾地说
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// ...
@Override
protected String[] getServletMappings() {
return new String[] {"/*"};
} // Neither with "/"
}
无效。