본문 바로가기

수업 복습하기/개인 페이지 만들기

[포트폴리오] 개인페이지 제작기 02

728x90
728x90

/ insertAndSelectTest

insert까지 했으면,  이제 insert하고 select까지 하는 지문을 연습해봅시다~

insert할 때, 우리가어떻게 만들었냐면, 키를 generate하게 만들었다. 

vo에 null이 아닌 값이 들어가 있어야 하기 때문에, 그걸 확인 할 수 있는 vo의 id의 값이 0이 아니면서, null이 아닌 것 까지 확인해야 하기 때문에 assertNotNull과 assertnotequals(0,value)를 확인해야한다.

 

방금 입력한 id를 바로 조회하는 것이다보니까. 안전성이 보장된다라는게 특징인듯?

그래서, vo에 작성한 타이틀과, 콘텐트, 작성자가 마지막에 insert된 아이들과 비교 할 수 있게,

또 assertequals를 사용해서 비교하는 단계를 거친다.

 

입력한 id가 있으니까, 그 id로 조회를 하고 그 조회해온 것과 입력을 위해 만들어놓은 vo와 제목 본문 작성자가 같으면 잘 조회했다는 것을 말하는 것이다.

 

/update

실수 하지 않기 위해, 직전에 하나의 column을 넣은 후에, 또 확인하는 과정을 거치면 된다.

 

+) inserted에 null값이 들어갔는데, 못들어가게 하도록 수정하자!

(id) IN (SELECT id 
FROM Board WHERE 
inserted IS NULL);하려는데 id가 safe update모드가 걸려있어서 이를 해제했다.

USE test;
CREATE TABLE Board (
	id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200) NOT NULL,
    content VARCHAR(2000) NOT NULL,
    writer VARCHAR(50) NOT NULL,
    inserted DATETIME DEFAULT NOW(),
    updated DATETIME DEFAULT NOW()
);

DESC Board;

SELECT * FROM Board ORDER BY id DESC;

DELETE FROM Board WHERE 
(id) IN (SELECT id 
		FROM Board 
        WHERE inserted IS NULL);
        
DELETE FROM Board WHERE updated IS NULL;
        
ALTER TABLE Board MODIFY COLUMN inserted DATETIME NOT NULL DEFAULT NOW();
ALTER TABLE Board MODIFY COLUMN updated DATETIME NOT NULL DEFAULT NOW();

 

/인서트 하자마자 바로 지우는 방식을 택하자!

	@Test
	public void insertAndDeleteTest() {
		BoardVO vo = new BoardVO();
		vo.setTitle("삭제용 제목");
		vo.setContent("삭제용 본문");
		vo.setWriter("tester");
		
		int cnt = mapper.insert(vo);
		
		assertEquals(1, cnt);
		
		cnt = mapper.delete(vo.getId());
		
		assertEquals(1, cnt);
		
		BoardVO deleted = mapper.read(vo.getId());
		assertNull(deleted);
	}

insert를 한 다음에, 잘 들어갔는지 확인하고 바로 지우는 단계를 밟도록 하자.

assertequals가 둘다 1인데, 입력된게 1이고 삭제된게 1인지 확인하는 것이다.

지운다음에 조회를 하면, 조회가 되지 않아야 하니까 assertNull로 조회를 해야한다.

 

/list 삽입되는지 test

@Test
	public void getListTest() {
		List<BoardVO> list = mapper.getList();
		assertNotNull(list);
		assertTrue(list.size() > 0);
		
		BoardVO vo = new BoardVO();
		vo.setTitle("list 테스트용 ");
		vo.setContent("list 테스트용 본문");
		vo.setWriter("tester");
		
		mapper.insert(vo);
		
		List<BoardVO> list2 = mapper.getList();
		
		assertEquals(list.size() + 1, list2.size());
		
		for (BoardVO item : list2) {
			assertNotNull(item.getId());
			assertNotNull(item.getTitle());
			assertNotNull(item.getContent());
			assertNotNull(item.getWriter());
			assertNotNull(item.getInserted());
			assertNotNull(item.getUpdated());
		}
	}

