Back-end Developer/Spring Framework, 설정 및 실습

15. 각 항목에 알맞는 데이터인지 확인하기

exponential-e 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



최종 결과




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

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

반응형