현재, login.jsp에 들어가서 로그인을 하려는 상태이다.
로그인을 시도하면 위와같은 에러가 뜬다. 도대체 왜 이러는 걸까??
일단, 코드를 따라가보도록 하자!!
web.xml에서 *.do는 모두 presentation-layor.xml을 따라가도록 설정되어 있다.
presentation-layor 파일에서는 /login.do가 실행되어있을 경우 LoginController가 실행되도록 설정되어 있다.
package sonny.spring.web.user;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import sonny.spring.web.user.impl.UserServiceImpl;
public class LoginController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("로그인 처리");
// 1. 사용자 입력 정보 추출
String id = request.getParameter("id");
String password = request.getParameter("password");
// 2. 데이터베이스 연동 처리
UserVO vo = new UserVO();
vo.setId(id);
vo.setPassword(password);
System.out.println(id);
System.out.println(password);
UserService userService = new UserServiceImpl();
UserVO user = userService.getUser(vo);
// 3. 화면 네비게이션
ModelAndView mav = new ModelAndView();
if(user != null){
mav.setViewName("health.html");
}else{
mav.setViewName("login.jsp");
}
return mav;
}
}
오류 메세지를 다시 한번 읽어보면, LoginController에서 UserVO user = userService.getUser(vo); 에서 오류가 발생하고,
package sonny.spring.web.user.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sonny.spring.web.user.UserService;
import sonny.spring.web.user.UserVO;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDAO userDAO;
@Override
public UserVO getUser(UserVO vo) {
return userDAO.getUser(vo);
}
}
여기서 userDAO.getUser(vo)를 실행시키려 하였는 데, userDAO 가 NULL 값 이어서 오류가 나온 것을 확인할 수 있다.
@Autowired를 주었는 데 왜 객체가 자동적으로 생성이 되지 않은 것일까???
그 이유는 다음과 같다.
위 그림을 보면, ServiceImpl에서 @Autowired를 사용해 UserDAO에게 객체를 주입한다.
마찬가지로, DAO에서 @Autowired를 사용해 JdbcTemplate에게 객체를 주입한다.
LoginController는 UserDAO가 주입된 ServiceImpl을 받아 사용해야 된다.
package sonny.spring.web.user;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import sonny.spring.web.user.impl.UserServiceImpl;
public class LoginController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("로그인 처리");
// 1. 사용자 입력 정보 추출
String id = request.getParameter("id");
String password = request.getParameter("password");
// 2. 데이터베이스 연동 처리
UserVO vo = new UserVO();
vo.setId(id);
vo.setPassword(password);
System.out.println(id);
System.out.println(password);
UserService userService = new UserServiceImpl();
UserVO user = userService.getUser(vo);
// 3. 화면 네비게이션
ModelAndView mav = new ModelAndView();
if(user != null){
mav.setViewName("health.html");
}else{
mav.setViewName("login.jsp");
}
return mav;
}
}
하지만, 위 코드를 보면, UserService userService = new UserServiceImpl()을 이용해 객체를 생성하고 있는 것을 보고 있다.
이렇게 한다면, 스프링컨테이너 상에서 LoginController와 userService가 연결되지 않았기 때문에 자동적으로, userDAO is null이 나온다.
따라서, 해결 방법은 의존성주입이다.
의존성 주입 중 생성자를 이용한 의존성 주입을 사용하겠다.
(왜 ? @Autowired를 사용하지 않고 생성자를 이용해 의존성을 주입하는 지는 다음 포스팅에서 다루도록 하겠다.)
먼저, LoginController에 생성자를 만들어준다.
package sonny.spring.web.user;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public class LoginController implements Controller {
UserService userService;
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("로그인 처리");
// 1. 사용자 입력 정보 추출
String id = request.getParameter("id");
String password = request.getParameter("password");
// 2. 데이터베이스 연동 처리
UserVO vo = new UserVO();
vo.setId(id);
vo.setPassword(password);
System.out.println(id);
System.out.println(password);
UserVO user = userService.getUser(vo);
// 3. 화면 네비게이션
ModelAndView mav = new ModelAndView();
if(user != null){
mav.setViewName("health.html");
}else{
mav.setViewName("login.jsp");
}
return mav;
}
public LoginController(UserService userService) {
super();
this.userService = userService;
}
}
<bean id="login" class="sonny.spring.web.user.LoginController">
<constructor-arg ref="userService"></constructor-arg>
</bean>
이제 다시 실행하면, 다시 에러가 뜬다.. (에러가 뜬다고 위의 설명이 잘못된 것이 아니라, 새로운 에러가 나온 것이다.)
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0' defined in ServletContext resource [/WEB-INF/config/presentation-layor.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'login' defined in ServletContext resource [/WEB-INF/config/presentation-layor.xml]: Cannot resolve reference to bean 'userService' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userService' available
아 왜 이러는 것일까?? 이는 다음 포스팅에서 다루겠습니다.
'Spring' 카테고리의 다른 글
EmptyResultDataAccessException 해결, jdbcTemplate.queryForObject에 관하여 (0) | 2022.08.21 |
---|---|
BeanCreationException, NoSuchBeanDefinitionException 에러 해결 (0) | 2022.08.19 |
Spring MVC 구조(2) (0) | 2022.07.29 |
Spring - BeanCreationException해결 / .metadata (0) | 2022.07.26 |
Spring MVC 구조 (0) | 2022.07.26 |