[11/1] 게시판 작성, 게시판 상세조회(게시글만), 아이디 저장 쿠키, 회원가입 동의

2022. 11. 1. 14:20·📗 self-study/📗 KH정보교육원 당산지원

<게시판>

🤦🏻‍♀️ 게시판 작성

더보기

1. BoardEnrollFormController (URL mapping: /enrollForm.bo)

자유게시판 작성 페이지를 띄우기만 할 용도

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// 게임 태그를 작성하기 위해(선택사항) 게임 테이블로부터 전체 게임을 조회해서 request에 담기
		ArrayList<Game> list = new BoardService().selectGameList();
		request.setAttribute("list", list);
		
		// 자유게시판 작성 페이지를 띄우기만 할 용도
		request.getRequestDispatcher("views/board/boardEnrollForm.jsp").forward(request, response);
	}

 

2. boardEnrollForm.jsp 글 작성 폼

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="com.insertcoin.member.model.vo.Member" %>
<%
	String contextPath = request.getContextPath();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
    <title>회원가입</title>

    <!-- CSS 스타일시트 -->
    <link href="resources/css/MemberEnrollForm.css" rel="stylesheet">
    <link href="resources/css/MainCss.css" rel="stylesheet">
    <link href="resources/css/MainContentCss.css" rel="stylesheet">

    <!-- jQuery 라이브러리 연결 -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>

    <!-- Bootstrap 프레임워크 연결 -->
    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
    <!-- Popper JS -->
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
    <!-- Latest compiled JavaScript -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
</head>

<body>

        <!-------------------------------------- 컨텐츠 영역 -------------------------------------->

        <!-- 컨텐츠 영역 -->
        <div class="content_container">

            <!-- 회원가입 창 -->
            <form id="enroll_form" action="<%= contextPath %>/enroll.me" method="post">

                <!-- 로고, 이메일, 인증번호, 비밀번호/확인, 닉네임 입력 영역 -->
                <div class="enroll_content">
                    <!-- 회원가입 창 로고 -->
                    <div style="text-align:center;">
                        <img src="resources/image/logo/insertcoin_logo.png" alt="insert_coin_logo" id="enroll_logo">
                    </div>
                    <!-- 회원가입 글자 -->
                    <div id="enroll_text"><h3>회원가입</h3><hr></div>

                    <!-- 로그인 정보 입력 폼 -->
                    <table align="center" id="enroll_table">
                        
                        <tr>
                            <th>이메일</th>
                        </tr>
                        <tr>
                            <th colspan="6">
                                <input type="email" name="memEmail" maxlength="30" onchange="emailCheck();" required> <br>
                            </th>
                        </tr>
                        <tr>
                            <td colspan="6">
                                <div><label id="emailCheckOutput"></label></div>
                            </td>
                        </tr>
                        <tr>
                            <th colspan="4">
                                <input type="text" name="certification_num" placeholder="인증번호를 입력하세요." required><br>
                                <div class="superscript">인증번호는 최대 10분간만 유효합니다.</div>
                                <td><button class="table_button_cert">요청</button></td>
                                <td><button class="table_button_cert">확인</button></td>
                            </th>
                            
                        </tr>
                        <tr>
                            <th colspan="6">비밀번호</th>
                        </tr>
                        <tr>
                            <th colspan="6">
                                <input type="password" class="pwd" id="pwd1" minlength="8" maxlength="16" required>
                            </th>
                        </tr>
                        <tr>
                            <th colspan="6">비밀번호 확인</th>
                        </tr>
                        <tr>
                            <th colspan="6">
                                <input type="password" class="pwd" id="pwd2" minlength="8" maxlength="16" required>
                            </th>
                        </tr>
                        <tr>
                            <th colspan="6">
                           		<div><label id="pwdCheckOutput"></label></div>
                            </th>
                        </tr>
                        <tr>
                            <th colspan="6">닉네임</th>
                        </tr>
                        <tr>
                            <th colspan="6">
                                <input type="text" name="memNickname" id="memNickname" minlength="2" maxlength="10" onchange="nicknameCheck();" required>
                            </th>
                        </tr>
                        <tr>
                            <td colspan="6">
                                <div><label id="nicknameCheckOutput"></label></div>
                            </td>
                        </tr>
                        <tr>
                            <!-- 가입하기 버튼 버튼 -->
                            <th colspan="6"><button type="submit" id="enroll_button">가입하기</button></th>
                        </tr>
                    </table>
                </div>
            </form>
        </div>
        
        <%@ include file = "../../views/common/footer.jsp" %>

        <script>
        	// 아이디 중복 체크용 제이쿼리
        	function emailCheck() {
        		var $memEmail = $("#enroll_table input[name=memEmail]");
        		
        		$.ajax({
        			url : "emailCheck.me",
        			data : {checkEmail : $memEmail.val()},
        			success : function(result) {
        				
        				// result 값은 "possible" 또는 "impossible"
        				if(result == "impossible") {
        					
        					$("#emailCheckOutput").text("이미 존재하는 아이디이므로 사용할 수 없습니다.").css("color","red").css("font-size","12px");
        					$memEmail.val("");
        					$memEmail.focus();
        					
        				} else {
        					
        					$("#emailCheckOutput").text("사용 가능한 아이디입니다!").css("color","rgb(232, 183, 34)").css("font-size","12px");
        					
        				}
        				
        			},
        			error : function () {
        				console.log("이메일 중복 체크용 ajax 통신 실패!");
        			}

        		});
        	}
        	
        	// 닉네임 중복 체크용 제이쿼리
        	function nicknameCheck() {
        		var $memNickname = $("#enroll_table input[name=memNickname]");
        		let nickname = $("#memNickname").val();
        		let regNickname = /^[a-zA-Z0-9ㄱ-ㅎ가-힣]{2,10}$/;
        		
        		$.ajax({
        			url : "nicknameCheck.me",
        			data : {checkNickname : $memNickname.val()},
        			success : function(result) {
        				
        				// result 값은 "possible" 또는 "impossible"
        				if(result == "impossible") {
        					
        					$("#nicknameCheckOutput").text("이미 존재하는 닉네임이므로 사용할 수 없습니다.").css("color","red").css("font-size","12px");
        					$memNickname.val("");
        					$memNickname.focus();
        					
        				} else {
                			if(regNickname.test(nickname) == false) {
            					$("#nicknameCheckOutput").text("닉네임은 2~10자로 한글/영문자/숫자/특수문자()가 포함될 수 있습니다.").css("color","red").css("font-size","12px");
       						} else {
        						$("#nicknameCheckOutput").text("사용 가능한 닉네임입니다!").css("color","rgb(232, 183, 34)").css("font-size","12px");
        					}
        				}
        				
        			},
        			error : function () {
        				console.log("닉네임 중복 체크용 ajax 통신 실패!");
        			}

        		});
        	}
        	
        	// 비밀번호 확인용 제이쿼리
        	$('.pwd').focusout(function() {
        		        		
        		let pwd1 = $("#pwd1").val();
        		let pwd2 = $("#pwd2").val();
        		let regPwd = /^[a-zA-Z0-9]{8,20}$/;
        		
        		if(pwd1 != "" && pwd2 != "") { // 사용자가 비밀번호, 비밀번호 확인을 모두 입력했다면
        			
        			if(pwd1 != pwd2) {
        				$("#pwdCheckOutput").text("비밀번호가 일치하지 않습니다. 다시 확인해 주세요.").css("color","red").css("font-size","12px");
        			} else {
        				if(regPwd.test(pwd2) == false) {
        					$("#pwdCheckOutput").text("비밀번호는 8~20자로 숫자/영어 대,소문자/특수문자()가 포함될 수 있습니다.").css("color","red").css("font-size","12px");
        				} else {
        					$("#pwdCheckOutput").text("비밀번호가 일치합니다!").css("color","rgb(232, 183, 34)").css("font-size","12px");
        				}
        			}
        			
        		}
        		
        	});
        </script>

