berryberrybin / kosta-jsp

jsp study
0 stars 0 forks source link

MVC구조 예제 - (2) #31

Open berryberrybin opened 2 years ago

berryberrybin commented 2 years ago

image

DispatcherServlet.java 개선 방법

berryberrybin commented 2 years ago

actionMapping.properties

HandlerMappingListener.java

@WebListener
public class HandlerMappingListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent sce)  { 

        Map<String, Controller> map = new HashMap<String, Controller>();

        // map.put()을 몇개 처리할지 알 수 없으며, 하나하나 넣기에는 귀찮음 
        //actionMapping.properties을 따로 생성하여 Map의 내용을 저장해서  관리 
        // ~.properties 파일 로딩 
        ResourceBundle rb = ResourceBundle.getBundle("kosta/mvc/listener/actionMapping"); 
        // 폴더를 가져오므로 .을 사용하는 것이 아닌 /을 사용하며, 확장자는 생략함  

        for(String key : rb.keySet()) {
            String value = rb.getString(key);
            System.out.println(key + " = " + value);
        }
    }

}

조금 더 개선

}

----------------------------------------------------------------------------------------
### 문제점 및 해결 방법
- 현재 value는 String타입이므로 Controller 객체 타입으로 변경해야 함
- Class<?> 을 이용하여 객체타입으로 변경 
- Class<?> 이란? 
   - 어떤 객체가 가지고 있는 필드, 생성자, 메소드의 정보를 동적으로 가져올수 있도록 도와주는 객체이다 
- reflection 개념
   - reflection 개념은 동적으로 즉 실행도중에 필요한 객체를 적절하게 생성하고 그 객체가 가지고 있는 생성자나 메소드를 동적으로 호출해줄수 있도록 하는 개념을 reflection이라고 하고, 자바에서 이 개념을 적용해 놓은 API가 Class<?> 이다.

### HandlerMappingList.java 최종 

```java
@WebListener
public class HandlerMappingListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent sce)  { 

        Map<String, Controller> map = new HashMap<String, Controller>();

        ServletContext application = sce.getServletContext();
        String fileName = application.getInitParameter("fileName");

        ResourceBundle rb = ResourceBundle.getBundle(fileName);
        try {
            for (String key : rb.keySet()) {
                String value = rb.getString(key);
                System.out.println(key + " = " + value);

                // String의 문자열을 Controller의 객체로 생성해야 함
                Class<?> className = Class.forName(value);
                Controller controller = (Controller) className.getDeclaredConstructor().newInstance();
                map.put(key, controller);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //모든 영역에서 map을 사용할 수 있도록 application에 저장해야 함
        application.setAttribute("map", map);
    }
}
berryberrybin commented 2 years ago

image

DispatcherServlet.java 최종

@WebServlet(urlPatterns = "/front", loadOnStartup = 1)
public class DispatcherServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    Map<String, Controller> map;

    @Override 
    public void init() throws ServletException{
        //init()에서 super.getServletContext() 을 통해 Application을 꺼낼 수 있음 
        // Object타입으로 나오므로 Map 형태로 downcasting되어야 함 
        map = (Map<String,Controller>)super.getServletContext().getAttribute("map");
    }

    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        Controller controller = null;
        String key = request.getParameter("key");

        controller = map.get(key);

        ModelAndView mv = controller.handleRequest(request, response);
        if (mv.isRedirect()) {
            response.sendRedirect(mv.getViewName());
        } else {
            request.getRequestDispatcher(mv.getViewName()).forward(request, response);
        }
    }
}