Spring

Spring Framework - Spring MVC Form Tag

728x90

참조한 강의 : Spring & Hibernate For Beginners (www.udemy.com/course/spring-hibernate-tutorial/)

 

 

- Spring MVC Form Tag

HTML 에서 Form 태그를 쓰는 이유는, 간단히 말하면 사용자의 입력을 받아서 서버와 통신을 하기 위함이다.

 

Spring 의 뷰 템플릿인 JSP 를 쓸때, 일반적인 HTML 처럼 Form 태그를 그냥 써도 되지만,

Spring MVC Form Tag 를 쓰면, Spring Container 가 관리하는, Bean 과 JSP 파일간의 데이터 바인딩 작업을 더 용이하게 해주는 장점이 있다. 더 유용한 이유는, 스프링이 JSP 와 Bean 간의 데이터 전달시에, getter/setter 메소드를 이용해서 전달하기 때문이다.

(만약 이런거 없이 HTML 의 Form tag 로만 받아오려면 HttpServletRequest, @RequestParam 등을 써서 가져와야함. 그러면 코드가 더 길어짐)

 

몇가지 예제를 통해서, Spring MVC Form Tag 를 어떻게 사용하는지 알아보자

 

 

예제 1 - Text Field 

먼저 학생에 대한 입력정보를 받아오는 프로그램을 만든다고 가정하고, 다음의 두개의 파일을 만들어보자

첫번째 예제에서는 학생의 이름만 받아오는 부분을 작성해보자.

 

- Student.java

public class Student {
    
    private String firstName;
    private String lastName;
        
    public Student() {}
 
    public String getFirstName() {
        return firstName;
    }
 
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
 
    public String getLastName() {
        return lastName;
    }
 
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    
}
cs

 

- StudentController.java

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
@RequestMapping("/student")
public class StudentController {
 
    @RequestMapping("/showForm")
    public String showForm(Model theModel) {
        Student theStudent = new Student();
        theModel.addAttribute("student", theStudent);
        return "student-form";
    }
    
    @RequestMapping("/processForm")
    public String processForm(@ModelAttribute("student") Student theStudent) {
        System.out.println("firstName : " + theStudent.getFirstName() + ", lastName : " + theStudent.getLastName());
        return "student-confirmation";
    }
}
cs

 

학생의 정보를 담을 Student 클래스를 만들었고, 이를 URL 매핑시켜서 로직을 처리할 컨트롤러인 StudentController 를 만들었다.

학생정보에 대한 URL 은 /student 를 부모 URL 로 잡으며,

하위 URL 에는

/student/showForm : 학생이 정보를 입력할 수 있는 폼 태그를 보여주는 화면

/student/processForm : 입력 받은 내용을 화면상에 보여주는 화면 으로 지정했다.

 

이전에는 사용되지 않았던 새로운 어노테이션인 @ModelAttribute 를 사용했다.

이는 모델의 키값을 기반으로 해당 모델의 인스턴스를 리턴하는 어노테이션이다.

 

컨트롤러와 모델을 정의했으니, 이번엔 뷰를 정의해보자

 

- student-form.jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
 
<!DOCTYPE html>
<html>
    <head>
        <title>Student Registration Form</title>
    </head>
    <body>
        <form:form action="processForm" modelAttribute="student">
            First name : <form:input path="firstName" />
            <br><br>
            
            Last name : <form:input path="lastName" />
            <br><br>
 
            <input type="submit" value="submit" />
        </form:form>
    </body>
</html>
cs

 

 

- student-confirmation.jsp

<!DOCTYPE html>
<html>
    <head>
        <title>Student Information</title>
    </head>
    <body>
        The Student name is : ${student.firstName} , ${student.lastName}
        <br><br>
    </body>
</html>
cs

 

위 두개의 JSP 파일에서 중요한것은 

1. JSTL 을 사용하는 부분에는 JSP 파일 최상단에 아래의 구문을 꼭 써줘야 한다는것

1
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
cs

 

2. 기존 HTML 태그와는 다르게 <form:form> ,  <form:input> 이런식으로 다른 태그를 사용한다는 것

 

3. <form:form> 태그의 modelAttribute 값은 컨트롤러에서 다루는 모델의 키값이랑 동일한 값을 갖는다는것

(여기선 키값이 student 임)

 

4. <form:input> 태그의 path 값과 멤버변수 이름이 동일해야 한다는것.

(Student.java 에서 private String firstName, private String lastName 과 JSP 파일의 path="firstName", path="lastName" 두개가 동일한 값을 가져야만 스프링이 찾을 수 있음)

-> 왜 동일한 값을 가져야하는가 하면, 스프링이 이 값들에 대해서 getter/setter 메소드로만, 값 가져오기 및 지정하기를 하기 때문임 

 