리스트가 더해졌으니까 list.size()+1 과 list2.size가 같은지 확인!

그다음에 item에 들어간 값들이 전부 null이 아닌지 확인할 것.

 

 

/이론수업

08 영속/비즈니스 계층의 crud 구현

persistence (dao, mapper 와 유사한 것)

 

/비즈니스계층 : 우리는 프로젝트가 작아서 비즈니스계층은 사용하지 않았었음.

우리가 수업시간에 이름지어서 사용했던 것들은 실제 이러한 이름으로 사용하면서 공부했다.

/9장 비즈니스와 persistence tier부분만 따로 떼서 보여주고 있는중

책에서는 시범적으로 운영하는 서비스 클래스와, 실제로 운영될 수 있는 서비스실행클래스 이렇게 하는데,

우리는 그냥 바로 운영할수 있는 클래스만들기로했따!

 

mapper dependency니까 인젝션 당해야한다. 그래서보통component 를쓰는데 service안에 componentㅔ가 있어서

@service를 사용한다.

 

root-context.xml수정했는데, component-scan만 붙어있으면 bean으로 만들겠다.라고 하는 식을 넣었따.

<context:component-scan base-package="org.zerock.service"></context:component-scan> (추가)

 

boardservice 왜만드는거야..ㅠ 궁금해죽겠네!!!

 

10,11장 같이 한꺼번에 만듬!

jsp 제외하고 우리가 만든 project 1 package

1.  게시물 목록부터 가져오는 일을 하자!

controller는 service한테 일을 시키고, service는 dao한테 일을 시킨다. 그렇게 때문에 controller는 service에 의존을 하고 있기 때문에, injection을 당해야 한다. 따라서 autowired를 할건데, 현장에서는 field에 붙이는 경우가 종종 있다!

 

// 5. forward / redirect
// jsp path : /WEB-INF/views/board/list.jsp

이 부분에서, 우리는 board/list만 넣어주면 되는데 (이미 설정값에 넣어놔서)

하지만, mapping을 보면, 이미 주소와 같기 때문에 따로 넣어줘야 할 이유가 없다.

 

/jsp 만들기!

위치 : ex00\src\main\webapp\WEB-INF\views\board\list.jsp'

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<link rel="stylesheet" href="<%=request.getContextPath()%>/resource/css/icon/css/all.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">

<title>Insert title here</title>
</head>
<body>

	<!-- .container>.row>.col>h1{게시물 목록} -->
	<div class="container">
		<div class="row">
			<div class="col">
				<h1>게시물 목록</h1>
				<!-- table.table>thead>tr>th*4^^tbody -->
				<table class="table">
					<thead>
						<tr>
							<th>
								<i class="fab fa-slack-hash"></i>
							</th>
							<th>제목</th>
							<th>
								<i class="fas fa-user"></i>
							</th>
							<th>작성일</th>
						</tr>
					</thead>
					<tbody>
						<c:forEach items="${list }" var="board">
							<tr>
								<td>${board.id }</td>
								<td>${board.title }</td>
								<td>${board.writer }</td>
								<td>${borard.inserted }</td>
							</tr>
						</c:forEach>
					</tbody>
				</table>
				table.
			</div>
		</div>
	</div>
	<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
</body>
</html>

 

/ 우선 /board/get?id=(숫자)를 입력했을 때, 원하는 페이지를 가져오게 하는 것 먼저!

실제로는 @RequestParam("id") Integer id 인데 다 생략하고 Integer id만 남는다

장황하게 작성했던걸, business logic에 집중해서  model을 활용해 간단하게 적어 내려갈 수 있었다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="b" tagdir="/WEB-INF/tags/board" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<link rel="stylesheet" href="<%=request.getContextPath()%>/resource/css/icon/css/all.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">

