Table of Contents

К списку

Hello, World!

Как и все нормальные люди, начнём изучение JSF с простенькой программы Hello, world!

Необходимые ингредиенты

Рецепт

  1. Создайте обычное веб-приложение со следующей стурктурой:
    jsf-helloworld/
                  WEB-INF/
                         lib/
                         web.xml
                         faces-config.xml
                  index.jspx
  2. Поместите в папку lib JAR-файлы с реализацией JSF.
  3. Отредактируйте файл web.xml и добавьте в него следующее содержимое:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.4"
             xmlns="http://java.sun.com/xml/ns/j2ee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
      <display-name>Hello, World</display-name>
      <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>server</param-value>
      </context-param>
      <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.jspx</param-value>
      </context-param>
      <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
      </context-param>
      <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>true</param-value>
      </context-param>
      <servlet>
        <display-name>Faces Servlet</display-name>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>
          javax.faces.webapp.FacesServlet
        </servlet-class>
        <load-on-startup>0</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
      </servlet-mapping>
      <listener>
        <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
      </listener>
      <security-constraint>
        <web-resource-collection>
          <web-resource-name>Restrict direct access to JSPs</web-resource-name>
          <url-pattern>*.jspx</url-pattern>
        </web-resource-collection>
        <auth-constraint></auth-constraint>
      </security-constraint>
    </web-app>

    Для тех, кто знаком с web-приложениями на Java, тут всё должно быть вполне понятно. Несколько пояснений:

    1. Я люблю JSPX, поэтому в качестве расширения для файлов, которые JSF должен считать свои страницы, выбрал именно jspx. Если вам так не нравится, то можете спокойно убрать параметр javax.faces.DEFAULT_SUFFIX (по умолчанию он равен именно .jsp).
    2. Сервлет, отвечающий за JSF, я привязываю к расширению *.jsf. Хотя в официальной документации чаще используется .faces, оно слишком длинное, поэтому я его не использую.
    3. Крайне необходимо запретить прямой доступ к JSP(X)-страницам. Т.к. если к ним обратиться напрямую (через из собственное расширение .jsp(x), а не через сервлет (расширение .jsf), то всё будет плохо. Это сделано с помощью security-constraint'а, которому не даны никакие роли.
    4. ВНИМАНИЕ! Совершенно необходимо не забыть добавить листенера, иначе ничего работать не будет. Самое гнусное, что это нигде не написано, поэтому все начинающие JSF-писатели тратят кучу времени на попытки выяснить, почему у них ничего не работает.
    5. Если вы решили использовать MyFaces, то вам понадобится убрать все настройки, начинающиеся на com.sun (они действительны только для Sun'овской реализации JSF) и изменить листенера на org.apache.myfaces.webapp.StartupServletContextListener.
  4. Отредактируйте файл faces-config.xml и добавьте в него следующее содержимое:
    <?xml version='1.0' encoding='UTF-8'?>
    <!DOCTYPE faces-config PUBLIC
        "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
        "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
    <faces-config>
    </faces-config>

    Это основной конфиг для JSF-приложений. В нём пока ничего нет, но он понадобится для последующих примеров.

  5. Отредактируйте файл index.jspx и добавьте в него следующее содержимое:
    <?xml version="1.0" encoding="UTF-8"?>
    <jsp:root xmlns:f="http://java.sun.com/jsf/core"
              xmlns:jsp="http://java.sun.com/JSP/Page"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:xsd="http://www.w3.org/2001/XMLSchema"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://www.w3.org/1999/xhtml"
              version="2.0">
        <f:view>
          <html>
          <body>
            <h:form>
              <h:outputText value="Hello, world!"/>
            </h:form>
          </body>
          </html>
        </f:view>
    </jsp:root>

    Что здесь что:

    1. <f:view> - это корень всех зол. Шучу. Это корневой тег, внутри которого должны располагаться все теги, имеющие отношение к JSF. Что делать когда теги используются в разных файлах, которые с помощью механизма <jsp:include> (или любых обёрток вокруг него) собираются в одну страницу, не спрашивайте. Потому что я пока что не знаю. Вообще, библиотека тегов <f:…> содержит в себе все базовые теги, не зависящие от того, какой будет формат у результирующих документов. А библиотека тегов <h:…> содержит теги, специфичные для HTML'я.
    2. <h:form> создаёт HTML-тег <form> и кучу всякой дряни, необходимой для функционирования JSF.
    3. И наконец, <h:outputText> выводит текст. Этот тег гораздо более функционален, чем просто вывод текста, но о его остальной функциональности вы узнаете потом.

Результат

Конечный WAR-файл (1.7mb) (для JBoss'а, нужно просто положить в папку deploy и любоваться результатом по ссылке http://localhost:8080/hello_world/index.jsf)