JSF 기초 1
참조 : JSF for nonbelievers: Clearing the FUD about JSF
기본 아키텍처
JSF 예제
1. web.xml 과 faces-config.xml 설정하기
1-1. web.xml
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup> 1 </load-on-startup>
</servlet>
<!-- Faces Servlet Mapping -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/calc/*</url-pattern>
</servlet-mapping>
이건 뭐 별 설명이 필요 없을 것 같네요. 스프링의 DispatcherServlet하고 비슷한 일을 할 듯 합니다. 중요 클래스니까 언제 한 번 열어봐야겠네요.
1-2. faces-config.xml
...
<managed-bean>
<description>
The "backing file" bean that backs up the calculator webapp
</description>
<managed-bean-name>CalcBean</managed-bean-name>
<managed-bean-class>com.arcmind.jsfquickstart.controller.CalculatorController</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<navigation-rule>
<from-view-id>/calculator.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/results.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
흠.. JSF에서 사용할 컨트롤러 빈의 이름과 스코프를 등록하고, 네비게이션을 등록해두네요. 네비게이션을 등록해둔 걸 보면, 서브밋 할 때 action="result.jsp" 같은 코드를 사용하지 않아도 알아서 가주겠죠?
2. 모델 객체 만들기
/**
* Calculator
*
* @author Rick Hightower
* @version 0.1
*/
public class Calculator {
//~ Methods ----------------------------------------------------------------
/**
* add numbers.
*
* @param a first number
* @param b second number
*
* @return result
*/
public int add(int a, int b) {
return a + b;
}
/**
* multiply numbers.
*
* @param a first number
* @param b second number
*
* @return result
*/
public int multiply(int a, int b) {
return a * b;
}
}
3. 컨트롤러 만들기(완전 POJO)
import com.arcmind.jsfquickstart.model.Calculator;
/**
* Calculator Controller
*
* @author $author$
* @version $Revision$
*/
public class CalculatorController {
//~ Instance fields --------------------------------------------------------
/**
* Represent the model object.
*/
private Calculator calculator = new Calculator();
/** First number used in operation. */
private int firstNumber = 0;
/** Result of operation on first number and second number. */
private int result = 0;
/** Second number used in operation. */
private int secondNumber = 0;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new CalculatorController object.
*/
public CalculatorController() {
super();
}
//~ Methods ----------------------------------------------------------------
/**
* Calculator, this class represent the model.
*
* @param aCalculator The calculator to set.
*/
public void setCalculator(Calculator aCalculator) {
this.calculator = aCalculator;
}
/**
* First Number property
*
* @param aFirstNumber first number
*/
public void setFirstNumber(int aFirstNumber) {
this.firstNumber = aFirstNumber;
}
/**
* First number property
*
* @return First number.
*/
public int getFirstNumber() {
return firstNumber;
}
/**
* Result of the operation on the first two numbers.
*
* @return Second Number.
*/
public int getResult() {
return result;
}
/**
* Second number property
*
* @param aSecondNumber Second number.
*/
public void setSecondNumber(int aSecondNumber) {
this.secondNumber = aSecondNumber;
}
/**
* Get second number.
*
* @return Second number.
*/
public int getSecondNumber() {
return secondNumber;
}
/**
* Adds the first number and second number together.
*
* @return next logical outcome.
*/
public String add() {
result = calculator.add(firstNumber, secondNumber);
return "success";
}
/**
* Multiplies the first number and second number together.
*
* @return next logical outcome.
*/
public String multiply() {
result = calculator.multiply(firstNumber, secondNumber);
return "success";
}
}
흠.. 이 코드를 보고서 좀 놀랐습니다. 스프링 2.5로 컨틀롤러를 만들어도, 가능하긴 한데, 수많은 애노테이션들이 붙고, 그 애노테이션들을 정말 잘 알고 있어야 했는데.. 결국 그 애노테이션들 없이는 스프링의 컨트롤러는 의미도 없고 재사용할 수도 없기 떄문에 엄밀히 따지면 POJO라고 하긴 좀 뭐했습니다. 그런데 JSF의 저 컨트롤러는 뭐.. 틈잡을것이 하나도 없습니다.
4. 뷰 만들기
4-1. index.jsp
흠.. 얘는 네비게이션에 등록하지도 않았고, JSF Servlet이 담당할 URL로 들어오지 않을테고.. 저기서 JSF Servlet이 담당할 URL로 포워딩시키는 군요.
4-2. calculator.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
<h:form id="calcForm">
<h:panelGrid columns="3">
<h:outputLabel value="First Number" for="firstNumber" />
<h:inputText id="firstNumber" value="#{CalcBean.firstNumber}" required="true" />
<h:message for="firstNumber" />
<h:outputLabel value="Second Number" for="secondNumber" />
<h:inputText id="secondNumber" value="#{CalcBean.secondNumber}" required="true" />
<h:message for="secondNumber" />
</h:panelGrid>
<h:panelGroup>
<h:commandButton id="submitAdd" action="#{CalcBean.add}" value="Add" />
<h:commandButton id="submitMultiply" action="#{CalcBean.multiply}" value="Multiply" />
</h:panelGroup>
</h:form>
</f:view>
흠~ 이제 좀 재밌는 코드가 나왔습니다.
맨위에 첫 줄은, 폼을 비록한 HTML 관련 태그들이 담겨있고, 두 번째 줄은 JSF가 사용할 로직, 벨리데이션, 컨트롤러등을 위한 태그들이 담겨있다고 합니다.
<f:view> 안에 들어가야 JSF 컴포넌트 트리를 만든다고 합니다. JSF 를 사용할 땐 저 안에 모든 JSF 컴포넌트를 넣어야 겠군요.
<h:form> 은, html 폼을 나타내는 JSF 컴포넌트인가 봅니다. 속성중에 column=3은 한 줄에 세칸이라는 뜻이고, 따라서 저 안에 있는 컴포넌트들은 세줄씩 마침 코드에서도 한 줄 띄어쓰기로 구분해주고 있네요.
<h:message>는 에러 메시지 보여줄 때 사용할 것 같은데, 뭘 참조하라는게 없군요. 자동으로 메시지 생성해서 넣어줄 것 같은데... 내가 원하는 메시지를 보여주고 싶을 땐 어떻게 해야되지??
JSP의 EL 처럼 JSF에도 EL 이 있는데, 그건 바로 #{}. CalcBean은 아까 faces-config.xml이였나.. 거기에 등록했던 컨트롤러이고, value 속성은 해당 컨트롤러의 필드값을 참조하고, action은 메소드를 호출하고 그 결과를 가져오나 보군요.
예상했던 것처럼 역시나 저 폼을 서브밋하면 어디로 갈지를 폼에다가 적지 않았습니다. 아까 저 페이지? URL?에 대한 네비게이션을 정의해두었죠.
4-3. result.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
...
<f:view>
First Number: <h:outputText id="firstNumber" value="#{CalcBean.firstNumber}"/>
<br />
Second Number: <h:outputText id="secondNumber" value="#{CalcBean.secondNumber}"/>
<br />
Result: <h:outputText id="result" value="#{CalcBean.result}"/>
<br />
</f:view>
흠.. 이번에도 역시 <f:view>를 써서 JSF 컴포넌트 트리로 감싸고, <h:outputText> 라는 컴포넌트를 쓰고 있군요. value를 사용해서 필드값들만 참조합니다. 간단하군요.
돌리는 건 내일해야 겠습니다. 11시 반도 안 됐는데 졸리네요;