** 이전에 만들었던 서블릿 프로젝트에서 JDBC가 아닌 Mybatis 프레임워크를, html의 submit 전송이 아닌 jquery를 이용한 ajax 통신을 사용해 로그인을 구현해보았다.
[Servlet] 로그인 구현하기
** 이전에 만들었던 JSP 프로젝트를 서블릿을 통해 MVC 패턴을 구현해보는 시간을 가져보았다. [JSP] 4강 - 로그인 기능 구현 // **문제해결** 본 포스팅은 정보 제공용이 아닌 유튜브 동빈나님의 JSP
egu99.tistory.com
0. 간단 프로세스
Servlet Controller에서 jsp로 forwarding
-> 로그인 jsp에서 id, pw를 ajax로 요청
-> Servlet Controller에서 dao의 login 메서드 호출
-> login 메서드는 mybatis mapper에 던지고 회원 정보 조회 후 반환
-> Servlet Controller에서 반환 받은 정보에 따라 로그인 성공 혹은 실패를 판단하고 임의의 chk값을 ajax로 응답
-> 응답 받은 jsp에서는 보내온 chk값에 따라 알림을 띄워줌.
1. LoginController2.java - doGet()
@WebServlet("/login2")
public class LoginControl2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
if (session.getAttribute("user") != null) {
PrintWriter script = response.getWriter();
script.println("<script>");
script.println("alert('이미 로그인 되었습니다.');");
script.println("location.href='main'");
script.println("</script>");
} else {
request.getRequestDispatcher("/WEB-INF/login2.jsp").forward(request, response);
}
}
}
- 로그인 버튼을 누르면 이쪽으로 오게 된다.
- jsp로 forward해주기 전에 session에서 로그인 회원 정보도 확인해본다.
2. login2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="e" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<!-- 로그인 컨테이너 -->
<div class="container">
<div class="col-lg-4">
<!-- 점보트론 -->
<div class="jumbotron" style="padding-top:20px;">
<form>
<h3 style="text-align: center;">로그인 화면</h3>
<div class="form-group">
<input type="text" id="loginId" class="form-control" placeholder="아이디를 입력하세요." name="userID" maxlength="20">
</div>
<div class="form-group">
<input type="password" id="loginPw" class="form-control" placeholder="비밀번호를 입력하세요." name="userPassword" maxlength="20">
</div>
<input type="button" id="login" class="btn btn-primary form-control" value="로그인">
</form>
</div>
</div>
</div>
<script type="text/javascript">
var lo = document.getElementById("login");
lo.addEventListener("click", function(event){
if(document.getElementById("loginId").value.length == 0){
alert("아이디가 누락되었습니다.");
event.preventDefault();
} else if(document.getElementById("loginPw").value.length == 0){
alert("패스워드가 누락되었습니다.");
event.preventDefault();
} else {
var id = $("#loginId").val().trim();
var pw = $("#loginPw").val().trim();
//비동기식 통신
$.ajax({
url : "./login2",
type: "Post",
dataType: "json",
data: {userID : id, userPW : pw}
}).done(function(res) {
console.log(res.chk);
if(res.chk == "1") {
alert("로그인 되었습니다");
location.href = "main";
}else {
alert("회원 정보가 없습니다.");
location.href = "login2";
}
}).fail(function(err) {
console.log(err);
});
}
});
</script>
</body>
</html>
- 이제 submit을 이용해 전달하지 않을 것이므로 input type을 button으로 바꿔주고 id를 넣어주었다.
- 이 id를 가지고 자바스크립트에서 addEventListener를 통해 로그인 버튼 클릭시 이벤트를 등록한다.
- ajax로 전송 전에 id와 pw의 누락 여부를 확인해준다.
- 누락되지 않았다면 jquery를 이용한 ajax 통신으로 사용자가 입력한 id와 pw를 컨트롤러로 요청과 함께 보낼 것이다.
- 요청 성공시 응답받는 결과는 res에 담길 것이고 컨트롤러에서 해당 회원이 있다면 chk라는 키값에 1을, 없다면 0을 보낼 것이므로 그에 따른 알림과 이동을 해준다.
** JQuery를 이용한 Ajax
// jQuery를 이용한 Ajax
$.ajax({
url: ,
type: ,
data: ,
dataType: ,
done: function(response) {
},
fail: function(error) {
},
always: function(response) {
}
});
속성 | 설명 |
url | 요청을 보낼 페이지의 경로 |
type | 요청을 보낼 방식. Get 또는 Post |
dataType | 리턴할 데이터의 타입을 지정. xml, html, srcipt, json, text |
data | 요청과 함께 서버로 전달될 데이터 |
timeout | 살패한 것으로 처리하기까지의 제한 시간. 단위는 ms |
async | 요청시 동기 유무를 선택. true(비동기, 기본값) 또는 false (동기). |
cache | 브라우저 cache 처리. true 또는 false. |
beforeSend | 요청을 전달하기 전 호출될 함수 ( 로딩 중 아이콘 표시 등 ) |
always | 성공 / 실패 이벤트 처리한 다음 실행될 함수 ( 로딩 중 아이콘 제거 등 ) |
done | 요청 성공시 호출될 함수 |
fail | 요청 실패시 호출될 함수 |
*여기서 get과 post 중 어떤걸 써야할까?
get방식은 전송 데이터가 header에 실려 url에 데이터가 노출되어 보안에 관련된 정보는
body에 포함되어 url에 데이터가 노출이 되지 않는 post방식을 쓰는 것이 바람직하다.
3. LoginController2.java - doPost()
@WebServlet("/login2")
public class LoginControl2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String userID = request.getParameter("userID");
String userPassword = request.getParameter("userPW");
HttpSession session = request.getSession();
HashMap<String, String> map = new HashMap<String, String>();
User user = UserDao2.getInstance().login(userID, userPassword);
if(user != null) {
map.put("chk", "1");
session.setAttribute("user", user);
}else {
map.put("chk", "0");
}
String gson = new Gson().toJson(map);
response.getWriter().write(gson);
//System.out.println(gson);
}
}
- 로그인 ID와 PW가 Ajax를 통해 이쪽으로 넘어오고 받은 ID와 PW를 인자로 Dao의 login 메서드를 호출한다.
- 이 메서드는 Mybatis로 DB에 접근하여 조회한 결과를 매핑한 User라는 VO객체를 반환하는데, 이 때 ID와 PW에 해당하는 회원이 존재시 VO객체가 null이 아닐 것이고 아이디와 패스워드 둘 중 하나라도 틀리다면 VO는 null일 것이다.
- 따라서 null이 아닐 때는 제대로 입력한 것이므로 map을 하나 만들어 chk라는 키에 1을 담고 회원 정보를 세션에 담아주고 null일 경우는 chk 키에 0을 담아준다.
- 이 map을 요청이 왔던 jsp로 응답을 해줘야하는데 위에서 dataType을 json으로 했기 때문에 json으로 응답해주어야하는데 어떻게 응답해야할까?
- Java 객체인 map을 어떻게 json으로 바꾸는 작업은 구글에서 만든 자바 오브젝트의 직렬화/역직렬화 라이브러리인 Gson이라는 패키지를 이용하면 쉽게 할 수 있다.
- Gson은 이곳에서 jar파일을 다운 받아 라이브러리를 추가해주면 된다.
4. MybatisConnector.java
public class MybatisConnector {
private static MybatisConnector conn;
SqlSessionFactory factory;
private MybatisConnector() {
try {
Reader reader = Resources.getResourceAsReader("config/mybatis/sqlConfig.xml");
factory = new SqlSessionFactoryBuilder().build(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
public static MybatisConnector getInstance() {
if(conn == null) {
conn = new MybatisConnector();
}
return conn;
}
public SqlSessionFactory getFactory() {
return factory;
}
}
- 환경 설정파일인 sqlConfig.xml을 참조하여 Mybatis에 필요한 SqlSessionFactory를 만들어 반환해주는 클래스.
- 이전에 Mybatis 설정할 때 작성했던 방식과 똑같다.
[Mybatis] 마이바티스 파헤쳐보기 - 1 -
1. MyBatis란? 관계형 데이터베이스 프로그래밍을 보다 쉽게 도와주는 프레임워크로 JDBC의 근간을 두고 있다. 마이바티스는 개발자가 지정한 SQL, 저장프로시저 그리고 몇가지 고급 매핑을 지원하
egu99.tistory.com
5. MybatisConnector.java
public class UserDao2 {
private static UserDao2 bao;
SqlSessionFactory factory;
private UserDao2() {
factory = MybatisConnector.getInstance().getFactory();
}
public static UserDao2 getInstance() {
if(bao == null) {
bao = new UserDao2();
}
return bao;
}
public User login(String userID, String userPassword) {
SqlSession session = factory.openSession();
HashMap<String, String> map = new HashMap<String, String>();
map.put("userID", userID);
map.put("userPW", userPassword);
User user = session.selectOne("user.login", map);
return user;
}
}
- MybatisConnector로부터 SqlSessionFactory를 얻고 이것으로부터 다시 SqlSession을 얻는다.
- 컨트롤러에서 이 login()을 호출할 때 ID값과 PW값을 인자로 넣어주었고 이것을 다시 여기서 map에 담아 selectOne 메서드로 user라는 네임스페이스를 가진 mapper의 login을 실행할 때 인자로 넣어준다.
- selectOne의 반환값은 User 클래스로, id와 pw가 제대로 입력했다면 회원정보가 매핑된 User 클래스가, 아니라면 null이 저장될 것이다.
- 이 매핑된 User클래스를 login()을 호출한 컨트롤러로 반환해준다.
6. userMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="user">
<select id="login" resultType="User" parameterType="java.util.Map">
select * from user where userID = #{userID} and userPassword = #{userPW};
</select>
</mapper>
- 바로 위에서 selectOne 메서드를 실행할 때 map을 함께 넣어주었고 여기서 select의 속성인 parameterType으로 java.util.Map을 지정해줌으로써 파라미터로 map을 받을 수 있다.
- #{map 키값}으로 sql문에 저장한 map의 value를 꽂아줄 수 있다.
- resultType으로 User클래스를 지정했으므로 아이디와 비밀번호가 일치한 회원 정보가 User클래스에 매핑되어 반환될 것이다. 일치하지 않는다면 null이 반환된다.
7. 결과 화면
♣ 참고 및 인용
'웹 개발 한걸음' 카테고리의 다른 글
[Mybatis + Ajax] 아이디 중복 확인 구현해보기 (0) | 2021.05.10 |
---|---|
[Javascript] 정규표현식 유효성 검사 + 비밀번호 재확인 구현해보기 (0) | 2021.05.06 |
[Mybatis] 마이바티스 파헤쳐보기 - 2 - (0) | 2021.04.28 |
[Mybatis] 마이바티스 파헤쳐보기 - 1 - (0) | 2021.04.22 |
[Design Pattern] 싱글톤 패턴 배워보기 (0) | 2021.04.15 |