본문 바로가기
멀티캠퍼스 풀스택 과정/백엔드

Spring:10 게시판 리스트 글 등록하고 보여주고 조회수증가 -2

by 이쟝 2022. 3. 18.

1. 글을 DB에 등록하기 위해서 boardInsert( ) 메서드를 생성하고 DB 등록

1. Mapper.xml에 쿼리문 생성한다. 

insert는 반환형이 int!! 클라이언트로부터 데이터를 받아서 BulletinBrdVO안에 저장되어서 넘어온다. 

bltnBrdMapper.xml  

<?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.mycampus.myappy.dao.BulletinBrdDAO">
	<insert id="boardInsert">
		insert into board(subject, content, userid, ip)
		value(#{subject},#{content},#{userid},#{ip})
	</insert>
</mapper>

2. DAO에 등록해주는 boardInsert( ) 생성한다.

package com.mycampus.myappy.dao;

import com.mycampus.myappy.vo.BulletinBrdVO;

public interface BulletinBrdDAO {
	// 글등록(DB연결)
	public int boardInsert(BulletinBrdVO vo); // 클라이언트가 입력한 정보
}

3. BulletinService에 boardInsert(  ) 생성한다.

package com.mycampus.myappy.service;

import com.mycampus.myappy.vo.BulletinBrdVO;

public interface BulletinBrdService {
	//글 등록(DB)
	public int boardInsert(BulletinBrdVO vo);
}

 

4. BulletinServiceImpl에 BulletinService를 구현하기 위한 boardInsert( )를 생성한다. 

package com.mycampus.myappy.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mycampus.myappy.dao.BulletinBrdDAO;
import com.mycampus.myappy.vo.BulletinBrdVO;

@Service
public class BulletinBrdServiceImpl implements BulletinBrdService {

	@Autowired
	BulletinBrdDAO dao;
	
	@Override
	public int boardInsert(BulletinBrdVO vo) {
		return dao.boardInsert(vo);
	}

}

5. Controller로 Mapping 한다. 

bulletinBrdWrite.jsp 

글 등록 폼에서 등록을 누르면 action이 실행되게 한다! 
<h1>글 등록 폼</h1>
<form method="post" action="/myappy/board/bulletinBrdWriteOk" id="boardFrm">

BulletinBrdController.jsp

ResponseEntity란? 
- ResponseEntity는 사용자의 HttpRequest에 대한 응답 데이터를 포함하는 클래스이다.
- ResponseEntity는 HttpEntity를 상속 받음으로써 HttpStatus, HttpHeaders, HttpBody를 포함한다. 
- 기본적으로 Body, Headers, Status 코드를 기준으로 작성을 한다.
- 객체로 생성 시 Status 코드는 필수 값이다.
- 제네릭을 사용해서 Body의 타입을 지정할 수 있습니다.
package com.mycampus.myappy.controller;

@RestController // @Controller + @ResponseBody
@RequestMapping("/board/*")
public class BulletinBrdController {
	
	@Autowired
	BulletinBrdService service;

	// 글 등록 하기(DB)
	@PostMapping("bulletinBrdWriteOk")
	public ResponseEntity<String> boardWriteOk(BulletinBrdVO vo, HttpServletRequest request){
		vo.setIp(request.getRemoteAddr());  // 접속자 아이피(request로 주소를 구한다음에 vo의 ip컬럼에 현재 접속자의 ip를 넣어준다.) 

		// 글쓴이 session 로그인 아이디를 구한다.(현재 로그인한 유저와 같아야 한다.) 
		vo.setUserid((String)request.getSession().getAttribute("logId"));
		
		ResponseEntity<String> entity = null; // 데이터와 처리 상태를 가진다. 
		
		// 한글인코딩(UTF-8지원하기)
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-Type", "text/html; charset=utf-8");
	
		try {
			service.boardInsert(vo); // boardInsert 메서드 실행
			
			// 등록성공 (bulletinBrdWriteOk.jsp를 따로 만들지 않고 script로 실행한다.)
			String msg = "<script>alert('글이 등록되었습니다.');";
			msg += "location.href='/myappy/board/bulletinBrdList';</script>";
			entity = new ResponseEntity<String>(msg, headers,HttpStatus.OK); //200
			
		}catch(Exception e) {
			e.printStackTrace();
			// 등록 실패
			String msg = "<script>alert('글등록에 실패했습니다.로그인해주세요');";
			msg += "history.back();</script>";
			entity = new ResponseEntity<String>(msg, headers, HttpStatus.BAD_REQUEST); //400
		}
		return entity;
	}
}
더보기
// 한글인코딩(UTF-8지원하기)
HttpHeaders headers = new HttpHeaders();

//(1)		
headers.add("Content-Type", "text/html; charset=utf-8");

//(2)
Charset utf8 = Charset.forName("UTF-8");
MediaType mediaType = new MediaType("text","html", utf8);
headers.setContentType(mediaType);

//(3)
headers.setContentType(new MediaType("text","html",Charset.forName("UTF-8")));
vo.setIp(request.getRemoteAddr());

- Spring MVC 기반의 서버에서 개발할 때에 컨트롤러에서 받은 HttpServletRequest 객체를 사용하면 간단하게 IP를 얻을 수 있다. r(equest.getRemoteAddr()로 클라이언트의 ip를 얻어올 수 있다.)

- 하지만 얻어온 정보는 0:0:0:0:0:0:0:1로, 이는 IPv6 형식의 값이다. 대부분의 프로젝트에서 원하는 IP 형식은 우리가 흔히 아는 127.0.0.1과 같은 IPv4 형식의 값일 것이다.
- 이를 위해서는 서버 구동 시 vm arguments로 -Djava.net.preferIPv4 Stack=true를 주면 IPv4형식을 얻을 수 있다.

[프로젝트 우클릭 > Run configurations > 왼쪽 메뉴 상단 Tomcat v9.0 Server 클릭 > Arguments > VM arguments에 -Djava.net.preferIPv4 Stack=true를 추가하고 apply 하고 close]


- vm arguments를 준 뒤 가져온 ip는 IPv4 형식임을 확인할 수 있다.


2. 등록된 글을 게시판 리스트에서 확인할 수 있게 한다. 

1. DB에서 데이터를 가져오기 위해서 쿼리문을 작성한다. 

Mapper.xml에 쿼리문 생성한다. 

- select는 resultType이 필요하다. BulletinBrdVO객체로 DB에서 데이터가 넘어온다. 
- select no, subject, userid, views, date_format(writedate, '%m/%d %H:%i') writedate from board order by no desc

bltnBrdMapper.xml 

<?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.mycampus.myappy.dao.BulletinBrdDAO">
	<select id="boardList" resultType="com.mycampus.myappy.vo.BulletinBrdVO">
		select no, subject, userid, views, date_format(writedate, '%m/%d %H:%i') writedate
		from board order by no desc
	</select>
</mapper>

2. DAO, Service, ServiceImpl에 게시판 리스트를 볼 수 있는 boardList( ) 생성한다.

객체 BulletinBrdVO를 List형식으로 서버에서 가져온다. 
package com.mycampus.myappy.dao;
import java.util.List;
import com.mycampus.myappy.vo.BulletinBrdVO;

public interface BulletinBrdDAO {
	//게시판 리스트 보기
	public List<BulletinBrdVO> boardList(BulletinBrdVO vo);
}
package com.mycampus.myappy.service;
import java.util.List;
import com.mycampus.myappy.vo.BulletinBrdVO;
public interface BulletinBrdService {

	//게시판 리스트 보기
	public List<BulletinBrdVO> boardList(BulletinBrdVO vo);
}
package com.mycampus.myappy.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mycampus.myappy.dao.BulletinBrdDAO;
import com.mycampus.myappy.vo.BulletinBrdVO;

@Service
public class BulletinBrdServiceImpl implements BulletinBrdService {

	@Autowired
	BulletinBrdDAO dao;
    
	@Override
	public List<BulletinBrdVO> boardList(BulletinBrdVO vo) {
		return dao.boardList(vo);
	}
}

3. Controller에서 미리 만들어놓았던 List맵핑 주소에 연결한다.

BullentinBrdController

- mav.addObject("list", service.boardList(vo); 를 추가해준다. 
- 리스트에 표시하기 위해서 vo(리스트)를 매개변수로 받는다. 
	@Autowired
	BulletinBrdService service;
	
	// board/bulletinBrdList 맵핑주소
	@GetMapping("bulletinBrdList")
	public ModelAndView boardList(BulletinBrdVO vo) {
		ModelAndView mav = new ModelAndView();
		mav.addObject("list", service.boardList(vo));
		mav.setViewName("board/bulletinBrdList");
		return mav;
	}

bullentinBrdList.jsp

mav에서 설정한 list는 <c:forEach>의 items과 동일해야 하고, var는 데이터를 받아올 수 있는 vo객체여야 한다.
제목을 누르면 a 태그로 인해서 bulletinBrdView로 이동해야 한다.(무슨 번호의 글인지의 데이터를 가지고)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<link rel="stylesheet" href="/myappy/css/bulletinBrdListStyle.css" type="text/css"/>
<div class="container">
	<h1>게시판 목록</h1>
	<div><a href="<%=request.getContextPath()%>/board/bulletinBrdWrite">글쓰기</a></div>
	<br>
	<ul class="boardList">
		<li>번호</li>
		<li>제목</li>
		<li>작성자</li>
		<li>조회수</li>
		<li>등록일</li>
	
		<c:forEach var="vo" items="${list}">
			<li>${vo.no}</li>
			<li><a href="/myappy/board/bulletinBrdView?no=${vo.no}">${vo.subject}</a></li>
			<li>${vo.userid}</li>
			<li>${vo.views}</li>
			<li>${vo.writedate}</li>
		</c:forEach>
	</ul>
</div>


3. 제목을 클릭하면 게시판 글 내용을 볼 수 있게 해 준다. 

1. DB 쿼리문을 작성한다.

- 매개변수로 pk인 번호(no)가 서버로 넘어가서 VO객체로 넘어온다. 
- select no, subject, content, userid, views, writedate from board where no=사용자가 클릭한 레코드 넘버(no)
<?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.mycampus.myappy.dao.BulletinBrdDAO">
	<select id="boardSelect" resultType="com.mycampus.myappy.vo.BulletinBrdVO">
		select no, subject, content, userid, views, writedate 
		from board where no=#{param1}
	</select>
</mapper>

 

2. DAO, Service, ServiceImpl에 게시판 글을 볼 수 있는 boardSelect( ) 생성한다.

package com.mycampus.myappy.dao;
import com.mycampus.myappy.vo.BulletinBrdVO;
public interface BulletinBrdDAO {
	// 게시판 글1개 보기
	public BulletinBrdVO boardSelect(int no); // 레코드 번호를 가지고 DB에서 select
}
package com.mycampus.myappy.service;
import com.mycampus.myappy.vo.BulletinBrdVO;
public interface BulletinBrdService {
	// 게시판 글1개 보기
	public BulletinBrdVO boardSelect(int no);
}
package com.mycampus.myappy.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mycampus.myappy.dao.BulletinBrdDAO;
import com.mycampus.myappy.vo.BulletinBrdVO;

@Service
public class BulletinBrdServiceImpl implements BulletinBrdService {

	@Autowired
	BulletinBrdDAO dao;

	@Override
	public BulletinBrdVO boardSelect(int no) {
		return dao.boardSelect(no);
	}
}

3. Controller에서 bulletinBrdView를 맵핑 주소로 연결한다.

BullentinBrdController

bulletinBrdList에서 제목을 누르면 bulletinBrdView로 넘어가게 한다. 
"vo"는 데이터를 가져오기 위한 임의의 변수명이고, service안에 있는 boardSelect에서 레코드를 가지고 데이터를 가지고 온다.
	// 글 내용 보기
	@GetMapping("bulletinBrdView")
	public ModelAndView boardView(int no) { // 레코드값(no)만 클라이언트에서 가져오기
		 ModelAndView mav = new ModelAndView();
		 mav.addObject("vo", service.boardSelect(no));
		 mav.setViewName("/board/bulletinBrdView");
		 return mav;
	}

4. 게시판 글 내용 폼인 bulletinBrdView 파일 생성한다. 

vo는 controller에서 addObject로 했던 임의의 변수를 사용하고 뒤에는 BulletinBrdVO와 동일한 변수명으로 DB에서 데이터를 가지고 온다. 
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<div class="container">
	<h1>글내용보기</h1>
	<ul>
		<li>번호: ${vo.no}</li>
		<li>작성자 : ${vo.userid}</li>
		<li>작성일 : ${vo.writedate}</li>
		<li>조회수 : ${vo.views}</li>
		<li>제목 : ${vo.subject}</li>
		<li>글내용</li>
		<li>${vo.content}</li>
	</ul>
</div>

4. 등록된 글을 볼 때마다 조회수를 자동으로 카운트해준다. 

1. DB 쿼리문을 작성한다. 

- 매개변수로 pk인 번호(no)가 서버로 넘어가서 서버에서 views+1을 해준다.
- 데이터를 변경해야 하니까 update문을 사용한다.  
- update board set views=views+1 where no=등록된 글의 번호(no)

bltnBrdMapper.xml 

<?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.mycampus.myappy.dao.BulletinBrdDAO">
	<update id="viewsCount">
		update board set views=views+1 where no=#{param1}
	</update>
</mapper>

2. DAO, Service, ServiceImpl에 조회수를 세는 viewsCount( ) 생성한다.

package com.mycampus.myappy.dao;
public interface BulletinBrdDAO {
	//조회수 카운트
	public void viewsCount(int no);
}
package com.mycampus.myappy.service;
public interface BulletinBrdService {
	//조회수 카운트
	public void viewsCount(int no);
}
package com.mycampus.myappy.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mycampus.myappy.dao.BulletinBrdDAO;

@Service
public class BulletinBrdServiceImpl implements BulletinBrdService {

	@Autowired
	BulletinBrdDAO dao;
    
	@Override
	public void viewsCount(int no) {
		dao.viewsCount(no);
	}
}

3. Controller에서 맵핑 주소로 연결한다.

위에서 사용했던 boardView( )를 사용한다. service.viewCount(no);를 추가한다.
	// 글 내용 보기
	@GetMapping("bulletinBrdView")
	public ModelAndView boardView(int no) { // 레코드값(no)만 클라이언트에서 가져오기
		 ModelAndView mav = new ModelAndView(); 
		 service.viewsCount(no);
		 mav.addObject("vo", service.boardSelect(no));
		 mav.setViewName("/board/bulletinBrdView");
		 return mav;
	}