이를 실행해보면 다음과 같이 정상적으로 나오게 된다.

 

입력
결과

 

 

예제 2 - Drop Down List

이번에는, Drop Down List 를 만들어보자

 

여러개의 국가 목록 중에서 자신의 국가를 선택하도록 하는 Drop Down List 를 만들자

 

먼저 Student.java 에 멤버 변수로 국가정보를 담을 변수를 하나 생성하고 getter/setter 를 추가하면된다.

 

- Student.java

public class Student {
 
    private String country;
    
    public Student() {}
 
    public String getCountry() {
        return country;
    }
 
    public void setCountry(String country) {
        this.country = country;
    }
    
}
cs

 

그리고 JSP 파일을 수정해야한다

 

- student-form.jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
 
<!DOCTYPE html>
<html>
    <head>
        <title>Student Registration Form</title>
    </head>
    <body>
        <form:form action="processForm" modelAttribute="student">
            First name : <form:input path="firstName" />
            <br><br>
            
            Last name : <form:input path="lastName" />
            <br><br>
            
            Country : 
            <form:select path="country">
                <form:option value="BR" label="Brazil" />
                <form:option value="IN" label="India" />
                <form:option value="KR" label="Korea" />
                <form:option value="FR" label="France" />
                <form:option value="CO" label="Colombia" />
                <form:option value="USA" label="United States Of America" />
            </form:select>
            <br><br>
        
        </form:form>
    </body>
</html>
cs

 

 

- student-confirmation.jsp

<!DOCTYPE html>
<html>
    <head>
        <title>Student Information</title>
    </head>
    <body>
        The Student name is : ${student.firstName} , ${student.lastName}
        <br><br>
        Country : ${student.country}
    </body>
</html>
cs

 

이를 실행해보면, 다음과 같이 나오게 된다.

입력
결과

 

결과가 잘 나오긴 했지만, 위의 student-form.jsp 처럼 국가 각각을 일일이 하드 코딩하는 것은 보기에도 별로 좋지 못하다.

이런 방식 대신에 properties 파일을 불러오게해서, 처리하면 코드양이 더 줄어들것이다.

이를 위해선 properties 파일을 만들고 (주의 : 파일의 위치가 반드시 xml 에서 설정한 값과 일치해야함)

xml 파일에 가서 설정값을 바꿔주고, 자바 코드와 JSP 코드를 다르게 작성해야 한다.

 

- countries.properties

BR=Brazil
FR=France
CO=Colombia
IN=India
KR=Korea
US=United States Of America
cs

 

- spring-mvc-demo-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:context="http://www.springframework.org/schema/context" 
        xmlns:mvc="http://www.springframework.org/schema/mvc" 
        xmlns:util="http://www.springframework.org/schema/util" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans     
            http://www.springframework.org/schema/beans/spring-beans.xsd     
            http://www.springframework.org/schema/context     
            http://www.springframework.org/schema/context/spring-context.xsd     
            http://www.springframework.org/schema/mvc         
            http://www.springframework.org/schema/mvc/spring-mvc.xsd 
            http://www.springframework.org/schema/util     
            http://www.springframework.org/schema/util/spring-util.xsd">
 
    <!-- Add support for component scanning -->
    <context:component-scan base-package="com.luv2code.springdemo" />
 
    <!-- Add support for conversion, formatting and validation support -->
    <mvc:annotation-driven/>
    
    <!-- Define Spring MVC view resolver -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
    <!-- mvc resources mapping -->
    <mvc:resources mapping="/resources/**" location="/resources/"/>
    
    <!-- load properties file -->
    <util:properties id="countryOptions" location="classpath:../countries.properties" />
 
</beans>
cs

 

- StudentController.java

import java.util.Map;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
 
@Controller
@RequestMapping("/student")
public class StudentController {
    
    @Value("#{countryOptions}")
    private Map<StringString> countryOptions;
    
    @RequestMapping("/showForm")
    public String showForm(Model theModel) {
        Student theStudent = new Student();
        theModel.addAttribute("student", theStudent);
        theModel.addAttribute("theCountryOptions", countryOptions);
        return "student-form";
    }
    
    @RequestMapping("/processForm")
    public String processForm(@ModelAttribute("student") Student theStudent) {
        System.out.println("firstName : " + theStudent.getFirstName() + ", lastName : " + theStudent.getLastName());
        return "student-confirmation";
    }
}
cs

 

Map 을 이용해서 국가 ISO 값을 키값으로, 국가의 이름을 value 로 하는 것으로 정의해주고,

모델에 이 Map 을 추가해준다.

 

- student-form.jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
 
<!DOCTYPE html>
<html>
    <head>
        <title>Student Registration Form</title>
    </head>
    <body>
        <form:form action="processForm" modelAttribute="student">
            First name : <form:input path="firstName" />
            <br><br>
            
            Last name : <form:input path="lastName" />
            <br><br>
            
            Country : 
            <form:select path="country">
                <form:options items="${theCountryOptions}" />
            </form:select>
            <br><br>
            
        </form:form>
    </body>
