기존 방식
@WebServlet(name = "frontControllerServletV4", urlPatterns = "/front-controller/v4/*")
@RequiredArgsConstructor
public class FrontControllerServletV4 extends HttpServlet {
private static final String PREFIX = "/WEB-INF/views/";
private static final String SUFFIX = ".jsp";
private final Map<String, ControllerV4> controllerV4Map = new ConcurrentHashMap<>();
private final MemberRepository memberRepository;
@PostConstruct
public void setUp() {
controllerV4Map.put("/front-controller/v4/members/new-form", new MemberFormControllerV4());
controllerV4Map.put("/front-controller/v4/members/save", new MemberSaveControllerV4(memberRepository));
controllerV4Map.put("/front-controller/v4/members", new MemberListControllerV4(memberRepository));
}
- 위의 프론트 컨트롤러는 한가지 방식의 컨트롤러 인터페이스만 사용할 수 있다.
- 만약 프론트 컨트롤러가 다양한 방식의 컨트롤러를 사용할 수 있게 하려면 어댑터 패턴을 이용하면된다.
어댑터 패턴
- 핸들러 어댑터
- 중간에 어댑터 역할을 하는 어댑터가 추가되었는데 이름이 핸들러 어댑터다.
- 어댑터 역할을 해주는 덕분에 다양한 종류의 컨트롤러를 호출할 수 있다.
- 핸들러
- 컨트롤러의 이름을 더 넓은 범위인 핸들러로 변경하였다.
- 그 이유는 이제 어댑터가 있기 때문에 꼭 컨트롤러의 개념 뿐만 아니라 어떠한 것이든 해당하는 종류의 어댑터만 있으면 다 처리할 수 있기 때문이다.
- 기존에는 프론트 컨트롤러에서 바로 컨트롤러를 호출하였지만
- 이제는 핸들러 어댑터 목록에서 핸들러를 처리할 수 있는 어댑터를 조회한다음
- 컨트롤러를 호출하는 것이 아니라 핸들러 어댑터를 호출한 다음에 핸들러 어댑터에서 컨트롤러(핸들러)를 호출한다.
MyHandlerAdapter
public interface MyHandlerAdapter {
boolean supports(Object handler);
ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException;
}
- boolean supports(Object handler)
- handler는 컨트롤러를 말한다.
- 어댑터가 해당 컨트롤러를 처리할 수 있는지 판단하는 메소드다.
- ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
- 어댑터는 실제 컨트롤러를 호출하고 그 결과로 ModelView를 반환해야 한다.
- 실제 컨트롤러가 ModelView를 반환하지 못하면 어댑터가 ModelView를 직접 생성해서라도 반환해야 한다.
- 이전에는 프론트 컨트롤러가 실제 컨트롤러를 호출했지만 이제는 이 어댑터를 통해서 실제 컨트롤러가 호출된다.