Spring-MyWeb SNS 게시판

정원·2022년 6월 27일

Spring-MyWeb

목록 보기
13/16

22.06.27 snsboard 테이블 생성,등록하기,목록띄우기

snsboard 테이블 생성

-- SNS 게시판
CREATE TABLE snsboard (
    bno NUMBER(10,0) PRIMARY KEY,
    writer VARCHAR2(50) NOT NULL,
    uploadpath VARCHAR2(100) NOT NULL,
    fileloca VARCHAR2(100) NOT NULL,
    filename VARCHAR2(50) NOT NULL,
    filerealname VARCHAR2(50) NOT NULL,
    content VARCHAR2(2000),
    regdate DATE DEFAULT sysdate
);

CREATE SEQUENCE snsboard_seq
    START WITH 1
    INCREMENT BY 1
    MAXVALUE 1000
    NOCYCLE
    NOCACHE;

SnsBoardVO

<script>
package com.spring.myweb.command;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class SnsBoardVO {
	
	private int bno;
	private String writer;
	private String uploadpath;
	private String fileloca;
	private String filename;
	private String filerealname;
	private String content;
	private Timestamp regdate;
}
</script>

ISnsBoardMapper

package com.spring.myweb.snsboard.mapper;

public interface ISnsBoardMapper {
	
	//등록
	void insert(SnsBoardVO vo);
	
	//목록
	List<SnsBoardVO> getList(PageVO paging);
	
	//상세
	SnsBoardVO getDetail(int bno);
	
	//삭제
	void delete(int bno);
}

db-config.xml

db-config에 mapper 등록

<mybatis-spring:scan base-package="com.spring.myweb.freeboard.mapper"/>
<mybatis-spring:scan base-package="com.spring.myweb.reply.mapper"/>
<mybatis-spring:scan base-package="com.spring.myweb.user.mapper"/>
<mybatis-spring:scan base-package="com.spring.myweb.snsboard.mapper"/>

SnsBoardMapper

<?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.spring.myweb.snsboard.mapper.ISnsBoardMapper">
	
</mapper>

ISnsBoardService

package com.spring.myweb.snsboard.service;
public interface ISnsBoardService {

	//등록
	void insert(SnsBoardVO vo);

	//목록
	List<SnsBoardVO> getList(PageVO paging);

	//상세
	SnsBoardVO getDetail(int bno);

	//삭제
	void delete(int bno);
}

SnsBoardService

package com.spring.myweb.snsboard.service;

@Service
public class SnsBoardService implements ISnsBoardService {
	
	@Autowired
	private ISnsBoardMapper mapper;
	
	@Override
	public void insert(SnsBoardVO vo) {

	}

	@Override
	public List<SnsBoardVO> getList(PageVO paging) {
		return null;
	}

	@Override
	public SnsBoardVO getDetail(int bno) {
		return null;
	}

	@Override
	public void delete(int bno) {

	}
}

snsList.jsp

로그인 안한 사람이라면 로그인 진행될수 있게 한다.

<div class="menu1">
	<c:choose>
		<c:when test="${login != null}">
			<p>
			<img src="../resources/img/profile.png"> &nbsp;&nbsp; ${login.userName}님
			</p>
			<ul>
				<li>내정보</li>
				<li>내쿠폰</li>
				<li>내좋아요게시물</li>
			</ul>
		</c:when>
		<c:otherwise>
			<button type="button" class="btn btn-info" onclick="location.href=<c:url value='/user/userLogin'/>">로그인</button>
		</c:otherwise>
	</c:choose>
</div>

비동기 파일 업로드(등록하기)

form태그 없이 비동기로 form데이터 보내기

snsList.jsp

