Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

방카@Dev

[Spring]Ch9.데이터베이스:관리자 회원가입 기능 만들기_올인원 스프링 프레임워크 본문

BackEnd/Spring

[Spring]Ch9.데이터베이스:관리자 회원가입 기능 만들기_올인원 스프링 프레임워크

방카킴 2024. 6. 9. 14:23
 

올인원 스프링 프레임워크

올인원 스프링 프레임워크 작품소개: 기초부터 실무까지 한 권에 담은 올인원 스프링 프레임워크!웹 서비스의 핵심인 스프링 프레임워크의 전체적인 구조와 핵심 이론을 다양한 예제 프로젝트

ridibooks.com

참고로 위 책은 정말 성의없는 책이다. 학원교재라서 보지만, 코드에 오류가 너무많은 책. 책을 쓰는데 정말 성의가 없다. 이런걸 삼만원 주고 팔다니;;

1. 관리자 회원가입 Spring MVC 구조

- @RequestMapping은 value와 Method 속성을 가지고 있음.

- value 속성에는 사용자 요청 정보를 명시 method에는 요청 정보가 전송되는 방식을 명시(GET,POST)

- method가 get이면 @GetMapping("/url")

- method가 Post면 @PostMapping("/url")

package com.office.library.admin;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/admin") //필수가 아님.명시하지 않으면 클라이언트의 모든 요청을 처리할 수 있는 컨트롤러가 됨
public class AdminHomeController {

		@RequestMapping(value= {"","/"}, method = RequestMethod.GET)
		public String home() {
			System.out.println("[AdminHomeController] home()");
			
			String nextPage = "admin/home";
			
			return nextPage;
		}
}

 

package com.office.library.admin.member;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/admin/member")
public class AdminMemberController {
	
	@Autowired
	AdminMemberService adminMemberService;
	
	//회원가입
	@RequestMapping(value="/createAccountForm", method = RequestMethod.GET)
	public String createAccountForm() {
		System.out.println("[AdminMemberController]createAccountForm()");
		String nextPage = "admin/member/create_account_form";
		return nextPage;
	}
	
	@RequestMapping(value="/createAccountConfirm", method = RequestMethod.POST)
	public String createAccountConfirm(AdminMemberVo adminMemberVo) {
		System.out.println("[AdminMemberController] createAccountConfirm()");
		
		String nextPage = "admin/member/create_account_ok";
		
		int result = adminMemberService.createAccountConfirm(adminMemberVo);
		
		if (result <= 0)
			nextPage = "admin/member/create_account_ng";
		return nextPage;
	}
	
}

 

<create_account_form.jsp>

<%@ 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>
<head>
<meta charset="UTF-8">

<jsp:include page="../../include/title.jsp" />

<link href="<c:url value='/resources/css/admin/create_account_form.css' />" rel="stylesheet" type="text/css">

<jsp:include page="../include/create_account_form_js.jsp" />

</head>
<body>

	<jsp:include page="../../include/header.jsp" />
	
	<jsp:include page="../include/nav.jsp" />
	
	<section>
		
		<div id="section_wrap">
		
			<div class="word">
			
				<h3>CREATE ACCOUNT FORM</h3>
				
			</div>
		
			<div class="create_account_form">
			
				<form action="<c:url value='/admin/member/createAccountConfirm' />" name="create_account_form" method="post">
					
					<input type="text" name="a_m_id" placeholder="INPUT ADMIN ID."> <br>
					<input type="password" name="a_m_pw" placeholder="INPUT ADMIN PW."> <br>
					<input type="password" name="a_m_pw_again" placeholder="INPUT ADMIN PW AGAIN."> <br>
					<input type="text" name="a_m_name" placeholder="INPUT ADMIN NAME."> <br>
					<select name="a_m_gender">
						<option value="">SELECET ADMIN GENDER.</option>
						<option value="M">Man</option>
						<option value="W">Woman</option>
					</select> <br>
					<input type="text" name="a_m_part" placeholder="INPUT ADMIN PART."> <br>
					<input type="text" name="a_m_position" placeholder="INPUT ADMIN POSITION."> <br>
					<input type="email" name="a_m_mail" placeholder="INPUT ADMIN MAIL." ><br>
					<input type="text" name="a_m_phone" placeholder="INPUT ADMIN PHONE."> <br>
					<input type="button" value="create account" onclick="createAccountForm();"> 
					<input type="reset" value="reset">
					
				</form>
				
			</div>
			
			<div class="login">
				
				<a href="<c:url value='/admin/member/loginForm' />">login</a>
				
			</div>
		
		</div>
		
	</section>
	
	<jsp:include page="../../include/footer.jsp" />
	