</body>
</html>

 

3. GAME, ATTACHMENT 클래스 생성

package com.insertcoin.game.model.vo;

import java.sql.Date;

public class Game {
	
	
	// 필드부 
	private int gameNo; //	GAME_NO	NUMBER
	private String gameName; //	GAME_NAME	VARCHAR2(100 BYTE)
	private int memNo; //	MEM_NO	NUMBER
	private String gameGenre; //	GAME_GENRE	VARCHAR2(20 BYTE)
	private String gameOs; //	GAME_OS	VARCHAR2(10 BYTE)
	private String gameContent; //	GAME_CONTENT	VARCHAR2(4000 BYTE)
	private int gameDonateDefault; //	GAME_DONATE_DEFAULT	NUMBER
	private String gameFreeDownload; //	GAME_FREE_DOWNLOAD	CHAR(1 BYTE)
	private Date gameRegisterDate; //	GAME_REGISTER_DATE	DATE
	private String gameShow; //	GAME_SHOW	CHAR(1 BYTE)
	private String gamePageColor; //	GAME_PAGE_COLOR	VARCHAR2(10 BYTE)
	


	// 생성자부
	public Game() {
		super();
	}
	
	
	public Game(int gameNo, String gameName, int memNo, String gameGenre, String gameOs, String gameContent,
			int gameDonateDefault, String gameFreeDownload, Date gameRegisterDate, String gameShow,
			String gamePageColor) {
		super();
		this.gameNo = gameNo;
		this.gameName = gameName;
		this.memNo = memNo;
		this.gameGenre = gameGenre;
		this.gameOs = gameOs;
		this.gameContent = gameContent;
		this.gameDonateDefault = gameDonateDefault;
		this.gameFreeDownload = gameFreeDownload;
		this.gameRegisterDate = gameRegisterDate;
		this.gameShow = gameShow;
		this.gamePageColor = gamePageColor;
	}
	
	// 게시판 게임 태그용 생성자
	public Game(int gameNo, String gameName) {
		super();
		this.gameNo = gameNo;
		this.gameName = gameName;
	}
	
	// 메소드부 
	public int getGameNo() {
		return gameNo;
	}

	public void setGameNo(int gameNo) {
		this.gameNo = gameNo;
	}


	public String getGameName() {
		return gameName;
	}


	public void setGameName(String gameName) {
		this.gameName = gameName;
	}


	public int getMemNo() {
		return memNo;
	}


	public void setMemNo(int memNo) {
		this.memNo = memNo;
	}


	public String getGameGenre() {
		return gameGenre;
	}


	public void setGameGenre(String gameGenre) {
		this.gameGenre = gameGenre;
	}


	public String getGameOs() {
		return gameOs;
	}


	public void setGameOs(String gameOs) {
		this.gameOs = gameOs;
	}


	public String getGameContent() {
		return gameContent;
	}


	public void setGameContent(String gameContent) {
		this.gameContent = gameContent;
	}


	public int getGameDonateDefault() {
		return gameDonateDefault;
	}


	public void setGameDonateDefault(int gameDonateDefault) {
		this.gameDonateDefault = gameDonateDefault;
	}


	public String getGameFreeDownload() {
		return gameFreeDownload;
	}


	public void setGameFreeDownload(String gameFreeDownload) {
		this.gameFreeDownload = gameFreeDownload;
	}


	public Date getGameRegisterDate() {
		return gameRegisterDate;
	}


	public void setGameRegisterDate(Date gameRegisterDate) {
		this.gameRegisterDate = gameRegisterDate;
	}


	public String getGameShow() {
		return gameShow;
	}


	public void setGameShow(String gameShow) {
		this.gameShow = gameShow;
	}


	public String getGamePageColor() {
		return gamePageColor;
	}


	public void setGamePageColor(String gamePageColor) {
		this.gamePageColor = gamePageColor;
	}


	@Override
	public String toString() {
		return "Game [gameNo=" + gameNo + ", gameName=" + gameName + ", memNo=" + memNo + ", gameGenre=" + gameGenre
				+ ", gameOs=" + gameOs + ", gameContent=" + gameContent + ", gameDonateDefault=" + gameDonateDefault
				+ ", gameFreeDownload=" + gameFreeDownload + ", gameRegisterDate=" + gameRegisterDate + ", gameShow="
				+ gameShow + ", gamePageColor=" + gamePageColor + "]";
	}

}
package com.insertcoin.common.model.vo;

import java.sql.Date;

public class Attachment {
	
	//  필드부
	private int attachmentNo; // 파일번호
	private String attachmentPath; // 파일경로
	private String attachmentName; // 원본 파일명
	private String attachmentRename; // 수정 파일명
	private Date attachmentUploadDate; // 업로드일
	private String attachmentStatus; // 삭제유무
	private int memNo; // 참조 회원번호
	private int gameNo; // 참조 게임등록번호
	private int reviewNo; // 참조 리뷰등록번호
	private int genNo; // 참조 일반게시판 게시글번호
	private int genCommentNo; // 참조 일반게시판 댓글번호
	private int devNo; // 참조 개발자게시판 게시글번호
	private int devCommentNo;  // 참조 개발자게시판 댓글번호	
	private int noticeNo; // 참조 공지사항번호
	
	

	// 생성자부
	
	public Attachment() {
		super();
	}
	public Attachment(int attachmentNo, String attachmentPath, String attachmentName, String attachmentRename,
			Date attachmentUploadDate, String attachmentStatus, int memNo, int gameNo, int reviewNo, int genNo,
			int genCommentNo, int devNo, int devCommentNo, int noticeNo) {
		super();
		this.attachmentNo = attachmentNo;
		this.attachmentPath = attachmentPath;
		this.attachmentName = attachmentName;
		this.attachmentRename = attachmentRename;
		this.attachmentUploadDate = attachmentUploadDate;
		this.attachmentStatus = attachmentStatus;
		this.memNo = memNo;
		this.gameNo = gameNo;
		this.reviewNo = reviewNo;
		this.genNo = genNo;
		this.genCommentNo = genCommentNo;
		this.devNo = devNo;
		this.devCommentNo = devCommentNo;
		this.noticeNo = noticeNo;
	}
	
