고래씌

[JSP] 4-1. DB 이용하여 로그인 기능 만들기 본문

Server/JSP과 Servlet

[JSP] 4-1. DB 이용하여 로그인 기능 만들기

고래씌 2023. 12. 6. 17:14

 

회원서비스 C(Insert) R(Select) U(Update) D(Delete)
로그인    O    
회원가입 O      
[아이디중복검사]   O    
마이페이지   O    
정보변경     O  
회원탈퇴     O O

 

일반게시판서비스 - 게시판리스트조회(R) - 페이징 처리

                                    / 게시판 상세조회(R) / 게시판 작성(C) - 첨부파일 업로드/

                                  게시판 수정(U)/게시판 삭제(U/D) / [댓글등록(C) /댓글리스트 조회(R)]
   
사진게시판서비스 - 게시판리스트조회(R)-썸네일/ 게시판 상세조회(R) / 게시글 작성(C)

 

 

 

① JSP_Project1 파일 구조

 

 

② 서버계정 추가

 

 

■ MEMBER 테이블

 

 

=> 해당 MEMBER 테이블에 있는 값을 자바에 입력

package com.kh.member.model.vo;

import java.sql.Date;

public class Member {
	private int userNo; 		// USER_NO
	private String userId; 		// USER_ID
	private String userPwd; 	//	USER_PWD
	private String userName; 	//	USER_NAME
	private String phone; 		// PHONE
	private String email; 		// EMAIL
	private String address; 	// ADDRESS
	private String interest; 	//	INTEREST
	private Date enrollDate;  	// ENROLL_DATE
	private Date modifyDate; 	//	MODIFY_DATE
	private String status; 		// STATUS
	
	
	public Member() {
		
	}


	public Member(int userNo, String userId, String userPwd, String userName, String phone, String email,
			String address, String interest, 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.interest = interest;
		this.enrollDate = enrollDate;
		this.modifyDate = modifyDate;
		this.status = status;
	}


	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 getInterest() {
		return interest;
	}


	public void setInterest(String interest) {
		this.interest = interest;
	}


	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 + ", interest=" + interest
				+ ", enrollDate=" + enrollDate + ", modifyDate=" + modifyDate + ", status=" + status + "]";
	}

}

 

 

 

③ 사용자에게 보여질 화면 작성

JSP_Project1\WebContent\views\common - menubar.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<%
	// System.out.println(request.getContextPath());
	String contextPath = request.getContextPath();
	// 동적으로 페이지 이동이 가능하게 하기 위해서
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Popper JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<style>
	#Login-form, #user-info{float:right;}
	#user-info a {
		text-decoration: none;
		color: black;
		font-size : 12px;
	}
	
	.nav-area{background:black;}
	.menu{
		display:table-cell;
		height:50px;
		width:150px;
	}
	
	.menu a {
		text-decoration:none;
		color: white;
		font-size: 20px;
		font-weight:bold;
		display:block;
		width:100%;
		height:100%;
		line-height:50px;  /* 글자 가운데로 조정 */
	}
	
	.menu a:hover{
		background:dargray;
	}
</style>
<body>
	<h1 align="center">Welcome C Class</h1>
	
	<div class="login-area">
	
		<!-- 로그인 전에 보여지는 로그인 form -->
		<form id="login-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" onclick="">회원가입</button>
					</th>
				</tr>
			</table>
		</form>
	</div>
	
	<br clear="both">  <!-- 폼이 끝나는 위치에 clear를 이용하여 float 속성 지워줌 -->
	<br>
	
	<div class="nav-area" align="center">
		<div class="menu"><a href="">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>

 

 

<%
    String contextPath = request.getContextPath();
%>

 

 

=> 동적으로 페이지 이동이 가능하게 하기 위해서 이와 같이 설정하였다.

 

 

■ driver.properties 파일

 

 

 

■ JDBCTemplate.java 파일