</body>
</html>

- <input>, <select>의 name에 명시된 속성 값은 실제로 관리자 정보가 저장되는 데이터베이스의 컬럼명과 동일하게 함

 

package com.office.library.admin.member;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AdminMemberService {
	
	final static public int ADMIN_ACCOUNT_ALREADY_EXIST = 0;
	final static public int ADMIN_ACCOUNT_CREATE_SUCCESS = 1;
	final static public int ADMIN_ACCOUNT_CREATE_FAIL = -1;
	
	@Autowired
	AdminMemberDao adminMemberDao;
	
	public int createAccountConfirm(AdminMemberVo adminMemberVo) {
		System.out.println("[AdminMembaerSerivce]createAccountConfirm()");
		
		boolean isMember = adminMemberDao.isAdminMember(adminMemberVo.getA_m_id());
		
		if(!isMember) {
			int result = adminMemberDao.insertAdminAccount(adminMemberVo);
			
			if(result>0) {
				return ADMIN_ACCOUNT_CREATE_SUCCESS;
			} else {
				return ADMIN_ACCOUNT_CREATE_FAIL;
			}
		} else {
			return ADMIN_ACCOUNT_ALREADY_EXIST;
		}
	}
}

 

2. JDBCTemplate으로 데이터베이스 연동

 

스프링에서는 JDBC보다 세련된 jdbcTemplate 클래스를 제공한다. 이를 이용하면 'JDBC 드라이버 로드, 데이터베이스 연결' 같은 반복 작업을 하지 않고 'SQL 쿼리 작성 및 실행' 작업에 집중할 수 있는 장점이 있다. 

 

(1) <pom.xml>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${org.springframework-version}</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
<dependency>
    <groupId>org.mariadb.jdbc</groupId>
    <artifactId>mariadb-java-client</artifactId>
    <version>3.4.0</version>
</dependency>

<!-- mysql -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.13</version>
		</dependency>

 

(2) <jdbc-context.xml>

경로 : src/main/webapp/WEB-INF/spring/

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
		
	<!-- <context:property-placeholder location="/WEB-INF/spring/property/real.info.properties" /> -->
	
	<!-- MariaDB connection 객체 -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="org.mariadb.jdbc.Driver" />
		<property name="url" value="jdbc:mariadb://127.0.0.1:3306/db_library" />
		<property name="username" value="root" />
		<property name="password" value="qwe123!@#" />
	</bean>

	<!-- MySQL connection 객체 -->
    <beans:bean id="dataSource"
	class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <beans:property name = "driverClassName" value = "com.mysql.cj.jdbc.Driver"/>
        <beans:property name = "url" value ="jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&amp;useSSL=false"/>
        <beans:property name = "username" value="root"/>
        <beans:property name = "password" value="qwe123!@#"/>
	</beans:bean>
    
	<!-- JdbcTemplate 객체 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<!-- TransactionManager 객체 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	
</beans>

 

(3) <web.xml>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
    /WEB-INF/spring/root-context.xml
    /WEB-INF/spring/jdbc-context.xml
    /WEB-INF/spring/security-context.xml		
    </param-value>
