이전 포스팅에서 Controller를 생성하고 JSP와 연동까지 했었다.
이번에는 Database를 연동하여 로그인을 할 것이다.
1. pom.xml
Dependency 추가
<!-- Gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<!-- MariaDB -->
<!-- <dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
</dependency> -->
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!-- log4j2 -->
<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
<version>1.16</version>
</dependency>
2. application.yml
driver 및 연결 정보 설정 추가
datasource:
# MARIADB
#driverClassName: org.mariadb.jdbc.Driver
#url: jdbc:mariadb://localhost:3306/sample_db?characterEncoding=UTF-8&serverTimezone=UTC
# MYSQL
# 기본
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sample_db?characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: root
3. MyBatis
MyBatis 설정
Spring Boot를 하면서 MyBatis를 연결하려니 패키지 별로 config
를 지정하는게 잘 되지않았다.
예를 들어 관리자패키지, 클라이언트패키지가 각각 있을 때 config.xml
을 apage-config.xml, client-config.xml
형식으로 각각 mapper.xml
을 참조하도록 하고 싶었으나 되지않았다. 기본적으로 config.xml
은 1개만 지정할 수 있는 것 같다.
(구글링해보니 직접적인 config.xml
의 분리는 되지 않으나 Java config
로 바꾸면 가능하다는 글을 봤지만 어려워서 패스)
그리고 application.yml
에서 mybatis
옵션 중 config-location
을 추가하면 sqlSessionFactory
에서 찾지 못한다는 에러가
발생하여 Java로 별도의 Config를 생성
한다.
MyBatisConfig.java
우선 MyBatisConfig.java
파일을 만들어 다음과 같이 작성한다.
(application.yml 에서 datasource를 작성하지 않고 Java에서 작성해도 무방하나 글쓴이는 datasource는 여기서 쓰지않음)
package com.sample;
import java.io.IOException;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisConfig {
@Autowired
ApplicationContext applicationContext;
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws IOException {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
// classpath는 현재 src/main/resources 이다
factoryBean.setConfigLocation(applicationContext.getResource("classpath:/mybatis/mybatis-config.xml"));
factoryBean.setMapperLocations(applicationContext.getResources("classpath:/mybatis/mapper/**/*.xml"));
return factoryBean;
}
@Bean
public SqlSessionTemplate sqlSession(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
DataSource
와 SqlSession
을 각각 Bean
으로 지정한다.DataSource
에서는 MyBatis
의 설정 파일
과 Mapper 경로
를 지정해준다.
mybatis-config.xml
application.yml
파일이 있는 경로에 mybatis/mybatis-config.xml
을 생성
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias alias="ApageManageVo" type="com.sample.apage.manage.service.ApageManageVo" />
</typeAliases>
</configuration>
application.yml
파일이 있는 경로에 mybatis/mapper/apage/ApageManageMapper.xml
을 생성
ApageManageMapper.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="com.sample.apage.manage.service.impl.ApageManageMapper">
<!-- 관리자 로그인 -->
<select id="selectMemberByUserIdAndUserPw" parameterType="ApageManageVo" resultType="ApageManageVo">
SELECT seq, userId, userPw, userPwEnc, name, tel, phone, email, zipCode, addr1, addr2, remoteIp, level
FROM adm_member
WHERE userId=#{userId}
AND userPw=#{userPw}
</select>
</mapper>
주의할 점은 mapper
의 namespace
경로를 전체경로로 적어야한다.
(config에서 alias 설정이 가능하면 그렇게 해도된다.
난 안되던데..
)
ApageManageVo.java
다음 Lombok을 이용한 Vo를 작성
package com.sample.apage.manage.service;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
public class ApageManageVo {
private String seq; // 일련번호
private String userId; // 아이디
private String userPw; // 비밀번호
private String userPwEnc; // 비밀번호 암호화 SHA2-256
private String name; // 이름
private String tel; // 전화번호
private String phone; // 휴대폰
private String email; // 이메일
private String zipCode; // 우편번호
private String addr1; // 대표주소
private String addr2; // 상세주소
private String remoteIp; // 접근IP
private String accessIp; // 허용IP 문자열
private String level; // 관리자 권한
private String regDate; // 등록일
private String editDate; // 수정일
private String lastLoginDate; // 마지막 로그인 일시
}
@Data
보다 필요한 속성만 쓰는게 좋은 듯하다.
ApageManageService.java
다음 Impl
과 연결할 interface
를 만든다.
기존에 쓰던 방식은
Controller -> Service -> ServiceImpl -> DAO -> DB
였다면 Spring Boot 에서는
Controller -> Service -> ServiceImpl -> Mapper -> DB
방식인 듯하다. (자세하게 얘기하면 흐름이 길어서 패스)
package com.sample.apage.manage.service;
import javax.servlet.http.HttpServletRequest;
public interface ApageManageService {
// 관리자 정보
public ApageManageVo selectMemberByUserIdAndUserPw(ApageManageVo vo) throws Exception;
}
ApageManageServiceImpl.java
package com.sample.apage.manage.service.impl;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import javax.servlet.http.HttpServletRequest;
import com.sample.apage.manage.service.impl.ApageManageMapper;
import com.sample.apage.manage.service.ApageManageVo;
import com.sample.common.utils.NUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ApageManageServiceImpl implements ApageManageService {
@Autowired
ApageManageMapper mapper;
@Override
public ApageManageVo selectMemberByUserIdAndUserPw(ApageManageVo vo) throws Exception {
return mapper.selectMemberByUserIdAndUserPw(vo);
}
}
ApageManageMapper.java
package com.sample.apage.manage.service.impl;
import java.util.HashMap;
import com.sample.apage.manage.service.ApageManageVo;
import org.apache.ibatis.annotations.Mapper;
// Mapper 지정 필수
// 여기서 사용되는 메서드의 이름은 Mapper.xml 에서의 쿼리별 id값이된다. (틀리면안됨)
@Mapper
public interface ApageManageMapper {
// 관리자 정보
public ApageManageVo selectMemberByUserIdAndUserPw(ApageManageVo vo) throws Exception;
}
ApageManageController.java
다음 ApageManageController.java
를 아래와 같이 작성한다.
package com.sample.apage.manage.web;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.google.gson.Gson;
import com.sample.apage.manage.service.ApageManageService;
import com.sample.apage.manage.service.ApageManageVo;
import com.sample.common.utils.NUtil;
import com.sample.common.utils.ShaEncryption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ApageManageController {
private final Logger log = LoggerFactory.getLogger(getClass());
@Autowired
private ApageManageService ApageManageService;
/**
* 관리자 로그인페이지
*
* @param request
* @param response
* @param session
* @param model
* @return
* @throws Exception
*/
@RequestMapping(value = "/apage.do")
public String adminLogin(HttpServletRequest request, HttpServletResponse response, HttpSession session,
ModelMap model) throws Exception {
ApageManageVo mv = (ApageManageVo) session.getAttribute("adminInfo");
if (mv != null && !mv.getSeq().equals("")) {
// 로그인한 상태라면 메인페이지로 이동
return "redirect:/apage/index.do";
}
return "apage/apageLogin";
}
/**
* 관리자 로그인
*
* @param request
* @param response
* @param session
* @param vo
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/apage/adminLoginJson.do")
public void adminLoginJson(HttpServletRequest request, HttpServletResponse response, HttpSession session,
@ModelAttribute("vo") ApageManageVo vo) throws Exception {
Gson gson = new Gson();
Map<String, Object> data = new HashMap<String, Object>();
try {
log.info("adminLoginJson.do ::: {}", vo);
ApageManageVo avo = ApageManageService.selectMemberByUserIdAndUserPw(vo);
if (avo != null) {
// 로그인정보 세션에 저장
session.setAttribute("adminInfo", avo);
// 로그인 정보 일치
data.put("rs", "1");
} else {
// 로그인 정보 불일치
data.put("rs", "2");
}
response.getWriter().print(gson.toJson(data));
} catch (Exception e) {
e.printStackTrace();
response.getWriter().print(gson.toJson(data));
}
}
/**
* 관리자 메인 페이지
*/
@RequestMapping(value = "/apage/index.do", method = RequestMethod.GET)
public String requestMethodName(HttpServletRequest request, HttpServletResponse response, HttpSession session,
@ModelAttribute("vo") ApageManageVo vo) throws Exception {
return "apage/index";
}
}
apageLogin.jsp
로그인 페이지를 간단하게 작성
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko" lang="ko">
<head>
<link href="/resources/favicon.ico?v=2" type="image/x-icon" rel="shortcut icon" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>관리자로그인</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#userId").focus();
});
function doLogin() {
if ($("#userId").val() == "" || $("#userId").val() == null) {
alert("아이디는 필수 입력 항목입니다.");
return;
}
if ($("#userPw").val() == "" || $("#userPw").val() == null) {
alert("패스워드는 필수 입력 항목입니다.");
return;
}
$.ajax({
type: "POST",
url: "<c:url value='/apage/adminLoginJson.do'/>",
data: {
userId: $.trim($("#userId").val()),
userPw: $.trim($("#userPw").val()),
},
dataType: "json",
success: function (data) {
if (data.rs == "1") {
location.replace("<c:url value='/apage/index.do'/>");
} else {
alert("아이디 또는 패스워드를 확인하세요.");
}
},
error: function (data, status, err) {
alert("로그인에 실패하였습니다.");
},
});
}
</script>
</head>
<body class="pg-log">
<div class="log-panel">
<h1>
<span>관리자 시스템</span>
</h1>
<fieldset class="log-frm">
<legend>관리자 로그인</legend>
<p>
<label for="userId"><input type="text" id="userId" style="ime-mode: disabled" placeholder="아이디" title="아이디 입력" /></label>
</p>
<p>
<label for="password"
><input
type="password"
id="userPw"
placeholder="비밀번호"
title="비밀번호 입력"
onkeypress="if(event.keyCode =='13'){doLogin()}"
/></label>
</p>
<input type="submit" value="로그인" onclick="doLogin();" />
</fieldset>
<p class="log-foot">
<span>ⓒCopyright(c) 2020. All rights reserved.</span>
</p>
</div>
<!-- //log-panel -->
</body>
</html>
index.jsp
로그인 후 Hello World
출력할 임시 페이지
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Hello World !!!</h1>
</body>
</html>
실행결과
임의의 admin 계정을 DB에 직접적으로 밀어넣고 로그인을 테스트했다.
- sample_db
실행된 쿼리
쿼리 조회 결과
호출된 index.jsp 페이지
HikariCP
HikariCP
를 적용시켜보자. HikariCP
를 쓰는 이유는 속도가 아주 빠르다고한다.
그러면 일단 쓰고봐야지..
이전에 작성했던 application.yml
에서 다음과 같이 수정 및 추가한다.
Spring Boot
에서는HikariCP
가 이미starter jdbc
에 같이 들어있어서 따로 의존성 추가할 필요 없다.
datasource:
# MARIADB
#driverClassName: org.mariadb.jdbc.Driver
#url: jdbc:mariadb://localhost:3306/sample_db?characterEncoding=UTF-8&serverTimezone=UTC
# MYSQL
# 기본
# driverClassName: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/sample_db?characterEncoding=UTF-8&serverTimezone=UTC
# username: root
# password: root
# MYSQL
# log4j, Hikari 응용
driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://localhost:3306/sample_db?characterEncoding=UTF-8&serverTimezone=UTC
# Hikari
hikari.username: root
hikari.password: root
hikari.maximum-pool-size: 10
hikari.connection-test-query: SELECT 1
logback
에 대한 내용은 다음 포스팅에서 설명한다.
Previous Chapter
Next Chapter
'Backend > Spring' 카테고리의 다른 글
Spring Boot - (5) AOP 설정 (0) | 2020.11.26 |
---|---|
Spring Boot - (4) logback 설정 (0) | 2020.11.23 |
Ajax를 통한 JSON 데이터 주고 받기 (Spring Boot로 수정) (2) | 2020.11.19 |
Spring Boot - (2) Controller 생성 및 JSP 연동 (0) | 2020.11.14 |
Spring Boot - (1) 환경세팅 (0) | 2020.11.14 |