웹개발/스프링연습

[2]Spring-legacy [로그인, 로그아웃 추가]

무한경쟁시대 2021. 11. 15. 16:39

<작성기준: 이 페이지에서 있는 코드를 넣으면 하나의 프로젝트(이전기능 포함)를 만들 수 있음.>

<views, resources 다운로드: https://dev-junyeong.tistory.com/18>

스프링레거시 + Mysql < 마이바티스사용 >


<만들어야 하는 것>

1. Script.java (StringBuilder를 사용하여 자바스크립트를 쓰기위함. 뒤로가기, 리다이렉트)

2. MemberService.java 

3. MemberController(내용 추가)

4. MemberMapper.java(내용 추가)

5. Join.jsp(내용 수정: jstl c태그 추가 및 세션에 따라 탑메뉴반응)

 


<주요사항>

0. ajax코드는 아직 미구현이므로 Join.jsp는 아래 것을 사용해야한다.

1. redirect를 스프링방식으로 할 때 ResponseEntity<String>

자바스크립트를 활용해서 뒤로가기(history.back)나 특정페이지(location.href="")가기

 

2. mapper에서 쿼리문을 작성할 때 #방식과 $방식이 있다.

#방식은 #{id}처럼 사용하고

$방식은 '${id}' 처럼 사용한다.

작은따움표가 있고 없고의 차이가 난다.

 

3. @Service 가 있는 클래스는 보통 @Controller가 있는 클래스와 mapper인터페이스 사이에서 존재하며

@Transactional을 처리하기 위해서 존재한다. 그러므로 트랜잭션 처리없는 경우

서비스가 없더라도 작동한다.

 

groupid는 com.example

 

[MemberService]

package com.example.service;

import java.util.List;

import org.springframework.stereotype.Service;

import com.example.domain.MemberVO;
import com.example.mapper.MemberMapper;

//1차적으로 트랜잭션을 위해서 쓰는 클래스이다. 
//컨트롤러는 서비스에게 요구하는 패턴으로 많이 쓴다.
@Service
//@Transactional //필요한 곳에만 올 수 있다.
public class MemberService {
	private MemberMapper memberMapper;

	// @Autowired 애노테이션이 생성자에서는 생략가능 
	public MemberService(MemberMapper memberMapper) {
		super();
		this.memberMapper = memberMapper;
	}
	
	// 회원가입하기
	public void register(MemberVO memberVO) {
		
		long beginTime = System.currentTimeMillis();
		
		memberMapper.insert(memberVO); //서비스가 매퍼에 의존해서 처리함
		
		long endTime = System.currentTimeMillis();
		
		long diff = endTime - beginTime;
		System.out.println("메소드 실행시간 : " + diff + "ms");
	}
	
	public MemberVO getMemberById(String id) {
		MemberVO memberVO = memberMapper.getMemberById(id);
		return memberVO;
	}
	
	public List<MemberVO> getMembers(){
		return memberMapper.getMembers();
	}
	
	public int deleteMemberById(String id) {
		int rowCount = memberMapper.deleteMemberById(id);
		return rowCount;
	}
	
	public void updateMember(MemberVO memberVO) {
		memberMapper.updateMember(memberVO);
	}
}

 

[MemberMapper]

package com.example.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.example.domain.MemberVO;
//인터페이스에서는 객체 직접 생성할 순 없다. 
public interface MemberMapper {
	
	@Insert("INSERT INTO member (id, passwd, name, birthday, gender, email, recv_email, reg_date) "
			+ " VALUES (#{id}, #{passwd}, #{name}, #{birthday}, #{gender}, #{email}, #{recvEmail}, #{regDate}) ")
	void insert(MemberVO memberVO);
	//, (), (), () 소괄호 여러개 붙여서 여러 행 insert 가능
	
	@Select("SELECT * FROM member WHERE id = #{id}")//매개변수인 id 실제론 'abc' 이런식으로 아이디 들어옴
	MemberVO getMemberById(String id);//그래서 id부분에 '쓰면안됨' 다만, '${id}' 달러로 쓰면 이렇게 써야함