<script>
$(function() {
	
	//등록하기 버튼 클릭 이벤트
	$('#uploadBtn').click(function() {
		regist();
	});
	
	//등록을 담당하는 함수
	function regist() {
		//세션에서 현재 로그인 중인 사용자 정보(아이디)를 얻어오기
		const user_id = '${sessionScope.login.userId}'
		//자바스크립트의 파일 확장자 체크 검색.
		let file = $('#file').val();
		
		console.log(user_id); //kim1234
		console.log(file); //C:\fakepath\sky.jpg
		//.을 제거한 확장자만 얻어낸 후 그것을 소문자로 일괄 변경
		file = file.slice(file.indexOf('.')+1).toLowerCase();
		console.log(file); //jpg
		
		if(file !== 'jpg' && file !== 'png' && file !== 'jpeg' && file !== 'bmp'){
			alert('이미지 파일(jpg,png,jpeg,bmp)만 등록이 가능합니다.');
			$('#file').val(''); //input창 비우기
			return;
		} else if(user_id === ''){ //세션 데이터가 없다 -> 로그인 X
			alert('로그인인 필요한 서비스 입니다.');
			return;
		}
		
		//ajax 폼 전송의 핵심 FormData 객체.
		const formData = new FormData();
		const data = $('#file');
		
		console.log('폼데이터: ' + formData);
		console.log('data: ' + data);
		console.log(data[0]); //input type="file" 요소를 지목할 때 사용.
		console.log(data[0].files); //파일 태그에 담긴 파일 정보를 확인하는 키값.
		console.log(data[0].files[0]); //사용자가 등록한 최종 파일 정보
		/*
		data[index] -> 파일 업로드 버튼이 여러개 존재할 경우 요소의 인덱스를 지목해서 가져오는 방법.
		우리는 요소를 id로 취득했기 때문에 하나만 찍히지만, class 이름 같은 걸로 지목하면 여러개가 취득되겠죠?
		files[index] -> 파일이 여러 개 전송되는 경우, 몇 번째 파일인지를 지목.
		우리는 miltiple 속성을 주지 않았기 때문에 0번 인덱스 밖에 없는 겁니다.
		*/
		
		//FormData 객체에 사용자가 업로드한 파일의 정보다 들어있는 객체를 전달해야한다.
		formData.append('file', data[0].files[0]);
		//formData.append('file', data[0].files[1]); //miltiple사용했을 경우 파일마다 정보를 넣어준다.
		//content(글 내용) 값을 얻어와서 폼 데이터에 추가
		const content = $('#content').val();
		formData.append('content', content);
		
		//비동기 방식으로 파일 업로드 및 게시글 등록을 진행
		$.ajax({
			url: '<c:url value="/snsBoard/upload"/>',
			type: 'post',
			data: formData, //폼 데이터 객체를 넘깁니다.
			contentType: false,
			//ajax 방식에서 파일을 넘길 때는 반드시 false로 처리 -> "multipart/form-data"로 선언됨.
			processData: false, //폼 데이터를 &변수=값&변수=값..형식으로 변경되는 것을 막는 요소
			success: function(result) {
				if(result === 'success'){
					$('#file').val(''); //파일 선택지 비우기
					$('#content').val(''); //글 영역 비우기
					$('.fileDiv').css('display', 'none'); //미리보기 감추기
					getList(1, true); //글 목록 함수 호출.
				} else {
					alert('업로드에 실패했습니다. 관리자에게 문의해 주세요.');
				}
			},
			error: function(request, status, error) {
				console.log('code: ' + request + '\n message: ' + request.responseText + "\n" + 'error: ' + error);
				alert('업로드에 실패했습니다. 관리자에게 문의해 주세요.');
			}
		});
	}
}); //end jQuery
</script>

SnsBoardController

<script>
@PostMapping("/upload")
@ResponseBody
public String upload(MultipartFile file, String content, HttpSession session) {
		
	String writer = ((UserVO)session.getAttribute("login")).getUserId();
		
	//날짜별로 폴더를 생성해서 파일을 관리
	SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	Date date = new Date();
	String fileloca = sdf.format(date);
		
	//저장할 폴더 경로
	String uploadPath = "C:\\Users\\jwons\\OneDrive\\바탕 화면\\upload\\" + fileloca;
	File folder = new File(uploadPath);
	if(!folder.exists()) {
		folder.mkdirs(); //폴더가 존재하지 않는다면 생성하라.
	}
		
	//원본 파일명.
	String fileRealName = file.getOriginalFilename();
		
	//파일명을 고유한 랜덤 문자로 생성.
	UUID uuid = UUID.randomUUID();
	String uuids = uuid.toString().replaceAll("-", ""); //'-'다 삭제
		
	//확장자를 추출합니다.
	String fileExtension = fileRealName.substring(fileRealName.indexOf("."), fileRealName.length());
		
	System.out.println("저장할 폴더 경로: " + uploadPath);
	System.out.println("실제 파일명: " + fileRealName);
	System.out.println("폴더 명: " + fileloca);
	System.out.println("확장자: " + fileExtension);
	System.out.println("고유랜덤문자 : " + uuids);
		
	String fileName = uuids + fileExtension;
	System.out.println("변경해서 저장할 파일명: " + fileName);
		
	//업로드한 파일을 서버 컴퓨터 내의 지정한 경로에 실제로 저장.
	File saveFile = new File(uploadPath + "\\" + fileName);
	try {
		file.transferTo(saveFile);
	} catch (Exception e) {
		e.printStackTrace();
	}
		
	//DB에 insert 작업을 실행.
	SnsBoardVO snsVO = new SnsBoardVO(0, writer, uploadPath, fileloca, fileName, fileRealName, content, null);
	service.insert(snsVO);
		
	return "success";
}
</script>

