지금 까지 로그인 처리를 위해 다오(DAO), 서비스(Service), 컨트롤러(Controller)를 생성하였습니다.
"ServletContextListener"에서 다오(DAO) 클래스를 사용할 수 있게 의존성 주입(Dependency Injection - DI)를 하겠습니다.
이전 "자바 데이터베이스 매니저 만들기 2"를 통해 데이터베이스매핑맵(databaseMappingMap)을 추가하였습니다.
// DBId-Database 맵
Map<String, TestDatabaseManager> databaseMappingMap = new HashMap<String, TestDatabaseManager>();
String databaseManagers = sce.getServletContext().getInitParameter("DatabaseManager");
if (databaseManagers != null && !databaseManagers.trim().isEmpty()) {
String[] databaseManagerPaths = databaseManagers.trim().split("\n|,|;|\\s+");
for (String databaseManagerPath : databaseManagerPaths) {
databaseManagerPath = databaseManagerPath.trim();
if (!databaseManagerPath.isEmpty()) {
TestDatabaseManager testDatabaseManager = new TestDatabaseManager(databaseManagerPath);
if (testDatabaseManager.isInitDriver()) {
databaseMappingMap.put(testDatabaseManager.getId(), testDatabaseManager);
}
}
}
}
11. "TestServletContextListener.java"의 "contextInitialized"에 DAO 클래스에 대한 의존성 주입을 위해 저장소매핑맵(repositoryMappingMap)을 추가합니다.
// Repository-Class 맵
Map<String, Object> repositoryMappingMap = new HashMap<String, Object>();
"@TestAnnRepository"어노테이션이 적용된 DAO 클래스를 스캔하여 인스턴스를 생성하고 DAO 클래스의 인터페이스(interface)와 생성된 인스턴스를 저장소매핑맵(repositoryMappingMap)에 추가합니다.
for (Class<?> findClass : classes) {
TestAnnRepository annoRepository = findClass.getAnnotation(TestAnnRepository.class);
if (annoRepository != null) {
Object repositoryeInstance = null;
try {
repositoryeInstance = findClass.newInstance();
Class<?>[] interfaces = findClass.getInterfaces();
for (int i = 0; i < interfaces.length; ++i) {
repositoryMappingMap.put(interfaces[i].getName(), repositoryeInstance);
System.out.println("[Repository] " + findClass.getName() + " 인스턴스를 생성함");
}
} catch (InstantiationException | IllegalAccessException e) {
//e.printStackTrace();
System.out.println(findClass.getName() + "의 인스턴스를 생성하지 못함");
}
}
}
그리고 생성된 인스턴스에서 선언된 맴버 필드 리스트를 가져와서 "@TestAnnAutowired"어노테이션과 "@TestAnnQualifier"어노테이션이 있는지 확인합니다.
Field[] Fields = findClass.getDeclaredFields();
for (Field field : Fields) {
TestAnnAutowired testAnnAutowired = field.getAnnotation(TestAnnAutowired.class);
TestAnnQualifier testAnnQualifier = field.getAnnotation(TestAnnQualifier.class);
if (testAnnAutowired != null && testAnnQualifier != null) {
}
}
맴버 필드의 타입으로 데이터베이스매핑맵(databaseMappingMap)에서 ID와 일치하는 데이터베이스 매니저 클래스를 가져옵니다.
TestDatabaseManager testDatabaseManager = (TestDatabaseManager) databaseMappingMap.get(testAnnQualifier.value());
if (testDatabaseManager != null) {
}
맴버 필드에 접근할 수 있게 설정하고 "set"메소드를 통해 값을 주입(인젝션)합니다.
field.setAccessible(true);
try {
field.set(repositoryeInstance, testDatabaseManager);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
전체 소스입니다.
// Repository-Class 맵
Map<String, Object> repositoryMappingMap = new HashMap<String, Object>();
for (Class<?> findClass : classes) {
TestAnnRepository annoRepository = findClass.getAnnotation(TestAnnRepository.class);
if (annoRepository != null) {
Object repositoryeInstance = null;
try {
repositoryeInstance = findClass.newInstance();
Class<?>[] interfaces = findClass.getInterfaces();
for (int i = 0; i < interfaces.length; ++i) {
repositoryMappingMap.put(interfaces[i].getName(), repositoryeInstance);
System.out.println("[Repository] " + findClass.getName() + " 인스턴스를 생성함");
}
} catch (InstantiationException | IllegalAccessException e) {
//e.printStackTrace();
System.out.println(findClass.getName() + "의 인스턴스를 생성하지 못함");
}
if (repositoryeInstance != null) {
Field[] Fields = findClass.getDeclaredFields();
for (Field field : Fields) {
TestAnnAutowired testAnnAutowired = field.getAnnotation(TestAnnAutowired.class);
TestAnnQualifier testAnnQualifier = field.getAnnotation(TestAnnQualifier.class);
if (testAnnAutowired != null && testAnnQualifier != null) {
System.out.println("[Repository Field] " + field.getType().getName() + " 타입의 " + field.getName() + " 맴버 필드을 찾음");
TestDatabaseManager testDatabaseManager = (TestDatabaseManager) databaseMappingMap.get(testAnnQualifier.value());
if (testDatabaseManager != null) {
field.setAccessible(true);
try {
field.set(repositoryeInstance, testDatabaseManager);
System.out.println("[Repository Field] " + field.getName() + "에 의존성 주입을 처리함");
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
System.out.println("[Repository Field] " + field.getName() + "에 의존성 주입을 처리하지 못함");
}
}
}
}
}
}
}
12. "TestServletContextListener.java"의 "contextInitialized"에 서비스(Service) 클래스에서 선언된 맴버 필드 리스트를 가져와서 "@TestAnnAutowired"어노테이션이 있는 DAO 인터페이스 필드에 주입(인젝션)하는 부분을 추가합니다.
// Service-Class 맵
Map<String, Object> serviceMappingMap = new HashMap<String, Object>();
for (Class<?> findClass : classes) {
TestAnnService annoService = findClass.getAnnotation(TestAnnService.class);
if (null != annoService) {
Object serviceInstance = null;
try {
serviceInstance = findClass.newInstance();
Class<?>[] interfaces = findClass.getInterfaces();
for (int i = 0; i < interfaces.length; ++i) {
serviceMappingMap.put(interfaces[i].getName(), serviceInstance);
System.out.println("[Service] " + findClass.getName() + "서비스 인스턴스를 생성함");
}
} catch (InstantiationException | IllegalAccessException e) {
//e.printStackTrace();
System.out.println(findClass.getName() + "의 서비스 인스턴스를 생성하지 못함");
}
if (null != serviceInstance) {
Field[] Fields = findClass.getDeclaredFields();
for (Field field : Fields) {
TestAnnAutowired testAnnAutowired = field.getAnnotation(TestAnnAutowired.class);
if (null != testAnnAutowired) {
System.out.println("[Service Field] " + field.getType().getName() + " 타입의 " + field.getName() + " 맴버 필드을 찾음");
Object objectImplement = (Object) repositoryMappingMap.get(field.getType().getName());
if (null != objectImplement) {
field.setAccessible(true);
try {
field.set(serviceInstance, objectImplement);
System.out.println("[Service Field] " + field.getName() + "에 의존성 주입을 처리함");
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
System.out.println("[Service Field] " + field.getName() + "에 의존성 주입을 처리하지 못함");
}
}
}
}
}
}
}
13. "TestDispatcherServlet.java"의 "service"메소드에 "redirect"를 처리하기 위해 "response"의 "sendRedirect"메소드를 추가합니다.
if (!modelAndView.isViewNameEmpty()) {
if (modelAndView.getViewName().startsWith("redirect:")) {
response.sendRedirect(modelAndView.getViewName().substring(9));
} else {
RequestDispatcher dispatcher = request.getRequestDispatcher(modelAndView.getViewName());
dispatcher.forward(request, response);
}
}
14. "Servers"탭에서 "tomcat8"를 선택하고 "start"버튼(start the server)을 클릭합니다.
"Console"탭을 클릭하면 "@TestAnnRepository"어노테이션이 적용된 DAO 클래스의 인스턴스를 생성하고 "@TestAnnQualifier"어노테이션이 적용된 DAO 클래스 맴버 필드에 데이터베이스 매니저 클래스를 주입한 것을 확인할 수 있습니다. 그리고 서비스 클래스 맴버 필드에 DAO 클래스가 주입된 것을 확인할 수 있습니다.
[Console]
ServletContext 초기화 실행
basePackage : com.home.project.test2
데이터베이스 프로퍼티를 읽음
데이터베이스 드라이버(class org.mariadb.jdbc.Driver)가 로딩됨
[Repository] com.home.project.test2.dao.TestLoginDaoImpl 인스턴스를 생성함
[Repository Field] com.home.project.test2.database.TestDatabaseManager 타입의 testDatabaseManager 맴버 필드을 찾음
[Repository Field] testDatabaseManager에 의존성 주입을 처리함
[Service] com.home.project.test2.service.TestLoginService서비스 인스턴스를 생성함
[Service Field] com.home.project.test2.dao.ITestLoginDao 타입의 testLoginDao 맴버 필드을 찾음
[Service Field] testLoginDao에 의존성 주입을 처리함
[Service] com.home.project.test2.service.TestService1서비스 인스턴스를 생성함
웹 브라우저에서 "http://localhost:8080/test2/testform.do"를 입력합니다.
아이디는 "1"를 패스워드는 "1"를 입력하고 "로그인"버튼을 클릭합니다.
"Console"탭을 보면 마리아디비(MariaDB)에서 쿼리한 것을 확인할 수 있습니다.
[Console]
id : 1, password : 1
데이터베이스에 연결됨
Statement를 생성함
Query[SELECT MBR_ID, MBR_PWD, MBR_PWD_SALT, MBR_NM FROM MBR_ACCOUNT_TB WHERE MBR_ID = '1']를 실행함
Statement를 종료함
데이터베이스에서 연결을 종료함
ServletRequest에 속성 추가 - 속성명 : errorMessage, 속성 값 : 아이디/패스워드가 정확하지 않습니다.
정상적인 로그인을 위해 아이디는 "testid"를 패스워드는 "testpwd"를 입력하고 "로그인"버튼을 클릭합니다.
"Console"탭을 보면 마리아디비(MariaDB)에서 쿼리가 되어 "UserVO"객체가 생성되고 인증된 것을 확인할 수 있습니다.
[Console]
id : testid, password : testpwd
데이터베이스에 연결됨
Statement를 생성함
Query[SELECT MBR_ID, MBR_PWD, MBR_PWD_SALT, MBR_NM FROM MBR_ACCOUNT_TB WHERE MBR_ID = 'testid']를 실행함
Statement를 종료함
데이터베이스에서 연결을 종료함
HttpSession에 속성 추가 - 속성명 : auth, 속성 값 : com.home.project.test2.vo.UserVO@43992e24
Session Manager Count : 1, Add ID : testid, Session ID : F17C9BECD60628EBBAE72C2C6CB32B1E
Annotation(어노테인션)을 이용하여 "SpringFramework"와 같은 Annotation(어노테인션)기반의 MVC모델을 구성하였습니다.