Spring MVC响应输出没有标题

时间:2014-03-31 19:55:09

标签: java spring spring-mvc

我设置了一个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,而是直接输出到浏览器......?

2 个答案:

答案 0 :(得分:0)

这里涉及一些概念。

首先,我们需要了解Servlet Specification关于订单网址模式匹配的内容

  
      
  1. 容器会尝试找到路径的完全匹配   请求servlet的路径。成功匹配选择servlet。
  2.   
  3. 容器将递归尝试匹配最长的路径前缀。   这是通过使用一次逐步降低路径树的目录来完成的   '/'字符作为路径分隔符。最长的比赛决定了   选择了servlet。
  4.   
  5. 如果网址路径中的最后一段包含扩展名(例如.jsp),   servlet容器将尝试匹配处理请求的servlet   对于扩展名。扩展名被定义为最后一部分   最后一个'。'字符后的段。
  6.   
  7. 如果前三个规则都没有导致servlet匹配,那么   容器将尝试提供适合的内容   资源要求。 如果为。定义了“默认”servlet   应用程序,将使用。许多容器提供隐式   用于提供内容的默认servlet
  8.   

您的DispatcherServlet已映射到

dispatcher.addMapping("/*");

。因此,它声明将在步骤2中使用的路径映射。此DispatcherServlet基本上处理所有请求。

假设您将请求发送至

http://yourhost.com/context/

您的MainController及其main()处理程序方法将用于处理请求。该方法返回视图名称index。您的InternalResourceViewResolver会将该视图名称解析为

/WEB-INF/jsp/index.jsp

该路径将获得RequestDispatcherforward将获得enables。由于您的DispatcherServlet已映射到/*,因此选择Servlet来处理内部forward。通常,它没有任何方法来处理它,因为您没有映射到该路径的@Controller处理程序方法。但是,你确实有

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

DefaultServletHttpRequestHandler {{3}}配置。

  

启用转发到“默认”Servlet。使用此方法时   DefaultServletHttpRequestHandler将尝试自动检测   “默认”Servlet名称。或者,您可以指定名称   默认Servlet通过enable(String)。

DefaultServletHttpRequestHandler已注册并用于尝试处理@ControllerDispatcherServlet个实例未处理的任何请求。

因此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 "/"
}

无效。