	// 메소드부 
	public int getAttachmentNo() {
		return attachmentNo;
	}
	public void setAttachmentNo(int attachmentNo) {
		this.attachmentNo = attachmentNo;
	}
	public String getAttachmentPath() {
		return attachmentPath;
	}
	public void setAttachmentPath(String attachmentPath) {
		this.attachmentPath = attachmentPath;
	}
	public String getAttachmentName() {
		return attachmentName;
	}
	public void setAttachmentName(String attachmentName) {
		this.attachmentName = attachmentName;
	}
	public String getAttachmentRename() {
		return attachmentRename;
	}
	public void setAttachmentRename(String attachmentRename) {
		this.attachmentRename = attachmentRename;
	}
	public Date getAttachmentUploadDate() {
		return attachmentUploadDate;
	}
	public void setAttachmentUploadDate(Date attachmentUploadDate) {
		this.attachmentUploadDate = attachmentUploadDate;
	}
	public String getAttachmentStatus() {
		return attachmentStatus;
	}
	public void setAttachmentStatus(String attachmentStatus) {
		this.attachmentStatus = attachmentStatus;
	}
	public int getMemNo() {
		return memNo;
	}
	public void setMemNo(int memNo) {
		this.memNo = memNo;
	}
	public int getGameNo() {
		return gameNo;
	}
	public void setGameNo(int gameNo) {
		this.gameNo = gameNo;
	}
	public int getReviewNo() {
		return reviewNo;
	}
	public void setReviewNo(int reviewNo) {
		this.reviewNo = reviewNo;
	}
	public int getGenNo() {
		return genNo;
	}
	public void setGenNo(int genNo) {
		this.genNo = genNo;
	}
	public int getGenCommentNo() {
		return genCommentNo;
	}
	public void setGenCommentNo(int genCommentNo) {
		this.genCommentNo = genCommentNo;
	}
	public int getDevNo() {
		return devNo;
	}
	public void setDevNo(int devNo) {
		this.devNo = devNo;
	}
	public int getDevCommentNo() {
		return devCommentNo;
	}
	public void setDevCommentNo(int devCommentNo) {
		this.devCommentNo = devCommentNo;
	}
	public int getNoticeNo() {
		return noticeNo;
	}
	public void setNoticeNo(int noticeNo) {
		this.noticeNo = noticeNo;
	}
	@Override
	public String toString() {
		return "Attachment [attachmentNo=" + attachmentNo + ", attachmentPath=" + attachmentPath + ", attachmentName="
				+ attachmentName + ", attachmentRename=" + attachmentRename + ", attachmentUploadDate="
				+ attachmentUploadDate + ", attachmentStatus=" + attachmentStatus + ", memNo=" + memNo + ", gameNo="
				+ gameNo + ", reviewNo=" + reviewNo + ", genNo=" + genNo + ", genCommentNo=" + genCommentNo + ", devNo="
				+ devNo + ", devCommentNo=" + devCommentNo + ", noticeNo=" + noticeNo + "]";
	}

}

 

4. BoardService

	public ArrayList<Game> selectGameList() {
		
		Connection conn = getConnection();
		ArrayList<Game> list = new BoardDao().selectGameList(conn);
		
		close(conn);
		
		return list;
	}
	
	public int insertBoard(Board b, Attachment at) {
		
		Connection conn = getConnection();
		
		// Dao의 메소드 1개 = 쿼리문 1개
		// 첨부파일이 있든 없든 간에 무조건 일어나야 하는 BOARD 테이블 INSERT 요청 먼저
		int result1 = new BoardDao().insertBoard(conn, b); // 성공 1, 실패 0
		
		// 한 개의 트랜잭션에 테이블의 변동이 있는 DML이 두 번 실행
		// 두 번의 DML 중 하나라도 실패한다면 전부 rollback / 두 번 모두 성공해야 commit
		
		// 만약 첨부파일이 있다면 Attachment 테이블에 insert 요청 보내기
		// 두 번째 요청에 대한 결과값을 담을 수 있는 변수 세팅
		// 기본값 0으로 설정하면 첨부파일 없을 때는 무조건 실패이니 기본값 1
		int result2 = 1;
		
		if(at != null) { // 첨부파일이 있다면
			result2 = new BoardDao().insertAttachment(conn, at);
		}
		
		// 트랜잭션 처리는 result1 > 0 %% result2 > 0 일 때만 커밋
		if(result1 > 0 && result2 > 0) {
			commit(conn);
		} else {
			rollback(conn);
		}
		
		close(conn);

		// 하나라도 실패해서 0이 나오면 실패여야 하기 때문에 곱셈 결과로 보냄 
		return result1 * result2;

	}

 

5. BoardDao

	public ArrayList<Game> selectGameList(Connection conn) {
		
		// SELECT문 => ResultSet 객체 (여러 행 조회)
		ArrayList<Game> list = new ArrayList<>();
		PreparedStatement pstmt = null;
		ResultSet rset = null;
		
		String sql = prop.getProperty("selectGameList");
		
		try {
			pstmt = conn.prepareStatement(sql);
			rset = pstmt.executeQuery();
			
			while(rset.next()) {
				
				list.add(new Game(rset.getInt("GAME_NO"),
								  rset.getString("GAME_NAME")));
				
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(rset);
			close(pstmt);
		}
		return list;
	}
	
	public int insertBoard(Connection conn, Board b) {
		
		// insert문 => int (처리된 행 개수)
		int result = 0;
		PreparedStatement pstmt = null;
		
		String sql = prop.getProperty("insertBoard");
		
		try {
			pstmt = conn.prepareStatement(sql);
			
			// GEN_CATEGORY / GAME_NO / MEM_NO / GEN_TITLE / GEN_CONTENT
			// genCategory / gemeNo / memNo / genTitle / genContent
			pstmt.setString(1, b.getGenCategory());
			// pstmt.setInt(2, b.getGameNo());
			pstmt.setInt(2, Integer.parseInt(b.getMemNo()));
			pstmt.setString(3, b.getGenTitle());
			pstmt.setString(4, b.getGenContent());
			
			result = pstmt.executeUpdate();
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(pstmt);
		}
	
		return result;
	
	}
	
	public int insertAttachment(Connection conn, Attachment at) {
		
		// INSERT문 => int 처리된 행의 개수
		
		int result = 0;
		PreparedStatement pstmt = null;
		
		String sql = prop.getProperty("insertAttachment");
		
		try {
			pstmt = conn.prepareStatement(sql);
			
			// private String attachmentName; // 원본 파일명
			// private String attachmentRename; // 수정 파일명
			// private String attachmentPath; // 파일경로
			
			pstmt.setString(1, at.getAttachmentName());
			pstmt.setString(2, at.getAttachmentRename());
			pstmt.setString(3, at.getAttachmentPath());
			
			result = pstmt.executeUpdate();
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(pstmt);
		}
		
		System.out.println(result);
		
		return result;

	}

 

6. board-mapper.xml

	<entry key="selectGameList">
		SELECT *
		FROM GAME
	</entry>
	
	<entry key="insertBoard">
		INSERT INTO GEN_BOARD (GEN_NO
						 , GEN_CATEGORY
						 , MEM_NO
						 , GEN_TITLE
						 , GEN_CONTENT
						 , GEN_REGISTER_DATE)
				VALUES 	  (SEQ_GEN_NO.NEXTVAL
						 , ?
						 , ?
						 , ?
						 , ?
						 , SYSDATE)
	</entry>
	
	<entry key="insertAttachment">
		INSERT INTO ATTACHMENT (ATTACHMENT_NO
							  , GEN_NO
							  , ATTACHMENT_NAME
							  , ATTACHMENT_RENAME
							  , ATTACHMENT_PATH)
					 VALUES    (SEQ_ATTACHMENT_NO.NEXTVAL
							  , SEQ_GEN_NO.CURRVAL
							  , ?
							  , ?
							  , ?)
	</entry>

 

7. BoardInsertController (URL mapping: /insert.bo)

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// 일반 게시글 추가 기능
		// 1. Board 테이블에 insert
		// 2. 만약 첨부파일이 있다면 Attachment 테이블도 insert
		
		// 인코딩 설정
		request.setCharacterEncoding("UTF-8");
		
		// memNo: 작성자 번호
		// genCategory: 카테고리 번호(현재 String으로 받아 왔음)
		// gameNo: 게임 번호
		// genTitle: 게시글 제목
		// genContent: 게시글 내용
		// upfile: 첨부파일
		
		// multipart/form-data 형식인지 검사
		if(ServletFileUpload.isMultipartContent(request)) {
			
			// 전송된 파일을 처리할 작업 내용
			// 용량 제한
			int maxSize = 10 * 1024 * 1024;
			
			// 전달된 파일을 저장할 서버의 실 경로
			String savePath = request.getSession().getServletContext().getRealPath("/resources/image/board/gen/post/");
			
			// 전달된 파일명 수정 및 서버에 업로드
			MultipartRequest multiRequest = new MultipartRequest(request, savePath, maxSize, "UTF-8", new MyFileRenamePolicy());
			
			// DB에 기록할 데이터를 뽑아서 VO 객체에 담기
			String memNo = multiRequest.getParameter("memNo");
			String genCategory = multiRequest.getParameter("genCategory");
			// String gameNo = multiRequest.getParameter("gameNo");
			String genTitle = multiRequest.getParameter("genTitle");
			String genContent = multiRequest.getParameter("genContent");
			
			Board b = new Board();
			b.setMemNo(memNo);
			b.setGenCategory(genCategory);
			// b.setGameNo(null);
			b.setGenTitle(genTitle);
			b.setGenContent(genContent);
			
			// 만약 첨부파일이 있다면 첨부파일에 대한 정보도 뽑아서 VO 객체에 담기
			Attachment at = null;
			
			if(multiRequest.getOriginalFileName("upfile") != null) {
				
				at = new Attachment();
				at.setAttachmentName(multiRequest.getOriginalFileName("upfile")); // 원본명
				at.setAttachmentRename(multiRequest.getFilesystemName("upfile")); // 수정명, 실제 서버에 업로드된 파일명
				at.setAttachmentPath("resources/image/board/gen/post/");
				
			}
			
			// 이 시점 기준으로 첨부파일이 없다면 at == null
			// 서비스 요청
			int result = new BoardService().insertBoard(b, at);
			
			// 결과에 따른 응답 페이지 지정
			if(result > 0) { // 성공 /jsp/list.bo?currentPage=1 요청 (가장 최신글)
				
				request.getSession().setAttribute("alertMsg", "게시글이 성공적으로 작성되었습니다.");
				response.sendRedirect(request.getContextPath() + "/list.bo?currentPage=1");

			} else { // 실패
				
				// 첨부파일이 있었을 경우 이미 업로드된 첨부파일을 굳이 서버에 보관할 필요가 없음
				if(at != null) {
					
					new File(savePath + at.getAttachmentRename()).delete();
					 
				}
				
				request.setAttribute("errorMsg", "게시글 작성 실패");
				request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
				
			}
						
		}
		
	}

 