	@Select("SELECT * FROM member WHERE ORDER BY id") //멤버 여러개 List로
	List<MemberVO>getMembers();
	
	@Select("SELECT COUNT(*) FROM member WHERE id = #{id}")//아이디 중복체크를 위해
	int getCountById(String id);
	
	@Delete("DELETE FROM member WHERE id = #{id}")//회원 탈퇴
	int deleteMemberById(String id);
	
	@Update(" UPDATE member SET passwd = #{passwd}, name = #{name}, birthday = #{birth}, gender = #{gender}, email = #{email}, recv_email = #{recvEmail} WHERE id = #{id} " )
	void updateMember(MemberVO memberVO);//update는 void 해야한다.
}

 

[Script.java] 여기는 StringBuilder로 자바스크립트를 사용하는 곳

(쓰레드 개념때문에 지역변수로 StringBuilder쓴다)

package com.example.util;

public class Script {
	
	public static String href(String alertMessage, String locationPath) {
		StringBuilder sb = new StringBuilder();

		sb.append("<script>");
		sb.append("alert('" + alertMessage + "');");
		sb.append("location.href = '" + locationPath + "';"); // 특정 이동경로로 요청
		sb.append("</script>");
		return sb.toString();
	}
	
	public static String back(String alertMessage) {
		StringBuilder sb = new StringBuilder();
		
		sb.append("<script>");
		sb.append("alert('" + alertMessage + "');");
		sb.append("history.back();"); // 뒤로가기
		sb.append("</script>");
		return sb.toString();
	}
	
}

 

[MemberController]

package com.example.controller;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.domain.MemberVO;
import com.example.service.MemberService;
import com.example.util.Script;

@Controller
@RequestMapping("/member/*")
public class MemberController {
	
	//스프링 빈들끼리는 memberMapper필요하네? 스프링이 주입시켜줌
	@Autowired
	private MemberService memberService;
	
	 
	@GetMapping("/join")
	public String join() {
		System.out.println("join 호출 됨...");
		return "member/join";
	}
	
	//ResponseEntity 응답데이터 html문서를 문자열로 간단하게 준다
	@PostMapping("/join")
	public ResponseEntity<String> join(MemberVO memberVO) {
		
		//비밀번호 암호화
		String passwd = memberVO.getPasswd();
		String hasedPw= BCrypt.hashpw(passwd, BCrypt.gensalt());
		memberVO.setPasswd(hasedPw);
		
		String birthday = memberVO.getBirthday();//하이픈 삭제 "2021-08-25"
		birthday = birthday.replace("-", "");//20210825
		memberVO.setBirthday(birthday);
		
		memberVO.setRegDate(new Date());//현재시점의 날짜 객체
		
		memberService.register(memberVO);
		System.out.println(memberVO);//이건 스프링세상이기때문에 프린트됨. 롬복??
//		String test = memberVO.toString();
//		System.out.println(test);
//		return "redirect:/member/login"; //새로고침하면 웹에 담겨있던 Post된 정보가 한번더 보내져서 에러
//		스프링방식으로 해보기
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-Type", "text/html; charset=UTF-8");//어떤 자료형인지 content-type
		String str = Script.href("회원가입 성공!", "/member/login");//자바스크립트 실행하는 방식
		return new ResponseEntity<String>(str, headers, HttpStatus.OK);
	}
	
	@GetMapping("/login")
	public String login() {
		return "member/login";
	}
	
