회원가입은 어떤식으로 작동할것 같은가?
1. VIEW에 회원가입을위한 정보를 작성한다.
2. 버튼을 눌러 서버로 DB에 저장해달라고 '요청' 한다.
3. 작성한 정보는 Model 객체로 만들어지고 , DAO를 통해 DB에 저장이 된다.
로그인은 어떤식으로 작동할것 같은가?
1. VIEW에 로그인을 위한 정보를 작성한다 (아이디, 패스워드)
2. DAO를 통해 작성한 정보를 바탕으로 SELECT를 한다.
3. 실행결과가 있다면 분기하여 세션을 저장하여 다른페이지로 이동할때 그 세션을 계속 불러오도록 한다(?)
제가 이해하기 편하도록, 제가 이해한대로 써봤습니다..
반드시 이렇다. 라고 생각하지는 말아주세요 불확실한 정보입니다
ㅎㅇ
정리해야될거 선(先)정리
1. 로그인페이지 , 회원가입 페이지로 이동하게 해주는 페이지
2. 로그인 Form , 회원가입 Form (아이디 중복검사, 주소검색)
3. 로그인과 회원가입만을 위한 객체 LoginReqDto , JoinReqDto 생성, 이해하기
나중에 게시판이되어 게시글을 보여줄
list.jsp 를 생성합니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="../layout/header.jsp" %>
</body>
</html>
index.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>인덱스 페이지입니다.</h1>
</body>
</html>
<%
response.sendRedirect("board/list.jsp");
%>
header.jsp (부트스트랩, 제이쿼리 선언)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Cos 블로그</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-md bg-dark navbar-dark">
<a class="navbar-brand" href="#">블로그</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsibleNavbar">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">회원가입</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">로그인</a>
</li>
</ul>
</div>
</nav>
<br>
대충 이런모양이 나옵니다
로그인을 누르면 나올 화면인
loginFrom.jsp
를 생성합니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@include file="../layout/header.jsp" %>
<!-- x-www-form-urlencoded -->
<div class="container">
<form action="/blog/user?cmd=login" method="post">
<div class="form-group">
<input type="text" id="username" name="username" class="form-control"
placeholder="Enter Username" required"/>
</div>
<div class="form-group">
<input type="password" name="password" class="form-control"
placeholder="Enter Password" required />
</div>
<button type="submit" class="btn btn-primary">로그인완료</button>
</form>
</div>
</body>
</html>
회원가입 화면인
JoinForm.jsp
를 생성합니다
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@include file="../layout/header.jsp"%>
<div class="container">
<form action="/blog/user?cmd=join" method="post" onsubmit="return valid();">
<div class="d-flex justify-content-end">
<button type="button" class="btn btn-info" onClick="usernameCheck();">중복검사</button>
</div>
<div class="form-group">
<input type="text" id="username" name="username" class="form-control"
placeholder="Enter Username" required"/>
</div>
<div class="form-group">
<input type="password" name="password" class="form-control"
placeholder="Enter Password" required />
</div>
<div class="form-group">
<input type="email" name="email" class="form-control"
placeholder="Enter Email" required />
</div>
<div class="d-flex justify-content-end">
<button type="button" class="btn btn-info" onClick="goPopup();">주소검색</button>
</div>
<div class="form-group">
<input type="text" name="address" id="address" class="form-control" placeholder="Enter Address" required/>
</div>
<button type="submit" class="btn btn-primary">회원가입완료</button>
</form>
</div>
<script>
var isChecking = false;
function valid(){
if(isChecking == false){
alert("아이디 중복체크를 해주세요");
}
return isChecking;
}
function usernameCheck(){
// DB에서 확인해서 username이 없다면 isChecking = true
var username = $("#username").val();
$.ajax({
type: "POST",
url: "/blog/user?cmd=usernameCheck",
data: username,
contentType: "text/plain; charset=utf-8",
dataType: "text" // 응답 받을 데이터의 타입을 적으면 자바스크립트 오브젝트로 파싱해줌.
}).done(function(data){
if(data === 'ok'){ // 유저네임 있다는 것
isChecking = false;
alert('유저네임이 중복되었습니다.')
}else{
isChecking = true;
$("#username").attr("readonly", "readonly");
alert("해당 유저네임을 사용할 수 있습니다.")
}
});
}
function goPopup() {
// 주소검색을 수행할 팝업 페이지를 호출합니다.
// 호출된 페이지(jusopopup.jsp)에서 실제 주소검색URL(https://www.juso.go.kr/addrlink/addrLinkUrl.do)를 호출하게 됩니다.
var pop = window.open("/blog/user/jusoPopup.jsp", "pop",
"width=570,height=420, scrollbars=yes, resizable=yes");
}
function jusoCallBack(roadFullAddr) {
var addressEl = document.querySelector("#address");
addressEl.value = roadFullAddr;
}
</script>
</body>
</html>
ㅡㅡㅡㅡAjax 통신 정의ㅡㅡㅡㅡㅡ
Ajax (Async Javascript And XML)는 웹 페이지에서 새로운 데이터를 보여주려고 할 때 웹페이지 전체를 새로고침 하지 않고, 보여주고자 하는 데이터가 포함된 페이지의 일부 만을 로드 하기 위한 기법입니다.
Ajax는 비동기 처리 모델 (또는 non-blocking 이라고도 함)을 사용하여 데이터를 처리합니다.
동기 처리 모델에서 브라우저는 자바스크립트 코드를 만나면 스크립트를 처리하기 전까지 다른 작업을 일시 중지하고, 자바스크립트 코드의 처리가 끝난 후 기존 작업을 진행합니다.
반면에 Ajax를 사용하면 브라우저는 서버에 데이터를 요청한 뒤 페이지의 나머지를 로드하고 페이지와 사용자의 상호작용을 처리합니다.
Ajax 동작방식
function usernameCheck(){
// DB에서 확인해서 username이 없다면 isChecking = true
var username = $("#username").val();
$.ajax({
type: "POST",
url: "/blog/user?cmd=usernameCheck",
data: username,
contentType: "text/plain; charset=utf-8",
dataType: "text" // 응답 받을 데이터의 타입을 적으면 자바스크립트 오브젝트로 파싱해줌.
}).done(function(data){
if(data === 'ok'){ // 유저네임 있다는 것
isChecking = false;
alert('유저네임이 중복되었습니다.')
}else{
isChecking = true;
$("#username").attr("readonly", "readonly");
alert("해당 유저네임을 사용할 수 있습니다.")
}
});
}
//UserController.java (Servlet)
else if(cmd.equals("usernameCheck")) { //유저네임 중복체크
BufferedReader br = request.getReader(); //input 에 입력된 username을 읽음
String username = br.readLine();
System.out.println(username);
//DB와 통신함 (service -> Dao)
//Dao 에서 Select 해보고 int 결과값을 리턴해줌. 있으면 1 없으면 not 1
int result = userService.유저네임중복체크(username);
PrintWriter out = response.getWriter();
if(result == 1) {
out.print("ok");
}else {
out.print("fail");
}
out.flush();
}
- 요청(request) - 브라우저가 서버에 정보를 요청한다.
바로 위에있는 JoinForm.jsp 에서 첫번째 Form의 중복검사 action이 usernameCheck() 함수를 가지고있는데,
그 함수는 파일 하단에. 자바스크립트 함수로 정의되어 있습니다.
이 함수가 JQuery를 이용한 Ajax 요청방법입니다. ( Web Front 에 입력된 데이터를 서버로 전송 )
type : 요청방식 (get, post, delete, put) // url : 요청주소 ( Controller 에서 Servlet이 처리함 )
data : 서버로 보낼 데이터. (위 함수에서는 var username = $("#username").val() 이 전송되는중)
contentType : 응답받을 데이터의 형태, 보통은 데이터를 처리하기위해 JSON 이겠지만
Controller의 결과값을 보면 ok , fail 의 단순 문자열이기때문에 text
응답에 성공을 한다면, done(function(data){ '대충 실행될 명령' } ) 분기로 가서
응답받은 데이터( data << Ajax 함수의 data 아님. Ajax의 결과값임 )로 해야할 일을 처리합니다.
data를 result 로 바꾸는게 좀 보기 편할거같네요 - 서버의 동작 - 서버는 JSON, XML 등의 형식으로 데이터를 전달한다.
최근에는 JSON을 가장 많이 사용하고 있습니다. - 응답(response) - 브라우저에서 이벤트가 발생하여 콘텐츠를 처리한다.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
명심할것!!!!!!! 컨트롤러 ↔ 서비스 ↔ DAO (DB)
User의 컨트롤을 담당 (로그인, 회원가입, 로그아웃)
UserController.java (Servlet 파일)
package com.cos.blog.web;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
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.cos.blog.domain.user.User;
import com.cos.blog.domain.user.dto.JoinReqDto;
import com.cos.blog.domain.user.dto.LoginReqDto;
import com.cos.blog.service.UserService;
import com.cos.blog.util.Script;
//http://localhost:8000/blog/user
@WebServlet("/user")
public class UserController extends HttpServlet {
private static final long serialVersionUID = 1L;
public UserController() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doProcess(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doProcess(request, response);
}
protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
UserService userService = new UserService();
String cmd = request.getParameter("cmd");
// http://localhost:8000/blog/user?cmd=loginForm
if(cmd.equals("loginForm")) { //로그인 페이지
// 서비스 호출
RequestDispatcher dis = request.getRequestDispatcher("user/loginForm.jsp");
dis.forward(request, response);
//response.sendRedirect("user/loginForm.jsp");
}else if(cmd.equals("login")) { //로그인 완료
// 서비스 호출
String username = request.getParameter("username");
String password = request.getParameter("password");
LoginReqDto dto = new LoginReqDto();
dto.setUsername(username);
dto.setPassword(password);
User userEntity = userService.로그인(dto);
if(userEntity != null) {
HttpSession session = request.getSession();
session.setAttribute("principal", userEntity); //인증주체
//response.sendRedirect("index.jsp"); //로그인 성공
RequestDispatcher dis = request.getRequestDispatcher("index.jsp");
dis.forward(request, response);
}else {
Script.back(response, "로그인 실패");
}
}else if(cmd.equals("joinForm")) { //회원가입 페이지
RequestDispatcher dis = request.getRequestDispatcher("user/joinForm.jsp");
dis.forward(request, response);
//response.sendRedirect("user/joinForm.jsp");
}else if(cmd.equals("join")) { //회원가입 완료
// 서비스 호출
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
String address = request.getParameter("address");
JoinReqDto dto = new JoinReqDto();
dto.setUsername(username);
dto.setPassword(password);
dto.setEmail(email);
dto.setAddress(address);
System.out.println("회원가입 : "+dto);
int result = userService.회원가입(dto); //DB와 통신함 (service -> Dao)
if(result == 1) {
RequestDispatcher dis = request.getRequestDispatcher("index.jsp");
dis.forward(request, response);
}else {
Script.back(response, "회원가입 실패 -1");
}
}else if(cmd.equals("usernameCheck")) { //유저네임 중복체크
BufferedReader br = request.getReader();
String username = br.readLine();
System.out.println(username);
int result = userService.유저네임중복체크(username); //DB와 통신함 (service -> Dao)
PrintWriter out = response.getWriter();
if(result == 1) {
out.print("ok");
}else {
out.print("fail");
}
out.flush();
}else if(cmd.equals("logout")) { //로그아웃
HttpSession session = request.getSession();
session.invalidate(); //즉시 세션 만료
RequestDispatcher dis = request.getRequestDispatcher("index.jsp");
dis.forward(request, response);
}
}
}
UserService.java 작성
package com.cos.blog.service;
import com.cos.blog.domain.user.User;
import com.cos.blog.domain.user.UserDao;
import com.cos.blog.domain.user.dto.JoinReqDto;
import com.cos.blog.domain.user.dto.LoginReqDto;
import com.cos.blog.domain.user.dto.UpdateReqDto;
public class UserService {
private UserDao userDao;
public UserService() {
userDao = new UserDao();
}
public int 회원가입(JoinReqDto dto) {
int result = userDao.save(dto);
return result;
}
public User 로그인(LoginReqDto dto) {
return userDao.findByUsernameAndPassword(dto);
}
public int 회원수정(UpdateReqDto dto) {
return -1;
}
public int 유저네임중복체크(String username) {
int result = userDao.findByUsername(username);
return result;
}
}
DB.java 에 아래의 함수 생성
public static void close(Connection conn, PreparedStatement pstmt) {
try {
conn.close();
pstmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}
UserDao.java 작성 (대부분 SQL문)
public int save(JoinReqDto dto) { // 회원가입
String sql = "INSERT INTO user(username, password, email, address, userRole, createDate) VALUES(?,?,?,?, 'USER', now())";
Connection conn = DB.getConnection();
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, dto.getUsername());
pstmt.setString(2, dto.getPassword());
pstmt.setString(3, dto.getEmail());
pstmt.setString(4, dto.getAddress());
int result = pstmt.executeUpdate();
return result;
} catch (Exception e) {
e.printStackTrace();
} finally { // 무조건 실행
DB.close(conn, pstmt);
}
return -1;
}
public int findByUsername(String username) { //아이디 중복 체크
String sql = "SELECT * FROM user WHERE username = ?";
Connection conn = DB.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username); //dto가 아닌 그냥 username
rs = pstmt.executeQuery(); //조회 결과가 1건이라도 있으면 1 , 없으면 -1
if(rs.next()) { //1건이라도 있다 = true 일때 실행
return 1; // 있어
}
} catch (Exception e) {
e.printStackTrace();
} finally { // 무조건 실행
DB.close(conn, pstmt, rs);
}
return -1; // 없어
}
public User findByUsernameAndPassword(LoginReqDto dto) { // 로그인
String sql = "SELECT id, username, email, address FROM user WHERE username = ? and password =?";
Connection conn = DB.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, dto.getUsername()); //dto가 아닌 그냥 username
pstmt.setString(2, dto.getPassword());
rs = pstmt.executeQuery();
// Persistence API
if(rs.next()) { //1건이라도 있다 = true 일때 실행
User user = User.builder()
.id(rs.getInt("id"))
.username(rs.getString("username"))
.email(rs.getString("email"))
.address(rs.getString("address"))
.build();
return user;
}
} catch (Exception e) {
e.printStackTrace();
} finally { // 무조건 실행
DB.close(conn, pstmt, rs);
}
return null; // 없어
}
한글 데이터 요청 , 응답시 한글 깨짐을 방지하기위한
CharConfig.java 생성 (doFilter)
package com.cos.blog.config;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CharConfig implements Filter{
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
request.setCharacterEncoding("utf-8");
response.setContentType("text/html; charset=utf-8");
// String username = request.getParameter("username");
// System.out.println("username : "+username);
//
// PrintWriter out = response.getWriter();
// out.println("안녕");
// out.flush();
chain.doFilter(request, response);
}
}
뒤로가기를 함수로 따로 구현하기 위한
Script.java 작성
package com.cos.blog.util;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
public class Script {
public static void back(HttpServletResponse resp, String msg) throws IOException {
PrintWriter out = resp.getWriter();
resp.setContentType("text/html; charset=utf-8"); //utf-8로 응답하겠다
out.println("<script>");
out.println("alert('"+msg+"');");
out.println("history.back();");
out.println("</script>");
out.flush();
}
패키지정리는 알아보기쉽게.. (언젠간 한눈에 보일거같습니다)
Dto란? Data Transfer Object
데이터 교환만을 위한 객체로, DB에서 데이터를 얻어 Service나 Controller 등으터 보낼 때 사용하는 객체를 말한다.
User , Board 처럼 이미 모델이 만들어져있지만 각각 상황에 따라 일부 필드(변수)는 요구되지않는 요청이 생길 수 있다.
예를 들자면 로그인을 위한 데이터를 받고싶다고 하자. (아이디, 패스워드 만 있으면 됨)
그러나 User 모델은 로그인만을 하기위해 사용하기에는 쓸데없는 변수가 너무많다.
그럴때, 오로지 로그인만을 위한 DTO(Data Transfer Object : 데이터 전송 객체)를 만들어서 사용하는것이다.
미완성 게시물입니다. 이후 내용 추가
추가할 내용
유저네임 중복검사 , 로그인 구현
Ajax 통신 이해하기, (Reader, Writer) 이해하기,
(get,setAttribute) 이해하기,
RequestDispatcher 이해하기
집에서 새로 프로젝트 만들어서 내가 작성한내용 따라해서 리뷰하기.
'국비지원 Spring프레임워크 > JSP dynamic web project blog' 카테고리의 다른 글
blog 6. 글 목록 페이징 하기 (0) | 2021.02.23 |
---|---|
blog 5. 글 목록 보기 (0) | 2021.02.16 |
blog 4. URI 직접 접근 필터링하기 (0) | 2021.01.29 |
blog 3. 글작성, DB INSERT (0) | 2021.01.27 |
blog 1. DB생성 , Model 생성, DB연동 + JUnit 테스트 (0) | 2021.01.08 |