8. MyFileRenamePolicy

package com.insertcoin.common;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.oreilly.servlet.multipart.FileRenamePolicy;

public class MyFileRenamePolicy implements FileRenamePolicy {

	// 기존 파일 전달받아 파일명 수정 작업 후 수정된 파일 자체를 return

	@Override
	public File rename(File originFile) {
		
		// 원본 파일명
		String originName = originFile.getName();
		
		// 수정 파일명
		// gen_post__yyyymmdd_nnnnn
		// 파일 업로드 시간
		String text = "gen_post_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
		
		// 5자리 랜덤값
		int ranNum = (int)(Math.random() * 90000) + 10000;
		
		// 원본파일 확장자
		String ext = originName.substring(originName.lastIndexOf("."));
		
		// 결합
		String changeName = text + ranNum + ext;
		
		// 수정된 파일명으로 원본파일명 적용 후 파일 객체로 변환
				
		return new File(originFile.getParent(), changeName);
	}
	
}

 

🤦🏻‍♀️ 게시판 상세조회

더보기

1. boardDetailView.jsp (하드코딩)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>자유게시판 상세 게시글</title>

    <!-- CSS 스타일시트 -->
    <link href="resources/css/boardDetailView.css" rel="stylesheet">

</head>
<body>

    <!-- 전체 영역 -->
    <div class="wrap">
    
		<%@ include file = "../../views/common/header.jsp" %>

        <!-- 컨텐츠 영역 -->
        <div class="content_container">

            <div class="outer">
                <div id="title">자유게시판</div>
                    <!-- 조회할 게시물이 보여질 자리 -->
                    <table align="center" class="list-area">
                        <thead>
                            <tr id="board_title" class="line">
                                <th width="1000">
                                    <div class="board_left">[카테고리명] 글제목</div>
                                </th>
                                <td>
                                    <div class="board_right">2022.11.01</div>
                                </td>
                            </tr>
                        </thead>
                        <tbody>
                            <tr class="line">
                                <td>
                                    <div class="board_left">user01</div>
                                </td>
                                <td>
                                    <div class="board_right">조회수 26&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;신고 0</div>
                                </td>
                            </tr>
                            <tr class="line">
                                <td colspan="3">
                                    <div id="board_text">
                                        안녕하세요 제가 이걸 만들 수 있을까요? 글의 길이에 따라 보여지는 창이 달라진다라...
                                        테스트 중입니다 얼마나 길어져야 이게 자기 마음대로 엥 쓰다보니까 알아서 길이가 달라지는 것 같은데 착각일까요?
                                        아아ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ방금 또 한 줄이 자기 마음대로 넘어갔네요<br><br>
                                        br을 먹여 봐도 넘어갑니다 신기방기
                                    </div>
                                    </td>
                            </tr>
                            <tr>
                                <td colspan="3">
                                    <div>
                                        <button class="table_button">수정</button>
                                        <button class="table_button">삭제</button>
                                        <button class="table_button">목록</button>
                                        <button type="button" id="red_board" class="btn btn-primary" data-toggle="modal" data-target="#myReport">신고</button>
                                        
                                        <!--------------------------------------------- 신고 모달창 ------------------------------------------------>
                                        <!-- The Modal -->
                                        <div class="modal fade" id="myReport">
                                            <div class="modal-dialog modal-dialog-centered">
                                            <div class="modal-content">
                                            
                                                <!-- Modal Header -->
                                                <div class="modal-header">
                                                <h5 class="modal-title">게시글 신고</h5>
                                                <button type="button" class="close" data-dismiss="modal">&times;</button>
                                                </div>
                                                
                                                <!-- Modal body -->
                                                <div class="modal-body">
                                                    <b>신고사유</b><br>
                                                    <input type="checkbox" id="1" value="1"><label for="1">&nbsp;스팸</label><br>
                                                    <input type="checkbox" id="2" value="2"><label for="2">&nbsp;음란성</label><br>
                                                    <input type="checkbox" id="3" value="3"><label for="3">&nbsp;증오심 표현</label><br>
                                                    <input type="checkbox" id="4" value="4"><label for="4">&nbsp;잘못된 정보</label><br>
                                                    <input type="checkbox" id="5" value="5"><label for="5">&nbsp;기타</label><br>
                                                    <input type="text" placeholder="내용을 입력해 주세요" style="width:300px;">
                                                </div>
                                                
                                                <!-- Modal footer -->
                                                <div class="modal-footer">
                                                <button class="modal_button button1" type="reset">취소</button>
                                                <button class="modal_button button2" type="submit">신청</button>
                                                </div>
                                                
                                            </div>
                                            </div>
                                        </div>
                                        <!--------------------------------------------- 신고 모달창 ------------------------------------------------>

                                    </div>
                                </td>
                            </tr>
                            <tr>
                                <td colspan="2">
                                    <div id="comment_count">댓글 2개</div>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                    <table class="comment_table">
                        <tr>
                            <td rowspan="2" width="5%">
                                <img src="resources/image/profile/profile_default.png" id="profile_photo">
                            </td>
                            <td>
                                <div class="comment_info1">
                                    <div>내닉넴짱짱</div>
                                </div>
                            </td>
                            <td>
                                <div class="comment_info2">
                                    <div>2022.10.23 12:02</div>
                                </div>
                            </td>
                            <td>
                                <button id="comment_info3" class="btn btn-primary" data-toggle="modal" data-target="#myReport">신고</button>
                            </td>
                        </tr>
                        <tr class="line">
                            <td>어디보자... 점점 구색을 갖추는듯하나 아직 고칠 게 많아 보입니다 ^^</td>
                        </tr>
                        <tr>
                            <td  rowspan="2" width="5%">
                                <img src="resources/image/profile/profile_default.png" id="profile_photo">
                            </td>
                            <td>
                                <div class="comment_info1">
                                    <div>하지만만약내닉네임이길어진다면</div>
                                </div>
                            </td>
                            <td>
                                <div class="comment_info2">
                                    <div>2022.10.23 12:28</div>
                                </div>
                            </td>
                            <td>
                                <button id="comment_info3" class="btn btn-primary" data-toggle="modal" data-target="#myReport">신고</button>
                            </td>
                        </tr>
                        <tr class="line">
                            <td colspan="3">제가 볼때는 별로같은데요... 일단 이 작업을 하고 나서 글씨 크기부터 좀 줄여야겠어요 전혀 분간이 안되네요 가독성 구려요 그리고 댓글이 더 길어지면 어떻게 되는지도 봐야겠어요</td>
                        </tr>
                        <tr>
                            <td colspan="4">
                                <div class=comment_container> 댓글쓰기 <br>
                                    <textarea class="comment_textarea" placeholder="명예훼손, 개인정보 유출, 분쟁 유발, 허위사실 유포 등의 글은 이용약관에 의해 제재는 물론 법률에 의해 처벌받을 수 있습니다. 건전한 커뮤니티를 위해 자제를 당부드립니다."></textarea>
                                    <button id="comment_submit">등록</button>
                                </div>    
                                
                            </td>
                        </tr>
                    </table>

                    <!-- 조회할 게시물이 보여질 자리 -->
                    <table align="center" class="list-area">
                        <thead>
                            <tr id="board_title">
                                <!-- th[width=]*6 + Enter -->
                                <th width="100">글번호</th>
                                <th width="100">카테고리</th>
                                <th width="700">제목</th>
                                <th width="150">작성자</th>
                                <th width="70">조회수</th>
                                <th width="150">작성일</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr class="line">
                                <td>15</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>14</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>13</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>12</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>11</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>10</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>9</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>8</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>7</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>6</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>5</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>4</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>3</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>2</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>1</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                        </tbody>
                    </table>

                    <br>
                    <div class="board_search board_left">
                        <input type="button" value="글쓰기" class="board_button">
                    </div>
        
                    <div class="board_search board-right">
                        <select class="board_search">
                            <option selected>제목+내용</option>
                            <option value="10">제목</option>
                            <option value="20">내용</option>
                            <option value="30">작성자</option>
                            <option value="40">댓글</option>
                            <option value="50">게임명</option>
                        </select>
                        <input type="text">
                        <button class="board_button">검색</button>
                    </div>
            
                    <br><br>
                    <!-- 페이징바 -->
                    <div align="center" class="paging-area">
                    <button>1</button>
                    <button>2</button>
                    <button>3</button>
                    <button>4</button>
                    <button>5</button>
                    <button>6</button>
                    <button>7</button>
                    <button>8</button>
                    <button>9</button>
                    <button>10</button>
                    </div>
                </div>
            
        </div>

    </div>

