티스토리 뷰

반응형


| Spring Boot Project



시작 전에

..\sts-bundle\sts-3.9.14.RELEASE\STS.ini 파일을 열고

하단에 인코딩 설정을 추가해주자.


-Dfile.encoding=utf-8


//


대략적인 순서(?)는

1. 프로젝트 생성

2. DTO 생성

3. mybatis 설정파일 배치

3-1. type alias 및 mapper 설정 추가

4. mapper scan 처리

5. mapper xml 파일 편집

5-1. name space는 Repo Interface 활용

6. 테스트 실행

7. 서비스 생성 및 테스트

8. Controller 생성




|| Lombok Setting



DTO 자동완성.

[Spring-Boot] Lombok을 사용해보자.




|| Spring Boot Setting



[Spring-Boot] 기본 설정(Spring Starter Project)




|| 단위 테스트



Spring Boot 에서는 @SpringBootTest로 바로 단위 테스트가 가능하다.


Spring 에서의 단위 테스트는 아래를 참고해보자.

[Spring] 단위 테스트(spring-test, JUnit)



|| Service and Controller



Spring 과 달라진 부분은

1. Config 설정(ApplicationConfig, MVCConfig)은 모두 application.properties 로 이동

2. Repository는 Interface만 사용

3. Service, Controller 는 동일하다


[Spring] Spring@MVC 구조 및 @annotation 살펴보기.




|| View



이미 기본 설정에서 설정하긴 했다..!


1. application.properties에 View resolver 설정

2. pom.xml에 필요한 라이브러리 추가

3. src/main/webapp/WBE-INF/views 폴더 구조 생성

4. JSP 생성

5. Controller에서 JSP 호출 테스트




thymeleaf ?!

thymeleaf 는 동적인 html 파일이다.

/src/main/resources/templates/ 에 작성해준다.

근데.. 아직은 .jsp 를 많이 사용한다고 한다.. :(

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1 th:text="${msg}" >Thymeleaf is best?</h1>
</body>
</html>
cs



|| Example Code




||| controller


/src/main/java/com/example/demo/controller/UserController.java

1
2
3
4
5
6
7
8
9
@Controller
public class UserController {
 
    @GetMapping("/")
    public String index() {
        return "index";
    }
    
}
cs


/src/main/java/com/example/demo/controller/UserRestController.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
@RestController  // @ResponseBody 생략
@RequestMapping("/user")
public class UserRestController {
 
    @Autowired
    UserService service;
    
    @GetMapping("/{id}")  
    public User getUser(@PathVariable String id) {
        return service.select(id);
    }
    
    @GetMapping 
    public List<User> getAllUser() {
        return service.selectAll();
    }
    
    @PostMapping  
    public User insert(@RequestBody User user) {
        return service.insert(user);
    }
    
    @PutMapping   
    public User update(@RequestBody User user) {
        return service.update(user);
    }
    
    @DeleteMapping("/{id}")  
    public int delete(@PathVariable String id) {
        return service.delete(id);
    }
}
cs



||| dto


/src/main/java/com/example/demo/model/dto/User.java

1
2
3
4
5
6
7
8
9
10
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
 
    private String id;
    private String name;
    private String pass;
 
}
cs



||| repo


/src/main/java/com/example/demo/model/repo/UserReop.java

1
2
3
4
5
6
7
8
9
10
11
12
public interface UserRepo {
    int insert(User user);
 
    int update(User user);
 
    int delete(String id);
 
    User select(String id);
 
    List<User> selectAll();
}
 
cs



||| service


/src/main/java/com/example/demo/model/service/UserService.java

1
2
3
4
5
6
7
8
9
10
11
public interface UserService {
    User insert(User user);
 
    User update(User user);
 
    int delete(String id);
 
    User select(String id);
 
    List<User> selectAll();
}
cs


/src/main/java/com/example/demo/model/service/UserServiceImpl.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
39
40
41
42
43
@Service
public class UserServiceImpl implements UserService {
 
    @Autowired
    UserRepo repo;
 
    @Override
    public User select(String id) {
        return repo.select(id);
    }
 
    @Override
    public List<User> selectAll() {
        return repo.selectAll();
    }
 
    @Override
    @Transactional
    public User insert(User user) {
        int result = repo.insert(user);
        if (result == 1) {
            return repo.select(user.getId());
        } else {
            return null;
        }
    }
 
    @Override
    public User update(User user) {
        int result = repo.update(user);
        if (result == 1) {
            return repo.select(user.getId());
        } else {
            return null;
        }
    }
 
    @Override
    public int delete(String id) {
        return repo.delete(id);
    }
 
}
cs



||| Application


/src/main/java/com/example/demo/DemoApplication.java

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@MapperScan("com.example.demo.model.repo")
public class DemoApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
 
}
cs



||| resources


/src/main/resources/application.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# datasource Connection
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springtest?serverTimezone=UTC&useUniCode=yes&characterEncoding=UTF-8
spring.datasource.username=yourId
spring.datasource.password=yourPw
 
# mybatic config
mybatis.config-location=classpath:/mybatis-config.xml
 
# mvc config
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
 
logging.level.com.example=trace
cs


/src/main/resources/mybatis-config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
<configuration>
 
    <!-- 사용하려는 DTO에 대한 축약 이름 -->
    <typeAliases>
        <typeAlias type="com.example.demo.model.dto.User" alias="user" />
    </typeAliases>
    
    <!-- 사용할 쿼리에 대한 등록 -->
    <mappers>
        <mapper resource="userinfo.xml" />
    </mappers>
    
</configuration>
cs


