JSF 2 + Maven + Jetty。 CDI、フォーム、AJAX

今回はJavaコードがあります。 入力データを処理するフォームとロジックを記述します。 この投稿は、JSF 2および/またはJSF 1.2が何であるかを知っている人向けではなく、faces-config.xmlはプロジェクト内の単なるファイルではありません。 見て、私は警告した...



Cdi



JSF 2.3.0以降、標準の@ManagedBean



アノテーション@ManagedBean



非推奨になりました。 つまり フォームからJavaコードにアクセスするには、プロジェクトCDI(Context and Dependency Injection)-Weldに追加する必要があります。



pom.xml



ファイルにpom.xml



追加します。



  <dependencies> ... <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet</artifactId> <version>2.4.3.Final</version> </dependency> </dependencies>
      
      





ファイル/src/main/webapp/WEB-INF/beans.xml



作成します。



 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all"> </beans>
      
      





悪いアドバイス
最後の投稿へのコメントで、彼らは気づいた:



リスナーの登録に特別な特異性はありますか?


オッケー! ファイル/src/main/webapp/WEB-INF/web.xml



追加します。

 <web-app ... <listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener> ... </web-app>
      
      





実行: mvn jetty:run







トレースバック 機能しない理由を読みます。



ファイル/src/main/webapp/WEB-INF/jetty-env.xml



作成します。



 <?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd"> <Configure id="webAppCtx" class="org.eclipse.jetty.webapp.WebAppContext"> <Call name="prependServerClass"> <Arg>-org.eclipse.jetty.server.handler.ContextHandler</Arg> </Call> <Call name="prependServerClass"> <Arg>-org.eclipse.jetty.servlet.FilterHolder</Arg> </Call> <Call name="prependServerClass"> <Arg>-org.eclipse.jetty.servlet.ServletContextHandler</Arg> </Call> <Call name="prependServerClass"> <Arg>-org.eclipse.jetty.servlet.ServletHolder</Arg> </Call> <New id="BeanManager" class="org.eclipse.jetty.plus.jndi.Resource"> <Arg> <Ref id="webAppCtx"/> </Arg> <Arg>BeanManager</Arg> <Arg> <New class="javax.naming.Reference"> <Arg>javax.enterprise.inject.spi.BeanManager</Arg> <Arg>org.jboss.weld.resources.ManagerObjectFactory</Arg> <Arg/> </New> </Arg> </New> </Configure>
      
      





ファイル/src/main/webapp/WEB-INF/web.xml



追加します。



 <web-app ... <resource-env-ref> <resource-env-ref-name>BeanManager</resource-env-ref-name> <resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type> </resource-env-ref> ... </web-app>
      
      





@ManagedBean



代わりに@ManagedBean



が機能するようになりました。 CDIは良好であり、JSF 2.3.0以降重要であると考えると、JSFのCDIは意図された目的に使用され、JSFに直接関連しないことを理解する価値があります。

もうCDIには戻りません!



FormDataおよびFormCtrlクラス



それでは、いくつかのコードを書きましょう。 2つのクラスが必要になります-最初にデータを送信し、2番目にこのデータを処理する関数があります。



リトリート
実装の観点からは、フォームのロジックを2つの別々のクラスに分ける必要はありませんが、これはテストの観点とアーキテクチャの観点の両方から「正しい」です。



データ/src/main/java/ru/habr/FormData.java







 package ru.habr; import javax.enterprise.context.RequestScoped; import javax.inject.Named; @Named @RequestScoped public class FormData { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
      
      





ハンドラー/src/main/java/ru/habr/FormCtrl.java







 package ru.habr; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; @Named @RequestScoped public class FormCtrl { @Inject FormData formData; public String doAction() { //     ... System.out.println(formData.getUsername()); System.out.println(formData.getPassword()); return null; } }
      
      





FormData



ですべてが明確な場合、 FormData



FormCtrl



詳しく見る価値FormCtrl



ます。



  1. @Inject



    おかげで、フォームデータはformData



    フィールドのハンドラークラスで利用できます。
  2. 「ハンドラーメソッドは文字列を返す必要がある」という論文に固執することをお勧めしますが、これは必須ではありません。 この文字列は、後でナビゲーションで使用されますが、後で詳しく説明します。




ここではすべてがシンプルです! ファイル/src/main/webapp/index.xhtml



追加します。



 <h:body> ... <h:form id="habrForm"> <h:inputText value="#{formData.username}"/><br/> <h:inputSecret value="#{formData.password}"/><br/> <h:commandButton action="#{formCtrl.doAction}" value="Send"> </h:commandButton> </h:form> </h:body>
      
      





実行: mvn jetty:run





確認: http://127.0.0.1:8080/



: http://127.0.0.1:8080/



: http://127.0.0.1:8080/







アヤックス



それは2017年であり、フォームはまだAJAXなしです! /src/main/webapp/index.xhtml



ファイル/src/main/webapp/index.xhtml



、いくつかの変更を行います。



 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:f="http://xmlns.jcp.org/jsf/core"> ... <h:body> ... <h:inputText value="#{formData.username}"/><br/> <h:inputSecret value="#{formData.password}"/><br/> <h:commandButton action="#{formCtrl.doAction}" value="Send"> <f:ajax execute="@form" render="@form"/> </h:commandButton> </h:body> </html>
      
      





変更点:



  1. xmlns:f="http://xmlns.jcp.org/jsf/core"



    タグライブラリ定義を追加xmlns:f="http://xmlns.jcp.org/jsf/core"



    これがなければ、AJAXを実装できますが、ペンでそれを処理する必要があります。これは長くて恩知らずです。
  2. h:commandButton



    内で<f:ajax execute="@form" render="@form"/>



    execute



    -サーバーに送信する必要があるもの(フォーム全体/すべてのフォームフィールド)を示しrender



    -AJAX実行後にサーバーから更新する必要があるものを示します。


f:ajax



については、個別に記述できます。 これで、ページの現在のフォームだけでなく、ページの任意の要素を送信/更新できることを知っているだけで十分です。



あとがき



プロジェクトの機能はまだ非常に控えめですが、私続けます!



All Articles