SnsBoardService

@Override
public void insert(SnsBoardVO vo) {
	mapper.insert(vo);
}

SnsBoardMapper

<!-- 등록하기 -->
<insert id="insert">
	INSERT INTO snsboard
	(bno, writer, uploadpath, fileloca, filename, filerealname, content)
	VALUES(snsboard_seq.NEXTVAL, #{writer}, #{uploadpath}, #{fileloca}, #{filename}, #{filerealname}, #{content})
</insert>

목록띄우기

snsList.jsp

<script>
//리스트 작업
let str = '';
let page = 1;
getList(1, true);

function getList(page, reset) {
	if(reset === true){
		str = ''; //화면 리셋 여부가 true라면 str변수를 초기화.
	}
	
	$.getJSON(
		'<c:url value="/snsBoard/getList?pageNum=' + page + '" />',
		function(list) {
			console.log(list);
			
			for(let i=0; i<list.length; i++){
				str +=
					`<div class="title-inner">
					<!--제목영역-->
					<div class="profile">
						<img src="<c:url value='/img/profile.png'/>">
					</div>
					<div class="title">
						<p>` + list[i].writer + `</p>
						<small>` + timeStamp(list[i].regdate) +`</small> &nbsp;&nbsp;
						<a href="">이미지 다운로드</a>
					</div>
				</div>
				<div class="content-inner">
					<!--내용영역 내용은 NOT NULL이 아니라서 삼항연산식을 이용해서 검사-->
					<p>` + (list[i].content === null ? '' : list[i].content) +`</p>
				</div>
				<div class="image-inner">
					<!-- 이미지영역 -->
					<img src="<c:url value='/snsBoard/display?fileLoca=` + list[i].fileloca + `&fileName=` + list[i].filename + `'/>">
					
				</div>
				<div class="like-inner">
					<!--좋아요-->
					<img src="../resources/img/icon.jpg"> <span>522</span>
				</div>
				<div class="link-inner">
					<a href="##"><i class="glyphicon glyphicon-thumbs-up"></i>좋아요</a>
					<a href="##"><i class="glyphicon glyphicon-comment"></i>댓글달기</a> 
					<a href="##"><i class="glyphicon glyphicon-remove"></i>삭제하기</a>
				</div>
				</div>`;
				$('#contentDiv').html(str);
			} //end for
		}
	);//end getJSON
}//end getList()
</script>

SnsBoardController

//비동기 통신 후 가져올 글 목록
@GetMapping("/getList")
@ResponseBody
public List<SnsBoardVO> getList(PageVO paging){
	paging.setCpp(3);
	return service.getList(paging);
}

SnsBoardService

@Override
public List<SnsBoardVO> getList(PageVO paging) {
	return mapper.getList(paging);
}

mybatis-config.xml

SnsBoardVO 별칭 추가

<typeAliases>
	<typeAlias type="com.spring.myweb.command.UserVO" alias="user" />
	<typeAlias type="com.spring.myweb.command.ReplyVO" alias="reply" />
	<typeAlias type="com.spring.myweb.command.FreeBoardVO" alias="board" />
	<typeAlias type="com.spring.myweb.command.SnsBoardVO" alias="sns" />
</typeAliases>

SnsBoardMapper

<!-- 글 전체 목록 -->
<select id="getList" resultType="sns">
	SELECT * FROM	
		(
		SELECT ROWNUM AS rn, tbl.* FROM
			(
			SELECT * FROM snsboard
			ORDER BY bno DESC
			) tbl
		)
	<![CDATA[
	WHERE rn > (#{pageNum}-1) * #{cpp}
	AND rn <= #{pageNum} * #{cpp}
	]]>
</select>

0개의 댓글