ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 15. 각 항목에 알맞는 데이터인지 확인하기
    Back-end Developer/Spring Framework, 설정 및 실습 2019. 1. 21. 14:38

    제목만 봐도 어느정도 예상은 될거같아요.

    데이터를 생성하고 DB에 접근해 해당 데이터를 주입하는것이 생각보다 매우 쉽고 간단했죠.
    물론 개념 자체가 단순하고 그런건 아니라.. 저도 꽤나 찾아봤어요.
    ㅋㅋㅋㅋ 그렇다고 완전히 쫙- 파악이 되고 그런건 아니었지만..ㅠㅠ

    어쨌든 그 데이터를 넣긴 넣었는데, 사실 매우 허술하죠?
    입력으로 들어가는 데이터 항목 자체도 적지만요.
    데이터가 형식에 맞는지, 또 중복된 데이터는 없는지, 이런 것을 확인하는 절차 자체가 없다는게 매우 흠이에요.

    데이터 구성이 상당히 체계적이진 않기 때문에, 중복 데이터를 처리는 못해도 형식에 맞는 데이터인지 정도만 체크 해볼게요.
    정규화 표현식(Regular Expression: regex)으로 직접 해보는 것도 좋지만,  좀 더 간단한 어노테이션을 활용 할게요.


    Validation 사용하기

    doCreate 메소드에서 인자로 들어오는 Offer 데이터가 타당한지 확인을 해야합니다.
    이에 사용될 어노테이션은 '@Valid'인데요. 이 또한 라이브러리가 필요합니다.
    pom.xml dependencies에서 hibernate-validator 다운로드해주세요.

    Hibernate-validator 다운로드


    다음으로 OffersController의 doCreate 메소드에서 '@Valid'로 request가 들어올때 검사할 수 있도록 합니다.
    그리고 뭐 결과 내용을 확인해보는 것도 좋을테니, BindingResult 객체를 인자로 받아오도록 합니다.
    에러가 발생하면 리스트를 받아와 어떤 문제인지 출력하고, 
    다시 데이터를 입력 할 수 있도록 "createoffer"를 반환 해줍시다.

    doCreate 메소드

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @RequestMapping("/docreate")
    public String doCreate(Model model, @Valid Offer offer, BindingResult result) {
        if(result.hasErrors()) {
            System.out.println("Form data does not Validate");
                
            List<ObjectError> errors = result.getAllErrors();
            for(ObjectError error: errors) {
                System.out.println(error.getDefaultMessage());
            }
                
            return "createoffer";        
        }
            
        offersService.insert(offer);
        return "offercreated";
    }
    cs



    Validation 설정하기


    이렇게 어노테이션을 달아 놓기만 해서 처리가 된다면 정말 편리하겠지만, 그건 너무 큰 바람인거 같구요.

    우리가 Offer.java 클래스에서 어떤 데이터 필드가 타당하고 타당하지 못한지, 기준을 정해줘야합니다.


    name 필드에는 '@Size'를 사용할게요.

    길이는 최소 2 ~ 최대 50까지 설정합니다.

    email 필드는 '@Email'과 '@NotEmpty'를 사용합니다.

    사실 '@NotEmpty'는 이메일에 굳이 할 필요는 없으니.. 이름 필드에다 적용하셔도 될거같아요.

    text 필드도 마찬가지로 '@Size' 사용합니다.


    그리고 각 어노테이션 마다 이에 만족하지 못할시 에러메시지를 적절히 적어주세요.


    Offer.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    package kr.ac.snut.model;
     
    import javax.validation.constraints.Size;
     
    import org.hibernate.validator.constraints.Email;
    import org.hibernate.validator.constraints.NotEmpty;
     
    public class Offer {
        private int id;
        
        @Size(min = 2, max = 50, message = "Name size must be between 2 and 50 chars")
        private String name;
        
        @Email(message = "Please enter a valid email address")
        @NotEmpty(message = "Email address cannot be empty")
        private String email;
        
        @Size(min = 1, max = 1000, message = "Text size must be between 1 and 1000 chars")
        private String text;
        
        public Offer() {}
        
        public Offer(int id, String name, String email, String text) {
            this.id = id;
            this.name = name;
            this.email = email;
            this.text = text;
        }
        
        public Offer(String name, String email, String text) {
            this.name = name;
            this.email = email;
            this.text = text;
        }
     
        ... 하단부는 변경사항이 없기 때문에 생략합니다.
    }
     
    cs



    각 항목별 에러 발생



    Spring form tag 사용하기 (Data Buffering)


    문제점이 하나있는데요.

    데이터를 막 입력하다가 버튼을 눌렀는데, 그게 조건과 안맞아서 에러가 발생하는 것 까진 의도했습니다.

    하지만 의도되지 않은 동작이 하나 있죠... 에러 발생하니까, 데이터가 싹- 날아가버리네요. ㅎㅎ


    Spring form tag를 사용하면, 이 문제를 해결할 수 있습니다.

    우선 taglib을 통해 Spring form을 추가해주세요.


    그리고 아래에 form 태그와 input 태그가 존재하는 부분에 스스로 설정하신 prefix를 붙여주세요.

    form 태그 내에 modelAttribute 추가해주시고, input 태그의 name 항목을 path로 바꿔줍니다.


    offercreate.jsp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="sform" uri="http://www.springframework.org/tags/form" %>
     
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css"
            href="${pageContext.request.contextPath}/resources/css/main.css">
     
    <title>Insert title here</title>
    </head>
    <body>
        <sform:form method="get" action="${pageContext.request.contextPath}/docreate" modelAttribute="offer">
            <table class="formtable">
                <tr>
                    <td class="label">Name: </td>
                    <td><sform:input class="control" path="name" type="text"/><br>
                    </td>
                </tr>
                <tr>
                    <td class="label">Email: </td>
                    <td><sform:input class="control" path="email" type="text"/><br>
                    </td>
                </tr>
                <tr>
                    <td class="label">Text: </td>
                    <td><sform:textarea class="control" path="text" rows="10" cols="10"></sform:textarea><br>
                    </td>
                </tr>
                <tr>
                    <td class="label"></td>
                    <td><input class="control" value="Create offer" type="submit"/></td>
                </tr>
            </table>
        </sform:form>
    </body>
    </html>
     
    cs



    이렇게 하면 뭐 다 마무리가 됩니다.

    근데 이제보니 doCreate 메소드에는 Offer 객체가 존재합니다만.. 이를 호출하는 offerCreate 메소드에는 존재하지 않아요..

    이게 무슨일이람..!ㅠㅠ

    그래서 model Attribute 추가를 통해 빈 생성자라도 넣어줍시다.


    createOffer 메소드 속성추가

    1
    2
    3
    4
    5
    6
    @RequestMapping("/createoffer")
    public String createOffer(Model model) {
        model.addAttribute(new Offer());
        
        return "createoffer";
    }
    cs



    타당성 검증 코드 결과 영상




    사용자 화면에 에러 출력


    콘솔에 에러 메시지를 발생해서는 우리밖에 볼 수가 없죠..

    사용자도 봐야 그래도 만든 의미가 있으니까 만들어줍시다.


    createoffer.jsp에서 항목에 맞는 에러 태그를 생성해줄게요.

    그리고 글자 크기랑 색도 조금 설정하는게 좋을거 같습니다. 

    에러에 대한 class selector를 main.css에 추가해주세요.


    .error

    1
    2
    3
    4
    5
    .error{
        font-size: small;
        color: red;
        margin-left: 10px;
    }
    cs


    offercreate.jsp에 각 항목별로 error 태그도 추가해주시고, 그 안에 class selector도 넣어주세요.


    offercreate.jsp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="sform" uri="http://www.springframework.org/tags/form" %>
     
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" type="text/css"
            href="${pageContext.request.contextPath}/resources/css/main.css">
     
    <title>Insert title here</title>
    </head>
    <body>
        <sform:form method="get" action="${pageContext.request.contextPath}/docreate" modelAttribute="offer">
            <table class="formtable">
                <tr>
                    <td class="label">Name: </td>
                    <td><sform:input class="control" path="name" type="text"/><br>
                    <sform:errors class="error" path="name"></sform:errors>
                    </td>
                </tr>
                <tr>
                    <td class="label">Email: </td>
                    <td><sform:input class="control" path="email" type="text"/><br>
                    <sform:errors class="error" path="email"></sform:errors>
                    </td>
                </tr>
                <tr>
                    <td class="label">Text: </td>
                    <td><sform:textarea class="control" path="text" rows="10" cols="10"></sform:textarea><br>
                    <sform:errors class="error" path="text"></sform:errors>
                    </td>
                </tr>
                <tr>
                    <td class="label"></td>
                    <td><input class="control" value="Create offer" type="submit"/></td>
                </tr>
            </table>
        </sform:form>
    </body>
    </html>
    cs



    최종 결과




    이렇게 모든 내용이 끝났습니다.

    이제 알고리즘 개념들도 정리하고 스프링은 좀 더 많이 쓰는 방향으로 더 실용적인 기능들을 추가해 나갈 예정입니다.

    반응형

    댓글

Designed by minchoba.