헬린코린이

[Servlet & JSP] MVC 모델 2 이용한 JSP 본문

Programming/Servlet & JSP

[Servlet & JSP] MVC 모델 2 이용한 JSP

HCD 2023. 1. 2. 18:59

먼저 가볍게 MVC 패턴을 설명하자면

소프트웨어 공학도에서 사용하는 디자인 패턴 중 하나로 Model, View, Controller의 앞 글자를 따서 만든 디자인 패턴입니다.

Model : 백그라운드에서 동작하며, 사용자가 원하는 데이터나 정보를 제공합니다.

View : 사용자의 요청을 화면으로 출력합니다.

Controller: 사용자의 요청을 처리하고, 그 요청에 따른 전체적인 흐름을 제어합니다.

 

사용자는 얻고자 하는 정보나 기능을 컨트롤러에게 요청합니다.

컨트롤러는 사용자의 요청을 수신하고 그에 맞는 비즈니스 로직을 수행합니다.

비즈니스 로직을 수행하면서 컨트롤러는 필요에 따라 모델을 호출하여 데이터를 요청합니다.

요청을 모두 처리하면 뷰를 통해 사용자가 원하는 정보를 시작적으로 보여줍니다.

MVC 패턴은 크게 모델 1, 모델 2로 나뉘는데

여기서는 모델 2를 이용하였습니다.

모델 2는 모델 1에서 유지보스가 힘들다는 단점을 보완하기 위해 나온 모델입니다.

기존에 뷰와 컨트롤러의 역할을 모두 수행하던 JSP는 뷰의 역할만 하게 하고,

대신 컨트롤러 역할을 Servlet이 수행합니다.

 

MVC2로 개발하게 되면 HTML과 JAVA 코드가 분리되어 확장에 용이하고 유지보수가 수월해집니다.

하지만 초기 설계단계에서 비용이 많이 들어 개발 시간이 오래 걸린다는 단점이 있습니다.

그렇다면 MVC2를 이용한 JSP코드를 간단하게 보겠습니다.

우선 데이터베이스와 연동을 위해 

JDBCUtil 이라는 파일을 만들어 결합도를 낮추었습니다.