/src/main/resources/userinfo.xml

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
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.model.repo.UserRepo">
 
    <!-- User select(String id); -->
    <select id="select" parameterType="string" resultType="user">
        select *
        from user
        where id=#{id}
    </select>
 
    <!-- List<User> selectAll(); -->
    <select id="selectAll" resultType="user">
        select *
        from user
        order by id
    </select>
 
    <!-- int insert(User user); -->
    <insert id="insert" parameterType="user">
        insert into user
        values(#{id}, #{name}, #{pass})
    </insert>
 
    <!-- int update(User user); -->
    <update id="update" parameterType="user">
        update user
        set name = #{name}, pass = #{pass}
        where id = #{id}
    </update>
 
    <!-- int delete(String id);  -->
    <delete id="delete" parameterType="string">
        delete from user
        where id=#{id};
    </delete>
 
</mapper>
cs



||| Unit Test


/src/test/java/com/example/demo/RepoTest.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@SpringBootTest
public class RepoTest {
 
    @Autowired
    UserRepo repo;
    
    @Test
    public void selectTest() {
        User user = repo.select("Cristoval");
        assertEquals(user.getName(), "jihun");
    }
    
    @Test
    public void selectAllTest() {
        List<User> user = repo.selectAll();
        assertEquals(user.size(), 1);
    }
    
    @Test
    @Transactional
    public void insertTest() {
        User user = new User("Cristoval""jihun""1234");
        int result = repo.insert(user);
        assertEquals(1, result);
        
        User selected = repo.select("Cristoval");
        assertEquals(selected.getName(), "jihun");
    }
    
    @Test
    @Transactional
    public void updateTest() {
        User selected = repo.select("Cristoval");
        selected.setName("jihun");
        int result = repo.update(selected);
        
        assertEquals(1, result);
        
        selected = repo.select("Cristoval");
        assertEquals(selected.getName(), "jihun");
    }
    
    @Test
    @Transactional
    public void deleteTest() {
        int result = repo.delete("Cristoval");
        
        assertEquals(1, result);
        
        User selected = repo.select("Cristoval");
        assertNull(selected);
    }
}
 
cs



||| views


/src/main/webapp/WEB-INF/views/index.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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set value="${pageContext.request.contextPath }" var="root"/>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script
    src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
    <h1>사용자 관리</h1>
    <table border="1">
        <tr>
            <th>아이디</th>
            <th>이름</th>
            <th>비밀번호</th>
            <tbody id="usertable"></tbody>
    </table>
    
    <h2>사용자 상세 정보</h2>
    <ul>
        <li>아이디: <input type="text" id="id">
        <li>이름: <input type="text" id="name">
        <li>비밀번호: <input type="text" id="pass">
    </ul>
    
    <input type="button" value="추가" id="add">
    <input type="button" value="수정" id="mod">
    <input type="button" value="삭제" id="del">
</body>
<script>
    function list() {
        // 페이지가 로딩되자마자 서버에 ajax로 요청 --> 사용자 목록을 얻은 후 표시해보자.
        $.ajax({
            url:"${root}/user",
            method:"get",
            // data:"",
            success:function(data){
                // console.log(data)
                // 1. 테이블의 기존 데이터를 지워주자.
                $("#usertable").empty();
                // 2. 새로 받아온 데이터로 채워주자.
                $.each(data, function(idx, item) {
                    console.log(idx, item)
                    let $tr = $("<tr data-id='" + item.id + "'><td>" + item.id + "</td><td>" + item.name + 
                            "</td><td>" + item.pass + "</td></tr>");
                    
                    $("#usertable").append($tr)
                })
             },
            error:errFunc
        });
    }
    
    function getUserInfoJSON(){
        // 화면 데이터 가져오기
        // step 1. 객체로 만들어주자.
        let user = {
                    "id":$("#id").val(),
                    "name":$("#name").val(),
                    "pass":$("#pass").val()
                    };
        // console.log(user);
        // step 2. 객체를 문자열로 변환한다.
        let strUser = JSON.stringify(user);
        // console.log(strUser)
        
        return strUser;
    }
    
    function errFunc() {
        alert("잠시 후 다시 시도해주세요.")
    }
    
    // 처음에 화면 채우기
    list();
    
    // 동적으로 추가되는 요소에게 이벤트 처리
    $("#usertable").on("dblclick""tr"function(){
        // 이벤트 핸들러에서의 this : event source
        console.log(this)
        let id = $(this).attr("data-id");
        // console.log("조회 대상: " + id);
        $.ajax({
            url:"${root}/user/" + id,
            // method:"GET",
            // data:"",
            success:function(data){
                console.log(data)
                $("#id").val(data.id);
                $("#name").val(data.name);
                $("#pass").val(data.pass);
            },
            error:errFunc
        })
    })
    
    $("#add").on("click"function(){
        
        $.ajax({
            url:"${root}/user",
            method: "POST",
            data: getUserInfoJSON(),
            // json Type의 데이터 전달.
            contentType:"application/json",
            success:function(data){
                // console.log(data)
                list();
                alert("추가되었습니다.");
            },
            error:errFunc
        })
    })
    
    $("#mod").on("click"function() {
        strUser = getUserInfoJSON();
        
        $.ajax({
            url: "${root}/user",
            method: "PUT",
            data:  getUserInfoJSON(),
            // json Type의 데이터 전달.
            contentType:"application/json",
            success:function(data){    
                // console.log(data)
                list();
                alert("수정되었습니다.");
            },
            error:errFunc
        })
    })
    
    $("#del").on("click"function() {
        
        $.ajax({
            url:"${root}/user/" + $("#id").val(),
            method:"DELETE",
            success:function(data){
                console.log(data)
                list();
                alert("삭제되었습니다.");
            }
        })
    })
 
</script>
</html>
cs



||| pom


/pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
cs





반응형
댓글
최근에 올라온 글
최근에 달린 댓글
링크
Total
Today
Yesterday