【问题标题】:How to serve .html files with Spring如何使用 Spring 提供 .html 文件
【发布时间】:2013-03-06 22:19:54
【问题描述】:

我正在使用 Spring 开发一个网站,并尝试提供不是 .jsp 文件(例如 .html)的资源

现在我已经注释掉了我的 servlet 配置的这一部分

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" 
        p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />

并尝试从控制器返回资源的完整路径。

@Controller
public class LandingPageController {

protected static Logger logger = Logger.getLogger(LandingPageController.class);

@RequestMapping({"/","/home"})
public String showHomePage(Map<String, Object> model) {
    return "/WEB-INF/jsp/index.html";   
   }
}

index.html 文件存在于该文件夹中。

注意:当我将 index.html 更改为 index.jsp 时,我的服务器现在可以正确地提供页面。

谢谢。

【问题讨论】:

  • 我认为 [this answer][1] 可能会有所帮助。 [1]:stackoverflow.com/questions/1483063/…
  • 不,这不是我想做的。我希望自己有一个文件夹,就像我用记事本++对网站静态内容进行编程一样。包含我的 index.html 的文件夹,所有内容都相对于该 index.html

标签: java spring spring-mvc


【解决方案1】:

如果你使用spring boot,你不能在你的application.properties文件中设置属性spring.mvc.view.prefixspring.mvc.view.suffix,而是从配置类中配置beanViewResolver

应用程序属性

# Configured in @Configuration GuestNav
#spring.mvc.view.prefix=/WEB-INF/views/
#spring.mvc.view.suffix=.jsp
# Live reload
spring.devtools.restart.additional-paths=.
# Better logging
server.tomcat.accesslog.directory=logs
server.tomcat.accesslog.file-date-format=yyyy-MM-dd
server.tomcat.accesslog.prefix=access_log
server.tomcat.accesslog.suffix=.log

主要方法

@SpringBootApplication
public class WebApp extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(WebApp.class);
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(WebApp.class, args);
    }

}

配置类