package common;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class JDBCUtil {
	
	// MySQL 설정
	static final String driverName="com.mysql.jdbc.Driver";
	static final String url="jdbc:mysql://localhost/테이블";
	static final String user="아이디";
	static final String passwd="비밀번호";
	public static Connection connect() {
		Connection conn=null;
		try {
			Class.forName(driverName);
			conn=DriverManager.getConnection(url, user, passwd);
		} catch(Exception e) {
			e.printStackTrace();
		} 
		return conn;
	}
	public static void disconnect(Connection conn,PreparedStatement pstmt) {
		try {
			pstmt.close();
			conn.close();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

MemberVO를 만들어주었습니다.

package member;

public class MemberVO {
	private String id;
	private String pw;
	private String name;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPw() {
		return pw;
	}
	public void setPw(String pw) {
		this.pw = pw;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() { //확인하기 위해 toString오버라이딩
		return "MemberVO [id=" + id + ", pw=" + pw + ", name=" + name + "]";
	}
}

DAO입니다.

package member;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import common.JDBCUtil;

public class MemberDAO {
	Connection conn;
	PreparedStatement pstmt;
	// 관리하기 편하기 위에서 관리 
	final String INSERT="INSERT INTO MEMBER VALUES(?,?,?)"; //insert 쿼리문
	final String UPDATE="UPDATE MEMBER SET PW=? WHERE ID=?"; // update 쿼리문
	final String DELETE="DELETE FROM MEMBER WHERE ID=?"; // delete 쿼리문
	final String SELECTONE="SELECT * FROM MEMBER WHERE ID=?"; // selectOne 쿼리문
	final String SELECTALL="SELECT * FROM MEMBER"; //selectAll 쿼리문
	//C
	public boolean insert(MemberVO mvo) {
		conn=JDBCUtil.connect(); //JDBCUtuil파일을 이용해 데이터베이스에 연결해줍니다.
		try { //혹시 모를 예외를 try-catch로 잡아줍니다.
			pstmt=conn.prepareStatement(INSERT); //insert쿼리문을 이용해 PreparedStatement 에 저장하고
			pstmt.setString(1, mvo.getId()); // 1번 ? 에 매개변수로 받아온 값을 세팅해주고
			pstmt.setString(2, mvo.getPw()); // 2번 ? 에 매개변수로 받아온 값을 세팅해주고
			pstmt.setString(3, mvo.getName()); // 3번 ? 에 매개변수로 받아온 값을 세팅해줍니다.
			pstmt.executeUpdate(); //다 세팅해주었으면 업데이트를 해주고
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {
			JDBCUtil.disconnect(conn, pstmt); // 위에 코드가 다 실행되었다면 무조건 실행될 수 있는 Finally이용해 데이터베이스 접근을 닫아줍니다.
		}
		return true;
	}
	//U
	public boolean update(MemberVO mvo) {
		conn=JDBCUtil.connect();	 //데이터베이스의 연결하고
		try {
			pstmt=conn.prepareStatement(UPDATE); //PreparedStatement에 update쿼리문을 넣고
			pstmt.setString(1, mvo.getPw()); // 1번째 ? 에 매개변수로 받아온 값을 세팅해주고
			pstmt.setString(2, mvo.getId());	// 2번째 ? 에 매개변수로 받아온 값을 세팅해줍니다.
			pstmt.executeUpdate(); //업데이트 해주고
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {
			JDBCUtil.disconnect(conn, pstmt);
		}// 위에 코드가 다 실행되었다면 무조건 실행될 수 있는 Finally이용해 데이터베이스 접근을 닫아줍니다.
		return true;
	}
	//D
	public boolean delete(MemberVO mvo) {
		conn=JDBCUtil.connect();//데이터베이스의 연결하고
		try {
			pstmt=conn.prepareStatement(DELETE);//PreparedStatement에 delete쿼리문을 넣고
			pstmt.setString(1, mvo.getId());	 // 1번째 ?에 매개변수로 받아온 값을 세팅해둡니다.
			pstmt.executeUpdate(); //업데이트 해주고
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {// 위에 코드가 다 실행되었다면 무조건 실행될 수 있는 Finally이용해 데이터베이스 접근을 닫아줍니다.
			JDBCUtil.disconnect(conn, pstmt);
		}
		return true;
	}
	//R
	public MemberVO selectOne(MemberVO mvo) {
		MemberVO data=null;
		conn=JDBCUtil.connect();//데이터베이스의 연결하고
		try {
			pstmt=conn.prepareStatement(SELECTONE);//PreparedStatement에 selectOne쿼리문을 넣고
			pstmt.setString(1, mvo.getId());	//1번쨰 ?에 매개변수로 받아온 값을 세팅해줍니다.
			ResultSet rs=pstmt.executeQuery(); // 값을 받와와야하기 때문에 ResultSet에 데이터베이스에서 받아온 값을 저장해주고
			if(rs.next()) { //값이 하나이기때문에 if문으로 .next()메서드를 호출하여 사용합니다.
				data=new MemberVO();//불러온 값을 저장하기 위한 인스턴스를 하나 생성해주고
				data.setId(rs.getString("ID"));  
				data.setName(rs.getString("NAME"));
				data.setPw(rs.getString("PW"));
			} // 그 인스턴스에 하나하나 저장해줍니다.
		} catch (SQLException e) {
			e.printStackTrace();
			return null; //받아온 값이 없다면 null을 반환합니다.
		} finally {// 위에 코드가 다 실행되었다면 무조건 실행될 수 있는 Finally이용해 데이터베이스 접근을 닫아줍니다.
			JDBCUtil.disconnect(conn, pstmt);
		}
		return data;
	}
	//R
	public ArrayList<MemberVO> selectAll(MemberVO mvo) {
		ArrayList<MemberVO> datas=new ArrayList<MemberVO>();
		conn=JDBCUtil.connect();//데이터베이스의 연결하고
		try {
			pstmt=conn.prepareStatement(SELECTALL);//PreparedStatement에 selectAll쿼리문을 넣고
			ResultSet rs=pstmt.executeQuery(); //이것또한 값을 받아와야하기때문에 ResultSet에 저장해줍니다.
			while(rs.next()) { //값이 여러개이기에 while문을 이용하였고
				MemberVO data=new MemberVO(); //list에 추가하기위해 임시 인스턴스를 만들어주고
				data.setId(rs.getString("ID"));
				data.setName(rs.getString("NAME"));
				data.setPw(rs.getString("PW"));
				datas.add(data); //list에 추가해줍니다.
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {// 위에 코드가 다 실행되었다면 무조건 실행될 수 있는 Finally이용해 데이터베이스 접근을 닫아줍니다.
			JDBCUtil.disconnect(conn, pstmt);
		}
		return datas;
	}
}

이제 jsp입니다.

index.jsp가 암묵적으로 지정된 첫 페이지입니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	response.sendRedirect("b_controller.jsp?action=main"); // 나, 회원목록 보여줘!
%>

 

메인인 Controller 모든 v나 m은 이곳을 거쳐가야 합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="member.*,java.util.*" errorPage="error/error.jsp" %>
<% request.setCharacterEncoding("UTF-8"); %>
<jsp:useBean id="mdao" class="member.MemberDAO" />
<jsp:useBean id="mvo" class="member.MemberVO" />
<jsp:setProperty property="*" name="mvo" />
<%
	String action=request.getParameter("action");
	// 사용자가 어떤 요청을 했는지에 대한 정보
	
	if(action.equals("main")){ //사용자가 넘겨준 action이 main이라면
		ArrayList<MemberVO> datas=mdao.selectAll(null); //m에 접근해서 값을 가져오고
		request.setAttribute("datas", datas); //그 값을 request에 저장합니다.
		pageContext.forward("b_main.jsp"); //그리고 main.jsp로 이동합니다.
	}
	else if(action.equals("mypage")){ //action이 mypage라면
		MemberVO data=mdao.selectOne(mvo); //값이 있는지 확인하고
		request.setAttribute("data", data); // 그 값을 request에 저장해줍니다.
		pageContext.forward("b_mypage.jsp");// 그리고 main.jsp로 이동합니다.
	}
	else if(action.equals("insert")){ //action이 insert라면
		if(mdao.insert(mvo)){ //추가가 완료 되었다면
			response.sendRedirect("b_controller.jsp?action=main"); //컨트롤러 main조건문을 실행합니다.
		}
		else{
			out.println("<SCRIPT>alert('등록 실패했습니다!');history.go(-1);</SCRIPT>");// 실패했다면 alert창을 띄어주고 다시 회원가입창으로 돌아갑니다.
		}
	}
	else if(action.equals("update")){ //action이 update라면
		if(mdao.update(mvo)){ //업데이트가 완료 되었다면
			response.sendRedirect("b_controller.jsp?action=main"); //컨트롤러 main조건문을 실행합니다.
		}
		else{
			out.println("<SCRIPT>alert('변경 실패했습니다!');history.go(-1);</SCRIPT>"); //실패했다면 alert창을 띄어주고 다시 정보변경창으로 돌아갑니다.
		}
	}
	else if(action.equals("delete")){ //action이 delete라면
		if(mdao.delete(mvo)){ //회원탈퇴가 완료 되었다면
			response.sendRedirect("b_controller.jsp?action=main");//컨트롤러 main조건문을 실행합니다.
		}
		else{
			out.println("<SCRIPT>alert('삭제 실패했습니다!');history.go(-1);</SCRIPT>"); //실패했다면 alert창을 띄어주고 다시 회원탈퇴창으로 돌아갑니다.
		}
	}
	else{
		out.println("<SCRIPT>alert('없는 요청입니다!');history.go(-1);</SCRIPT>");// 이 모든 것에 해당 안된다면 alert를 실행해주고 돌아갑니다.
	}
%>

회원가입하는 페이지입니다.

중복값은 처리하지 않았습니다. 간단한 예제이기에

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:useBean id="data" class="member.MemberVO" scope="request" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<form action="b_controller.jsp" method="post">
<input type="hidden" name="action" value="insert"> <!-- ?action=insert -->
아이디: <input type="text" name="id" required> <br>
비밀번호: <input type="password" name="pw" required> <br>
이름: <input type="text" name="name" required> <br>
<input type="submit" value="멤버등록">
</form>
<hr>
<a href="b_controller.jsp?action=main">메인으로 돌아가기</a>

</body>
</html>

회원가입한 정보들을 보여주는 main페이지입니다.

 

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="member.*,java.util.*" %>
<jsp:useBean id="datas" class="java.util.ArrayList" scope="request" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<table border="1">
	<tr>
		<th>ID</th><th>PW</th><th>NAME</th>
	</tr>
	<%
		for(MemberVO v:(ArrayList<MemberVO>)datas){
	%>
	<tr>
		<td><a href="b_controller.jsp?action=mypage&id=<%=v.getId()%>"><%=v.getId()%></a></td><td><%=v.getPw()%></td><td><%=v.getName()%></td>
	</tr>
	<%
		}
	%>
</table>
<hr>
<a href="b_insert.jsp">새 멤버 등록하기</a>

</body>
</html>

정보변경과 삭제를 같이 한 페이지입니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<jsp:useBean id="data" class="member.MemberVO" scope="request" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<script type="text/javascript">
	function del(){
		ans=confirm("정말 삭제하시겠습니까?");
		if(ans==true){
			document.form.action.value="delete";
			document.form.submit();
		}
		else{
			return;
		}
	}
</script>

<form action="b_controller.jsp" method="post" name="form">
<input type="hidden" name="action" value="update">
아이디: <input type="text" name="id" value="<%=data.getId()%>" readonly> <br>
비밀번호: <input type="password" name="pw" required> <br>
이름: <input type="text" name="name" value="<%=data.getName()%>" readonly> <br>
<input type="submit" value="멤버정보변경"> <input type="button" value="멤버삭제" onClick="del()">
</form>
<hr>
<a href="b_controller.jsp?action=main">메인으로 돌아가기</a>

</body>
</html>

 

Comments