</context-param>

 

package com.office.library.admin.member;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

@Component
public class AdminMemberDao {
	
	@Autowired
	JdbcTemplate jdbcTemplate;
	
	@Autowired
	BCryptPasswordEncoder passwordEncoder;
	
	public boolean isAdminMember(String a_m_id) {
		System.out.println("[AdminMemberDao] isAdminMember()");
		
		String sql  = "SELECT COUNT(*) FROM tbl_admin_member"
					 + " WHERE a_m_id=?";
		
		int result = jdbcTemplate.queryForObject(sql, Integer.class, a_m_id);
		
		if(result>0)
			return true;
		else 
			return false;
	}
	
	public int insertAdminAccount(AdminMemberVo adminMemberVo) {
		System.out.println("[AdminMemberDao] insertAdmilnAccount");
		
		List<String> args = new ArrayList<String>();
		
		
		String sql = "INSERT INTO tbl_admin_member(";
				if(adminMemberVo.getA_m_id().equals("super admin")) {
					sql+="a_m_approval, ";
					args.add("1");
				}
				
				sql += "a_m_id, ";
				   args.add(adminMemberVo.getA_m_id());
				   
				   sql += "a_m_pw, ";
				   args.add(passwordEncoder.encode(adminMemberVo.getA_m_pw()));
				   
				   sql += "a_m_name, ";
				   args.add(adminMemberVo.getA_m_name());
				   
				   sql += "a_m_gender, ";
				   args.add(adminMemberVo.getA_m_gender());
				   
				   sql += "a_m_part, ";
				   args.add(adminMemberVo.getA_m_part());
				   
				   sql += "a_m_position, ";
				   args.add(adminMemberVo.getA_m_position());
				   
				   sql += "a_m_mail, ";
				   args.add(adminMemberVo.getA_m_mail());
				   
				   sql += "a_m_phone, ";
				   args.add(adminMemberVo.getA_m_phone());
				   
				   sql += "a_m_reg_date, a_m_mod_date) ";
				   
				   if (adminMemberVo.getA_m_id().equals("super admin")) 
					   sql += "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())";
				   else 
					   sql += "VALUES(?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())";
				   
			int result = -1;
			
			try {
				
				result = jdbcTemplate.update(sql, args.toArray());
				
			} catch (Exception e) {
				e.printStackTrace();
				
			}
			
			return result;
			
		}
}

※ SQL 쿼리 메서드

(1) jdbcTemplate.queryForObject(sql, Integer.class, a_m_id)

- jdbcTemplate의 queryForObject()를 이용해서 SQL문을 실행하고 결과를 result에 받음

- 세 개의 매개변수 (1) sql : SQL문 (2) Integer.class : 쿼리 실행 후 반환되는 데이터 타입 (3) a_m_id : 관리자 입력 아이디

- 단일값 반환

 

(2) jdbcTemplate.query(sql, 반환 타입)

-복수값 반환

 

(3) jdbcTemplate.update(sql, args.toArray())

- update() 를 이용하여 sql문 실행, args를 전달할때는 배열로 변경하여 전달 

 

3. 스프링 비밀번호 암호화 

- 스프링에는 데이터를 암호화하고 복호화하는 모듈로 spring-security-core가 있음 이 모듈을 이용하기 위해서는 pom.xml에 모듈을 설정하고 spring 폴더에 security-context.xml 파일을 만들어 BCryptPasswordEncoder Bean 객체를 생성하는 코드를 만듬

(1) <pom.xml>

<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>${org.springframework-version}</version>
</dependency>

 

(2) <security-context.xml>

경로 : src/main/webapp/WEB-INF/spring/

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
		
	<bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
	
</beans>

 

(3) <web.xml>

<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
    /WEB-INF/spring/root-context.xml
    /WEB-INF/spring/jdbc-context.xml
    /WEB-INF/spring/security-context.xml		
    </param-value>
</context-param>