	@PostMapping("/login")
	public ResponseEntity<String> login(String id, String passwd, String rememberMe, HttpSession session) {
		
		MemberVO memberVO = memberService.getMemberById(id);
		
		boolean isPasswdSame = false;
		String message = "";
		if(memberVO != null) {
			isPasswdSame = BCrypt.checkpw(passwd, memberVO.getPasswd());
			if(isPasswdSame == false) {//비밀번호가 일치하지 않음
				message = "비밀번호가 일치하지 않습니다.";
			}
		} else {//memberVO == null // 일치하는 아이디가 없음
			message = "존재하지 않는 아이디 입니다.";
		}
		// 로그인 실패시 (없는 아이디이거나 비밀번호 틀렸을 때)
		if(memberVO == null || isPasswdSame == false) {
			HttpHeaders headers = new HttpHeaders();
			headers.add("Content-Type", "text/html; charset=UTF-8");
			String str = Script.back(message);
			
			return new ResponseEntity<String> (str,headers,HttpStatus.OK);//200번
		}
		//로그인 성공시, 로그인 인증하기
		session.setAttribute("id", id);//map인데 키값은 스트링만 쓸 수 있다.
		
		HttpHeaders headers = new HttpHeaders();
		headers.add("Location", "/");//redirect 홈으로 보내는 경로
		
		return new ResponseEntity<String>(headers, HttpStatus.FOUND);//302번
	}//login
	/*
	 * 영역객체 4가지 application : 웹프로그램 한개당 유지됨 session : 사용자 한명당 유지됨 request : 사용자 요청
	 * 한개당 유지됨 pageContext : JSP 화면 한개 처리할동안 유지됨
	 * 
	 * 영역(scope)객체 수명주기 application > session > request > pageContext
	 * 
	 * el언어에서 검색순서 ${ id } pageScope -> requestScope -> sessionScope ->
	 * applicationScope
	 * 그래서 결론: jsp에서 sessionScope.id 안해도 id를 불러올 수 있는 것이다.
	 */
	
	@GetMapping("/logout")
	public String logout(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
		session.invalidate();
		return "redirect:/";
	}
}

 

