Как обслуживать.html файлы с помощью Spring

Я разрабатываю веб-сайт с помощью Spring и пытаюсь обслуживать ресурсы, которые не являются файлами.jsp (например,.html)

сейчас я закомментировал эту часть моей конфигурации сервлета

    <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, мой сервер теперь правильно обслуживает страницу.

Спасибо.

8 ответов

Решение

Первоначальная проблема заключается в том, что конфигурация определяет свойство suffix=".jsp" поэтому реализующий класс ViewResolver добавит .jsp до конца имя представления возвращается из вашего метода.

Однако, так как вы закомментировали InternalResourceViewResolver затем, в зависимости от остальной конфигурации вашего приложения, возможно, не будет зарегистрирован ни один другой ViewResolver. Вы можете обнаружить, что сейчас ничего не работает.

поскольку .html файлы являются статическими и не требуют обработки сервлетом, тогда более эффективно и проще использовать <mvc:resources/> картирование Это требует Spring 3.0.4+.

Например:

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

который будет проходить через все запросы, начиная с /static/ к webapp/static/ каталог.

Итак, поставив index.html в webapp/static/ и используя return "static/index.html"; из вашего метода Spring должен найти представление.

Предыстория проблемы

Первое, что нужно понять, это следующее: это не весна, которая рендерит файлы jsp. Это делает JspServlet (org.apache.jasper.servlet.JspServlet). Этот сервлет поставляется с Tomcat (Jasper Compiler), а не с пружиной. Этот JspServlet знает, как скомпилировать страницу jsp и как вернуть ее в виде HTML-текста клиенту. JspServlet в tomcat по умолчанию обрабатывает только запросы, соответствующие двум шаблонам: *.jsp и *.jspx.

Теперь, когда весна делает вид с InternalResourceView (или же JstlView) три вещи действительно имеют место:

  1. получить все параметры модели из модели (возвращаемой методом вашего контроллера, т.е. "public ModelAndView doSomething() { return new ModelAndView("home") }")
  2. представить эти параметры модели как атрибуты запроса (чтобы он мог быть прочитан JspServlet)
  3. переслать запрос в JspServlet. RequestDispatcher знает, что каждый запрос *.jsp должен быть перенаправлен в JspServlet (потому что это конфигурация tomcat по умолчанию)

Когда вы просто измените имя представления на home.html, tomcat не будет знать, как обрабатывать запрос. Это потому, что нет сервлетов, обрабатывающих запросы *.html.

Решение

Как это решить. Есть три наиболее очевидных решения:

  1. выставить HTML как файл ресурсов
  2. поручить JspServlet также обрабатывать *.html запросы
  3. написать свой собственный сервлет (или передать другой существующий запрос сервлета в *.html).

Для полных примеров кода, как этого добиться, обратитесь к моему ответу в другом посте: Как отобразить запросы в HTML-файл в Spring MVC?

Я бы просто добавил, что вам не нужно реализовывать метод контроллера для этого, так как вы можете использовать тег view-controller (Spring 3) в файле конфигурации сервлета:

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

Вы по-прежнему можете использовать тот же распознаватель View, но установите суффикс пустым.

<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";
}   

Я столкнулся с той же проблемой и попробовал различные решения для загрузки html-страницы из Spring MVC, следующее решение сработало для меня

Шаг 1 в файле web.xml сервера комментирует эти две строки

<!--     <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>
 -->

Шаг-2 введите следующий код в веб-приложение XML

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

Шаг-3 создайте класс статического контроллера

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

    }

}

Шаг 4 в файле конфигурации Spring измените суффикс на.htm .htm

Шаг 5 Переименуйте страницу в файл.htm, сохраните его в WEB-INF и постройте / запустите сервер.

localhost:8080/.../landingPage

Конфигурация Java для html-файлов (в данном случае index.html):

@Configuration
@EnableWebMvc
public class DispatcherConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/index.html").addResourceLocations("/index.html");
    }

}

Измените значение p: суффикс =".jsp" соответственно, в противном случае мы можем разработать собственный преобразователь представления

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

Похоже, вы пытаетесь сделать что-то вроде этого:

  • Статические представления HTML
  • Пружинные контроллеры, обслуживающие AJAX

В этом случае, как упоминалось ранее, наиболее эффективный способ - позволить веб-серверу (не Spring) обрабатывать запросы HTML как статические ресурсы. Итак, вам нужно следующее:

  1. Переадресация всех запросов.html, .css, .js, .png и т. Д. В обработчик ресурсов веб-сервера
  2. Сопоставьте все другие запросы с контроллерами Spring

Вот один из способов сделать это...

web.xml - привязать сервлет к корню (/)

<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 Framework. Я фанат YUI, который имеет множество шаблонных механизмов, включая Handlebars.

Если вы используете весеннюю загрузку, вы не должны устанавливать свойства spring.mvc.view.prefix а также spring.mvc.view.suffix в вашем файле application.properties вместо этого настройте bean-компонент ViewResolver из класса конфигурации.

application.properties

# 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 находится за пределами каталога ресурсов.
Таким образом, вы можете использовать шаблоны URL-адресов spring-mvc, но использовать статический контекст.

Другие вопросы по тегам