<title>Insert title here</title>
</head>
<body>
<b:navBar></b:navBar>
	<!-- .container>.row>.col>h1{게시물 조회} -->
	<div class="container">
		<div class="row">
			<div class="col">
				<h1>게시물 조회</h1>
				<div class="board-view">
					<!-- .form-group*3>label[for=input$]+input.form-control#input$[readonly] -->
					<div class="form-group">
						<label for="input1">제목</label>
						<input type="text" class="form-control" id="input1" readonly value="${board.title }" }>
					</div>
					<div class="form-group">
						<label for="input2">내용</label>
						<!-- <input type="text" class="form-control" id="input2" readonly=""> -->
						<textarea class="form-control" id="input2"  readyonly >${board.content }</textarea>
					</div>
					<div class="form-group">
						<label for="input3">작성자</label>
						<input type="text" class="form-control" id="input3" readonly value="${board.writer }">
					</div>
				</div>
			</div>
		</div>
	</div>
	<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
</body>
</html>

 

/이제 제목을 클릭하면, 그 게시물로 들어가게 하기 위해서는 list.jsp를 수정해야 한다.

우리는 복잡한 url을 사용하지 않기 때문에 a href="get?id=${board.id }와같은 방식을 넣었다.

 

/ 맨 위에, 간단한 링크를 만들도록 하자 ! 귀찮으니까 원하는 페이지로 바로 이동할 수 있게!

상대경로보다는, 절대경로가 나을 것 같으며 -> tag로 따로 빼도록 하겠다.

위치 : ex00\src\main\webapp\WEB-INF\tags\navBar.tag

안에들어간 건 bootstrap에서 navbar처음양식을 가지고와서, 필요없는 부분은 잘라내고 쓴다.

<%@ tag language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>

<c:url value="/board/list" var="listUrl"></c:url>
<c:url value="/board/register" var="registerUrl"></c:url>

<nav class="navbar navbar-expand-lg navbar-light bg-light">

    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" href="${listUrl }">목록</a>
      </li>
      <li class="nav-item active">
        <a class="nav-link" href="${registerUrl }">글쓰기</a>
      </li>
    </ul>
</nav>

 

/list.jsp와 get.jsp에 taglib을 넣은 후에, 아래 에 <b:navBar></b:navBar> 을 넣었고 그에 따라서

바로 화면 위에, 목록과 글쓰기를 편하게 왔다 갔다 할 수 있도록 만들었다

(navbar)라고 넣으니까, 인식을 잘 못한다 실수 하지 않도록 주의할 것 !

 

/이제 글쓰기 누르면 글쓰기 칸 만들 수 있게 합시다!

jsp에 맞춰서 postmapping형태로 작성하기 시작

jsp에 namevalue로 작성한게 쌍으로 넘어간다! BoardVO라는 bean에 담아주는걸 직접 request분석 가공없이,

business logic만 신경써서 작성해주면 된다.

board를 작성하고 그 걸 가져와서, 쓰자

 

한글을 쓰게 하기 위해서 web.xml에 필터를 추가했다.

  <filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encoding</filter-name>
    <servlet-name>appServlet</servlet-name>
  </filter-mapping>

/get.jsp에 수정 및 삭제 버튼 추가

보고있는 게시물 자체를 수정해야하니까, btn에 상대경로를 추가했다.

controller modify는 get과 같아서, getmapping에다가 modify를 추가하고, {}로 묶어 줬다.

 

/modify.jsp추가하기

jsp의 기본 틀은 get과 같지만, 제일 크게 다른 점은 primary key인 id가 존재하기 때문에, 게시물의 번호도 같이 전달을 해줘야된다는 점이다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="b" tagdir="/WEB-INF/tags/board"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<link rel="stylesheet" href="<%=request.getContextPath()%>/resource/css/icon/css/all.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">

<title>Insert title here</title>
</head>
<body>
	<b:navBar></b:navBar>
	<!-- .container>.row>.col>h1{게시물 작성} -->
	<div class="container">
		<div class="row">
			<div class="col">
				<h1>게시물 수정</h1>
				<!-- form>.form-group*3>label[for=input$]+input.form-control#input$ -->
				<form method="post">
					<!-- input:hidden[value][name=id] -->
					<input type="hidden" name="id" value="${board.id }">
					<div class="form-group">
						<label for="input1">제목</label>
						<input type="text" class="form-control" value="${board.title }" id="input1" name="title">
					</div>
					<div class="form-group">
						<label for="input2">내용</label>
						<textarea class="form-control" id="input2" name="content">${board.content}</textarea>
					</div>
					<div class="form-group">
						<label for="input3">작성자</label>
						<input type="text" class="form-control" id="input3" name="writer" readonly >
					</div>
					<button class="btn btn-outline-primary" type="submit">수정</button>
				</form>
			</div>
		</div>
	</div>
	<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>