[Join.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
    <%-- include head.jsp --%>
    <jsp:include page="/WEB-INF/views/include/head.jsp" />
</head>
<body>
    <%-- include topNavbar.jsp --%>
	<jsp:include page="/WEB-INF/views/include/topNavbar.jsp" />

    
    <!-- middle container -->
    <div class="container mt-4">
      <div class="row">

        <!-- Left Menu -->
        <div class="col-sm-3">

          <!-- Vertical Nav -->
          <ul class="nav flex-column nav-pills">
            <li class="nav-item">
              <a class="nav-link active" href="#">Active</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Link</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#">Link</a>
            </li>
            <li class="nav-item">
              <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
            </li>
          </ul>
          <!-- end of Vertical Nav -->
        </div>
        <!-- end of Left Menu  -->


        <!-- Right area -->
        <div class="col-sm-9">
          
          <!-- Contents area -->
          <div class="border border-info p-4 rounded">
            <h5>회원 가입</h5>

            <hr class="featurette-divider">

            <form action="/member/join" method="POST">
              <div class="form-group">
                <label for="id">
                  <i class="material-icons align-middle">account_box</i>
                  <span class="align-middle">아이디</span>
                </label>
                <input type="text" class="form-control" id="id" aria-describedby="idHelp" name="id" required autofocus>
                <small id="idHelp" class="form-text text-muted">아이디는 필수 입력 요소입니다.</small>
              </div>

              <div class="form-group">
                <label for="password">
                  <i class="material-icons align-middle">lock</i>
                  <span class="align-middle">비밀번호</span>
                </label>
                <input type="password" class="form-control" id="password" aria-describedby="pwdHelp" name="passwd" required>
                <small id="pwdHelp" class="form-text text-muted">비밀번호는 필수 입력 요소입니다.</small>
              </div>
              <div class="form-group">
                <label for="password2">
                  <i class="material-icons align-middle">check</i>
                  <span class="align-middle">비밀번호 재확인</span>
                </label>
                <input type="password" class="form-control" id="password2">
              </div>

              <div class="form-group">
                <label for="name">
                  <i class="material-icons align-middle">person</i>
                  <span class="align-middle">이름</span>
                </label>
                <input type="text" class="form-control" id="name" name="name">
              </div>

              <div class="form-group">
                <label for="birthday">
                  <i class="material-icons align-middle">event</i>
                  <span class="align-middle">생년월일</span>
                </label>
                <input type="date" class="form-control" id="birthday" name="birthday">
              </div>

              <div class="form-group">
                <label for="gender">
                  <i class="material-icons align-middle">wc</i>
                  <span class="align-middle">성별 선택</span>
                </label>
                <select class="form-control" id="gender" name="gender">
                  <option value="" disabled selected>성별을 선택하세요.</option>
                  <option value="M">남자</option>
                  <option value="F">여자</option>
                  <option value="U">선택 안함</option>
                </select>
              </div>

              <div class="form-group">
                <label for="email">
                  <i class="material-icons align-middle">mail</i>
                  <span class="align-middle">이메일 주소</span>
                </label>
                <input type="email" class="form-control" id="email" name="email">
              </div>

              <div class="text-center">
                <label class="mr-3">이벤트 등 알림 메일 수신동의 : </label>
                <div class="custom-control custom-radio custom-control-inline">
                  <input type="radio" id="customRadioInline1" name="recvEmail" class="custom-control-input" value="Y" checked>
                  <label class="custom-control-label" for="customRadioInline1">동의함</label>
                </div>
                <div class="custom-control custom-radio custom-control-inline">
                  <input type="radio" id="customRadioInline2" name="recvEmail" class="custom-control-input" value="N">
                  <label class="custom-control-label" for="customRadioInline2">동의 안함</label>
                </div>
              </div>
              
              <div class="my-3 text-center">
                <button type="submit" class="btn btn-primary">회원가입</button>
                <button type="reset" class="btn btn-primary ml-3">초기화</button>
              </div>
            </form>

          </div>
          <!-- end of Contents area -->
        </div>
        <!-- end of Right area -->
      </div>
    </div>
    <!-- end of middle container -->



    <%-- include bottomFooter.jsp --%>
	<jsp:include page="/WEB-INF/views/include/bottomFooter.jsp" />

    
    <%-- include javascripts.jsp --%>
    <jsp:include page="/WEB-INF/views/include/javascripts.jsp" />

<!-- <script>
	$('input#id').on('focusout', function () {
		
		let id = $(this).val();
		if (id.length == 0) {
			return;
		}
		
		// ajax 함수 호출
		$.ajax({
			url: '/api/members/' + id + '.json',
			method: 'GET',
			success: function (data) {
				console.log(typeof data);  // object
				console.log(data);  // {}
				
				if (data.count == 0) {
					$('small#idHelp').html('사용가능한 아이디 입니다.')
						.removeClass('text-muted').removeClass('text-danger')
						.addClass('text-success');
				} else { // data.count == 1
					$('small#idHelp').html('이미 사용중인 아이디 입니다.')
						.removeClass('text-muted').removeClass('text-success')
						.addClass('text-danger');
				}
			},
			error: function (request, status, error) {
				alert('code: ' + request.status + '\n message: ' + request.responseText + '\n error: ' + error);
			}
		});
		
		
	});


</script> -->
</body>
</html>

 

[src/main/resources 하단에 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">

<!-- 스프링 쓸 때는 여기가 아니라 root-context -->
<configuration>
	<!--  DB에서 데이터 조회 또는 삽입 등에서 null 값 허용-->
	<settings>
		<setting name="jdbcTypeForNull" value="NULL"/>
		<setting name="callSettersOnNulls" value="true" />
	<!-- 동일한 Select문이 또 요청되면 기존 캐시된 내용으로 가져옴. 속도향상 -->
		<setting name="cacheEnabled" value="true"/>
	<!-- 테이블의 컬럼명과 VO객체의 setter명 연결 규칙 설정 -->	
		<setting name="mapUnderscoreToCamelCase" value="true" />
	</settings>
</configuration>

 

[servlet-context.xml]

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<beans:bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver" />
	
	
	<context:component-scan base-package="com.example.controller" />
	
	
<!-- 	<beans:bean id="loginCheckInterceptor" class="com.example.interceptor.LoginCheckInterceptor" />
	
	<interceptors>
		<interceptor>
			<mapping path="/**" />
			<beans:bean class="com.example.interceptor.RememberMeInterceptor" />
		</interceptor>
		
		<interceptor>
			<mapping path="/member/*" />
			<exclude-mapping path="/member/join" />
			<exclude-mapping path="/member/login" />
			<beans:ref bean="loginCheckInterceptor" />
		</interceptor>
		
		<interceptor>
			<mapping path="/board/*" />
			<exclude-mapping path="/board/list" />
			<exclude-mapping path="/board/content" />
			<beans:ref bean="loginCheckInterceptor" />
		</interceptor>
	</interceptors> -->

</beans:beans>

 

[root-context.xml]

<?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"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd
		http://www.springframework.org/schema/beans https://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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">	
	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Root Context: defines shared resources visible to all other web components -->

	<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
		<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/study?useUnicode=true&amp;characterEncoding=utf8&amp;allowPublicKeyRetrieval=true&amp;useSSL=false&amp;serverTimezone=Asia/Seoul" />
		<property name="username" value="pjy" />
		<property name="password" value="1234" />
	</bean>
	
	<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
		<constructor-arg ref="hikariConfig" />
	</bean>
	
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:/mybatis-config.xml" />
	</bean>
	
	<mybatis-spring:scan base-package="com.example.mapper"/>
	
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<!-- @Transactional 애노테이션 기능 활성화 -->
	<tx:annotation-driven/>
	
	
	<context:component-scan base-package="com.example.service"/>
<!-- 	<context:component-scan base-package="com.example.sample" /> -->

<!-- 	<context:component-scan base-package="com.example.aop" /> -->
	<!-- @Aspect 애노테이션 기능 활성화 -->
	<aop:aspectj-autoproxy />
	
<!-- 	<context:component-scan base-package="com.example.task" /> -->
	<!-- @Scheduled 애노테이션 기능 활성화 -->
	<task:annotation-driven/>

		
</beans>

 

[web.xml]

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee; https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- 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</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
		<!-- Filter Post hangeul -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

[pom.xml]

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.example</groupId>
	<artifactId>myapp</artifactId>
	<name>test</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.8</java-version>
		<org.springframework-version>5.2.16.RELEASE</org.springframework-version>
		<org.aspectj-version>1.6.10</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
	</properties>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${org.springframework-version}</version>
			<scope>test</scope>
		</dependency>

		<!-- 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.springframework/spring-tx -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.7</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>2.0.6</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.26</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
		<dependency>
			<groupId>com.zaxxer</groupId>
			<artifactId>HikariCP</artifactId>
			<version>5.0.0</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.20</version>
			<scope>provided</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.mindrot/jbcrypt -->
		<dependency>
			<groupId>org.mindrot</groupId>
			<artifactId>jbcrypt</artifactId>
			<version>0.4</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
		<dependency>
			<groupId>net.coobird</groupId>
			<artifactId>thumbnailator</artifactId>
			<version>0.4.14</version>
		</dependency>

		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.11.0</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.3.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz-jobs -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz-jobs</artifactId>
			<version>2.3.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>2.8.8</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.12.5</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
		<dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-xml</artifactId>
			<version>2.12.5</version>
		</dependency>

		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>

		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-eclipse-plugin</artifactId>
				<version>2.9</version>
				<configuration>
					<additionalProjectnatures>
						<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
					</additionalProjectnatures>
					<additionalBuildcommands>
						<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
					</additionalBuildcommands>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>true</downloadJavadocs>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.5.1</version>
				<configuration>
					<source>${java-version}</source>
					<target>${java-version}</target>
					<compilerArgument>-Xlint:all</compilerArgument>
					<showWarnings>true</showWarnings>
					<showDeprecation>true</showDeprecation>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<version>1.2.1</version>
				<configuration>
					<mainClass>org.test.int1.Main</mainClass>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>