</body>

</body>
</html>

 

2. boardListView.jsp

	<script>
		// 게시글에 클릭 버튼 걸기
		$(function() {
			$(".list-area>tbody>tr").click(function() {
				location.href = "<%= contextPath %>/detail.bo?genNo=" + $(this).children().eq(0).text();
			});
		});
	</script>

 

 3. BoardDetailController (URL mapping: /detail.bo)

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// 해당 게시글 먼저 뽑기
		int genNo = Integer.parseInt(request.getParameter("genNo"));
		
		// 조회수 증가 / 게시글 조회(Board) / 첨부파일 조회(Attachment)
		// => 서비스로 요청 3번을 보내야 함
		BoardService bService = new BoardService();
		
		// 조회 수 증가 요청
		int result = bService.increaseCount(genNo);
		
		if(result > 0) { // 조회수 증가에 성공
			
			// 게시글 조회, 첨부파일 조회
			Board b = bService.selectBoard(genNo);
			Attachment at = bService.selectAttachment(genNo);
			
			// 게시글 정보 보내기
			request.setAttribute("b", b);
			request.setAttribute("at", at);
			
			// 게시글 상세 조회 페이지로 포워딩
			request.getRequestDispatcher("views/board/boardDetailView.jsp").forward(request, response);
			
		} else { // 조회수 증가에 실패했다면
			
			// 에러 문구 담아서 에러 페이지로 포워딩
			// 키값 오타 시 null
			request.setAttribute("errorMsg", "게시글 상세 조회 실패");
			request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
			
		}
	}

 

4. boardDetailView.jsp (동적 코딩)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="com.insertcoin.board.model.vo.Board, com.insertcoin.common.model.vo.Attachment" %>
<%
	// 필요한 데이터 먼저 뽑기
	Board b = (Board)request.getAttribute("b");
	// 게시글 번호, 카테고리명, 글 제목, 글 내용, 작성자 아이디, 작성일, 신고 수
	
	Attachment at = (Attachment)request.getAttribute("at");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>자유게시판 상세 게시글</title>

    <!-- CSS 스타일시트 -->
    <link href="resources/css/boardDetailView.css" rel="stylesheet">

