패키지가 여러개일 경우 설정 방법, AOP
*패키지를 여러개 나눌 경우 설정이 달라짐
1. servlet-context.xml
<!--<context:component-scan base-package="com.spring" /> -->
<context:component-scan base-package="com.spring.member" />
<context:component-scan base-package="com.spring.board" />
1. com.spring 아래에 모든 파일 (이렇게 해도되는데 규모가 클수록 위험함)
2. 직접 하나하나 지정해주기
2.mybatis-context.xml
- 여기도 역시 com.spring 이라고 써줘도 됨
3. log4j.xml
<!-- Application Loggers -->
<logger name="com.spring.member">
<level value="info" />
</logger>
<logger name="com.spring.board">
<level value="info" />
</logger>
- 여기도 역시 com.spring 이라고 써줘도 됨
AOP
- 관점 지향 프로그래밍
- 하나의 흐름에 특정한 시점에 수행되는 프로그램을 만드는 것. (특정한 시점에서 몰아서 처리)
- aop를 설명할 때는 interceptor가 일반적이라 예를 들면 됨
- 언제사용할까? > 로그인세션 처리 일일이 해주기 불편함. 이처럼 특정한 검사를 실행할 때 interceptor를 많이 사용함
사용방법
1. 설정 파일 추가
요청이 오면 하기 때문에 appservlet폴더 밑에 설정 추가 - new - spring bean configuration file -"interceptor-context.xml"- bean,mvc체크
<!-- interceptord의 묶음 -->
<!-- /* : 모든 요청을 가로채겠다 -->
<!-- bean class : 어디로 -->
<!-- mapping은 일치하는 요청은 인터셉터 한다. -->
<!-- exclude-mapping은 일치하는 요청은 제외한다. -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*"/>
<mvc:exclude-mapping path="/"/>
<mvc:exclude-mapping path="/join*"/>
<mvc:exclude-mapping path="/login.do"/>
<mvc:exclude-mapping path="/logout.do"/>
<bean class="com.spring.utils.LoginInter"/>
</mvc:interceptor>
</mvc:interceptors>
제외하는 이유 : 로그인창이나 회원가입창 등에서 로그인 유효성 체크하면 안되잖아
2. 패키지 - 클래스 생성
위에 설정파일에 내용의 경로에 따라 com.spring.utils 패키지의 LoginInter 클래스를 만들어줌
단 interceptor를 만들기위해선 특정한 클래스를 상속 받아야함 : handlerInterceptorAdapter
(+ 클래스가 상속받는 이유 : 1.부모의 메서드를 사용할 때, 2.특정한 틀만 갖추고 오버라이드 해서 쓸 때)
3. 오버라이드하기
주로 posthandle,prehandle메서드를 씀
- pre handler : 컨트롤러 가기전에 막음
- 컨트롤러를 거치기 전에 이곳을 들르게 된다.
- 반환값이 false면 해당 컨트롤러로 접근하지 못한다 .(하얀화면)
- 그래서 false반환보다는 response를 이용해서 다른 요청으로 보낸다.
- post handler : 뷰에 나갈 때 뭔가를 주고싶다 할 때
- 컨트롤러를 거치고 난 이후 뷰에 도달하기전에 들른다
- modelAndView 를 이용해 원하는 값을 뷰로 보낼 때 활용한다
4. Interceptor할 내용 클래스에 추가 <LoginInter클래스>
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("Controller 진입 전...");
HttpSession session = request.getSession();
String loginId = (String) session.getAttribute("loginId");
if(loginId == null) {
System.out.println("로그인 안함");
response.sendRedirect("/");
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView mav) throws Exception {
System.out.println("Controller 진입 후...");
String loginId = (String) request.getSession().getAttribute("loginId");
String content = "<div>안녕하세요"+ loginId + "님 <a href='logout.do'>로그아웃</a></div>";
mav.addObject("loginBox",content);
}
인자값 :
HttpServletRequest request : 요청에 대한 모든 정보를 갖고 있음
HttpServletResponse response : 페이지 튕겨줌
ModelAndView mav : 특정한 값을 넣어서 보내줌
redirect와 sendRedirect :
redirect:/ -> http://localhost:8080/member/ (member포함)
sendRedirect("/") -> http://localhost:8080/
: 그렇기 때문에 sendRedirect를 쓸 경우 꼬일 수 있음
해결방법
1. 서버에서 context경로 빼주기
2. context경로 같이 써주기 ex)member/
+preHandle메서드에서 response객체를 통해서 페이지이동을 하기 때문에, 메시지같은 값을 같이 갖고가지 못함.
예를들어 (로그인이 필요한 서비스입니다) 등의 메세지를 전달할 수 없다는 단점이 있다.
우회해서??어뜨케어떻게 해야된다는데 방법은 생각해보기
+postHandle메서드에선 modelAndView를 통해서 페이지 이동을 하거나 메세지를 전달할 수 있다.
+syso를 사용한 이유 : 로그 설정에서 나는 com.spring이라하지않고 board,member를 각각 써줘서 com.spring.util 설정을 안했기 때문
순서