@Configuration
@EnableWebMvc
public class DispatcherConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/views/**").addResourceLocations("/views/");
    }

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/notinuse/");
        viewResolver.setSuffix("");
        return viewResolver;
    }

}

控制器类

@Controller
public class GuestNav {

    @GetMapping("/")
    public String home() {
        return "forward:/views/guest/index.html";
    }
}

你必须把你的文件放在/webapp/views/guest/index.html目录下,小心,webapp目录在resources目录之外。
通过这种方式,您可以使用 spring-mvc 的 url 模式,但提供静态上下文。

【讨论】:

    【解决方案2】:

    html 文件的 Java 配置(在本例中为 index.html):

    @Configuration
    @EnableWebMvc
    public class DispatcherConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
    
            registry.addResourceHandler("/index.html").addResourceLocations("/index.html");
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题并尝试了各种解决方案来加载 html 来自 Spring MVC 的页面,以下解决方案对我有用

      服务器的 web.xml 中的 Step-1 注释这两行

      <!--     <mime-mapping>
              <extension>htm</extension>
              <mime-type>text/html</mime-type>
          </mime-mapping>--> 
      <!--     <mime-mapping>
              <extension>html</extension>
              <mime-type>text/html</mime-type>
          </mime-mapping>
       -->
      

      Step-2 在应用程序的 web xml 中输入以下代码

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

      Step-3 创建一个静态控制器类

      @Controller 
      public class FrontController {
           @RequestMapping("/landingPage") 
          public String getIndexPage() { 
          return "CompanyInfo"; 
      
          }
      
      }
      

      Step-4在Spring配置文件中修改后缀为.htm .htm

      Step-5 将页面重命名为 .htm 文件并将其存储在 WEB-INF 中并构建/启动服务器

      localhost:8080/.../landingPage
      

      【讨论】:

        【解决方案4】:

        听起来你正在尝试做这样的事情:

        • 静态 HTML 视图
        • Spring 控制器服务于 AJAX

        如果是这种情况,如前所述,最有效的方法是让 Web 服务器(而不是 Spring)将 HTML 请求作为静态资源处理。因此,您将需要以下内容:

        1. 将所有 .html、.css、.js、.png 等请求转发到 网络服务器的资源处理程序
        2. 将所有其他请求映射到 spring 控制器

        这是实现这一目标的一种方法...

        web.xml - 将 servlet 映射到根目录 (/)

        <servlet>
                    <servlet-name>sprung</servlet-name>
                    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                    ...
        <servlet>
        
        <servlet-mapping>
                    <servlet-name>sprung</servlet-name>
                    <url-pattern>/</url-pattern>
        </servlet-mapping>
        

        Spring JavaConfig

        public class SpringSprungConfig extends DelegatingWebMvcConfiguration {
        
            // Delegate resource requests to default servlet
            @Bean
            protected DefaultServletHttpRequestHandler defaultServletHttpRequestHandler() {
                DefaultServletHttpRequestHandler dsrh = new DefaultServletHttpRequestHandler();
                return dsrh;
            }
        
            //map static resources by extension
            @Bean
            public SimpleUrlHandlerMapping resourceServletMapping() {
                SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        
                //make sure static resources are mapped first since we are using
                //a slightly different approach
                mapping.setOrder(0);
                Properties urlProperties = new Properties();
                urlProperties.put("/**/*.css", "defaultServletHttpRequestHandler");
                urlProperties.put("/**/*.js", "defaultServletHttpRequestHandler");
                urlProperties.put("/**/*.png", "defaultServletHttpRequestHandler");
                urlProperties.put("/**/*.html", "defaultServletHttpRequestHandler");
                urlProperties.put("/**/*.woff", "defaultServletHttpRequestHandler");
                urlProperties.put("/**/*.ico", "defaultServletHttpRequestHandler");
                mapping.setMappings(urlProperties);
                return mapping;
            }
        
            @Override
            @Bean
            public RequestMappingHandlerMapping requestMappingHandlerMapping() {
                RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
        
                //controller mappings must be evaluated after the static resource requests
                handlerMapping.setOrder(1);
                handlerMapping.setInterceptors(this.getInterceptors());
                handlerMapping.setPathMatcher(this.getPathMatchConfigurer().getPathMatcher());
                handlerMapping.setRemoveSemicolonContent(false);
                handlerMapping.setUseSuffixPatternMatch(false);
                //set other options here
                return handlerMapping;
            }
        }
        

        其他注意事项

        • 隐藏 .html 扩展名 - 如果您委托静态资源请求,这超出了 Spring 的范围。查看 URL 重写过滤器。
        • 模板 - 您不希望在每个 HTML 页面中为常见元素重复标记。如果将 HTML 作为静态资源提供,这可能无法在服务器上完成。查看客户端 *VC 框架。我是 YUI 的粉丝,它有许多模板机制,包括 Handlebars。

        【讨论】:

          【解决方案5】:

          问题背景

          首先要了解的是:渲染jsp文件的不是spring。是 JspServlet (org.apache.jasper.servlet.JspServlet) 做的。这个 servlet 带有 Tomcat(jasper 编译器)而不是 spring。这个 JspServlet 知道如何编译 jsp 页面以及如何将其作为 html 文本返回给客户端。 tomcat 中的 JspServlet 默认只处理匹配两种模式的请求:*.jsp 和 *.jspx。

          现在,当 spring 使用 InternalResourceView(或 JstlView)渲染视图时,真正发生了三件事:

          1. 从模型中获取所有模型参数(由您的控制器处理程序方法返回,即"public ModelAndView doSomething() { return new ModelAndView("home") }"
          2. 将这些模型参数公开为请求属性(以便 JspServlet 可以读取)
          3. 将请求转发到 JspServlet。 RequestDispatcher 知道每个 *.jsp 请求都应该转发给 JspServlet(因为这是默认的 tomcat 配置)

          当您简单地将视图名称更改为 home.html 时,tomcat 将知道如何处理请求。这是因为没有 servlet 处理 *.html 请求。

          解决方案

          如何解决这个问题。有三个最明显的解决方案:

          1. 将 html 公开为资源文件
          2. 指示 JspServlet 也处理 *.html 请求
          3. 编写您自己的servlet(或将请求传递给另一个现有的servlet 到*.html)。

          有关如何实现此目的的完整代码示例,请参考我在另一篇文章中的回答:How to map requests to HTML file in Spring MVC?

          【讨论】:

            【解决方案6】:

            最初的问题是配置指定了一个属性 suffix=".jsp",因此 ViewResolver 实现类会将 .jsp 添加到从您的方法返回的视图名称的末尾。

            但是,既然您注释掉了 InternalResourceViewResolver,那么根据您的应用程序配置的其余部分,可能没有注册任何其他 ViewResolver。您可能会发现现在没有任何效果。

            由于.html 文件是静态 并且不需要servlet 处理,因此使用&lt;mvc:resources/&gt; mapping 更有效、更简单。这需要 Spring 3.0.4+。

            例如:

            <mvc:resources mapping="/static/**" location="/static/" />
            

            这会将所有以/static/ 开头的请求传递webapp/static/ 目录。

            因此,通过将index.html 放入webapp/static/ 并在您的方法中使用return "static/index.html";,Spring 应该会找到视图。

            【讨论】:

            • 令人惊讶的是这有效。只需稍作改动即可返回“static/index.html”。
            • 万分感谢!它解决了我在项目中的很多问题
            • 只是一点评论。我什至不必在方法中返回“page.html”,因为不再需要使用该方法。如果“方法”是指响应 GET 请求的 @Controller 类的方法,我们不再需要它们,就像 &lt;mvc:resources mapping&gt; 我们将拦截所有到 /static/... 的请求并将它们直接重定向到我们在 /webapp/static 中的资源,因此甚至没有调用控制器的类似“onHttpGet”的方法。所以我评论了那个方法,它仍然有效;-) 谢谢
            • @andyb AFAIK,Servlet 规范中没有 ** 这样的 URL 模式定义。如果要映射static 路径下的所有资源,则应使用/static/*。见这里:stackoverflow.com/questions/13843294/…如果我错了,请纠正我。
            • ** 是 Spring Path Pattern Comparison 的一部分,尽管他们好心地从 Apache Ant 借用了它 - 请参阅 AntPathMatcher。使用** 是完全有效的,在我的回答中它用于匹配任何子目录。希望这会有所帮助,但如果没有,请发表评论或提出其他问题,我很乐意提供帮助。
            【解决方案7】:

            我只是补充一点,您不需要为此实现控制器方法,因为您可以在 servlet 配置文件中使用 view-controller 标记(Spring 3):

            <mvc:view-controller path="/" view-name="/WEB-INF/jsp/index.html"/>
            

            【讨论】:

              【解决方案8】:

              您仍然可以继续使用相同的视图解析器,但将后缀设置为空。

              <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" 
                  p:prefix="/WEB-INF/jsp/" p:suffix="" />
              

              现在您的代码可以选择返回 index.html 或 index.jsp,如下例所示 -

              @RequestMapping(value="jsp", method = RequestMethod.GET )
              public String startJsp(){
                  return "/test.jsp";
              }
              
              @RequestMapping(value="html", method = RequestMethod.GET )
              public String startHtml(){
                  return "/test.html";
              }   
              

              【讨论】:

              • 我也尝试一起删除后缀。同样的交易。仅适用于 .JSP 而不适用于 .HTML
              • 没有。这是一个非常有趣的解决方案。你确定这对你有用吗
              • @Sashi,你能看看我在这个link的问题
              • 对我也不起作用。仅适用于 .jsp(Spring 版本:4.3.14)。
              【解决方案9】:

              相应更改 p:suffix=".jsp" 值,否则我们可以开发自定义视图解析器

              http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/servlet/view/UrlBasedViewResolver.html

              【讨论】:

                猜你喜欢
                • 2015-04-27
                • 2021-10-29
                • 2021-05-10
                • 2011-08-01
                • 2015-06-05
                • 1970-01-01
                • 1970-01-01
                • 2017-05-10
                • 1970-01-01
                相关资源
                最近更新 更多