</body>
</html>

그리고 기본 값에 , 우리가 미리 넣어놨던 게시물과 내용이 들어가 있어야 하기 때문에, value값을 추가해야한다.

작성자는 수정을 못하게 하기 위해서 readonly로 가져왔당

그리고 controller에 가서, modify 로 오는 식이 없어서 추가해줬다.

 

redirectattribute에 잘 되었다는 정보를 result로 전달해주었다.

	@PostMapping("/modify")
	private String modify(BoardVO board, RedirectAttributes rttr) {
		if(service.modify(board)) {
			rttr.addFlashAttribute("result", "success");
		}
		// 게시물 조회로 redirect
		/*
		 * rttr.addAttribute("id", board.getId());
		 * return "redirect:/board/get";
		 */

		// 목록 조회로 redirect
		return"redirect:/board/list";
	}

/ 게시물 수정 및 삭제 에서 삭제 할 수 있게 만들기 (컨트롤러 먼저만들었음)

	@PostMapping("/remove")
	public String remove(@RequestParam("id") Integer id, RedirectAttributes rttr) {

		if (service.remove(id)) {
			rttr.addFlashAttribute("result", id + "번 게시글이 삭제되었습니다.");
		}
		return "redirect:/board/list";
	}

그 다음에 modify.jsp 수정합시다.

삭제버튼을 누르면 form의 action attribute값이 변경되어야 한다. 이런일을 처리하는것 -> java script...가해야한다..

기억도안나는 자바스크립트뭐여~

와 자바스크립트는 들어도 무슨소린지 잘모르겠다...?

음. 선생님이 하시는말들을 죽죽 적어내려가보도록하자

 

removeSubmitButton을 클릭했을 때, modyfyForm의 어트리뷰트인 action이 remove로 변경되어야한다.는 것

 그 다음에 submit이 이루어져야한다.

근데, submit이 일어나는 일과 click되면 벌어나는 일이 다른 스레드에서 같이 일어나기 때문에, 삭제 버튼을 눌렀을 때, 더이상 진행되게 하지 않도록 하는 것이 필요하다 그래서 사용한것 : prevent객체

수정버튼을 눌렀을 때도, modify로 가야하기 때문에, 유사한 일이 일어나도록 미리 식을 짜놓자.

 

/list.jsp 에 모달 작성하기!

<!-- modal -->
	<c:if test="${not empty result }">
		<div class="modal" tabindex="-1" id="modal1">
			<div class="modal-dialog">
				<div class="modal-content">
					<div class="modal-header">
						<h5 class="modal-title">처리 결과</h5>
						<button type="button" class="close" data-dismiss="modal" aria-label="Close">
							<span aria-hidden="true">&times;</span>
						</button>
					</div>
					<div class="modal-body">
						<p>${result }</p>
					</div>
					<div class="modal-footer">
						<button type="button" class="btn btn-secondary" data-dismiss="modal">닫기</button>
					</div>
				</div>
			</div>
		</div>
	</c:if>
하고
script부분에 
	<script>
	$(document).ready(function(){
		$("#modal1").modal('show');
	});
	</script>
    추가

수정했을 때, result attribute를 추가했기때문에, result라는 어트리뷰트가 있을 때만, 모달이 존재하면 된다.

아이 정말 쉽지않넹~

 

/ 우선 모달 표시까지는 끝났고, 뒤로가기했을 때 모달이 뜨는게 싫어서 그부분을 날려보낼 수있게 해보자

history에서 state에 흔적이 남아있다면, 모달이 뜨지 않게 처리해보기~

history.state가 null일 때만, 코드를 남기게 하자.

  <script>
      $(document).ready(function() {

        if (history.state == null) {
          $("#modal1").modal('show');
          history.replaceState({}, null);
        }
      });
    </script>

728x90