</head>
<body>

    <!-- 전체 영역 -->
    <div class="wrap">
    
		<%@ include file = "../../views/common/header.jsp" %>

        <!-- 컨텐츠 영역 -->
        <div class="content_container">

            <div class="outer">
                <div id="title">자유게시판</div>
                    <!-- 조회할 게시물이 보여질 자리 -->
                    <table align="center" class="list-area">
                        <thead>
                            <tr id="board_title" class="line">
                                <th width="1000">
                                    <div class="board_left">[<%= b.getGenCategory() %>] <%= b.getGenTitle() %></div>
                                </th>
                                <td>
                                    <div class="board_right"><%= b.getGenRegister() %></div>
                                </td>
                            </tr>
                        </thead>
                        <tbody>
                            <tr class="line">
                                <td>
                                    <div class="board_left">작성자: <b><%= b.getMemNo() %></b></div>
                                </td>
                                <td>
                                    <div class="board_right">조회수 <%= b.getGenViews() %>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;신고 0</div>
                                </td>
                            </tr>
                            <tr class="line">
                                <td colspan="3">
                                    <div id="board_text">
                                        <%= b.getGenContent() %>
                                    </div>
                                    </td>
                            </tr>
                            <tr class="line">
                            	<th>첨부파일</th>
                            	<td colspan="3">
                            		<% if(at == null) { %>
                            			첨부파일이 없습니다.
                            		<% } else { %>
                            			<a download="<%= at.getAttachmentName() %>" href="<%= contextPath %>/<%= at.getAttachmentPath() + at.getAttachmentRename() %>">
                            				<%= at.getAttachmentName() %>
                            			</a>
                            		<% } %>
                            	</td>
                            </tr>
                            <tr>
                                <td colspan="3">
                                    <div>
										<% if(loginUser != null && loginUser.getMemNickname().equals(b.getMemNo())) { %>
											<button class="table_button">수정</button>
	                                        <button class="table_button">삭제</button>
	                                        <button type="button" id="red_board" class="btn btn-primary" data-toggle="modal" data-target="#myReport">신고</button>
	                                    <% } %>
                                        <button class="table_button" onclick="goToList();">목록</button>
                                        
                                        <!--------------------------------------------- 신고 모달창 ------------------------------------------------>
                                        <!-- The Modal -->
                                        <div class="modal fade" id="myReport">
                                            <div class="modal-dialog modal-dialog-centered">
                                            <div class="modal-content">
                                            
                                                <!-- Modal Header -->
                                                <div class="modal-header">
                                                <h5 class="modal-title">게시글 신고</h5>
                                                <button type="button" class="close" data-dismiss="modal">&times;</button>
                                                </div>
                                                
                                                <!-- Modal body -->
                                                <div class="modal-body">
                                                    <b>신고사유</b><br>
                                                    <input type="checkbox" id="1" value="1"><label for="1">&nbsp;스팸</label><br>
                                                    <input type="checkbox" id="2" value="2"><label for="2">&nbsp;음란성</label><br>
                                                    <input type="checkbox" id="3" value="3"><label for="3">&nbsp;증오심 표현</label><br>
                                                    <input type="checkbox" id="4" value="4"><label for="4">&nbsp;잘못된 정보</label><br>
                                                    <input type="checkbox" id="5" value="5"><label for="5">&nbsp;기타</label><br>
                                                    <input type="text" placeholder="내용을 입력해 주세요" style="width:300px;">
                                                </div>
                                                
                                                <!-- Modal footer -->
                                                <div class="modal-footer">
                                                <button class="modal_button button2" type="submit" data-dismiss="modal" onclick="report();">신청</button>
                                                </div>
                                                
                                            </div>
                                            </div>
                                        </div>
                                        <!--------------------------------------------- 신고 모달창 ------------------------------------------------>

                                    </div>
                                </td>
                            </tr>
                            <tr>
                                <td colspan="2">
                                    <div id="comment_count">댓글 2개</div>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                    <table class="comment_table">
                        <tr>
                            <td rowspan="2" width="5%">
                                <img src="resources/image/profile/profile_default.png" id="profile_photo">
                            </td>
                            <td>
                                <div class="comment_info1">
                                    <div>내닉넴짱짱</div>
                                </div>
                            </td>
                            <td>
                                <div class="comment_info2">
                                    <div>2022.10.23 12:02</div>
                                </div>
                            </td>
                            <td>
                                <button id="comment_info3" class="btn btn-primary" data-toggle="modal" data-target="#myReport">신고</button>
                            </td>
                        </tr>
                        <tr class="line">
                            <td>어디보자... 점점 구색을 갖추는듯하나 아직 고칠 게 많아 보입니다 ^^</td>
                        </tr>
                        <tr>
                            <td  rowspan="2" width="5%">
                                <img src="resources/image/profile/profile_default.png" id="profile_photo">
                            </td>
                            <td>
                                <div class="comment_info1">
                                    <div>하지만만약내닉네임이길어진다면</div>
                                </div>
                            </td>
                            <td>
                                <div class="comment_info2">
                                    <div>2022.10.23 12:28</div>
                                </div>
                            </td>
                            <td>
                                <button id="comment_info3" class="btn btn-primary" data-toggle="modal" data-target="#myReport">신고</button>
                            </td>
                        </tr>
                        <tr class="line">
                            <td colspan="3">제가 볼때는 별로같은데요... 일단 이 작업을 하고 나서 글씨 크기부터 좀 줄여야겠어요 전혀 분간이 안되네요 가독성 구려요 그리고 댓글이 더 길어지면 어떻게 되는지도 봐야겠어요</td>
                        </tr>
                        <tr>
                            <td colspan="4">
                                <div class=comment_container> 댓글쓰기 <br>
                                    <textarea class="comment_textarea" placeholder="명예훼손, 개인정보 유출, 분쟁 유발, 허위사실 유포 등의 글은 이용약관에 의해 제재는 물론 법률에 의해 처벌받을 수 있습니다. 건전한 커뮤니티를 위해 자제를 당부드립니다."></textarea>
                                    <button id="comment_submit">등록</button>
                                </div>    
                                
                            </td>
                        </tr>
                    </table>

                    <!-- 조회할 게시물이 보여질 자리 -->
                    <table align="center" class="list-area">
                        <thead>
                            <tr id="board_title">
                                <!-- th[width=]*6 + Enter -->
                                <th width="100">글번호</th>
                                <th width="100">카테고리</th>
                                <th width="700">제목</th>
                                <th width="150">작성자</th>
                                <th width="70">조회수</th>
                                <th width="150">작성일</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr class="line">
                                <td>15</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>14</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>13</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>12</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>11</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>10</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>9</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>8</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>7</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>6</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>5</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>4</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>3</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>2</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                            <tr class="line">
                                <td>1</td>
                                <td>게임</td>
                                <td>게시글 제목이다</td>
                                <td>user02</td>
                                <td>10</td>
                                <td>2022-05-01</td>
                            </tr>
                        </tbody>
                    </table>

                    <br>
                    <div class="board_search board_left">
                        <input type="button" value="글쓰기" class="board_button">
                    </div>
        
                    <div class="board_search board-right">
                        <select class="board_search">
                            <option selected>제목+내용</option>
                            <option value="10">제목</option>
                            <option value="20">내용</option>
                            <option value="30">작성자</option>
                            <option value="40">댓글</option>
                            <option value="50">게임명</option>
                        </select>
                        <input type="text">
                        <button class="board_button">검색</button>
                    </div>
            
                    <br><br>
                    <!-- 페이징바 -->
                    <div align="center" class="paging-area">
                    <button>1</button>
                    <button>2</button>
                    <button>3</button>
                    <button>4</button>
                    <button>5</button>
                    <button>6</button>
                    <button>7</button>
                    <button>8</button>
                    <button>9</button>
                    <button>10</button>
                    </div>
                </div>
            
        </div>

    </div>
    
    <script>
    	function goToList() {
    		location.href = "<%=contextPath %>/list.bo?currentPage=1";
    	}
    	
    	function report() {
    		alert("신고가 성공적으로 접수되었습니다.");
    	}
    </script>

</body>

</body>
</html>

 

5. BoardService

	// 조회수 증가용 서비스
	public int increaseCount(int genNo) {
		
		Connection conn = getConnection();
		
		int result = new BoardDao().increaseCount(conn, genNo);
		
		if(result > 0) {
			commit(conn);
		} else {
			rollback(conn);
		}
		close(conn);
		return result;
	}
	
	// Board 정보를 가지고 올 서비스
	public Board selectBoard(int genNo) {
		Connection conn = getConnection();
		Board b = new BoardDao().selectBoard(conn, genNo);
		
		close(conn);
		
		return b;
	}
	
	// Attachment 정보를 가지고 올 서비스
	public Attachment selectAttachment(int genNo) {
		Connection conn = getConnection();
		Attachment at = new BoardDao().selectAttachment(conn, genNo);
		
		close(conn);
		return at;
	}

 

