화면에 출력하는 용인데 sout을 사용하면 성능이 굉장히 안 좋아진다. 그래서 이걸 사용해서 출력을 할 수 있다.
위 툴을 resources에 가져와야 이 툴을 사용할 수 있다.
이 패키지 명도 우리가 사용하는 프로젝트와 맞춰줘야한다.
@Slf4j
@Controller
@RequestMapping("/exam01")
public class DeptController {
@Autowired
DeptService deptService;
@GetMapping("/dept")
public String getDeptAll(Model model){
List<Dept> list = deptService.findAll();
model.addAttribute("list", list);
log.debug("list: " + list);
return "exam01/dept/dept_all.jsp";
}
}
Slf4j라는 어노테이션을 사용해야한다.
그러고 log,debug에 출력할 내용을 입력하면된다.
이런 식으로 결과가 출력된다.
dno로 부서 정보들을 조회해보자.
dno를 이용하여 함수를 찾을 수 있게 하기위해 deptDao에 selectById가 이미 만들어져 있어서 이걸 가져와서 변수에 담고 변수를 리턴하면된다.
public Dept findByDno(Long dno){
Dept dept = deptDao.selectById(dno);
return dept;
}
여기서 dno는 기본키라서 중복이 없다. 이걸로 찾으면 무조건 한 건이 나온다.
service에서 만든 함수를 들고와서 comtroller에서 웹으로 전송해보자.
@GetMapping("/dept/{dno}")
public String getDeptId(@PathVariable long dno,
Model model){
// TODO: service 의 상세조회 함수(findById) 호출
Dept dept = deptService.findByDno(dno);
// TODO: jsp 로 dept(부서) 객체 전송
model.addAttribute("dept", dept);
return "exam01/dept/dept_by_dno.jsp";
}
PathVariable을 이용해서 주소창에 dno를 입력하면 그 입력된 dno로 해당 부서를 찾아주게 한다.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
<jsp:include page="../../common/header_dept.jsp"/>
<div class="container">
<table class="table container table-success table-striped">
<thead>
<tr>
<th scope="col">부서번호</th>
<th scope="col">부서이름</th>
<th scope="col">위치</th>
</tr>
</thead>
<tbody>
<tr>
<td>${dept.dno}</td>
<td>${dept.dname}</td>
<td>${dept.loc}</td>
</tr>
</tbody>
</table>
</div>
<jsp:include page="../../common/footer.jsp"/>
</script>
</body>
</html>
여기서 dno는 기본값이라 단 하나의 값만 가지기 때문에 반복문을 사용할 필요가 없다. 그리고 각 요소들만 보여주게해주면된다.
10번 부서만 출력이 된다.
여기서 상단의 메뉴로 각 부서의 정보를 출력하게 하고싶었다. 그래서 jsp에서 dropdown의 메뉴마다 dno에따른 정보가 출력되게 만들었다.
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
부서
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/exam01/dept">부서</a></li>
<li><a class="dropdown-item" href="/exam01/dept/10">10번 부서</a></li>
<li><a class="dropdown-item" href="/exam01/dept/20">20번 부서</a></li>
<li><a class="dropdown-item" href="/exam01/dept/30">30번 부서</a></li>
<li><a class="dropdown-item" href="/exam01/dept/40">40번 부서</a></li>
</ul>
</li>
header의 드롭다운 부분인데 여기에 각각 /exam01/dept/{dno}를 적어주어 연결을 해주었다.
새로운 부서가 추가되면 저장을 할 수 있는 기능을 만들어보자.
웹 전송방식에는 네 가지가 있다. 이번에는 post방식을 이용해서 입력받은 값을 spring에 전송해서 저장할 것이다.
근런데 여기서 put방식,delete방식 을 form태그에서 사용하려면 속성 추가를 해주어야한다. 나머지 두개는 기본으로 지원이 된다.
spring.mvc.hiddenmethod.filter.enabled=true
이거을 resources의 properties에 넣어주어야한다.
<form action="/exam01/dept/add" method="post" class="container">
<div class="mb-3">
<label for="dname" class="form-label">부서명</label>
<input type="text " class="form-control form-success" id="dname" name="dname" placeholder="ex) sales ">
</div>
<div class="mb-3">
<label for="loc" class="form-label" >부서 위치</label>
<input type="text " class="form-control " id="loc" name="loc" placeholder="ex) seoul ">
</div><%--여기서 name속성을 잘 적어줘야한다. 백엔드와 연결하는 부분이기때문--%>
<div><button type="submit" class="btn btn-success">저장</button></div>
</form>
form에서 신경써줘야하는 변수는 4개이다.
action 속성의 주소를 postMapping주소와 같게 만들어줘야 제출할 경우 그 함수가 실행이 된다.
method 속성을 post로 해주어야한다. 데이터를 전송할때는 post 조회는 get이다.
input 태그에 name속성의 값이 spring의 속성과 연결된다. 그래서 이걸 Dept(객체)의 속성과 같아지게 만드는 것이 중요하다.
또한 바꿔줘야할 것은 button의 type이다. type을 submit으로 바꿔줘야만 일반버튼이 제출 버튼으로 바뀌어 값이 전달된다.
public List<Dept> save(Dept dept){
List<Dept> depts = deptDao.insert(dept);
return depts;
}
여기선 dao에서 만든 insert함수를 사용해서 저장 기능을 만들어주는 것이라 큰 설명은 없다. 단지 리턴값은 없어도 되지만 잘 들어갔는지를 확인할때 사용할 수 있으니 들어간 데이터를 확인할 배열을 리턴해준다.
@GetMapping("/dept/addition")
public String addDept(Model model){
return "/exam01/dept/add_dept2.jsp";
}
@PostMapping("/dept/add")
public RedirectView createDept(@ModelAttribute Dept dept){
// 변수자리인데 왜 특정 클래스가 인식이 되나..
// => 이 어노테이션이 변수 자리에 있는 것과 같은 이름의 애를 우리의 클래스 중에 이름이 같은 것과 연결해준다.
// 인식이 된다면 검색 범위가 궁금? 만약 다른 패키지에 같은 이름이 있다면?
//=> 그래서 우리는 임포트로 인식을 시켜준다.import org.example.modelexam.model.Dept;을 해줌으로 패키지가 어디인지를 인식시켜준다.
deptService.save(dept);
return new RedirectView("/exam01/dept"); // 저장이 되면 이동할 페이지 주소 적어준다. 여기선 jsp나 html이 아닌 getMapping의, 즉 url을 적어주는 곳이다.
}
조회와는 다르게 save함수에서는 controller함수를 2개를 만들어 주어야한다.
새로운 데이터가 저장되었다.
부서 번호를 선착순으로 10단위씩 넣어주기로 하자. 보통 DB로 시퀀스를 해주는데 아직 DB와 연결을 안 했으니 자바로 만들어주자.
service함수를 수정해주면된다.
public List<Dept> save(Dept dept){
if (dept.getDno() == null) {
int count = deptDao.selectAll().size();
dept.setDno((count+1)*10);
}
List<Dept> depts = deptDao.insert(dept);
return depts;
}
Dno가 null일때 데이터의 총 개수에 1을 더해서 10을 곱하면 새로들어오는 데이터의 dno가 된다. 이 로직만 추가해주면 자동으로 dno가 추가된다.
시퀀스가 50으로 자동으로 생긴다.
<form action="/dept/edit/{dno}" method="post" class="container">
<input type="hidden" name="_method" value="put"/> <%-- 예전에는 put이 없어서 method에 put을 넣어도 안 먹힌다.
그래서 이 태그를 따로 넣어줘야 비로소 인식이 가능함. 이태그의 type은 hidden이라서 보이지 않는다.
name은 _method이다. value에는 method에 들어가는 값을 넣어주어야한다.--%>
<div class="mb-3">
<input type="hidden" class="form-control form-success" id="dno" name="dno" value="${dept.dno}" placeholder="ex) sales ">
<%--hidden 처리를 해서 사용자가 조작할 수 없게 안보이게 하고 백엔드로 날라가게는 했다.--%>
</div>
<div class="mb-3">
<label for="dname" class="form-label" >부서 이름</label>
<input type="text " class="form-control " id="dname" name="dname" value="${dept.dname}">
</div><%--여기서 name속성을 잘 적어줘야한다. 백엔드와 연결하는 부분이기때문--%>
<div class="mb-3">
<label for="loc" class="form-label" >부서 위치</label>
<input type="text " class="form-control " id="loc" name="loc" placeholder="ex) seoul " value="${dept.loc}">
</div><%--여기서 name속성을 잘 적어줘야한다. 백엔드와 연결하는 부분이기때문--%>
<div><button type="submit" class="btn btn-success">수정</button></div>
</form>
수정은 저장과 다르게 따로 처리를 해야하는 것이 있다.
action의 값을 controller의 PostMapping의 값과 같게 해줘야 전송이 되면 해당 함수가 실행된다. 또 다른 점은 예전에는 put이 없어서 method에 put을 넣어도 안 먹힌다. 그래서 속성으로 value = "put"을 가지는 태그를 따로 넣어줘야 비로소 인식이 가능함. 이태그의 type은 hidden으로 해서 보이지 않게 해야한다.
dno로 부서 정보를 가져와서 수정을한다. 그런데 dno가 몇 인지는 백엔드로 넘어가야하지만 만약 이 dno까지 사용자가 수정을 해버리면 고유한 값인 기본키가 망가지기때문에 문제가 생긴다 그래서 이건 type속성을 hidden으로 해주어 사용자가 건들이지 못하게 한다.
그림에서 3번은 값을 수정할 input을 만들어 준 것인데 이건 필수는 아니지만 수정을 하기 전에 원래 어떤 값인지를 사용자에게 보여주고 수정을 하는 것이 좋아서 value속성에 현재의 dname과 loc의 값을 주어, 현재 정보를 사용자에게 보여주었다.
마지막으로 form안의 button의 type을 "submit"으로 해주어서 클릭시 전송이 되게 만들어 주었다.
public List<Dept> save(Dept dept){
List<Dept> list = null;
if (dept.getDno() == null) {
int count = deptDao.selectAll().size();
dept.setDno((count+1)*10);
list = deptDao.insert(dept);
}else {
list = deptDao.update(dept);
}
return list;
}
이전의 코드에서는 else없이 if문만있었는데 save함수를 사용할 때 만약 null값이 있다면 이미 데이터가 존재한다는 것이므로 수정으로 볼수 있다. 그래서 이때는 else를 사용하여 update함수로 값을 받아들이게 했다.
@GetMapping("/dept/edition/{dno}") // 수정할 페이지를 만들어줄 것이다.
public String editDept(Model model, @PathVariable long dno){
Dept dept = deptService.findByDno(dno);
model.addAttribute("dept", dept);
return "exam01/dept/update_dept.jsp";
}
수정할 수 있는 페이지로 이동시켜 주는 함수이다. 이때 수정시 dno에 따른 정보를 수정하는 것이므로 dno를 @PathVariable로 받아야하고, 수정할 데이터가 눈에 보이면 무엇을 수정해야하는지 눈에 잘 보이기 때문에 model로 객체 정보를 눈에 보이게 해줬다.
위와 같은 그림이 완성된다.
@PutMapping("/dept/edit/{dno}") // 특정dno 인 정보를 수정해야하므로 dno를 적어줘야함
public RedirectView updateDept(@PathVariable long dno, @ModelAttribute Dept dept){
deptService.save(dept);
return new RedirectView("/exam01/dept");
}
2.객체를 수정하는 것이므로 @ModelAttribute를 사용해야하고 url로 dno를 받아야하므로 @PathVariable를 사용해야한다.
4.마지막으로 수정이 끝나면 이동할 페이지를 RedirectView()값에 적어 리턴한다.
현재 부서번호 10번의 위치는 pusan인데 이것을 서울로 바꿔보자.
서울로 수정 되었다.
수정페이지로 가기위해 url을 계속 입력해야하는게 굉장히 귀찮았다 그래서 버튼을 누르면 수정페이지로 이동할 수 있게 만들어보자.
<tr>
<td>${data.dno}</td>
<td>${data.dname}</td>
<td>${data.loc}<a class="btn btn-success" href="/exam01/dept/edition/${data.dno}" role="button">수정</a></td>
</tr>
a태그에 class를 button으로 해주고 href로 링크를 달아주었다. 근데 이 링크는 dno마다 링크가 달라지므로 링크를 ${}을 이용해야했다.
컨트롤러의 링크가 "/member/edition/{eno}" 이니 jsp에서는 "/exam01/dept/edition/${data.dno}"가 된다.

버튼이 생겼다.