</html>
cs

JSP 코드의 <form:option> 부분이 다 사라지고 <form:options> 한줄로 처리된것을 볼 수 있다.

이것도 실행해보면 동일한 결과가 나온다.

 

 

 

예제 3 - Radio Button

Radio Button 은 <form:radiobutton path="~" value="~" /> 이런형식으로 작성된다.

 

이번엔 해당 학생이 가장 선호하는 프로그래밍 언어를 선택한다고 해보자

그럴려면, 학생 클래스에 이 값을 담는 멤버 변수가 있어야 하고 getter/setter 가 있어야 한다.

그 후에, JSP 코드 또한 바꿔준다.

 

- Student.java

public class Student {
    
    private String favoriteLanguage;
        
    public Student() {}
 
    public String getFavoriteLanguage() {
        return favoriteLanguage;
    }
 
    public void setFavoriteLanguage(String favoriteLanguage) {
        this.favoriteLanguage = favoriteLanguage;
    }    
}
cs

 

- student-form.jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
 
<!DOCTYPE html>
<html>
    <head>
        <title>Student Registration Form</title>
    </head>
    <body>
        <form:form action="processForm" modelAttribute="student">
        
            Choose your favorite programming languages : <br>
            Java  <form:radiobutton path="favoriteLanguage" value="JAVA"/>
            C++  <form:radiobutton path="favoriteLanguage" value="C++"/>
            C#  <form:radiobutton path="favoriteLanguage" value="C#"/>
            Python  <form:radiobutton path="favoriteLanguage" value="Python"/>
            <br><br>
        
        </form:form>
    </body>
</html>
cs

 

- student-confirmation.jsp

<!DOCTYPE html>
<html>
    <head>
        <title>Student Information</title>
    </head>
    <body>
        The Student's favorite language is : ${student.favoriteLanguage}
        <br><br>
    </body>
</html>
cs

 

실행 결과

입력
결과

(이 예제도 선택 항목을 지정할때, <form:radiobutton /> 태그를 여러번쓰는데, 이를 기피하려면, Student.java 클래스에 이들을 담기 위한 별도의 자료구조를 만들어서 getter/setter 처리를 하던가 아니면, properties 파일을 만들어서 처리하면 된다)

 

 

 

예제 4 - Check Box

체크 박스는 <form:checkbox path="~" value="~" /> 이런식으로 태그를 작성하고, 이번에는 학생이 사용하는 운영체제를 고르도록 해보자.

(주의할것은 Check Box 는 동시에 여러개를 선택할 수 있다. 그래서, JSP 화면에 이들을 보여주기 위해서는, 반복문을 사용해서 보여줘야 하는데, 먼저 JSTL 을 불러올 수 있게 설정해줘야하고, <c:forEach> 라는 새로운 태그를 작성해야한다)

 

- Student.java

public class Student {
    
    private String[] operatingSystems;
    
    public Student() {}
 
    public String[] getOperatingSystems() {
        return operatingSystems;
    }
 
    public void setOperatingSystems(String[] operatingSystems) {
        this.operatingSystems = operatingSystems;
    }
    
}
cs

 

- student-form.jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
 
<!DOCTYPE html>
<html>
    <head>
        <title>Student Registration Form</title>
    </head>
    <body>
        <form:form action="processForm" modelAttribute="student">
            
            Choose your operating system : <br>
            Ubuntu <form:checkbox path="operatingSystems" value="Ubuntu" />
            CentOS <form:checkbox path="operatingSystems" value="CentOS" />
            Windows <form:checkbox path="operatingSystems" value="Windows" />
            Mac OS <form:checkbox path="operatingSystems" value="Mac OS" />
            
            <input type="submit" value="submit" />
        </form:form>
    </body>
</html>
cs

 

- student-confirmation.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
    <head>
        <title>Student Information</title>
    </head>
    <body>
        The Student's operating system is 
        <ul>
            <c:forEach var="element" items="${student.operatingSystems}">
                <li>${element}</li>
            </c:forEach>
        </ul>
    </body>
</html>
cs

 

student-confirmation.jsp 에서 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 를 써서 JSTL 을 불러온다는 점,

그리고 반복된 요소를 출력하기 위해서 <c:forEach var="element" items="${student.operatingSystmes}"> 를 사용한다는점에 주목해서 사용하면된다.

 

실행 결과

입력
결과

 

 

 

여기까지 Spring MVC Form Tag 에 대해서 간단한 사용법을 알아봤다.

다음은 Form 으로 부터 입력 받은 값들에 대해서 유효성 검증을 하는 방법을 알아본다.

728x90