package com.kh.common;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCTemplate {
	
	// 1. Connection 객체 생성 후 Connection을 반환하는 메소드
	public static Connection getConnection() {
		// Properties
		Properties prop = new Properties();  // 키, 밸류 형태로 문자열형태로 저장함
		
		// 읽어들이고자하는 driver.properties 파일의 물리적인 경로 제시
		String fileName = JDBCTemplate.class.getResource("/sql/driver/driver.properties").getPath();
		// 현재 경로의 절대경로로 driver.properties 파일을 찾는다.
		// C:\Web-workspace2\JSP_Project1\WebContent\WEB-INF\classes\sql\driver  => 이 위치를 찾는다
		
		try {
			prop.load(new FileInputStream(fileName));
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		Connection conn = null;
		
		// 1) jdbc driver 등록
		try {
			Class.forName(prop.getProperty("driver")); // 클래스를 찾아서 사용하겠다고 정의해둠
			
			// 2) db와 접속된 Connection 객체 생성
			conn = DriverManager.getConnection(prop.getProperty("url"),
							prop.getProperty("username"),
							prop.getProperty("password"));
					
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return conn;
        // conn 반환.
        // 우리 컴퓨터 안의 깔린Oracle DB 안에 1521포트에 이러한 계정정보로 로그인해서(username, password) 접속해서 
		// 접속한 상태자체를 반환하도록 함
	}
		
	//2. 전달받은 JDBC용 객체를 반납시켜주는 메소드(객체별로 오버로딩)
	//2_1) Connection객체를 전달받아서 반납시켜주는 메소드
	public static void close(Connection conn) {
		try {
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	//2_2) Statement객체를 전달받아서 반납시켜주는 메소드
	public static void close(Statement stmt) { // Statement + PreparedStatment 둘다
		// 매개변수로 전달 가능(다형성)
		try {
			stmt.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	//2_3) ResultSet 객체를 전달받아서 반납시켜주는 메소드(오버로딩)
	public static void close(ResultSet rset) {
		try {
			rset.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	// 3. 전달받은 Connection객체를 가지고 트랜잭션 처리를 해주는 메소드
	// 3_1.) Commit메소드
	public static void commit(Connection conn) {
		try {
			conn.commit();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	// 3_2) rollback메소드
	public static void rollback(Connection conn) {
		try {
			conn.rollback();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

}

 

 

- public static Connection getConnection 

=> conn 반환.
우리 컴퓨터 안의 깔린 Oracle DB 안에 1521포트에 이러한 계정정보로 로그인해서(username, password) 접속해서 접속한 상태자체를 반환하도록 함

 

 

■ LoginController.java

 

 

package com.kh.member.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kh.member.model.service.MemberService;
import com.kh.member.model.vo.Member;

/**
 * Servlet implementation class LoginController
 */
@WebServlet("/login.me")
public class LoginController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LoginController() {
        super();
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 1) 전달값이 한글이 있을 경우 인코딩처리를 해야했음
		request.setCharacterEncoding("UTF-8");
		
		// 2) 요청시 전달한 값을 꺼내서 변수에 기록
		String userId = request.getParameter("userId");
		String userPwd = request.getParameter("userPwd");
		
		// SELECT * FROM MEMBER WHERE USER_ID = ? AND USER_PWD = ? AND STATUS = 'Y'
		Member loginUser = new MemberService().loginMember(userId, userPwd);
		
		// 처리된 결과를 가지고 사용자가 보게될 화면을 지정
		System.out.println(loginUser);
	
	}

}

 

 

 

■ MemberService.java 파일

package com.kh.member.model.service;

import static com.kh.common.JDBCTemplate.*;

import java.sql.Connection;

import com.kh.member.model.dao.MemberDao;
import com.kh.member.model.vo.Member;


public class MemberService {
	
	/**
	 * 로그인 요청 서비스
	 * @param userId => 사용자가 입력한 아이디값.
	 * @param userPwd => 사용자가 입력했던 비밀번호값
	 * @return
	 */
	
	public Member loginMember(String userId, String userPwd) {
		// 1) 커넥션 생성
		// Connection conn = JDBCTemplate.getConnection();
		Connection conn = getConnection();    // 접속된 db 연결정보를 담는 변수
		// import static com.kh.common.JDBCTemplate.*; 를 하면 클래스를 생략하고 생성할 수 있다.
		
		// 2) 커넥션 전달
		Member m = new MemberDao().loginMember(conn, userId, userPwd);
		
		// 3) 커넥션 반납
		close(conn);
		
		// 4) 결과값 반납
		
		return m;
	}
}

 

 

=> 커넥션 생성하고 전달하고 반납하기 위해 JDBCTemplate.java 파일에 관련메소드를 생성해서 메소드 호출하여 사용하기 위함

 

Member m = new MemberDao().loginMember(conn, userId, userPwd);  

 

=> MemberDao()  클래스 의 loginMember메소드 호출

 

 

 

■ member-mapper.xml 파일

 

 

■ MemberDao 

package com.kh.member.model.dao;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import com.kh.common.JDBCTemplate;
import com.kh.member.model.vo.Member;

public class MemberDao {
	
	private Properties prop = new Properties();
	
	public MemberDao() {
		try {
			prop.loadFromXML(new FileInputStream(
					MemberDao.class.getResource("/sql/member/member-mapper.xml").getPath()
					));
                    // 물리적인 경로 반환됨
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public Member loginMember(Connection conn, String userId, String userPwd) {
		// SELECT문. ResultSet으로 반환받음. => Member객체로 변환
		Member m  = null;  
		PreparedStatement pstmt = null;  // 미완성된 sql문 보관하기 위한 변수
		ResultSet rset = null;   // SELECT문이 실행된 조회결과값들이 담겨질 객체
		String sql = prop.getProperty("loginMember");
		
		try {
			pstmt = conn.prepareStatement(sql);
			
			pstmt.setString(1, userId);  // userId를 넣음
			pstmt.setString(2, userPwd); // 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("ADDRESS"),
						rset.getString("EMAIL"),
						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;
	}
}

 

- rset = pstmt.executeQuery();   => PreparedStatement 객체로 SQL문을 실행하여 얻어온 레코드들을 ResultSet 타입의 변수로 참조한다.

 

 

- psmt = conn.prepareStatement(sql);  => connection 객체를 사용할 PreparedStatement 객체 생성

 

 

- String sql = prop.getProperty("loginMember");

 

 

 

 

=> SERVER계정의 DB에 저장되어있는 Member테이블에 "USER_NO","USER_ID", ....을 받아온다

 

 

 

=> DB에 저장되어있는 아이디, 패스워드를 입력하여 로그인하면 console창에 다음과 같은 화면이 출력된다.

 

 

 

 


2. 로그인을 하고 로그인 상태유지하도록 만들기

▶ 응답페이지에 전달할 값이 있을 경우 값을 어딘가에 담아야함(담아줄 수 있는 Servlet Scope 내장객체 4종류)


1) application : application에 담은 데이터는 웹 애플리케이션 전역에서 다 꺼내 쓸 수 있다.


2) session : session에 담은 데이터는 모든 jsp와 servlet에서 꺼내 쓸 수 있음
    - 한번 담은 데이터는 내가 직접 지우기전까지, 서버가 멈추기 전까지, 브라우저가 종료되기 전까지 접근해서 꺼내쓸 수 있음


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


4) page : 해당 jsp에서만 꺼내쓸 수 있다.


모든 Servlet Scope에 데이터를 담고자한다면 .setAttribute("키", "밸류");
    - 데이터를 꺼내고자한다면 .getAttribute("키");
    - 데이터를 지우고자한다면 .removeAttribute("키");

 

 

1) LoginController.java 파일에 로그인 유저에 따른 분기처리

HttpSession session;
session = request.getSession();

 

=> 로그인한 회원의 정보를 사용자가 로그아웃하기 전까지 쓸 수 있도록 session scope에 담아주도록 한다! 그러기위해선 우선, session을 얻어와야한다.

 

 

 

session.setAttribute("loginUser", loginUser);   // 유저이름 (키값,밸류값)
session.setAttribute("alertMsg", "성공적으로 로그인이 되었습니다.");  // (키값, 밸류값)

 

=> session에 해당 유저의 키값과 밸류를 넣어줌

 

 

① 포워딩 방식 응답뷰 출력

=> index.jsp로 포워딩 되긴하지만 url에는 서블릿 매핑주소가 그대로 남아있고, 요청시 전달한 내용들도(request) 그대로 남아있다.
새로고침을 하면 다시한번 로그인요청이 들어감. => 올바른 방법이 아니다!

 

 

② url 재요청방식

=> /jsp 이용해 재요청을 보낼 것이다.

/jsp => request.getContextPath()로 꺼내쓸 수 있음

response.sendRedirect(request.getContextPath());

 

 

request.setAttribute("errorMsg", "로그인에 실패했습니다.");

RequestDispatcher view = request.getRequestDispatcher("views/common/errorPage.jsp");

view.forward(request, response);

 

=> 로그인 실패시 errorPage.jsp로 이동하도록 설정

 

package com.kh.member.controller;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.kh.member.model.service.MemberService;
import com.kh.member.model.vo.Member;

/**
 * Servlet implementation class LoginController
 */
@WebServlet("/login.me")
public class LoginController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LoginController() {
        super();
    }


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}


	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 1) 전달값이 한글이 있을 경우 인코딩처리를 해야했음
		request.setCharacterEncoding("UTF-8");
		
		// 2) 요청시 전달한 값을 꺼내서 변수에 기록
		String userId = request.getParameter("userId");
		String userPwd = request.getParameter("userPwd");
		
		// SELECT * FROM MEMBER WHERE USER_ID = ? AND USER_PWD = ? AND STATUS = 'Y'
		Member loginUser = new MemberService().loginMember(userId, userPwd);
		
		// 처리된 결과를 가지고 사용자가 보게될 화면을 지정
		// System.out.println(loginUser);
		
		/* 
		 * * 응답페이지에 전달할 값이 있을 경우 값을 어딘가에 담아야함(담아줄 수 있는 Servlet Scope 내장객체 4종류)
		 * 1) application : application에 담은 데이터는 웹 애플리케이션 전역에서 다 꺼내 쓸 수 있다.
		 * 2) session : session에 담은 데이터는 모든 jsp와 servlet에서 꺼내 쓸 수 있음
		 * 				한번 담은 데이터는 내가 직접 지우기전까지, 서버가 멈추기 전까지, 브라우저가 종료되기 전까지
		 * 				접근해서 꺼내쓸 수 있음
		 * 3) request : request에 담은 데이터는 해당 request에 포워딩한 jsp에서만 꺼내쓸 수 있다.
		 * 4) page : 해당 jsp에서만 꺼내쓸 수 있다.
		 * 
		 * 모든 Servlet Scope에 데이터를 담고자한다면 .setAttribute("키", "밸류");
		 * 					  데이터를 꺼내고자한다면 .getAttribute("키");
		 * 					  데이터를 지우고자한다면 .removeAttribute("키");
		 */
		
		// 로그인 유저에 따른 분기처리
		// 로그인 실패
		if(loginUser == null) {
			request.setAttribute("erreoMsg", "로그인에 실패했습니다.");
			
			RequestDispatcher view = request.getRequestDispatcher("views/common/errorPage.jsp");
			
			view.forward(request, response);
		}else {   // 로그인 성공 => index 페이지로 이동
			// 로그인한 회원의 정보를 사용자가 로그아웃하기 전까지 쓸 수 있도록 session scope에 담아주기
			
			// Servlet에서 JSP내장객체인 session에 접근하고자 한다면 우선 session 객체를 얻어와야함
			HttpSession session;
			session = request.getSession();   // 사용자가 요청을 보낼때 쿠키,세션, 요청정보가 한꺼번에 담겨온다.
			
			session.setAttribute("loginUser", loginUser);   // 유저이름 (키값,밸류값)
			session.setAttribute("alertMsg", "성공적으로 로그인이 되었습니다.");  // (키값, 밸류값)
			
			// 1. 포워딩 방식 응답뷰 출력
			//	  index.jsp로 포워딩 되긴하지만 url에는 서블릿 매핑주소가 그대로 남아있고,
			//    요청시 전달한 내용들도(request) 그대로 남아있다.
			//	  새로고침을 하면 다시한번 로그인요청이 들어감. => 올바른 방법이 아니다!
			// 	  index.jsp
			
			// RequestDispatcher view = request.getRequestDispatcher("index.jsp"); // localhost:8082/jsp  // 포워딩하고자하는 경로 제시함
			// view.forward(request, response);    // 해당페이지를 포워딩 시킴
			
			// 2. url재요청방식
			//    /jsp  이용해 재요청을 보낼 것이다.
			//    /jsp => request.getContextPath()로 꺼내쓸 수 있음
			response.sendRedirect(request.getContextPath());
			
		}
	}

}

 

 

■ errorPage.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1 align="center" style="color:red"><%= (String)request.getAttribute("errorMsg") %></h1>
	

</body>
</html>

 

 

 

2) menubar.jsp 파일 로그인 성공했을 시 사용자가 볼 화면 수정하고, 알람메시지 띄우기

 

 

=> 새로고침을 하면 계속 이 메시지가 뜰 것이기 때문에 "성공적으로 로그인되었습니다" 메시지는 session에서 없애줘야한다. (한번 뜨고 그 다음부터 바꿔주어야하기 때문!)

 

 

▶ 로그인 성공했을 경우 사용자가 볼 화면

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="com.kh.member.model.vo.Member"%>
    
<%
	// System.out.println(request.getContextPath());
	String contextPath = request.getContextPath();    // /jsp
	// 동적으로 페이지 이동이 가능하게 하기 위해서
	
	Member loginUser = (Member)session.getAttribute("loginUser");
	// session.getAtrribute 반환형이 Object형이기 때문에 Member 자료형으로 강제형변환시켜줌
	// 로그인하기 전에는 : null
	// 로그인 완료 후에는 로그인한 회원의 정보가 담겨져 있을 것.
	System.out.println(loginUser);
	
	String alertMsg = (String) session.getAttribute("alertMsg");
	// 서비스 요청 전에는 null
	// 서비스 요청 성공 후에는 : alert으로 띄어줄 메시지 문구
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Popper JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<style>
	#Login-form, #user-info{float:right;}
	#user-info a {
		text-decoration: none;
		color: black;
		font-size : 12px;
		display : right;
	}
	
	.nav-area{background:black;}
	.menu{
		display:table-cell;
		height:50px;
		width:150px;
	}
	
	.menu a {
		text-decoration:none;
		color: white;
		font-size: 20px;
		font-weight:bold;
		display:block;
		width:100%;
		height:100%;
		line-height:50px;  /* 글자 가운데로 조정 */
	}
	
	.menu a:hover{
		background:dargray;
	}
</style>
<body>
	<script>
		// script 태그 내에서도 스크립팅 원소 사용 가능
		const msg = "<%= alertMsg %>";   // "서비스요청성공메시지" or "null"
		// 출력이 될 때 "" 을 같이 담아와서 넘겨오지 못하기 때문에 양쪽에 "을 붙임
		
		if(msg != "null"){
			alert(msg);
			// 알림창 띄어준 후 session안에 담긴 메시지는 지워줘야한다. 안그러면 새로고침할때마다 계속 뜰 것!!
			
			<% session.removeAttribute("alertMsg"); %>
		}
	</script>
	
	<h1 align="center">Welcome C Class</h1>
	
	<div class="login-area">
		<% if(loginUser == null) { %>
	
		<!-- 로그인 전에 보여지는 로그인 form -->
		<form id="login-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" onclick="">회원가입</button>
					</th>
				</tr>
			</table>
		</form>
		<% } else { %>
			<!-- 로그인 성공 후 -->
			<div id="user-info">
				<b><%= loginUser.getUserName() %>님</b> 환영합니다. <br><br>
				<div align="center">
					<a href="<%= contextPath %>/myPage.me">마이페이지</a>
					<a href="<%= contextPath %>/logout.me">로그아웃</a>
				</div>
			</div>
		<% } %>
	</div>
	
	<br clear="both">  <!-- 폼이 끝나는 위치에 clear를 이용하여 float 속성 지워줌 -->
	<br>
	
	<div class="nav-area" align="center">
		<div class="menu"><a href="">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>

 

 

=> 로그인 실패했을 경우

 

 

=> 로그인 성공했을 경우