6. BoardDao

	// 조회수 증가용 Dao
	 public int increaseCount(Connection conn, int genNo) {
		 
		 // UPDATE문 => int (처리된 행의 개수)
		 int result = 0;
		 PreparedStatement pstmt = null;
		 
		 String sql = prop.getProperty("increaseCount");
		 
		 try {
			pstmt = conn.prepareStatement(sql);
			
			pstmt.setInt(1, genNo);
			
			result = pstmt.executeUpdate();
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(pstmt);
		}
		 
		 return result;
		 
	 }
	 
	 // Board 정보용  DAO
	 public Board selectBoard(Connection conn, int genNo) {
		 
		 // SELECT문 => ResultSet 객체 (많아도 1행)
		 
		 Board b = null;
		 PreparedStatement pstmt = null;
		 ResultSet rset = null;
		 
		 String sql = prop.getProperty("selectBoard");
		 
		 try {
			pstmt = conn.prepareStatement(sql);
			
			pstmt.setInt(1, genNo);
			
			rset = pstmt.executeQuery();
			
			if(rset.next()) {
				
				b = new Board(rset.getInt("GEN_NO")
							, rset.getString("GEN_CATEGORY")
							, rset.getString("GAME_NAME") // 일단 게임 태그 제외
							, rset.getString("MEM_NICKNAME")
							, rset.getString("GEN_TITLE")
							, rset.getString("GEN_CONTENT")
							, rset.getDate("GEN_REGISTER_DATE")
							, rset.getInt("GEN_VIEWS"));
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(rset);
			close(pstmt);
		}
		 return b;
		 
	 }
	 
	 public Attachment selectAttachment(Connection conn, int genNo) {
		 
		 // SELECT문 => ResultSet 객체 (1행 조회)
		 Attachment at = null;
		 PreparedStatement pstmt = null;
		 ResultSet rset = null;
		 
		 String sql = prop.getProperty("selectAttachment");
		 
		 try {
			
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, genNo);
			
			rset = pstmt.executeQuery();
			
			if(rset.next()) {
				
				at = new Attachment();
				at.setAttachmentNo(rset.getInt("ATTACHMENT_NO"));
				at.setAttachmentName(rset.getString("ATTACHMENT_NAME"));
				at.setAttachmentRename(rset.getString("ATTACHMENT_RENAME"));
				at.setAttachmentPath(rset.getString("ATTACHMENT_PATH"));
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(rset);
			close(pstmt);
		}
		 return at;
		  
	 }

 

7. Board

	// 일반게시글 상세 조회용 생성자
	public Board(int genNo, String genCategory, String gameNo, String memNo, String genTitle, String genContent,
			Date genRegister, int genViews) {
		super();
		this.genNo = genNo;
		this.genCategory = genCategory;
		this.gameNo = gameNo;
		this.memNo = memNo;
		this.genTitle = genTitle;
		this.genContent = genContent;
		this.genRegister = genRegister;
		this.genViews = genViews;
	}

 

7. board-mapper.xml

	<entry key="increaseCount">
		UPDATE GEN_BOARD
			SET GEN_VIEWS = GEN_VIEWS + 1
		WHERE GEN_NO = ?
			AND GEN_SHOW = 'Y'
	</entry>
	
	<entry key="selectBoard">
		SELECT GEN_NO
		     , GEN_CATEGORY
		     , GAME_NAME
		     , M.MEM_NICKNAME
		     , GEN_TITLE
		     , GEN_CONTENT
		     , GEN_REGISTER_DATE
		     , GEN_VIEWS
		FROM GEN_BOARD B
		LEFT JOIN MEMBER M ON (B.MEM_NO = M.MEM_NO)
		LEFT JOIN GAME USING (GAME_NO)
		WHERE GEN_NO = ?
		    AND GEN_SHOW = 'Y'
	</entry>
	
	<entry key="selectAttachment">
		SELECT ATTACHMENT_NO
			 , ATTACHMENT_NAME
			 , ATTACHMENT_RENAME
			 , ATTACHMENT_PATH
		FROM ATTACHMENT
		WHERE GEN_NO = ?
			AND ATTACHMENT_STATUS = 'N'
	</entry>

 

🤦🏻‍♀️ 아이디 저장 쿠키

더보기

1. memberLoginForm.jsp

<%
	String contextPath = request.getContextPath();

	// 쿠키 불러오기
	// => request.getCookies() 메소드 => Cookie 타입의 배열로 리턴
	Cookie[] cookies = request.getCookies();
	
	// 배열에 담긴 여러 개의 쿠키 세트들 중에 내가 원하는 쿠키만 골라내는 작업 진행
	String saveEmail = "";
	if(cookies != null) {
		
		for(int i = 0; i < cookies.length; i++) {
			
			// System.out.println(i + " : " + cookies[i].getName() + " / " + cookies[i].getValue());
			// 서버는 기본적으로 JSSESIONID라는 쿠키를 만들어 줌
			// 쿠키로부터 name(키값)을 뽑아내려면 getName(), value(밸류값)을 뽑아내려면 getValue() 메소드 이용
			
			if(cookies[i].getName().equals("saveEmail")) {
				saveEmail = cookies[i].getValue();
				break; // 안 걸어도 상관없지만 쿠키가 많은 경우 해당 쿠키를 찾은 이후로는 굳이 계속 반복 돌면서 낭비할 필요가 없음!
			}
		}
	}
	
	// 이 시점 기준으로 "saveId"라는 키값을 가진 쿠키가 있었다면 String 타입으로 saveId라는 변수에 해당 아이디값 자체가 담겨 있을 것!
%>


<tr>
    <th id="emailSave">
        <input type="checkbox" id="saveEmail" name="saveEmail" value="y">
        <label for="saveEmail">이메일 저장</label>                        		
    </th>
</tr>


<script>
    // 모든 요소들이 화면에 다 로딩된 후 saveEmail이라는 자바 변수에 저장된 값을 불러옴
    // 이메일 입력창에 value 속성으로 설정해 둘 것 & 아이디 저장하기 체크박스에 체크 수행
    $(function () {

        var saveEmail = "<%= saveEmail %>";

        if(saveEmail != "") { // 쿠키가 있다면

            $("#login_form input[name=memEmail]").val(saveEmail);
            $("#saveEmail").attr("checked", true);
        }

    });

    function enrollPage() {
        location.href = "<%=contextPath %>/enrollForm.me";
    }
</script>

 

2. LoginController

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	    // 로그인 정보는 POST 방식으로 처리해야 함 => 인코딩 처리
	    request.setCharacterEncoding("UTF-8");
	    
	    // 요청 시 전달값을 꺼내기
	    // memEmail: 아이디 값(이메일)
	    String memEmail = request.getParameter("memEmail");
	    // memPwd: 비밀번호 값
	    String memPwd = request.getParameter("memPwd");
	    // memNickname: 닉네임값 (성공 메시지 표출 때 보여 주고자 함)
	    String memNickname = request.getParameter("memNickname");
	    // 이메일 저장
	    String saveEmail = request.getParameter("saveEmail"); // 체크를 했다면 "y", 하지 않았다면 null 값이 넘어옴
        
        if(saveEmail != null && saveEmail.equals("y")) {
            
            // 아이디를 저장하겠다
            // => saveEmail라는 키값으로 넘겨받았던 아이디값을 쿠키로 저장
            
            Cookie cookie = new Cookie("saveEmail", memEmail); // "saveId" - "user01"
            
            //                     1분          ==        60초
            //        1시간 ==      60분          ==      60 * 60초
            // 하루 == 24시간 == 1 * 24 * 60분 == 1 * 24 * 60 * 60초
            // 이틀 == 48시간 == 2 * 24 * 60분 == 2 * 24 * 60 * 60초
            cookie.setMaxAge(1 * 24 * 60 * 60); // 만료기간 1일 (초단위 작성)
            
            // 쿠키를 브라우저로 넘기기 => 응답 정보에 첨부함 (response 객체 사용)
            response.addCookie(cookie);
            
        } else {
            
            // 아이디를 저장하지 않겠다
            // => 아이디를 저장하고 있었던 쿠키 자체를 삭제
            // (쿠키를 삭제시키지 않으면 만료일까지 계속 살아 있기 때문)
            
            Cookie cookie = new Cookie("saveEmail", memEmail);
            cookie.setMaxAge(0); // 0초
            response.addCookie(cookie);
            
        }
	    
	    // 요청 시 전달값들을 VO 객체로 가공
	    Member m = new Member();
	    m.setMemEmail(memEmail);
	    m.setMemPwd(memPwd);
	    
	    // 가공한 VO 객체를 해당 요청을 처리하는 서비스 클래스의 메소드로 넘기기
	    Member loginUser = new MemberService().loginMember(m);
	    
	    // 처리된 결과 응답 뷰 지정
	    if(loginUser == null) { // 로그인 실패 => 에러 문구를 담아서 에러 페이지로 응답하기
	        
	        request.setAttribute("errorMsg", "로그인에 실패했습니다.");
	        RequestDispatcher view = request.getRequestDispatcher("views/common/errorPage.jsp");
	        view.forward(request, response);
	       
	    } else { // 로그인 성공 => 응답 페이지에 loginUser 데이터 전달, 메인 페이지로 응답
	        
	        HttpSession session = request.getSession();
	        session.setAttribute("loginUser", loginUser);
	        
	        session.setAttribute("alertMsg", loginUser.getMemNickname() + "님! 오늘도 즐거운 게임 하세요!");
	        response.sendRedirect(request.getContextPath());
	    }
	    
	}

 


