Programming Language/Javascript, ...

웹페이지 만들기(1) - 로그인(메뉴바)

Ma_Sand 2022. 5. 3. 09:31
반응형

Template

public class Template {
	// 1. Connection 객체 생성(DB 접속)한 후 Connection을 반환하는 메소드
	public static Connection getConnection() {
		// Map 계열 컬렉션(key-value)
		Properties prop=new Properties();
		
		// 읽어들일 driver.properties 파일의 물리적인 경로 설정
		// 실질적으로 배포되는 폴더는 WebContent이기 때문에 src/db/driver/driver.properties로 읽으면 안됨
		// WebContent/WEB-INF/classes에 있는 파일을 읽어야 함
		String fileName = JDBCTemplate.class.getResource("/db/driver/driver.properties").getPath();
		try {
			prop.load(new FileInputStream(fileName));
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		//  1) JDBC driver 등록
		Connection conn=null;
		
		try {
			Class.forName(prop.getProperty("driver"));
			conn=DriverManager.getConnection(prop.getProperty("url")
					                       , prop.getProperty("username")
					                       , prop.getProperty("password"));
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}
	
	// 2. 전달받은 Connection 객체를 가지고 commit해주는 메소드
	public static void commit(Connection conn) {
		try {
			if(conn!=null&&!conn.isClosed()) {
				conn.commit();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	// 3. 전달받은 Connection 객체를 가지고 rollback해주는 메소드
	public static void rollback(Connection conn) {
		try {
			if(conn!=null&&!conn.isClosed()) {
				conn.rollback();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	// 4. 전달받은 Connection 객체를 반납하는 메소드
	public static void close(Connection conn) {
		try {
			if(conn!=null&&!conn.isClosed()) {
				conn.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	// 5. 전달받은 Statement 객체를 반납시키는 메소드
	public static void close(Statement stmt) {
		try {
			if(stmt!=null&&!stmt.isClosed()) {
				stmt.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	// 6. 전달받은 ResultSet 객체를 반납시키는 메소드
	public static void close(ResultSet rset) {
		try {
			if(rset!=null&&!rset.isClosed()) {
				rset.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

 

 

 

 

VO

- SQL의 COLUMN_NAME와 DATA_TYPE을 Java 형태의 변수로 바꿔서 작성한다.

- 기본 생성자 구문과 매개변수 생성자 구문, setter/getter 메소드, overriding 구문을 작성한다.

public class Member {
	private int userNo; //USER_NO	NUMBER 
	private String userId;  //USER_ID	VARCHAR2(30 BYTE)
	private String userPwd;  //USER_PWD	VARCHAR2(100 BYTE)
	private String userName; //USER_NAME	VARCHAR2(15 BYTE)
	private String phone;  //PHONE	VARCHAR2(13 BYTE)
	private String email; //EMAIL	VARCHAR2(100 BYTE)
	private String address; //ADDRESS	VARCHAR2(100 BYTE)
	private String interst; //INTEREST	VARCHAR2(100 BYTE)
	private Date enrollDate;  //ENROLL_DATE	DATE
	private Date modifyDate;  //MODIFY_DATE	DATE
	private String status; //STATUS	VARCHAR2(1 BYTE)
	
	public Member() {}

	public Member(int userNo, String userId, String userPwd, String userName, String phone, String email,
			String address, String interst, Date enrollDate, Date modifyDate, String status) {
		super();
		this.userNo = userNo;
		this.userId = userId;
		this.userPwd = userPwd;
		this.userName = userName;
		this.phone = phone;
		this.email = email;
		this.address = address;
		this.interst = interst;
		this.enrollDate = enrollDate;
		this.modifyDate = modifyDate;
		this.status = status;
	}

	public Member(int userNo, String userId, String userPwd, String userName, String phone, String email,
			String address, String interst) {
		super();
		this.userNo = userNo;
		this.userId = userId;
		this.userPwd = userPwd;
		this.userName = userName;
		this.phone = phone;
		this.email = email;
		this.address = address;
		this.interst = interst;
	}

	public int getUserNo() {
		return userNo;
	}

	public void setUserNo(int userNo) {
		this.userNo = userNo;
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public String getUserPwd() {
		return userPwd;
	}

	public void setUserPwd(String userPwd) {
		this.userPwd = userPwd;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getInterst() {
		return interst;
	}

	public void setInterst(String interst) {
		this.interst = interst;
	}

	public Date getEnrollDate() {
		return enrollDate;
	}

	public void setEnrollDate(Date enrollDate) {
		this.enrollDate = enrollDate;
	}

	public Date getModifyDate() {
		return modifyDate;
	}

	public void setModifyDate(Date modifyDate) {
		this.modifyDate = modifyDate;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	@Override
	public String toString() {
		return "Member [userNo=" + userNo + ", userId=" + userId + ", userPwd=" + userPwd + ", userName=" + userName
				+ ", phone=" + phone + ", email=" + email + ", address=" + address + ", interst=" + interst
				+ ", enrollDate=" + enrollDate + ", modifyDate=" + modifyDate + ", status=" + status + "]";
	}
}

 

 

 

 

Controller

- servlet 파일로 작성한다.

- url/mappings에서 기존 파일 이름과 다른 이름으로 바꿔야 한다.

 

HttpServletRequest 객체와 HttpServletResponse 객체

 - request는 서버로 요청할 때의 정보(전달값, 전달방식 등)들이 담긴 객체이다.

 - response는 요청에 대해 응답할 객체이다.

 

응답페이지로 전달할 값이 있을 경우에 해당 전달값을 Servlet Scope 내장 객체에 담아서 보내야 한다.

Servlet Scope 내장 객체에는 application, session, request, page가 있다.

 - application: 웹 애플리케이션 전역에서 꺼내쓸 수 있는 가장 넓은 범위의 Scope이다.

 - session: session에 담은 데이터는 모든 jsp와 servlet에서 꺼내쓸 수 있다.

 - request: request에 담은 데이터는 해당 request를 포워딩한 응답 jsp에서만 꺼내쓸 수 있다.

 - page: 해당 jsp 페이지에서만 꺼내쓸 수 있다.

 

공통적으로 데이터를 담을 때 → .setAttribute("key", "value");

공통적으로 데이터를 얻을 때 → .getAttribute("key");

공통적으로 데이터를 지울 때 → .removeAttribute("key");

 

- 로그인 컨트롤러

@WebServlet("/login.me")
public class LoginController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
    public LoginController() {
        super();
    }
    
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 1) 전달값에 한글이 있을 경우 인코딩 처리를 해야 한다.(Post 방식)
		request.setCharacterEncoding("UTF-8");
        
		// 2) 요청 시 전달값(request의 parameter 영역)을 꺼내거 변수 또는 객체에 기록하기
		String userId = request.getParameter("userId");
		String userPwd = request.getParameter("userPwd");
        
		// 3) 해당 요청을 처리하는 서비스 클래스의 메소드를 호출
		Member loginUser=new MemberService().loginMember(userId, userPwd);
        
		// 4) 처리된 결과를 가지고 사용자에게 보여줄 뷰를 지정해서 포워딩 또는 url 재요청
		if(loginUser==null) { // 로그인 실패 -> 에러페이지 보여주기(RequestDispatcher 객체 사용)
			request.setAttribute("errorMsg", "로그인에 실패하였습니다.");
			// 응답페이지 jsp에 위임 시 필요한 객체
			RequestDispatcher view = request.getRequestDispatcher("views/common/errorPage.jsp");
			// 포워딩- 해당 경로로 선택된 뷰에 보내기
			view.forward(request,  response);
			
		} 
        // 로그인 성공 -> 인덱스 페이지로 돌아오기, 로그인 정보는 페이지를 이동해도 
        // 계속 가지고있어야 하므로 session 객체에 담아 사용한다.
        // Servlet에서 session을 사용하려면 객체를 얻어와야 한다.
        else { 
			HttpSession session = request.getSession();
			session.setAttribute("loginUser", loginUser);
			
			// 1. 포워딩 방식 응답 뷰 출력하기
			// RequestDispatcher view = request.getRequestDispatcher("응답페이지");
			// RequestDispatcher view = request.getRequestDispatcher("index.jsp");
			// view.forward(request, response);
            // session.removeAttribute("loginUser");
            
            // 2. url 재요청 방식
            response.sendRedirect(request.getContextPath());  // 동적 방식
		}
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

 

- 로그아웃 컨트롤러

@WebServlet("/logout.me")
public class LogoutController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public LogoutController() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 로그아웃 처리 -> session 만료시키기 invalidate() - session을 무효화(초기화)
		request.getSession().invalidate();
		
		// 응답페이지 -> JSP
		// index.jsp
		response.sendRedirect(request.getContextPath());
	}

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

 

 

 

 

Service

- Connection을 생성한 후 DB에 접속하고, Connection 객체와 Controller에서 전달받은 데이터를 Dao에 전달한다.

public class MemberService {
	// 로그인 요청 서비스
	public Member loginMember(String userId, String userPwd) {
		Connection conn = JDBCTemplate.getConnection();
		Member m = new MemberDao().loginMember(conn, userId, userPwd);
		JDBCTemplate.close(conn);
		
		return m;
	}
}

 

 

 

 

Dao

- SQL문을 실행하여 직접 접근하고, ResultSet이나 int형 변수로 결과를 받아 Service로 리턴한다.

public class MemberDao {
	private Properties prop = new Properties();
	
	public MemberDao() {
		String fileName = MemberDao.class.getResource("/db/member/member-mapper.xml").getPath();
		try {
			prop.loadFromXML(new FileInputStream(fileName));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public Member loginMember(Connection conn, String userId, String userPwd) {
		// SELECT문 -> 결과행이 1개 또는 0개(userId는 unique가 걸려있어서 중복 불가)
		// 결과값인 resultSet을 member 객체에 담아서 응답
		Member m = null;
		PreparedStatement pstmt = null;
		ResultSet rset = null;
		
		String sql = prop.getProperty("loginMember");
		try {
			pstmt=conn.prepareStatement(sql);
			pstmt.setString(1, userId);
			pstmt.setString(2, userPwd);
			rset=pstmt.executeQuery();
			if(rset.next()) {
				m=new Member(rset.getInt("USER_NO")
						   , rset.getString("USER_ID")
						   , rset.getString("USER_PWD")
						   , rset.getString("USER_NAME")
						   , rset.getString("PHONE")
						   , rset.getString("EMAIL")
						   , rset.getString("ADDRESS")
						   , rset.getString("INTEREST")
						   , rset.getDate("ENROLL_DATE")
						   , rset.getDate("MODIFY_DATE")
						   , rset.getString("STATUS"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCTemplate.close(rset);
			JDBCTemplate.close(pstmt);
		}
		return m;
	}
}

 

 

 

 

member-mapper

- xml 파일로 작성한다.

- properties를 사용하여 수정사항이 있어도 서버를 중단시키지 않고 프로그램을 작동시킬 수 있게 한다.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	<entry key="loginMember">
		SELECT * 
		FROM MEMBER 
		WHERE USER_ID=? 
		  AND USER_PWD=? 
		  AND STATUS='Y'
	</entry>
</properties>

 

 

 

 

menubar

- jsp 파일로 작성한다.

- 사용자에게 보여져야 하므로 WebContent 폴더 내에 생성한다.

- 로그인 시 로그인 폼을 Controller로 넘어갈 수 있게 경로를 작성한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="com.cd.member.model.vo.Member"%>
    // VO(Member 파일)를 import해야 로그인 시도했을 때
    // VO부터 Dao까지 단계가 거쳐져서 결과가 돌아온다.
<%
	Member loginUser = (Member)session.getAttribute("loginUser");
// loginUser가 null이면 로그인 전 화면을 보여준다.
// loginUser가 null이 아니면 로그인 후 화면을 보여준다.
    String contextPath = request.getContextPath();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Menu Bar</title>
<style>
    .nav-area{background-color: lightblue;}
    .menu{
        display: inline-block;
        height: 50px;
        width: 150px;
    }
    .menu a{
        text-decoration: none;
        color: whitesmoke;
        font-size: 20px;
        font-weight: bold;
        display: block;
        width: 100%;
        height: 100%;
        line-height: 50px;
    }
    .menu a:hover{
        background-color: rgb(87, 165, 255);
    }
</style>
</head>
<body>
	<h1 align="center">게시판</h1>
    <div class="login-area">
    <%if(loginUser==null){ %>
        <!-- 로그인 전에 보여지는 로그인 form -->
        <form action="<%=contextPath %>/login.me" method="post">
            <table>
                <tr>
                    <th>아이디</th>
                    <td><input type="text" name="userId" required></td>
                </tr>
                <tr>
                    <th>비밀번호</th>
                    <td><input type="password" name="userPwd" required></td>
                </tr>
                <tr>
                    <th colspan="2">
                        <button type="submit">로그인</button>
                        <button type="button">회원가입</button>
                    </th>
                </tr>
            </table>
        </form>
        <%} else{ %>
        <!-- 로그인 성공 후 보여질 영역 -->
        	<div id="user-info">
        		<b><%=loginUser.getUserName() %></b>님, 환영합니다! <br><br>
        		<a href="#">마이페이지</a>
        		<a href="<%=contextPath %>/logout.me">로그아웃</a>
        	</div>
        <%} %>
    </div>
    <br>
    <div class="nav-area" align="center">
        <div class="menu"><a href="<%=contextPath %>">HOME</a></div>
        <div class="menu"><a href="">공지사항</a></div>
        <div class="menu"><a href="">일반게시판</a></div>
        <div class="menu"><a href="">사진게시판</a></div>
    </div>
</body>
</html>

 

반응형