반응형
Interceptor
preHandle:
- 요청이 컨트롤러 메소드로 전달되기 전에 실행됩니다.
- 보통 요청을 가로채서 인증, 권한 체크 등 전처리 작업을 수행할 때 사용됩니다.
- 반환 값이 true일 경우, 컨트롤러 메소드가 호출됩니다. false일 경우, 이후 처리 과정이 중단됩니다.
postHandle:
- 컨트롤러 메소드가 실행된 후, DispatcherServlet이 화면을 렌더링하기 전에 실행됩니다.(return이 viewResolver에게 전달되기 전)
- 주로, 컨트롤러에서 처리한 결과를 가공하거나, 모델에 추가적인 데이터를 더할 때 사용됩니다.
- ModelAndView 객체를 통해 처리된 요청(attribute)에 접근할 수 있습니다.
afterCompletion:
- DispatcherServlet이 화면을 처리한 후에 실행됩니다.
- 주로 로깅, 리소스 정리, 세션/트랜잭션 종료 등 후처리 작업을 수행할 때 사용됩니다.
- 뷰 렌더링이 완료된 후 실행되므로, 뷰에 대한 처리가 끝난 후에 필요했던 작업들을 처리합니다.
servlet-context.xml
밑의 코드들 추가
<context:component-scan base-package="edu.springboard.interceptor" />
<interceptors><!-- interceptor 설정 정보들을 담는 위치 -->
<interceptor>
<!-- 로그인 체크를 해야하는 경로 -->
<mapping path="/login/notice/**"/><!-- /login/notice/의 모든 경로 -->
<!-- <mapping path="/login/notice/list.do"/>
<mapping path="/login/notice/write.do"/> -->
<!-- <exclude-mapping path="예외경로" /> --><!-- 스프링 3.2 이상 부터 사용가능 -->
<beans:ref bean="loginInterceptor"/><!-- @Component이기 때문에 첫글자 소문자 -->
</interceptor>
</interceptors>
<interceptors>:
- 모든 인터셉터 설정은 이 태그 내에 위치합니다.
- 여러 개의 <interceptor> 설정을 추가하여 다양한 경로에 대해 인터셉터를 설정할 수 있습니다.
<interceptor>:
- 하나의 인터셉터를 정의하는 태그입니다. 이 태그 내에서 경로 매핑과 처리할 빈을 지정합니다.
<mapping path="/login/notice/list.do"/>:
- path 속성은 이 인터셉터가 적용될 경로를 정의합니다. 이 경우, /login/notice/list.do 경로로 들어오는 요청에 대해 loginInterceptor 인터셉터가 실행됩니다.
<beans:ref bean="loginInterceptor"/>:
- 이 부분은 실제로 인터셉터로 사용할 객체를 빈으로 참조하는 부분입니다.
- loginInterceptor는 Spring 컨테이너에 등록된 빈의 이름이며, 이 빈은 @Component로 선언된 클래스일 수 있습니다.
- 이 객체는 인터셉터의 로직을 담당합니다.
로그인 여부 확인
package edu.springboard.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
UserService UserService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//매핑 경로 컨트롤러 메소드 호출 전에 실행
System.out.println("컨트롤러 메소드 실행 전 호출!");
HttpSession session = request.getSession();
if(session.getAttribute("loginUser") == null) {
//로그인 x
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
response
.getWriter()
.append("<script>alert('로그인 후 이용하세요.');"
+ "location.href='"
+ request.getContextPath()
+ "/login.do';</script>")
.flush();
return false; //더 이상 진행 x
}else {
//로그인 O
return true; //진행 o
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
//컨트롤러 메소드가 호출된 후 dispatcherservlet이 화면을 처리하기 전에 실행
//return이 viewResolver에게 전달되기 전
//modelAndView 객체 사용하면 처리된 request attribute에 접근할 수 있다
System.out.println("화면 전환 전 호출!");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
//dispatcherservlet이 화면 처리를 한 후에 실행
System.out.println("화면 전환 후 호출!");
}
}
package edu.springboard.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import edu.springboard.service.NoticeService;
import edu.springboard.util.PagingUtil;
import edu.springboard.vo.NoticeVO;
import edu.springboard.vo.SearchVO;
@RequestMapping(value="/login/notice")
@Controller
public class Notice2Controller {
@Autowired
public NoticeService noticeService;
@RequestMapping(value="/list.do")
public String noticeList(Model model,SearchVO searchVO
, @RequestParam(value="nowPage", required = false, defaultValue = "1") int nowPage) {
int total = noticeService.selectCount(searchVO);
System.out.println("공지글 갯수:" + total);
//int nowPage,int total, int perPage
PagingUtil paging = new PagingUtil(nowPage,total,3);
searchVO.setStart(paging.getStart());
searchVO.setPerPage(paging.getPerPage());
System.out.println("paging.getStart():"+ paging.getStart());
System.out.println("paging.getPerPage():"+ paging.getPerPage());
//비지니스 로직 : DB에 있는 전체 회원 목록 데이터 가져오기
List<NoticeVO> list = noticeService.selectAll(searchVO);
//모델 객체 사용하여 조회 데이터 화면으로 포워딩
model.addAttribute("list", list);
model.addAttribute("paging", paging);
model.addAttribute("total", total);
return "notice/list";
}
@RequestMapping(value="/write.do", method = RequestMethod.GET)
public String write(HttpServletRequest request,HttpServletResponse response) throws IOException {
/*
LoginInterceptor를 사용하여 글등록 화면 요청시 로그인이 안되어 있으면
로그인 페이지로 이동하도록 servlet-context.xml을 수정
*/
return "notice/write";
}
}
관리자 여부 확인
package edu.springboard.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import edu.springboard.vo.UserVO;
@Component
public class AdminInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession();
UserVO loginUser = (UserVO)session.getAttribute("loginUser");
if(loginUser != null && loginUser.getUauthor().equals("A")) {
return true; //관리자
}else {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
response
.getWriter()
.append("<script>alert('관리자만 접근 가능합니다.');"
+ "location.href='"
+ request.getContextPath()
+ "';</script>")
.flush();
return false; //일반회원
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
<interceptor>
<mapping path="/user/list.do"/>
<beans:ref bean="adminInterceptor"/><!-- @Component이기 때문에 첫글자 소문자 -->
</interceptor>
인터셉터 적용 순서
1. 클래스를 선언합니다. 이때 반드시 handlerInterceptor 인터페이스의 구현 클래스로 선언합니다
2. HandlerInterceptor
preHandle() : 컨트롤러 호출 전 실행되므로 주로 권한, 로그인, 인증, 인가 처리에 사용
postHandle() : 컨트롤러 호출 후 화면 전환 직전에 실행되어 modelAndView 객체를 사용하면
포워드하는 attribute에 접근가능
afterCompletion() : 화면 전환 후 실행되어 주로 로깅작업시 사용
3. 인터셉터의 각 메소드 시점에 맞춰 기능을 구현한다. preHandle() 사용시 리턴이 true이면 요청을 이어서 진행,
false이면 요청 중단이고 이때 화면 전환이 필요하면 response를 사용
4. 선언한 인터셉터와 적용 경로를 매핑하기 위하여 servlet-context.xml에 설정 정보를 추가
하나의 인터셉터에 여러 경로를 지정할 수 있으며 여러 인터셉터에 한 경로가 중복될 수도 있다
반응형
'Spring' 카테고리의 다른 글
[Spring] 스케줄러(Scheduler),시큐리티(Security) (1) | 2024.12.04 |
---|---|
[Spring] 필터(filter) (0) | 2024.12.03 |
[Spring] 파일 업로드 (0) | 2024.12.01 |
[Spring] AJAX 여러건의 데이터 받기 (0) | 2024.11.30 |
[Spring] AJAX 한 건의 데이터 받기 (1) | 2024.11.29 |