Validator

Spring MVC에서는 Validator를 구현하기 위해 ValidatorUtils를 이용한 입력 필드의 값 존재 여부의 validation 체크나 errors 객체를 통해 property파일 메시지를 출력해주는 validation 체크 방법을 지원한다. 이것은 jsp 페이지 에서form:errors를 태그를 통해 간단히 에러 메시지를 출력할 수 있으며 SimpleFormController를 사용하면 입력페이지에 에러 메시지를 출력해 줄 수 있다.

Validator 생성

  • ValidatorUtils 사용
  • Validator를 생성할 때 required 속성값의 validation을 체크하고 에러메시지를 프로퍼티 파일 없이 사용자가 지정해준 메시지로 출력 할 수 있도록 지원한다. 간단히 ValidatorUtils를 사용하여 구현할 수 있다. 다음은 validator를 구현한 UserValidator.java 의 일부이다.
    public class UserValidator implements Validator {
    
    	public boolean supports(Class clazz) {
    		return UserVO.class.isAssignableFrom(clazz);
    	}
    
    	public void validate(Object object, Errors errors) {
    
    		// validationUtils를 이용하여 입력값이 비었는지 체크
    		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userName",
    				"required", new Object[] { "userName" }, "Enter your name");
    		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password",
    				"required", new Object[] { "password" }, "Enter your password");
    ValidationUtils 클래스에 대한 API 는 여기를 참고한다.
  • Property 파일 사용
  • validation을 체크할 때 errors 인터페이스를 사용하여 properties 파일을 참조하여 에러 메시지를 출력할 수 있는데 그 예는 다음과 같다.
    public class UserValidator implements Validator {
    	public boolean supports(Class clazz) {
    		return HelloVO.class.isAssignableFrom(clazz);
    	}
    
    	public void validate(Object object, Errors errors) {
    		
    		HelloVO helloVO = (HelloVO) object;
    		if (helloVO.getPassword().length() < 6)
    			errors.rejectValue("password", "error.password.tooshort");
    
    		if (!helloVO.getPassword().equals(helloVO.getConfirmPassword()))
    			errors.rejectValue("confirmPassword", "error.confirm");
    	}
    }
    해당 조건에 만족하지 않는 입력 값이 있으면 properties파일에 미리 정의된 error.password.tooshort, error.confirm등의 메시지가 출력될 것이다. messageSource 정의 방법은Spring MVC 다국어 지원 기능 을 참고하고 errors 클래스의 API는 여기 를 참고한다.

    Validator 등록

    위에서 처럼 생성한 validator를 컨트롤러에도 추가해 주어야 한다. 다음은 UserController 빈 정의가 작성되어 있는 user-servlet.xml 파일의 일부이다.
    <bean name="/getUser.do"
    	class="anyframe.sample.springmvc.web.controller.basic.UserController">
    	<property name="userService" ref="userService" />
    	<property name="validator" ref="userValidator"/>
    </bean>
    <bean name="userValidator" class="anyframe.sample.springmvc.web.validator.UserValidator"/>
    이는 해당 Controller 클래스 내의 생성자 안에서 setValidator를 사용해 정의해줄 수도 있다.

    form:errors 태그 사용

    validatior에서 얻어진 메시지를 JSP페이지에서 쉽게 출력할 수 있도록 Spring MVC에서 제공하는 태그 라이브러리 중 form 태그의 form:errors태그를 사용할 수 있다. 이 태그를 사용하기 위해서는 다음과 같은 절차를 따른다.
    • 태그 라이브러리 등록

    • spring의 form 태그 라이브러리를 사용하기 위해서는 spring-form.tld파일이 필요하고 이는 spring-webmvc-2.5.2.jar 파일에 포함되어 있다. 이 폼 태그를 사용하기 위해서는 JSP 페이지에 taglib을 추가해줘야한다.
      <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    • form:form 태그 사용

    • 일단 form 태그를 사용하려면 commandName 속성을 지정해야 하는데 이 속성은 폼 이름과 트랜스퍼 오브젝트의 빈들과 1:1로 매핑시켜준다. commandName의 속성값을 지정해 주지 않을 경우 기본값은 command이고 이값은 request로 셋팅해 줘야 한다. 이값은 SimpleFormController를 사용할 경우 컨트롤러의 fomBackingObject를 통해 컨트롤러 내에서 지정해 줄 수도 있다. 자세한 방법은 본 매뉴얼 >> Spring MVC >> Basic >> Controller >> SimpleFormController 부분을 참고한다. form 태그는 여러가지 폼 입력 태그들을 갖는다. 각 타입에 따라 text타입은 <form:input> 기타 나머지 타입은 <form:password>와 같은 형태로 나타난다. 기타 폼 태그의 자세한 사항은 본 매뉴얼 >> Spring MVC >> Basic >> View >> Tag Library 를 참고한다. 이러한 입력 폼 태그는 path라는 속성에 이름을 지정해주는데 이는 반드시 트랜스퍼 오브젝트의 빈 이름과 같아야 한다. 또한 form태그에는 웹단에서 validator에서 발생시킨 에러 메시지를 출력해주는 <form:errors>태그를 갖고 이 태그 역시 path값을 지정해 줘야한다. path값에 "*" 값을 주게 되면 모든 error메시지를 출력한다. 다음은 form:errors 태그가 정의되어 있는 getUser.jsp 파일의 일부이다.
      <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
      <tr>
      	<td> Name :</td>
      	<td><form:input path="userName" />(required)</td>
      	<td><form:errors path="userName" /></td>
      </tr>
      <tr>
      	<td>password :</td>
      	<td><form:password path="password" />(required, 6자이상입력)</td>
      	<td><form:errors path="password" /></td>
      </tr>

    Resources


    출처 - http://dev.anyframejava.org/anyframe/doc/web/3.2.0/webfw/springmvc/basic/validator.html



    ===================================================================================

     

     

    입력값 검증을 위한 Validation 기능은 Valang, Jakarta Commons, Spring 등에서 제공한다.
    여기서는 Jakarta Commons Validator Spring Framework과 연동하여 사용하는 방법에 대해서 설명하고자 한다.
    Jakarta Commons Validator
    는 필수값, 각종 primitive type(int,long,float), 최대-최소길이, 이메일, 신용카드번호등의 값 체크등을 할 수 있도록 Template이 제공된다.
    Template Java 뿐 아니라 Javascript로도 제공되어 client-side, server-side의 검증을 함께 할 수 있으며, 
    Configuration
    과 에러메시지를 client-side, server-side 별로 따로 하지 않고 한곳에 같이 쓰는 관리상의 장점이 있다.
    Struts
    에서는 Commons Validator를 사용하기 위한 org.apache.struts.validator.ValidatorPlugIn 같은 플러그인 클래스를 제공하는데, 
    Spring
    에서는 Spring Modules 프로젝트에서 연계 모듈을 제공한다.
    여기서는 server-side, client-side validation을 위해, 
    설치방법, Spring Module에서 제공하는 핵심 클래스인 DefaultValidatorFactory, DefaultValidator와 설정파일인 validator-rules.xml, validator.xml 에 대한 간략한 설명과 
    예제 프로젝트인 easycompany에 적용하는 과정을 설명한다.

    1. commons-validator : Ver 1.3.1 아래 4개의 파일에 대한 dependency가 있다.

                               I.   commons-beanutils : Ver 1.7.0

                              II.   commons-digester : Ver 1.8

                             III.   commons-logging : Ver 1.0.4

                            IV.   oro : Ver 2.0.8

    2. spring modules : Ver 0.9 다운 받고 압축을 풀어 보면 여러 파일들이 있으나 여기서 필요한 건 spring-modules-validation.jar 뿐이다. 예제를 보려면 \samples\sources\spring-modules-validation-commons-samples-src.zip도 필요하다.

    3. 위에서 언급한 라이브러리들을 설치한다.

    Spring Validator Commons Validator의 연계를 위해 중요한 역활을 하는 클래스인 DefaultValidatorFactory, DefaultBeanValidator에 대해 간략하게 설명하자면 아래 표와 같다.

    DefaultValidatorFactory

    DefaultBeanValidator

    프로퍼티 'validationConfigLocationsApache'에 정의된 Validation rule을 기반으로 
    Commons Validator
    들의 인스턴스를 얻는다.

    DefaultBeanValidator org.springframework.validation.Validator implements하고 있지만,
    DefaultValidatorFactory
    가 가져온 Commons Validator의 인스턴스를 이용해 validation을 수행한다.
    Controller
    validation 수행할때 이 DefaultBeanValidator를 참조하면 된다.

    아래 코드를 참조해 빈 정의 파일(예제에는 easycompany-servlet.xml)에 다음과 같이 ValidatorFactory,Validator,validator-rules.xml,validation.xml 파일을 등록한다.

    ...
    <!-- Integration Apache Commons Validator by Spring Modules -->                                             
        <bean id="beanValidator" class="org.springmodules.validation.commons.DefaultBeanValidator">
                <property name="validatorFactory" ref="validatorFactory"/>
        </bean>
     
        <bean id="validatorFactory" class="org.springmodules.validation.commons.DefaultValidatorFactory">
                <property name="validationConfigLocations">
                            <list>
                          <!-- validator-rules.xml, validator.xml의 위치-->
                                         <value>/WEB-INF/conf/validator-rules.xml</value>
                                         <value>/WEB-INF/conf/validator.xml</value>
                            </list>
                </property>
        </bean>
    ...

    validator-rules.xml application에서 사용하는 모든 validation rule에 대해 정의하는 파일이다. 
    예제에 있는 validator-rules.xml의 필수값 체크 부분을 보면 아래와 같이 작성되어 있다.

          <validator name="required"
                classname="org.springmodules.validation.commons.FieldChecks"
                   method="validateRequired"
             methodParams="java.lang.Object,
                           org.apache.commons.validator.ValidatorAction,
                           org.apache.commons.validator.Field,
                           org.springframework.validation.Errors"
                      msg="errors.required">
             <javascript><![CDATA[
             .....
                ]]>
             </javascript>
          </validator>

    name

    validation rule(required,mask,integer,email…)

    classname

    validation check를 수행하는 클래스명(org.springmodules.validation.commons.FieldChecks)

    method

    validation check를 수행하는 클래스의 메소드명(validateRequired,validateMask…)

    methodParams

    validation check를 수행하는 클래스의 메소드의 파라미터

    msg

    에러 메시지 key

    javascript

    client-side validation을 위한 자바스크립트 코드

    Spring Modules에서 제공하는 validation rule에 따라 구성해보자.

    Spring Modules (0.9 기준)에서 제공하는 validation rule들은 아래와 같다. 

    name(validation rule)

    FieldCheck 클래스

    FieldCheck 클래스의 메소드

    기능

    required

    org.springmodules.validation.commons.FieldChecks

    validateRequired

    필수값 체크

    minlength

    org.springmodules.validation.commons.FieldChecks

    validateMinLength

    최소 길이 체크

    maxlength

    org.springmodules.validation.commons.FieldChecks

    validateMaxLength

    최대 길이 체크

    mask

    org.springmodules.validation.commons.FieldChecks

    validateMask

    정규식 체크

    byte

    org.springmodules.validation.commons.FieldChecks

    validateByte

    Byte형 체크

    short

    org.springmodules.validation.commons.FieldChecks

    validateShort

    Short형 체크

    integer

    org.springmodules.validation.commons.FieldChecks

    validateInteger

    Integer형 체크

    long

    org.springmodules.validation.commons.FieldChecks

    validateLong

    Long형 체크

    float

    org.springmodules.validation.commons.FieldChecks

    validateFloat

    Float형 체크

    double

    org.springmodules.validation.commons.FieldChecks

    validateDouble

    Double형 체크

    date

    org.springmodules.validation.commons.FieldChecks

    validateDate

    Date형 체크

    range

    org.springmodules.validation.commons.FieldChecks

    validateIntRange

    범위 체크

    intRange

    org.springmodules.validation.commons.FieldChecks

    validateIntRange

    int형 범위 체크

    floatRange

    org.springmodules.validation.commons.FieldChecks

    validateFloatRange

    Float형 범위체크

    creditCard

    org.springmodules.validation.commons.FieldChecks

    validateCreditCard

    신용카드번호체크

    email

    org.springmodules.validation.commons.FieldChecks

    validateEmail

    이메일체크

    validator-rules.xml을 직접 작성하는것 보다는 예제에 있는 파일을 참고하거나 copy해서 사용하면 편리하다.
    spring-modules-0.9.zip
    을 압축을 풀어보면 예제코드가 있다.(\samples\sources\spring-modules-validation-commons-samples-src.zip) 
    예제코드의 validator-rules.xml(\webapp\WEB-INF\validator-rules.xml)에는 모든 validation rule이 이미 정의되어 있다.

    org.springmodules.validation.commons.FieldChecks 클래스에는 필수값 체크, primitive 타입 체크등 여러 validation을 수행하는 메소드들이 있다. 
    FieldChecks
    클래스 소스를 열어 보면 실제 validation 처리는 Commons Validator에 위임하고 있다. 
    따라서 주의 할점은 Commons Validator에서 제공하는 validation rule중에, FieldChecks 클래스가 제공하지 않는 rule도 있다는 것이다. 
    예를 들어 Commons Validator 1.3.1 에서는 URL이나 IP 관련 Validator를 제공하지만, Spring Modules FieldChecks 클래스에 해당 메소드가 없기 때문에, 
    새로운 FieldCheck 클래스를 추가한 후 validation-rules.xml에 클래스와 메소드를 등록해야 사용할 수 있다.
    Spring Modules
    가 제공하는 validation rule외에 rule을 추가하는 방법에 대해서는 주민등록번호 validation rule 추가하기 를 참고하라. 

    validator.xml validation rule validation Form을 매핑한다. 
    form name
    field property name-rule Server-side Client-side인 경우에 따라 다르다.

    Server-side validation의 경우는,
    form name
    field property validation할 폼 클래스의 이름, 필드과 각각 매핑된다.(camel case) 
    폼 클래스가 Employee employee, DepartmentForm 이면 departmentForm form name으로 지정하라. 

    Client-side의 경우는, 
    form name
    JSP에서 설정한 <validator:javascript formName=employee” …/> 태그의 formName와 매핑되고, field property는 각각의 폼 필드의 이름과 일치하면 된다.

    따라서, Server-side, Client-side 둘 다 수행하려면,
    JSP
    <validator:javascript formName=employee” …/> 태그의 formName은 폼 클래스의 이름이 되어야 하고, JSP의 폼 필드들은 폼 클래스의 필드와 일치해야 한다.

    depends는 해당 필드에 적용할 (validator-rules.xml에 정의된 rule name) validator를 의미한다. 
    <arg key
    >는 메시지 출력시 파라미터를 지정하는 값이다. 
    아래와 같이 작성했다면, Employee 클래스의 name 필드에 대해서 필수값 체크를, age 필드에 대해서 integer 체크를, email 필드에 대해선 필수값과 email 유효값 체크를 하겠다는 의미이다.

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE form-validation PUBLIC 
        "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1//EN" 
        "http://jakarta.apache.org/commons/dtds/validator_1_1.dtd">
     
    <form-validation>
     
        <formset>
     
            <form name="employee">
             <field property="name" depends="required">
                         <arg0 key="employee.name" />
                            </field>
                            <field property="age" depends="integer">
                         <arg0 key="employee.age" />
                            </field>
                            <field property="email" depends="required,email">
                         <arg0 key="employee.email" />
                            </field>              
            </form>
     
        </formset>
     
    </form-validation>

    Controller

    Server-Side Validation을 위해 Controller validation 로직을 추가해 보자.
    위 설정 파일에서 등록한 DefaultBeanValidator Controller에서 validation을 수행한다.
    DefaultBeanValidator
    Commons Validator의 기능을 사용하지만 자신은 Spring Validator이기 때문에,
    사용자는 Spring Validator를 사용하듯이 Controller에서 validation 코딩을 하면 된다.

    package com.easycompany.controller.annotation;
    ...
    import org.springmodules.validation.commons.DefaultBeanValidator;
    ...
     
    @Controller
    public class UpdateEmployeeController {        
                ...
                @Autowired
                private DefaultBeanValidator beanValidator;
            ...
                @RequestMapping(value = "/updateEmployee.do", method = RequestMethod.POST)
                public String updateEmployee(@ModelAttribute("employee") Employee employee,                            
                                         BindingResult bindingResult, Model model) {
     
                            beanValidator.validate(employee, bindingResult); //validation 수행
                            if (bindingResult.hasErrors()) { //만일 validation 에러가 있으면...
                                         .....
                                         return "modifyemployee";
                            }
                            employeeManageService.updateEmployee(employee);
                            return "changenotify";
                }        
    }

    JSP

    Validation을 적용할 JSP를 작성한다.(modifyemployee.jsp) 
    form submit
    을 하면 이름, 나이, 이메일등의 입력값이 Employee 클래스에 바인딩이 되서 Controller에 전달이 되고, 
    Controller
    validation 수행 로직이 있으면 validator.xml 내용에 따라 validation이 이루어 진다. 
    만일 에러가 발생하면 <form:error/>에 에러에 해당하는 메시지를 출력한다. 에러 메시지에 관련해서는 아래 에러 메시지 등록을 참고하라.

    <form:form commandName="employee">
    <table>
            ....
                <tr>
                            <th>이름</th>
                            <td><form:input path="name" size="20"/><form:errors path="name" /></td>
                </tr>
                <tr>
                            <th>비밀번호</th>
                            <td><form:input path="password" size="10"/></td>
                </tr>
                <tr>
                            <th>나이</th>
                            <td><form:input path="age" size="10"/><form:errors path="age" /></td>
                </tr>
                <tr>
                            <th>이메일</th>
                            <td><form:input path="email" size="50"/><form:errors path="email" /></td>
                </tr>
    </table>
    <table width="80%" border="1">
                <tr>
                            <td>
                            <input type="submit"/>
                            <input type="button" value="LIST" onclick="location.href='/easycompany/employeeList.do'"/>
                            </td>
                </tr>
    </table>
     
    </form:form>

    에러 메시지 등록

    메시지 파일에 에러 메시지를 등록한다.
    validation
    에러가 발생하면 validator-rules.xml에서 정의했던 msg값으로 에러메시지의 key값을 찾아 해당하는 메시지를 출력해준다.
    예를 들어, email validation에서 에러가 발생하면 msg값이 errors.email 이므로, “유효하지 않은 이메일 주소입니다.”라는 에러 메시지를 JSP에 있는 <form:errors path=email /> 부분에 출력하게 된다.

    employee.name=이름
    employee.email=이메일
    employee.age=나이
    employee.password=비밀번호
     
    # -- validator errors --
    errors.required={0}은 필수 입력값입니다.
    errors.minlength={0} {1}자 이상 입력해야 합니다.
    errors.maxlength={0} {1}자 이상 입력할수 없습니다.
    errors.invalid={0}은 유효하지 않은 값입니다.
     
    errors.byte={0}  byte타입이어야 합니다.
    errors.short={0}  short타입이어야 합니다.
    errors.integer={0} integer 타입이어야 합니다.
     
    ....
     
    errors.email=유효하지 않은 이메일 주소입니다.

    TEST

    이름 필드에 값을 비우고 submit하면, name에 필수값(required) validation rule이 설정되어 있으므로 
    아래와 같이 이름 필드 옆에 에러 메시지가 출력 될 것이다. 
    설명: http://www.egovframe.org/wiki/lib/exe/fetch.php?media=egovframework:rte:ptl:security:server-validate.jpg

    validator.jsp 추가

    아래와 같은 내용의 validator.jsp를 작성한다.

    <%@ page language="java" contentType="javascript/x-javascript" %>
    <%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %>
    <validator:javascript dynamicJavascript="false" staticJavascript="true"/>

    /validator.do로 호출하도록 Controller에서 메소드를 추가하고 requestmapping 한다. 
    validator.jsp
     http://localhost:8080/easycompany/validator.do 브라우져에서 호출해보면, validator-rules.xml에서 정의한 javascript 함수들이 다운로드 되거나 화면에 print 되는 걸 확인할 수 있을 것이다.
    validator.jsp
    client-validation을 위해 validator-rules.xml에서 정의한 javascript 함수들을 로딩한다. 
    따라서 client-validation을 할 페이지에서는 이 validator.jsp 
    <script type=
    text/javascript src=<c:url value=/validator.do/>></script> 
    같이 호출한다.

    JSP 설정(taglib,javascript) 추가

    client-validation을 위해서는 해당 JSP에 아래와 같은 작업이 추가 되어야 한다.

    1. commons-validator taglib를 선언한다.
    <%@ taglib prefix=
    validator uri=http://www.springmodules.org/tags/commons-validator %>

    2. 필요한 자바 스크립트 함수를 generate 하기 위한 코드를 추가 한다. validation-rules.xml에서 선언한 함수를 불러 오기 위해, 위에서 작성한 validator.jsp를 아래와 같이 호출한다. 
    <script type=
    text/javascript src=<c:url value=/validator.do/>></script>

    3. 위의 자바 스크립트 함수를 이용해 필요한 validation과 메시지 처리를 위한 자바 스크립트를 generate 하기 위한 코드를 추가 한다. formName에는 validator.xml에서 정의한 form의 이름을 써준다. 
    <validator:javascript formName=
    employee staticJavascript=false xhtml=true cdata=false/>

    4. form submit시에 validateVO클래스명() 함수를 호출한다. 
    onsubmit=return validateEmployee(this)” ”>

    따라서 앞의 server-side validation에서 작성한 modifyemployee.jsp은 아래와 같이 변경된다.

    <!-- commons-validator tag lib 선언-->
    <%@ taglib prefix="validator" uri="http://www.springmodules.org/tags/commons-validator" %>
     
    ....
    <!--for including generated Javascript Code(in validation-rules.xml)-->
    <script type="text/javascript" src="<c:url value="/validator.do"/>"></script>
    <!--for including generated Javascript Code(validateEmployee(), formName:validator.xml에서 정의한 form의 이름)-->
    <validator:javascript formName="employee" staticJavascript="false" xhtml="true" cdata="false"/>
    <script type="text/javascript">
                function save(form){         
                            if(!validateEmployee(form)){
                                         return;
                            }else{
                                         form.submit();
                            }
                }
    </script>
    ....
    <form:form commandName="employee">
    <table>
            ....
                <tr>
                            <th>이름</th>
                            <td><form:input path="name" size="20"/><form:errors path="name" /></td>
                </tr>
                <tr>
                            <th>비밀번호</th>
                            <td><form:input path="password" size="10"/></td>
                </tr>
                <tr>
                            <th>나이</th>
                            <td><form:input path="age" size="10"/><form:errors path="age" /></td>
                </tr>
                <tr>
                            <th>이메일</th>
                            <td><form:input path="email" size="50"/><form:errors path="email" /></td>
                </tr>
    </table>
    <table width="80%" border="1">
                <tr>
                            <td>
                            <!--<input type="submit"/>-->
                    <input type="button" value="SAVE" onclick="save(this.form)"/> <!-- client-validation을 위해 바로 submit하지 않고 먼저 validateEmployee 함수를 호출-->
                            <input type="button" value="LIST" onclick="location.href='/easycompany/employeeList.do'"/>
                            </td>
                </tr>
    </table> 
    </form:form>
    ....

    TEST

    이번에도 이름 필드의 값을 지우고 저장 버튼을 누르면 아래와 같은 alert 메시지가 보일 것이다.
    설명: http://www.egovframe.org/wiki/lib/exe/fetch.php?media=egovframework:rte:ptl:security:client-validate.jpg

    §  Spring Modules Reference Documentation v 0.9, Chapter 17.Validation, P133~136

     

    출처 - http://www.egovframe.org/wiki/doku.php?id=egovframework:rte:ptl:security:jakarta_commons_validator&s[]=validator

     

     

    Commons Validator validation rule 추가하기

    개요

    Commons Validator primitive type, 필수값, 이메일등 흔히 사용되는 유형에 대한 validation rule template으로 제공하지만, 
    프로젝트의 특성에 따라 공통으로 사용되는 validation rule이 발생되고 이를 추가해야할 필요가 생길 수 있다. 
    공공프로젝트에서 흔히 사용되는 주민등록번호 validator를 추가해 봄으로써, validation rule을 추가하는 방법을 알아보고자 한다. 
    예제는 easycompany를 이용했다. 

    설명

    Spring Module을 이용해서 Commons Validator를 사용한다면 아래와 같은 내용을 validation rule 정의 파일(validator-rules.xml 같은)에서 보았을 것이다. 

          <!--필수값 체크 validation rule-->
          <validator name="required"
                classname="org.springmodules.validation.commons.FieldChecks"
                   method="validateRequired"
             methodParams="java.lang.Object,
                           org.apache.commons.validator.ValidatorAction,
                           org.apache.commons.validator.Field,
                           org.springframework.validation.Errors"
                      msg="errors.required">
             <javascript><![CDATA[
                ...
                ]]>
             </javascript>
          </validator>

    validator 태그의 각각의 attribute는 다음과 같은 의미를 같는다.

    name

    validation rule(required,mask,integer,email…)

    classname

    validation check를 수행하는 클래스명

    method

    validation check를 수행하는 클래스의 메소드명

    methodParams

    validation check를 수행하는 클래스의 메소드의 파라미터

    msg

    에러 메시지 key

    javascript

    client-side validation을 위한 자바스크립트 코드

    주민등록번호 rule을 아래와 같이 추가한다고 하면,

          <validator name="ihidnum"
                classname="egovframework.rte.ptl.mvc.validation.RteFieldChecks"
                   method="validateIhIdNum"
             methodParams="java.lang.Object,
                           org.apache.commons.validator.ValidatorAction,
                           org.apache.commons.validator.Field,
                           org.springframework.validation.Errors"                       
                  depends=""
                      msg="errors.ihidnum">
               <javascript><![CDATA[
                ...
                ]]>
             </javascript>
          </validator>

    필요한 작업은 아래와 같다. 

    1. FieldCheck class(RteFieldChecks) 작성

    2. Validator class(RteGenericValidator) 작성

    3. validator-rules.xml 설정

    4. validator.xml 설정

    5. 에러메시지 설정

    6. TEST

    org.springmodules.validation.commons.FieldChecks를 상속 받는 RteFieldChecks 클래스를 생성한다. 
    그리고 주민등록번호 validation을 담당할 validateIhIdNum 메소드를 추가한다. 
    주민등록번호 validation 로직이 RteFieldChecks.validateIhIdNum() 안에 있어도 되지만, org.springmodules.validation.commons.FieldChecks와 같은 방식으로 다른 Validator에 위임했다.

    package egovframework.rte.ptl.mvc.validation;
     
    import org.apache.commons.validator.Field;
    import org.apache.commons.validator.ValidatorAction;
    import org.springframework.validation.Errors;
    import org.springmodules.validation.commons.FieldChecks;
     
    public class RteFieldChecks extends FieldChecks{
     
                public static boolean validateIhIdNum(Object bean, ValidatorAction va,
                Field field, Errors errors){
                            //bean에서 해당 field 값을 추출
                            String ihidnum = FieldChecks.extractValue(bean, field); 
     
                    //주민등록번호 유효성 검사 알고리즘은 RteGenericValidator가 가지고 있다.
                            if(!RteGenericValidator.isValidIdIhNum(ihidnum)){ //유효한 주민등록번호가 아니면
                                         FieldChecks.rejectValue(errors, field, va); //에러 처리
                                         return false;
                            }else{
                                         return true;
                            }
                }
    }

    주민등록번호 유효성체크 로직이 있는 RteGenericValidator 클래스를 작성해 보자. 
    유효성 체크 기준은

    1. 값의 길이가 13자리이며, 7번째 자리가 1,2,3,4 중에 하나인가?

    2. 6자리의 값이 유효한 날짜인가?

    3. 주민등록번호 마지막 자리를 이용한 check

    로 했다.

    package egovframework.rte.ptl.mvc.validation;
    import java.io.Serializable;
    import org.apache.commons.validator.GenericTypeValidator;
     
    public class RteGenericValidator implements Serializable {          
                public static boolean isValidIdIhNum(String value) {                   
                            //값의 길이가 13자리이며, 7번째 자리가 1,2,3,4 중에 하나인지 check.
                            String regex = "\\d{6}[1234]\\d{6}";
                            if (!value.matches(regex)) {
                                         return false;
                            }
     
                            // 6자리의 값이 유효한 날짜인지 check.
                            try {
                                         String strDate = value.substring(0, 6);
                                         strDate = ((value.charAt(6) == '1' || value.charAt(6) == '2') ? "19":"20") + strDate;
                                         strDate = strDate.substring(0, 4) + "/" + strDate.substring(4, 6)
                                                                 + "/" + strDate.substring(6, 8);
     
                                         SimpleDateFormat dateformat = new SimpleDateFormat("yyyy/MM/dd");
                                         Date date = dateformat.parse(strDate);
                                         String resultStr = dateformat.format(date);
     
                                         if (!resultStr.equalsIgnoreCase(strDate)) {
                                                     return false;
                                         }
     
                            } catch (ParseException e) {
                                         // TODO Auto-generated catch block
                                         e.printStackTrace();
                                         return false;
                            }
     
                            //주민등록번호 마지막 자리를 이용한 check.
                            char[] charArray = value.toCharArray();
                            long sum = 0;
                            int[] arrDivide = new int[] { 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5 };
                            for (int i = 0; i < charArray.length - 1; i++) {
                                         sum += Integer.parseInt(String.valueOf(charArray[i]))
                                                                 * arrDivide[i];
                            }
     
                            int checkdigit = (int) ((int) (11 - sum % 11)) % 10;
                            return (checkdigit == Integer.parseInt(String.valueOf(charArray[12]))) ? true
                                                     : false;
                }
    }

    validator-rules.xml 설정

    이제 주민등록번호 validation rule을 추가해 보자. 
    rule
    이름은 ihidnum으로 하고 위에서 작성한 코드를 바탕으로 설정하면, (이미 위 개요에 나온 대로) 아래와 같다. 
    client-validation
    을 위해서 자바스크립트 코드도 추가했다. 

          <validator name="ihidnum"
                classname="egovframework.rte.ptl.mvc.validation.RteFieldChecks"
                   method="validateIhIdNum"
             methodParams="java.lang.Object,
                           org.apache.commons.validator.ValidatorAction,
                           org.apache.commons.validator.Field,
                           org.springframework.validation.Errors"                       
                  depends=""
                      msg="errors.ihidnum">
               <javascript><![CDATA[
               function validateIhIdNum(form) {
                    var bValid = true;
                    var focusField = null;
                    var i = 0;
                    var fields = new Array();
                    oIhidnum = new ihidnum();                
                    for (x in oIhidnum) {
                      var field = form[oIhidnum[x][0]];
                      if (field.type == 'text' ||
                                 field.type == 'hidden' ||
                            field.type == 'textarea') {
                            if (trim(field.value).length==0 || !checkIhIdNum(field.value)) {
                                if (i == 0) {
                                    focusField = field;
                                }
                                fields[i++] = oIhidnum[x][1];
                                bValid = false;
                            }
                        }
                    }
                    if (fields.length > 0) {
                        alert(fields.join('\n'));
                    }
                    return bValid;
                }
     
                /**
                 * Reference: JS Guide
                 * http://jsguide.net/ver2/articles/frame.php?artnum=002
                 */             
                function checkIhIdNum(ihidnum){
     
                        fmt = /^\d{6}[1234]\d{6}$/;
                        if(!fmt.test(ihidnum)){
                                    return false;
                        }
     
                        birthYear = (ihidnum.charAt(7) <= "2") ? "19" : "20";
                                                     birthYear += ihidnum.substr(0, 2);
                                                     birthMonth = ihidnum.substr(2, 2) - 1;
                                                     birthDate = ihidnum.substr(4, 2);
                                                     birth = new Date(birthYear, birthMonth, birthDate);
     
                                                     if( birth.getYear() % 100 != ihidnum.substr(0, 2) ||
                                                         birth.getMonth() != birthMonth ||
                                                         birth.getDate() != birthDate) {
                                                         return false;
                                                     }
     
                        var arrDivide = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5];                
                        var checkdigit = 0;                    
                        for(var i=0;i<ihidnum.length-1;i++){
                                    checkdigit += parseInt(ihidnum.charAt(i)) * parseInt(arrDivide[i]);
                        }
                        checkdigit = (11 - (checkdigit%11))%10;
                        if(checkdigit != ihidnum.charAt(12)){
                                    return false;
                        }else{
                                    return true;
                        }
                }
                ]]>
             </javascript>
          </validator>

    validator.xml 설정

    ihidnum이란 필드에 주민등록번호 validation 체크를 해보자. 
    validator.xml
    에 필요한 내용을 추가하고. 

    <form-validation>
        <formset>
            <form name="employee">
             ...
                            <field property="ihidnum" depends="ihidnum"/>
                    ... 
            </form>
        </formset>
    </form-validation>

    messages 프로퍼티에 에러메시지를 추가하자.

    errors.ihidnum=유효하지 않은 주민등록번호입니다.

    TEST

    주민등록번호 server-side,client-side validatin을 위한 환경은 다 갖추어졌다. 
    이제 EmployeeController validation을 추가하고,(이미 추가되어 있다면 pass) 

    package com.easycompany.controller.annotation;
    ...
    import org.springmodules.validation.commons.DefaultBeanValidator;
    ...
     
    @Controller
    public class EmployeeController {     
                ...
                @Autowired
                private DefaultBeanValidator beanValidator;
            ...
                @RequestMapping(value = "/updateEmployee.do", method = RequestMethod.POST)
                public String updateEmployee(@ModelAttribute("employee") Employee employee,                            
                                         BindingResult bindingResult, Model model) {
     
                            beanValidator.validate(employee, bindingResult); //validation 수행
                            if (bindingResult.hasErrors()) { //만일 validation 에러가 있으면...
                                         .....
                                         return "modifyemployee";
                            }
                            employeeManageService.updateEmployee(employee);
                            return "changenotify";
                }        
    }

    VO Class(com.easycompany.model.Employee.java)에 주민등록번호 필드를 추가하고,

    package com.easycompany.model;
    public class Employee {
            ....
                private String ihidnum;
                private String ihidnum1;
                private String ihidnum2;
            ...
                public String getIhidnum() {
                            return ihidnum1+ihidnum2;
                }
                public String getIhidnum1() {                        
                            return ihidnum1;
                }
                public void setIhidnum1(String ihidnum1) {
                            this.ihidnum1 = ihidnum1;
                }
                public String getIhidnum2() {
                            return ihidnum2;
                }
                public void setIhidnum2(String ihidnum2) {
                            this.ihidnum2 = ihidnum2;
            }
    }

    JSP(/easycompany/webapp/jsp/modifyemployee.jsp)에 주민등록번호 입력 필드를 추가하자.

    ...
                <tr>
                            <th>주민번호</th>
                            <td>
                                         <form:input path="ihidnum1" size="10"/> - <form:input path="ihidnum2" size="10"/><form:errors path="ihidnum" />
                                         <form:hidden path="ihidnum"/>
                            </td>
                </tr>
    ...

    주민등록번호를 입력하지 않거나, 틀린번호를 입력시엔 아래와 같은 경고창이 뜬다. 
    설명: http://www.egovframe.org/wiki/lib/exe/fetch.php?media=egovframework:rte:ptl:validation:ihidnum-validation.jpg 
    틀린 입력값으로 client를 통과하더라도 Controller에서 validation이 추가로 동작하므로, server-side에서 validation error가 일어날것이다.

    §  Spring Modules Reference Documentation v 0.9, Chapter 17.Validation, P133~136

     

    출처 - http://www.egovframe.org/wiki/doku.php?id=egovframework:rte:ptl:security:jakarta_commons_validator&s[]=validator

     



    'Framework & Platform > Spring' 카테고리의 다른 글

    spring - @SessionAttributes 와 SessionStatus  (0) 2012.05.21
    Spring - Validation  (0) 2012.05.21
    Spring - @ModelAttribute  (0) 2012.05.21
    Spring - @RequestParam  (0) 2012.05.21
    Spring - ModelAndView  (0) 2012.05.21
    Posted by linuxism
    ,


    @ModelAttribute

    @ModelAttribute의 속성은 아래와 같다.

    이름타입설명
    valueString바인드하려는 Model 속성 이름.




    @ModelAttribute는 실제적으로 ModelMap.addAttribute와 같은 기능을 발휘하는데, Controller에서 2가지 방법으로 사용된다.

    1.메소드 리턴 데이터와 Model 속성(attribute)의 바인딩. 
    메소드에서 비지니스 로직(DB 처리같은)을 처리한 후 결과 데이터를 ModelMap 객체에 저장하는 로직은 일반적으로 자주 발생한다.

    ...
    	@RequestMapping(value = "/updateDepartment.do", method = RequestMethod.GET)
    	public String formBackingObject(@RequestParam("deptid") String deptid, ModelMap model) {
    		Department department = departmentService.getDepartmentInfoById(deptid); //DB에서 부서정보 데이터를 가져온다.
    		model.addAttribute("department", department); //데이터를 모델 객체에 저장한다.
    		return "modifydepartment";
    	}
    ...

    @ModelAttribute를 메소드에 선언하면 해당 메소드의 리턴 데이터가 ModelMap 객체에 저장된다.
    위 코드를 아래와 같이 변경할수 있는데, 사용자로 부터 GET방식의 /updateDepartment.do 호출이 들어오면,
    formBackingObject 메소드가 실행 되기 전에 DefaultAnnotationHandlerMapping이 org.springframework.web.bind.annotation.support.HandlerMethodInvoker을 이용해서 
    (@ModelAttribute가 선언된)getEmployeeInfo를 실행하고, 결과를 ModelMap객체에 저장한다.
    결과적으로 getEmployeeInfo 메소드는 ModelMap.addAttribute(“department”, departmentService.getDepartmentInfoById(…)) 작업을 하게 되는것이다.

    ...
    	@RequestMapping(value = "/updateDepartment.do", method = RequestMethod.GET)
    	public String formBackingObject() {
    		return "modifydepartment";
    	}
     
    	@ModelAttribute("department")
    	public Department getEmployeeInfo(@RequestParam("deptid") String deptid){
    		return departmentService.getDepartmentInfoById(deptid); //DB에서 부서정보 데이터를 가져온다.
    	}
    	또는
    	public @ModelAttribute("department") Department getDepartmentInfoById(@RequestParam("deptid") String deptid){
    		return departmentService.getDepartmentInfoById(deptid);
    	}
    ...

    2.메소드 파라미터와 Model 속성(attribute)의 바인딩. 
    @ModelAttribute는 ModelMap 객체의 특정 속성(attribute) 메소드의 파라미터와 바인딩 할때도 사용될수 있다.
    아래와 같이 메소드의 파라미터에 ”@ModelAttribute(“department”) Department department” 선언하면 department에는 (Department)ModelMap.get(“department”) 값이 바인딩된다.
    따라서, 아래와 같은 코드라면 formBackingObject 메소드 파라미터 department에는 getDepartmentInfo 메소드가 ModelMap 객체에 저장한 Department 데이터가 들어 있다.

    ...
    	@RequestMapping(value = "/updateDepartment.do", method = RequestMethod.GET)
    	public String formBackingObject(@ModelAttribute("department") Department department) { //department에는 getDepartmentInfo에서 구해온 데이터들이 들어가 있다.
    		System.out.println(employee.getEmployeeid());
    		System.out.println(employee.getName());
    		return "modifydepartment";
    	}
     
    	@ModelAttribute("department")
    	public Department getDepartmentInfo(@RequestParam("deptid") String deptid){
    		return departmentService.getDepartmentInfoById(deptid); //DB에서 부서정보 데이터를 가져온다.
    	}
    ...


    출처 - http://www.egovframe.org/wiki/doku.php?id=egovframework:rte:ptl:annotation-based_controller&s[]=requestmapping


    employee.getEmployeeid()가 아닌 department.getEmployeeid()가 아닌가 싶다.


    ===================================================================================


    • @ModelAttribute

    • HTTP Request에 포함된 파라미터를 Model 객체로 바인딩함, @ModelAttribute의 'name'으로 정의한 Model객체를 다음 View에서 사용 가능


    @ModelAttribute

    @ModelAttribute는 컨트롤러에서 다음과 같이 두 가지 방법으로 사용할 수 있다.
    • 컨트롤러 메소드에 정의

    • 입력 폼 페이지에서 출력해 줄 reference data를 전달하고자 할 때. 
      SimpleFormController의 referenceData() 메소드와 같은 역할

    • 컨트롤러 메소드의 입력 argument에 정의

    • 메소드의 argument로 입력된 Command 객체에 이름을 부여하고자 할 때.
    다음은 위에서 설명한 두가지 방법으로 @ModelAttribute를 사용한 EditUserController 의 예이다.
    @Controller
    @RequestMapping("/user.do")
    public class EditUserController {
        // 컨트롤러 메소드에 정의
        @ModelAttribute("deptList")
        public List populateDeptList() throws Exception {
            return deptService.getDeptList();
        }
        
        @RequestMapping(params = "param=add")
        public String addUser(@ModelAttribute("user")
            User user, BindingResult result, SessionStatus status) throws Exception {
            ...중략...
        }
    }


    출처 - http://dev.anyframejava.org/anyframe/doc/web/3.2.0/webfw/springmvc/basic/annotation_controller.html#aModelAttribute


    ===================================================================================


    Q >  controller 단에서, 예를 들면 아래 인자값 3개의 차이점을 알고 싶습니다.
    3개 모두가 같은 의미인것 같은데...
    BbsVO selectBbs(
            BbsVO bbsVO,
            @ModelAttribute("bbsVO") BbsVO bbsVO,
            @RequestParam(value="bbsVO") BbsVO bbsVO,
    )throws Exception{}

     

    A >

    우선 첫번째의 경우와 두번째의 경우 모두.. 앞 request parameter들이 VO에 담기는 역할은 똑같습니다..
    다만, 두번째의 경우는 @ModelAttribute에 지정된 이름으로 모델 정보에 담아지기 때문에 
    View부분(보통 JSP)에서 bbsVO라는 모델이름으로 해당 VO 값들을 참조할 수 있습니다...

    세번째의 경우는 bbsVO라는 request parameter를 BbsVO에 넣으라는 의미로.. 위 두개의 의미와 차이가 있으며.. 
    하나의 값을 일반적인 VO에 넣을 수 없기 때문에.. 잘못된 형식입니다..

    정리하자면.. 두번째 형식을 사용하시면 됩니다.

     

     

    Q > 아래 소스를 비교해 주셨으면 합니다. 
    @RequestMapping("/sample/addSampleView.do")
    public String addSampleView(@ModelAttribute("searchVO") SampleDefaultVO searchVO, Model model)throws Exception { 
     model.addAttribute("sampleVO", new SampleVO());
     return "sample/egovSampleRegister";
    }

    ---->
    @RequestMapping("/sample/addSampleView.do")
    public String addSampleView(SampleDefaultVO searchVO, Model model)throws Exception { 
     model.addAttribute("sampleVO", new SampleVO());
     return "sample/egovSampleRegister";
    }
    이렇게 하는 것의 차이점을 알고 싶습니다. 의미상으로는 같은 건가요? 
    A  >  
    @ModelAttribute를 사용하는 이유는 Model 속성(VO)과 메소드 파라미터의 바인딩을 위해서입니다. 
    즉, serchVO에 웹 request parameter값을 넣으려면 @ModelAttribute를 지정하셔야 합니다.
    다만, 실제 @ModelAttribute 없이 테스트를 하셔도 parameter값들은 들어가도록 되어 있습니다. 
    (Spec.상의 설명과 DispatcherServlet 구현상의 차이인 것 같습니다.) 
    다시 말씀드리면 위 경우만으로 보면 차이점이 없습니다.
    그러나 다음 JSP인 egovSampleRegister.jsp에서 serchVO 값을 참조하려면 반드시 @ModelAttribute를 지정하셔야 합니다.
    @ModelAttribute에 지정된 name으로 JSP 페이지에서 참조할 할 수 있도록 Model정보로 담겨지기 때문입니다.
    (별도로 두번째 방식에서 model.attribute("searchVO", searchVO); 코드를 추가하셔도 같은 기능을 수행합니다.)

     

     

    Q> jsp 내의 <% %> 안에서 db에서 가져온 값을 사용하는 방법 

    A>

    Controller에서 담겨진 model 정보는 request 상의 attribute로 jsp에 전달됩니다.
    즉 jsp 서버 사이드 스크립트(<% ... %>)에서는 다음과 같은 형식으로 사용하실 수 있습니다.
    <%
    DataVO data = (DataVO)request.getAttriubte("data");
    %>

     

     

    Q> db에 저장된 테그 표시

    A> <c:out value="${....}" escapeXml="false" /> 

     

     

    Q> 오라클 10g clob 등록방법

    A>

    조회는 resultmap에 clob로 선언을 해주어 표시를 했습니다.
    저장은 #contents:CLOB# 이런 방법으로 저장함.

     

    Q >  DB resource

    egovframework/spring/context-datasource.xml

    ./WEB-INF/classes/egovframework/spring/context-datasource.xml


    ex)

    @Controller
    @RequestMapping("/annot/registMember.do")
    @SessionAttributes("memberInfo") //세션에 저장할 모델 객체
    public class RegistMemberAnnotController {
     private Validator validator = new MemberInfoValidator();

     @ModelAttribute("memberInfo") // 스프링은 memberInfo를 뷰에 전달한다.
     public MemberInfo formBacking(HttpServletRequest reqeust) {
      MemberInfo memberInfo = new MemberInfo();
      memberInfo.setAddress(new Address());
      return memberInfo;
     }

     @RequestMapping(method = RequestMethod.GET)
     public String showForm() {
      return "registMemberFormUseAnnot";
     }

     @RequestMapping(method = RequestMethod.POST)
     public String processSubmitForm(@ModelAttribute("memberInfo") //ModelAttribute를 이용하여 커맨드 객체의 이름을 준다.
     MemberInfo command, BindingResult errors, SessionStatus sessionStatus) {
      validator.validate(command, errors);
      if (errors.hasErrors()) {
       return showForm();
      }
      // 로직 처리
      sessionStatus.setComplete(); //세션에 적용된 모델 객체를 삭제할 때 사용
      return "registMember";
     }
    }





    'Framework & Platform > Spring' 카테고리의 다른 글

    Spring - Validation  (0) 2012.05.21
    spring - Validator  (0) 2012.05.21
    Spring - @RequestParam  (0) 2012.05.21
    Spring - ModelAndView  (0) 2012.05.21
    Spring - contextConfigLocation  (0) 2012.05.16
    Posted by linuxism
    ,


    @RequestParam

    @RequestParam은 Controller 메소드의 파라미터와 웹요청 파라미터와 맵핑하기 위한 어노테이션이다.
    관련 속성은 아래와 같다.

    이름타입설명
    valueString파라미터 이름
    requiredboolean해당 파라미터가 반드시 필수 인지 여부. 기본값은 true이다.

    아래 코드와 같은 방법으로 사용되는데, 
    해당 파라미터가 Request 객체 안에 없을때 그냥 null값을 바인드 하고 싶다면, pageNo 파라미터 처럼 required=false로 명시해야 한다.
    name 파라미터는 required가 true이므로, 만일 name 파라미터가 null이면 org.springframework.web.bind.MissingServletRequestParameterException이 발생한다.

    @Controller
    public class HelloController {
     
        @RequestMapping("/hello.do")
        public String hello(@RequestParam("name") String name, //required 조건이 없으면 기본값은 true, 즉 필수 파라미터 이다. 파라미터 pageNo가 존재하지 않으면 Exception 발생.
    			@RequestParam(value="pageNo", required=false) String pageNo){ //파라미터 pageNo가 존재하지 않으면 String pageNo는 null.
    	...		
        }
    }

    위에서 작성한 LoginController의 login 메소드를 보면 파라미터 아이디와 패스워드를 Http Request 객체에서 getParameter 메소드를 이용해 구하는데,
    @RequestParam을 사용하면 아래와 같이 변경할수 있다.

    package com.easycompany.controller.annotation;
    ...
    @Controller
    public class LoginController {
     
    	@Autowired
    	private LoginService loginService;
     
    	@RequestMapping(value = "/loginProcess.do", method = RequestMethod.POST)
    	public String login(
    			HttpServletRequest request,
    			@RequestParam("id") String id,
    			@RequestParam("password") String password) {		
     
    		Account account = (Account) loginService.authenticate(id,password);
     
    		if (account != null) {
    			request.getSession().setAttribute("UserAccount", account);
    			return "redirect:/employeeList.do";
    		} else {
    			return "login";
    		}
    	}
    }


    출처 - http://www.egovframe.org/wiki/doku.php?id=egovframework:rte:ptl:annotation-based_controller&s[]=requestmapping

    ===================================================================================

    스프링2.5 Annotation 기반의 Controller를 만들때 편하게 사용할 수 있는 것이 @RequestParam 이다.

    1. 에제를 보면  
    2. public ModelAndView add(@RequestParam("userId") long userId) {  
    3. ...  
    4. }  

    이전의 컨틀롤러와 비교해 보자. 더이상 HttpServletRequest 명시하지 않아도 된다.

    1. public ModelAndView add(HttpServletRequest req, HttpServletResponse res)  
    2. throws Exception {  
    3. String userId = req.getPrameter("userId");  
    4. }  

    또 한가지의 장점은 이클립스 같은 IDE에서 주석을 만들때 자동으로 param 주석을 만들어 주어 가독성이 좋아진다.

    1. /**  
    2.      * 추가하기  
    3.      * @param userId  
    4. */  
    5. public ModelAndView add(@RequestParam("userId") long userId) {  
    6. ...  
    7. }  

    RequestParam은 기본적으로 필수 파라미터 이기 때문에 반드시 요청한 파라미터가 있어야 한다.

    만약 요청에 따라 파라미터 없이 호출이 필요할때는

    @RequestParam(value="userId", required=false) 로 설정하면 필수 파라미터조건을 해제할 수 있다.

     

    단점은 위에 첫번째 소스와 같이 primitive type인 경우 인데, long 타입의 userId 값으로 설정했는데

    만약  add.do?userId=&userName 이런식으로 "userId=" 아무런 값도 오지 않으면 IllegalStateException 오류가 발생합니다.

    다음과 같이

    1. java.lang.IllegalStateException: Optional long parameter 'targetUserId' is not present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.  

     

    일단은 두번재와 같이 String으로 받은후 long 형으로 변환하는 메소드를 통해서 변환하면 되지만

    뭔가 더 좋은 방법을 찾아봐야 겠네요.


    출처 - http://parang.springlog.com/pages/1400852


    ===================================================================================















    SearchController

    public ModelAndView serchInternal()
    @RequestParam("query") 는 반드시 넘겨야할 값 (required = false를 입력하지 않았을 경우)

    ModelAndView로 리턴하면 jsp에서 값을 받아 들일 수 있다

    defaultValue 전송되지 않았을 경우 기본값 1

    public ModelAndView searchExternal()

    메소드는 의무사항이 없기 때문에 external.do로 호출이 가능하다

     














    dispatcher-servlet.xml
    01.<?xml version="1.0" encoding="UTF-8"?>
    02. 
    10. 
    11. 
    12.<!-- 파라미터로 전송된 데이터 처리 -->
    13.<bean id="searchController" class="madvirus.spring.chap06.controller.SearchController" />
    14. 
    15.<!-- View 글로벌 설정 -->
    16.<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    17.<property name="prefix" value="/WEB-INF/view/" />
    18.<property name="suffix" value=".jsp" />
    19.</bean>
    20.</beans>






    SearchController.java
    01.package madvirus.spring.chap06.controller;
    02. 
    03.import org.springframework.stereotype.Controller;
    04.import org.springframework.web.bind.annotation.RequestMapping;
    05.import org.springframework.web.bind.annotation.RequestParam;
    06.import org.springframework.web.servlet.ModelAndView;
    07. 
    08.@Controller
    09.public class SearchController {
    10. 
    11.@RequestMapping("/search/internal.do")
    12.public ModelAndView serchInternal(
    13.@RequestParam("query") String query,
    14.@RequestParam(value = "p", defaultValue = "1"int pageNumber) {
    15. 
    16.System.out.println("query=" + query + ",pageNumber=" + pageNumber);
    17. 
    18.return new ModelAndView("search/internal");
    19.}
    20. 
    21. 
    22.@RequestMapping("/search/external.do")
    23.public ModelAndView searchExternal(
    24.@RequestParam(value = "query", required = false) String query,
    25.@RequestParam(value = "p", defaultValue = "1"int pageNumber) {
    26. 
    27.System.out.println("query=" + query + "mpageNumber=" + pageNumber);
    28. 
    29.return new ModelAndView("search/external");
    30.}
    31.}







    search/external.jsp
    01.<%@ page language="java" contentType="text/html; charset=UTF-8"
    02.pageEncoding="UTF-8"%>
    03.<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    04.<html>
    05.<head>
    06.<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    07.<title>외부 검색</title>
    08.</head>
    09.<body>
    10.외부 검색
    11.</body>
    12.</html>





    search/internal.jsp 
    01.<%@ page language="java" contentType="text/html; charset=UTF-8"
    02.pageEncoding="UTF-8"%>
    03.<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    04.<html>
    05.<head>
    06.<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    07.<title>내부 검색</title>
    08.</head>
    09.<body>
    10.내부 검색
    11.</body>
    12.</html>


    출처 - http://javai.tistory.com/567














    'Framework & Platform > Spring' 카테고리의 다른 글

    spring - Validator  (0) 2012.05.21
    Spring - @ModelAttribute  (0) 2012.05.21
    Spring - ModelAndView  (0) 2012.05.21
    Spring - contextConfigLocation  (0) 2012.05.16
    Spring - 기초 설정 - xml별 역할  (0) 2012.05.16
    Posted by linuxism
    ,