<회원가입>

🤦🏻‍♀️ 개인정보 수집 및 이용 동의

더보기

1. header.jsp

<% if (loginUser == null) { %>
    <li>
        <a id="login_menu" onclick="loginPage();">로그인</a>
        <ul>
            <li><a onclick="loginPage();">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;로그인</a></li>
            <li><a onclick="enrollPolicyPage();">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;회원가입</a></li>
        </ul>
    </li>
<% } else { %>
    <li>
    <a href="" class="main_menu">
        <img src="resources/image/profile/profile_default.png" id="header_profile">
        InsertCoin
    </a>
    <ul>
        <li><a href="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;마이페이지</a></li>
        <li><a href="<%= contextPath %>/logout.me">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;로그아웃</a></li>
    </ul>
</li>
<% } %>


    <script>
  	
    	function enrollPolicyPage() {
    		location.href = "<%=contextPath %>/enrollPolicy.me";
    	}
    	
    </script>

 

2. memberEnrollPolicy.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입_동의</title>
    <!-- CSS 스타일시트 -->
    <link href="resources/css/memberEnrollPolicy.css" rel="stylesheet">
</head>
<body>

    <!-- 전체 영역 -->
    <div class="wrap">
    
		<%@ include file = "../../views/common/header.jsp" %>

		<!-- 컨텐츠 영역 -->
        <div class="content_container">

            <!-- 회원가입 창 -->
            <form id="enroll_form" action="<%= contextPath %>/enrollForm.me" method="post">
 
                <!-- 로고, 개인정보 수집 및 이용 동의 체크, 버튼 영역 -->
                <div class="enroll_content">
                    <!-- 회원가입 창 로고 -->
                    <div style="text-align:center;">
                        <img src="resources/image/logo/insertcoin_logo.png" alt="insert_coin_logo" id="enroll_logo">
                    </div>
                    <!-- 회원가입 글자 -->
                    <div id="enroll_text"><h3>회원가입</h3><hr></div>

                    <!-- 회원가입 개인정보 동의 폼 -->
                    <table align="center" id="enroll_table">
                        
                        <tr>
                            <th>개인정보 수집 및 이용 동의</th>
                            <td>(필수)</td>
                        </tr>
                        <tr>
                            <th colspan="2">
                                <textarea cols="40" rows="5" style="resize:none;" readonly>
INSERT COIN은 이용자들의 개인정보보호를 매우 중요시하며, 이용자가 회사의 서비스를 이용함과 동시에 온라인상에서 회사에 제공한 개인정보가 보호 받을 수 있도록 최선을 다하고 있습니다. 이에 INSERT COIN은 통신비밀보호법, 전기통신사업법, 정보통신망 이용촉진 및 정보보호 등에 관한 법률 등 정보통신서비스제공자가 준수하여야 할 관련 법규상의 개인정보보호 규정 및 정보통신부가 제정한 개인정보보호지침을 준수하고 있습니다. INSERT COIN은 개인정보 보호정책을 통하여 이용자들이 제공하는 개인정보가 어떠한 용도와 방식으로 이용되고 있으며 개인정보보호를 위해 어떠한 조치가 취해지고 있는지 알려 드립니다</textarea>
                            </th>
                        </tr>
                        <tr>
                            <th colspan="2">
                                <input type="checkbox" id="agreeCheck" name="agreeCheck" checked><label for="agree">개인정보 수집 및 이용에 동의합니다.</label>
                            </th>
                        </tr>
                    </table>
                    <br>
                    <div>
                     	<input type="button" id="reset_button" class="buttons" value="취소" onclick="goToHome();">
                     	<input type="button" id="submit_button" class="buttons" name="checkButton" onclick="enrollPage();" value="확인">
                    </div>
                       
                </div>
            </form>
        </div>
        
        <%@ include file = "../../views/common/footer.jsp" %>
     </div>
     
     <script>
     	function goToHome() {
     		location.href = "<%= contextPath %>";
     	}
     	
     	// 약관 동의 시 확인 버튼 클릭할 수 있게
     	$(function() {
     		
     		$("#agreeCheck").change (function () {
     			
     			var st = this.checked;
     			
     			if(st) {
     				$("input[name=checkButton]").prop("disabled", false);
     			} else {
     				$("input[name=checkButton]").prop("disabled", true);
     			}
     			
     		});
     		
     	});
     	
     	function enrollPage() {
     		location.href = "<%= contextPath %>/enrollForm.me";
     	}
     </script>

</body>
</html>

 

저작자표시 비영리 변경금지 (새창열림)
'📗 self-study/📗 KH정보교육원 당산지원' 카테고리의 다른 글
  • [11/3] 게시판 검색
  • [11/2] 게시판 상세조회, 게시글 수정, 게시글 삭제, 댓글 작성/수정/삭제
  • [10/31] 게시판
  • [10/30] 회원가입 디테일 잡기
천재강쥐
천재강쥐
  • 천재강쥐
    디버거도 버거다
    천재강쥐
  • 전체
    오늘
    어제
    • Category (467)
      • 진짜 너무 궁금한데 이걸 나만 몰라...? (0)
      • 💾 Portfolio (2)
      • 🐤 CodingTest (28)
        • Java (20)
        • ᕕ(ꐦ°᷄д°᷅)ᕗ❌ (5)
      • 🚀 from error to study (142)
        • AI (1)
        • Cloud (2)
        • DB (12)
        • Front-End (16)
        • Github (14)
        • Java (39)
        • Mac (7)
        • Normal (29)
        • Server (22)
      • 📘 certificate (44)
        • 📘 리눅스마스터1급 (1)
        • 📘⭕️ 정보처리기사 (40)
        • 📘⭕️ SQLD (3)
      • 📗 self-study (234)
        • 📗 inflearn (35)
        • 📗 생활코딩 (8)
        • 📗 KH정보교육원 당산지원 (190)
      • 🎨 Scoop the others (0)
        • 📖 Peeking into other people.. (0)
        • 🇫🇷 (0)
        • 📘⭕️ 한국사능력검정시험 심화 (11)
        • 오블완 (4)
  • 인기 글

  • hELLO· Designed By정상우.v4.10.1
천재강쥐
[11/1] 게시판 작성, 게시판 상세조회(게시글만), 아이디 저장 쿠키, 회원가입 동의
상단으로

티스토리툴바