2022. 10. 7. 16:29ㆍDev.Program/Java & Spring
<qna_board_write.jsp>
책 618
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>MVC_Board</title> <style type="text/css"> #registForm{ width:500px; height: 610px; border: 1px solid red; margin: auto; } h2 { text-align: center; } table { margin: auto; width: 450px; } .td_left { width: 150px; background: orange; } .td_right { width: 300px; background: skyblue; } #commandCell { text-align: center; } </style> </head> <body> <!-- 게시판 등록 --> <section id="writeForm"> <h2>게시판글등록</h2> <form action="BoardWritePro.bo" method="post" enctype="multipart/form-data" name="boardForm"> <table> <tr> <td class="td_left"><label for="board_name">글쓴이</label></td> <td class="td_right"><input type="text" name="board_name" id="board_name" required="required" /></td> </tr> <tr> <td class="td_left"><label for="board_pass">비밀번호</label></td> <td class="td_right"><input name="board_pass" type="password" id="board_pass" required="required" /></td> </tr> <tr> <td class="td_left"><label for="board_subject">제 목</label></td> <td class="td_right"><input name="board_subject" type="text" id="board_subject" required="required" /></td> </tr> <tr> <td class="td_left"><label for="board_content">내 용</label></td> <td><textarea id="board_content" name="board_content" cols="40" rows="15" required="required"></textarea></td> </tr> <tr> <td class="td_left"><label for="board_file"> 파일 첨부 </label></td> <td class="td_right"><input name="board_file" type="file" id="board_file" required="required" /></td> </tr> </table> <section id="commandCell"> <input type="submit" value="등록"> <input type="reset" value="다시쓰기" /> </section> </form> </section> <!-- 게시판 등록 --> </body> </html> |
> required = “required” 속성
- 경고메세지 / 자동포커스
> style =”resize:none;” 추가
- 이렇게 사이즈 조절되던 textarea 가
- →
> WEB-INF lib 폴더에
- cos.jar 넣기
- 주소창 확인(Ctrl+F11 로 들어가지 않기)
> 일단 여기서 아무거나 입력하고 글쓰기 버튼 클릭해보기
- 주소창 확인!
위에 실행되는 과정======================================================
BoardWriteForm.bo <view화면>
- BoardFrontController.java에서 BoardWriteForm.bo 입력할 경우 /board/qna_board_write.jsp 이동할 view 페이지 경로 지정해 둠
- (BoardWriteForm.bo → BoardFrontController.java → qna_board_write.jsp)
글쓰기 버튼 클릭 시
요청
→ BoardWritepro.bo요청으로 BoardFrontController.java 로 다시 감
BoardFrontController.java
- 여기서 execute 메서드를 호출
- (→ new BoardWriteProAction을 생성해서 execute 메서드 호출)
BoardWriteProAction.java
- execute 메서드에서
- (원래는 처리하고 ActionForward를 리턴해주는데 우린 지금 null 리턴)
다시 FrontController 로 가보면
- 여기에 null이 저장되는거!
- forward 에 null이 저장되어있기 때문에 이 부분 실행이 안되므로 그냥 그렇게 끝남!
====================================================================
569p
- 쿼리는 여기 저장해야함
- Alt + S 치면 현재 구문 실행됨(Ctrl+Alt+X는 전체실행)
Create table board ( board_num int, board_name varchar(20) not null, board_pass varchar(15) not null, board_subject varchar(50) not null, board_content varchar(2000) not null, board_file varchar(50) not null, board_re_ref int not null, board_re_lev int not null, board_re_seq int not null, board_readcount int default 0, board_date date, primary key(board_num) ); |
- 전체 선택(블럭 지정) 후 Alt + X
576p
======== vo 패키지에 BoardBean.java 만들기
< BoardBean.java >
package vo; import java.sql.Date; public class BoardBean { private int board_num; private String board_name; private String board_pass; private String board_subject; private String board_content; private String board_file; private int board_re_ref; private int board_re_lev; private int board_re_seq; private int board_readcount; private Date board_date; public int getBoard_num() { return board_num; } public void setBoard_num(int board_num) { this.board_num = board_num; } public String getBoard_name() { return board_name; } public void setBoard_name(String board_name) { this.board_name = board_name; } public String getBoard_pass() { return board_pass; } public void setBoard_pass(String board_pass) { this.board_pass = board_pass; } public String getBoard_subject() { return board_subject; } public void setBoard_subject(String board_subject) { this.board_subject = board_subject; } public String getBoard_content() { return board_content; } public void setBoard_content(String board_content) { this.board_content = board_content; } public String getBoard_file() { return board_file; } public void setBoard_file(String board_file) { this.board_file = board_file; } public int getBoard_re_ref() { return board_re_ref; } public void setBoard_re_ref(int board_re_ref) { this.board_re_ref = board_re_ref; } public int getBoard_re_lev() { return board_re_lev; } public void setBoard_re_lev(int board_re_lev) { this.board_re_lev = board_re_lev; } public int getBoard_re_seq() { return board_re_seq; } public void setBoard_re_seq(int board_re_seq) { this.board_re_seq = board_re_seq; } public int getBoard_readcount() { return board_readcount; } public void setBoard_readcount(int board_readcount) { this.board_readcount = board_readcount; } public Date getBoard_date() { return board_date; } public void setBoard_date(Date board_date) { this.board_date = board_date; } } |
570p
585p
BoardWritePro.bo 에서 BoardList.bo 주소 요청(주소 바뀜 == 리다이렉트)
BoardList.bo ⇒ qna_board_list.jsp 보여줄 거!
< BoardWriteProAction.java >
@Override public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception { // System.out.println("BoardWriteProAction"); // 현재 BoardWritePro.bo 에서 BoardList.bo 서블릿 주소를 요청하여 Redirect 방식으로 포워딩 // 1. ActionForward 객체 생성 ActionForward forward = new ActionForward(); // 2. 포워딩 방식 지정 => Redirect 방식이므로 파라미터에 true 전달(필수) forward.setRedirect(true); // 3. 포워딩 할 주소 지정 => 서블릿 주소 BoardList.bo 요청 forward.setPath("BoardList.bo"); // 4. ActionForward 객체 리턴 return forward; } |
→ 이제 이거 들고 FrontController 로 감
< BoardFrontController.java >
- 추가
else if(command.equals("/BoardList.bo")) { forward = new ActionForward(); forward.setPath("/board/qna_board_list.jsp"); } |
- 일단 else if 문 추가해놓기
- 이렇게 할 건 아니고 나중에는 list 가져올 거!
======== board 폴더에 qna_board_list.jsp 만들기
- 게시판 등록 페이지에서 등록 버튼 누르기
- 여기로 이동하면 됨!
======== WebContent 에 boardUpload 폴더 만들기
< BoardWriteProAction.java >
- javax.servlet
> 실제 저장되는 폴더 경로
- D:\workspace_jsp_model2\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\MVC_Board\boardUpload
- ⇒ 이클립스로 실행하기 때문에 이 경로를 찾아가는 거!
< BoardWriteProAction.java >
- 파라미터 5개 짜리
@Override public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception { // System.out.println("BoardWriteProAction"); // 현재 컨텍스트(객체) 정보 가져오기 위해 request 객체로부터 getServletContext() 메서드 호출 ServletContext context = request.getServletContext(); // 프로젝트 상에서의 가상 업로드 폴더 위치 지정 String saveFolder = "/boardUpload"; // 현재 위치(WebContent)의 하위폴더이므로 "/폴더명" 사용 // ServletContext 객체를 사용하여 가상 폴더에 대응하는 실제 폴더 위치 가져오기 // => 이클립스 사용 시 실제 업로드 폴더 위치 // 워크스페이스\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps 폴더 내의 // 프로젝트명에 해당하는 폴더가 있으며 그 폴더 내에 업로드 폴더가 위치함 String realFolder = context.getRealPath(saveFolder); // 업로드 할 최대 파일 사이즈 지정(전체 숫자 입력 보단 단위별로 분리하는 것이 좋다!) int fileSize = 1024 * 1024 * 10; // 1024byte = 1KByte * 1024 = 1MB * 10 = 10MB // MultiPartRequest 객체 생성 => cos.jar 필요 MultipartRequest multi = new MultipartRequest( request, // request 객체 전달 realFolder, // 파일이 업로드 될 실제 폴더 fileSize, // 한 번에 업로드 가능한 파일 최대크기 "UTF-8", // 파일 명에 대한 인코딩 방식 new DefaultFileRenamePolicy() // 파일명 중복 시 중복 파일명을 처리할 객체 ); // 게시글 작성을 위해 입력받은 데이터를 저장할 BoardBean 객체 생성 // => MultiPartRequest 객체로부터 입력받은 데이터를 가져와서 BoardBean 객체에 저장 BoardBean bb = new BoardBean(); bb.setBoard_name(multi.getParameter("board_name")); bb.setBoard_pass(multi.getParameter("board_pass")); bb.setBoard_subject(multi.getParameter("board_subject")); bb.setBoard_content(multi.getParameter("board_content")); bb.setBoard_file(multi.getOriginalFileName((String)multi.getFileNames().nextElement())); System.out.println("작성자 : " + bb.getBoard_name()); System.out.println("패스워드 : " + bb.getBoard_pass()); System.out.println("제목 : " + bb.getBoard_subject()); System.out.println("내용 : " + bb.getBoard_content()); System.out.println("파일명 : " + bb.getBoard_file()); // 현재 BoardWritePro.bo 에서 BoardList.bo 서블릿 주소를 요청하여 Redirect 방식으로 포워딩 // 1. ActionForward 객체 생성 ActionForward forward = new ActionForward(); // 2. 포워딩 방식 지정 => Redirect 방식이므로 파라미터에 true 전달(필수) forward.setRedirect(true); // 3. 포워딩 할 주소 지정 => 서블릿 주소 BoardList.bo 요청 forward.setPath("BoardList.bo"); // 4. ActionForward 객체 리턴 return forward; } |
- 같은 파일을 계속 넣을 경우 파일탐색기 에서 이런식으로 저장됨 (파일명 뒤에 숫자 저장됨)
bb.setBoard_file(multi.getOriginalFileName( (String)multi.getFileNames().nextElement() ));
- 실행창
- 파일의 원본 이름
bb.setBoard_file(multi.getFilesystemName( (String)multi.getFileNames().nextElement() ));
- 파일이 업로드되서 저장되는 이름
< Service 클래스 >
======== svc 패키지에 BoardWriteProService.java 만들기
XXXService로 만듬! Action 패키지랑만 관련있음!
599p
- 호출하려면 계속 인스턴스를 생성해야함(비효율적)
⇒ 그래서 static 메서드로 만든다! 그럼 클래스명.메서드() 로 호출 가능!
- 이런식으로! 근데 더 간단하게 가능!
< static import 기능 >
- static 으로 만들어진 멤버들을 그냥 불러올 수 있다!
- import static db.jdbcUtil.*;
- 이렇게 쓰면 이제 밑에 오류남!
- jdbcUtil 지워보기!
package svc; import java.sql.Connection; //import db.jdbcUtil; import vo.BoardBean; //static import 기능을 사용하여 db 패키지의 JdbcUtil 클래스명 내에 있는 메서드를 지정시 //클래스명 없이 바로 메서드를 호출할 수 있다! //=> db.JdbcUtil.getConnection; 이라고 지정하면 getConnection() 메서드만 호출 가능하지만 // db.JdbcUtil.*; 형태로 지정하면 JdbcUtil 클래스의 모든 static 메서드를 호출 가능 import static db.jdbcUtil.*; //Action 클래스로부터 요청받은 작업을 DAO 클래스를 사용하여 처리하고 그 결과를 리턴하는 클래스 public class BoardWriteProService { // 글 등록 요청 처리를 위한 registArticle() 메서드 정의 // => 파라미터 : BoardBean 객체(boardBean) // => 리턴타입 : boolean public boolean registArticle(BoardBean bb) { boolean isWriteSuccess = false; // 글 등록 성공 여부를 리턴할 변수 // DB 작업을 위한 준비 => Connection 객체, DAO 객체, DAO 객체의 메서드 호출 // Connection con = JdbcUtil.getConnection(); Connection con = getConnection(); // static import 로 지정된 메서드 호출 return isWriteSuccess; } } |
======== dao 패키지로 가서 BoardDAO.java 만들기
- 싱글톤 패턴 구현
★ < 싱글톤 패턴 실제 정의할 때의 문법 순서 > ★
1. 멤버변수 선언 및 인스턴스 생성(private static)
2. 생성자 정의(private)
3. Getter 정의(public static)
package dao; import java.sql.Connection; public class BoardDAO { /* * ------------ 싱글톤 디자인 패턴을 활용한 BoardDAO 인스턴스 작업 ------------- * 1. 외부에서 인스턴스 생성이 불가능하도록 private 접근제한자를 사용하여 생성자 정의 * 2. 직접 인스턴스를 생성하여 변수(instance)에 저장 * 3. 외부에서 인스턴스를 전달받을 수 있도록 Getter 메서드 정의 * 4. getInstance() 메서드에 인스턴스 생성없이 접근 가능하도록 static 메서드로 정의 * => 메서드 내에서 접근하는 멤버변수 instance 도 static 변수로 정의 * 5. 인스턴스를 통해 instance 변수에 접근 불가능하도록 접근제한자 private 지정 */ private BoardDAO() {} private static BoardDAO instance; public static BoardDAO getInstance() { // BoardDAO 객체가 없을 경우에만 생성 if(instance == null) { instance = new BoardDAO(); } return instance; } // --------------------------------------------------------------------------------- Connection con; // Connection 객체 전달받아 저장할 변수 선언 // Service 클래스로부터 Connection 객체를 전달받는 메서드 setConnection() 정의 public void setConnection(Connection con) { this.con = con; // 이름이 똑같기 때문에 this. 적음 } } |
public int insertArticle(BoardBean boardBean) { int insertCount = 0; return insertCount; } |
- 추가!
< BoardWriteProService.java >
- 이 4개는 무조건 세트! (Service 클래스에선 무조건 쓴다)
package svc; import java.sql.Connection; import dao.BoardDAO; //import db.JdbcUtil; import vo.BoardBean; // static import 기능을 사용하여 db 패키지의 JdbcUtil 클래스명 내에 있는 메서드를 지정시 // 클래스명 없이 바로 메서드를 호출할 수 있다! // => db.JdbcUtil.getConnection; 이라고 지정하면 getConnection() 메서드만 호출 가능하지만 // db.JdbcUtil.*; 형태로 지정하면 JdbcUtil 클래스의 모든 static 메서드를 호출 가능 import static db.jdbcUtil.*; // Action 클래스로부터 요청받은 작업을 DAO 클래스를 사용하여 처리하고 그 결과를 리턴하는 클래스 public class BoardWriteProService { // 글 등록 요청 처리를 위한 registArticle() 메서드 정의 // => 파라미터 : BoardBean 객체(boardBean) // => 리턴타입 : boolean public boolean registArticle(BoardBean boardBean) { System.out.println("BoardWriteProService - registArticle()"); boolean isWriteSuccess = false; // 글 등록 성공 여부를 리턴할 변수 // DB 작업을 위한 준비 => Connection 객체, DAO 객체, DAO 객체의 메서드 호출 // 1. DB 작업에 필요한 Connection 객체 가져오기 // Connection con = JdbcUtil.getConnection(); Connection con = getConnection(); // static import 로 지정된 메서드 호출 // 2. DB 작업을 위한 BoardDAO 객체 생성 => 싱글톤 패턴으로 생성된 객체 가져오기 BoardDAO boardDAO = BoardDAO.getInstance(); // 3. BoardDAO 객체에 Connection 객체 전달 boardDAO.setConnection(con); // 4. BoardDAO 객체의 insertArticle() 메서드를 호출하여 글 등록 처리 // => 파라미터 : BoardBean 객체, 리턴타입 : int(insertCount) int insertCount = boardDAO.insertArticle(boardBean); // 5. 리턴받은 작업 결과 판별 // => insertCount 가 0보다 크면 commit() 실행, isWriteSuccess 를 true 로 변경 // => 아니면, rollback() 실행 if(insertCount > 0) { commit(con); isWriteSuccess = true; } else { rollback(con); } // 6. Connection 객체 반환 close(con); // 7. 작업 결과 리턴 return isWriteSuccess; } } |
< BoardWriteProAction.java >
// BoardWriteProService 클래스의 인스턴스 생성 BoardWriteProService boardWriteProService = new BoardWriteProService(); // registArticle() 메서드를 호출하여 글 등록 요청 // => 파라미터 : BoardBean 객체, 리턴타입 : boolean(isWriteSuccess) boolean isWriteSuccess = boardWriteProService.registArticle(boardBean); // 리턴받은 결과를 사용하여 글 등록 결과 판별 if(!isWriteSuccess) { System.out.println("글 등록 실패!"); } else { System.out.println("글 등록 성공!"); } |
- 추가 해주기!
> Server 재시작 후 다시 글쓰기부터 실행해보기 ⇒ 글등록 눌렀을 때 콘솔창에
- 이렇게 떠야함(지금은 BoardDAO insertArticle() 메서드에서 insertCount에 0을 return 했기 때문!)
> 어디서 오류났는지 모를 때
어디서 오류났는 지 모를 때엔 Action.java / Service.java 중간중간에
System.out.println("A");
System.out.println("B");
System.out.println("C");
이런 식으로 적어 놓고 다시 실행시켜보기!
B 까지 나온다면 B 이후가 잘못된거고 이런식으로 알 수 있음!
> DB 적용이 됐었는데 갑자기 안될 때
- 프로젝트 우클릭 & Refresh
글이 성공했을 때에만 BoardList.bo로 넘어가야함!
- 끌고 올라가면
- return 할 게 없어서 오류남
- 안에서 리턴해주고 밑에서 null 리턴하는 방법
우린 저거 말고 다른 방법
- 맨 위에 선언!
- 이렇게 바꿔줌
==== 주말동안 새 프로젝트 만들어보기!
'Dev.Program > Java & Spring' 카테고리의 다른 글
MVC2 - (4) (0) | 2022.10.07 |
---|---|
MVC2 - (3) (0) | 2022.10.07 |
MVC2 - (1) (0) | 2022.10.07 |
자바 Swing(스윙) - (5) (0) | 2022.10.06 |
자바 Swing(스윙) - (4) (0) | 2022.10.06 |