MVC2 - (2) Service 클래스

2022. 10. 7. 16:29Dev.Program/Java & Spring

728x90

<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="등록">&nbsp;&nbsp; <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 리턴하는 방법

 

우린 저거 말고 다른 방법

  • 맨 위에 선언!
  • 이렇게 바꿔줌



==== 주말동안 새 프로젝트 만들어보기!



728x90

'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