MVC(2)

부트캠프(END)/Web|2022. 7. 28. 22:05

이제 TYPE 어노테이션뿐만 아니라 METHOD 어노테이션까지 추가해서, 

DAO 까지 만들어보자.

예시로 Model은 하나만 만들 것이기 때문에 xml이나 Interface 등은 사용하지 않는다.

 

 

가보자고~

 

 

우선 어노테이션을 만들어 준다!

메모리를 할당할 클래스는 @Controller 로 구분하고,

메서드는 @RequestMapping으로 구분할 것이다.

 

Controller.java (Annotation)

package controller;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
//Controller 어노테이션이 들어간다 = Model이다.
@Retention(RUNTIME)
@Target(TYPE)
public @interface Controller {}

 

RequestMapping.java (Annotation)

package controller;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
//@ReuqestMapping("list.do");
@Retention(RUNTIME)
@Target(METHOD)
//메서드를 찾아준다.
public @interface RequestMapping {
  //이 안에 들어가는 문자열로 구분할 것이다.
  public String value();
}

RequestMapping의 경우 메모리를 할당할 지 말지 구분하는 것이 아니라,

손쉽게 원하는 메서드를 찾아주는 인덱스 역할을 한다.

→ 원하는 메서드의 위에 @RequestMapping("") 을 붙이면,

으로 해당 메서드를 찾을 수 있도록 해 준다.

 

 

FoodDAO.java (Class) - DBCP

server.xml에 등록해준 대로 데이터베이스에 연결하고 값을 가져온다.

package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

public class FoodDAO {
  private Connection conn;
  private PreparedStatement ps;

  public void getConnection() {
    try {
      Context init = new InitialContext(); //탐색기를 열고
      Context c = (Context) init.lookup("java://comp/env"); 
      //Connection이 저장돼 있는 곳으로!
      DataSource ds = (DataSource) c.lookup("jdbc/oracle");
      conn = ds.getConnection();
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  public void disConnection() {
    try {
      if (ps != null) ps.close();
      if (conn != null) conn.close();
    } catch (Exception ex) {
      System.out.println("disConnection() Error");
      ex.printStackTrace();
    }
  }

  public List < CategoryVO > categoryListData(int no) {
    List < CategoryVO > list = new ArrayList < CategoryVO > ();
    try {
      int start = 0, end = 0;
      if (no == 1) { //믿고 보는 맛집 리스트
        start = 1;
        end = 12;
      }
      if (no == 2) { //지역별 인기 맛집
        start = 13;
        end = 18;
      }
      if (no == 3) { //메뉴별 인기 맛집
        start = 19;
        end = 30;
      }
      getConnection();
      String sql = "SELECT cno, title, subject, poster " +
        "FROM food_category " +
        "WHERE cno BETWEEN ? AND ?";
      ps = conn.prepareStatement(sql);
      ps.setInt(1, start);
      ps.setInt(2, end);
      ResultSet rs = ps.executeQuery();
      while (rs.next()) {
        CategoryVO vo = new CategoryVO();
        vo.setCno(rs.getInt(1));
        vo.setTitle(rs.getString(2));
        vo.setSubject(rs.getString(3));
        vo.setPoster(rs.getString(4));
        list.add(vo);
      }
      rs.close();
    } catch (Exception ex) {
      ex.printStackTrace();
    } finally {
      disConnection(); //재사용을 위한 반환
    }
    return list;
  }

  public List < FoodVO > food_list(int cno) {
    List < FoodVO > list = new ArrayList < FoodVO > ();
    try {
      getConnection();
      String sql = "SELECT fno, name, tel, type, poster, address " +
        "FROM food_house " +
        "WHERE cno=?";
      ps = conn.prepareStatement(sql);
      ps.setInt(1, cno);
      ResultSet rs = ps.executeQuery();
      while (rs.next()) {
        FoodVO vo = new FoodVO();
        vo.setFno(rs.getInt(1));
        vo.setName(rs.getString(2));
        vo.setTel(rs.getString(3));
        vo.setType(rs.getString(4));
        vo.setPoster(rs.getString(5));
        vo.setAddress(rs.getString(6));

        list.add(vo);
      }
      rs.close();
    } catch (Exception ex) {
      ex.printStackTrace();
    } finally {
      disConnection();
    }

    return list;
  }
}

 

 

FoodModel.java (Class)

@Controller로 FoodModel 클래스에 메모리를 할당한다.

그리고 @RequestMapping으로 각 메서드를 찾을 값을 지정하고, request에 값을 담아 전송하는 기능을 구현한다.

리턴값은 결과 화면을 출력할 jsp페이지의 이름으로 지정한다.

package model;

import controller.Controller;
import controller.RequestMapping;
import dao.*;

import java.util.*;

import javax.servlet.http.HttpServletRequest;

@Controller
public class FoodModel {
  @RequestMapping("food/category.do")
  public String food_category(HttpServletRequest request) {
    String no = request.getParameter("no");
    if (no == null)
      no = "1";
    FoodDAO dao = new FoodDAO();
    List < CategoryVO > list = dao.categoryListData(Integer.parseInt(no));
    request.setAttribute("list", list);
    System.out.println("food_category() call~");
    //		request.setAttribute("msg", "카테고리 출력합니다.");
    return "../food/category.jsp";
  }
  @RequestMapping("food/food_list.do")
  public String food_list(HttpServletRequest request) {
    String cno = request.getParameter("cno");
    FoodDAO dao = new FoodDAO();
    List < FoodVO > list = dao.food_list(Integer.parseInt(cno));
    request.setAttribute("list", list);
    System.out.println("food_list() call~");
    //		request.setAttribute("msg", "카테고리별 맛집 출력합니다.");
    return "../food/food_list.jsp";
  }
}

 

 

이제 DispatcherServlet.java (Servlet)에서 clsList에 모델을 등록하고,

@RequestMapping으로 지정해준 값을 이용해 그에 맞는 메서드를 호출한다.

 

//사용자가 요청한 URL을 읽어 온다. (맨 뒤에 .do)
String uri = request.getRequestURI();
uri = uri.substring(request.getContextPath().length() + 1);
System.out.println(uri); //food/category.do

 

우선 사용자가 요청한 URI를 읽어 온다.

request.getRequestURI()로, 전체 URL에서 URI부분만 읽는다.

URL = http:localhost:8080/0727MVCProject5/food/category.do
URI = /0727MVCProject5/food/category.do 부분만.

그리고 getContextPath()로 "/0727MVCProject"을 불러와 해당 위치 이후의 값을 읽어 온다.

결과적으로, food/category.do 부분만 읽어 uri 라는 변수에 저장하는 것이다.

이 URI와 RequestMapping에 등록된 값이 같은 메서드를 호출하라! 고 시키는 것이다.

단, ?no=1과 같은 파라미터들은 request에 따로 담겨 오는것이기 때문에 request.getRequestURI()에서 제외된다.

 

 

Model을 등록한 클래스 리스트(clsList)에서

리스트에 있는 모든 클래스를 가져와 메모리를 할당하고 그 안의 모든 메서드를 가져 온다.

RequestMapping 객체를 생성하여 methods 중 @RequestMapping을 가진 메서드를 불러 온다.

그리고 그 안에서 rm.value()와 동일한 URI를 가진 메서드를 불러와 호출하고,

그 메서드가 적절한 처리 후 결과에 request에 담아 보내 준다!

 

for (String cls: clsList) {
  Class clsName = Class.forName(cls);
  if (clsName.isAnnotationPresent(Controller.class) == false)
    continue;
  Object obj = clsName.getDeclaredConstructor().newInstance();
  Method[] methods = clsName.getDeclaredMethods();
  for (Method m: methods) {
    RequestMapping rm = m.getAnnotation(RequestMapping.class);
    if (uri.equals(rm.value())) {
      //rm이 갖고있는 값
      String jsp = (String) m.invoke(obj, request);
      //obj가 가진 메서드를 찾아서 호출한다.
      RequestDispatcher rd = request.getRequestDispatcher(jsp);
      rd.forward(request, response);
      return;
    }
  }
}

 

위 과정의 전체를 나타내면 아래와 같다.

 

DispatcherServlet.java (Servlet)

package controller;
//Dispatcher이 컨트롤러 이름임
import java.io.IOException;
import java.lang.reflect.Method;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import model.*;

@WebServlet("*.do")
/*
 내가 마음대로 둬도된다. 
 *은 그 자리에 어떤 단어가 들어와도 이 서블릿(DispatcherServelt)을 찾아줄 수 있다는 뜻
 list.do, find.do 등.. 다 DispatcherServelt을 찾아줄 수 있게 된다.
 URI가 do로 끝나지 않으면 "요청된 리소스 [/0727MVCProject5/food/category.ex]은(는) 가용하지 않습니다." 뜸 */
public class DispatcherServlet extends HttpServlet {
  private static final long serialVersionUID = 1 L;
  List < String > clsList = new ArrayList < String > ();

  public void init(ServletConfig config) throws ServletException {
    clsList.add("model.FoodModel");
  }

  protected void service(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
    try {
      //사용자가 요청한 URL을 읽어 온다. (맨 뒤에 .do)
      String uri = request.getRequestURI();
      uri = uri.substring(request.getContextPath().length() + 1);
      //http://localhost:8080/0727MVCProject5/food/category.do 이 전체는 URL
      //URI는 /0727MVCProject5/category.do 부분만.
      //ContextPath는 0727MVCProject
      //?no=1 이런거는 request에 담겨 오는것임. request.getRequestURI()에서 제외됨
      System.out.println(uri); //food/category.do
      //이 URI와 RequestMapping 이름이랑 같으면 호출하라! 고 시키는 것임

      for (String cls: clsList) {
        Class clsName = Class.forName(cls);
        //Controller도 꼭 붙여줘야함
        if (clsName.isAnnotationPresent(Controller.class) == false)
          continue;
        Object obj = clsName.getDeclaredConstructor().newInstance();
        //생성자를 가져와서 메모리 할당을 하겠다~
        //메서드 찾기
        Method[] methods = clsName.getDeclaredMethods();
        //이 안에 있는 메서드를 모두 가져와라.
        for (Method m: methods) {
          //메서드에 있는 어노테이션을 가져온다. 
          //(어노테이션은 한 번에 여러 개도 올라갈 수 있음)
          RequestMapping rm = m.getAnnotation(RequestMapping.class);
          if (uri.equals(rm.value())) {
            //rm이 갖고있는 값
            String jsp = (String) m.invoke(obj, request);
            //obj가 가진 메서드를 찾아서 호출한다.
            RequestDispatcher rd = request.getRequestDispatcher(jsp);
            rd.forward(request, response);

            return;
          }
        }
      }
    } catch (Exception ex) {}
  }

}

 

받은 결과값들을 화면에 적절하게 뿌려주면 끝!

 

category.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
  .container{
    margin-top: 50px;
  }
  .row{
    margin: 0px auto;
    width: 960px;
  }
</style>
</head>
<body>
  <%-- <h1>${msg }</h1> --%>
  <div class="container">
    <div class="row">
      <div class="text-center">
        <a href="category.do?no=1" class="btn btn-sm btn-success">믿고 보는 맛집 리스트</a>
        <a href="category.do?no=2" class="btn btn-sm btn-danger">지역별 맛집 리스트</a>
        <a href="category.do?no=3" class="btn btn-sm btn-primary">메뉴별 맛집 리스트</a>
      </div>
    </div>
    <div style="height: 20px"></div>
    <div class="row">
      <c:forEach var="vo" items="${list }">
        <div class="col-md-4">
            <div class="thumbnail">
            <a href="food_list.do?cno=${vo.cno }">
                <img src="${vo.poster }" alt="Lights" style="width:250px; height:200px;">
                <div class="caption">
                 <p>${vo.title }</p>
               </div>
            </a>
           </div>
        </div>
      </c:forEach>
    </div>
  </div>
</body>
</html>

food_list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
  .container{
    margin-top: 50px;
  }
  .row{
    margin: 0px auto;
    width: 700px;
  }
</style>
</head>
<body>
  <%-- <h1>${msg }</h1> --%>
  <div class="container">
    <div class="row">
    <c:forEach var="vo" items="${list }">
      <table class="table">
        <tr>
          <th width="30%" class="text-center" rowspan="4">
            <img src="${vo.poster }" style="width:200px; height:150px">
          </th>
          <td width="70%"><h3>${vo.name }</h3></td>
        </tr>
        <tr>
          <td width="70%">${vo.address }</td>
        </tr>
        <tr>
          <td width="70%">${vo.tel }</td>
        </tr>
        <tr>
          <td width="70%">${vo.type }</td>
        </tr>
      </table>
    </c:forEach>
    </div>
  </div>
</body>
</html>

 

 

완성~

01

 

 

 

Mac과 Windows 공동 작업을 위한 XML 읽기

지금까지는 패키지 단위로 클래스를 읽어올 때 수동으로 경로를 입력하거나, 

xml에 등록하거나, 직접 클래스명을 지정하여 등록해 왔다! 

 

이번에는...

⑴ xml파일에 패키지를 등록하고,

현재 위치를 인식하여 해당 xml파일의 경로를 자동으로 지정하고,

⑶ xml을 읽어 그 패키지 안에 있는 클래스도 자동으로! 읽어오도록 해 볼 것이다.

 

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<component-scan base-package="model"/>
</beans>

 

*경로 구분자를 사용할 때 직접 입력하지 않고, File.separator 을 사용해 주면 

Mac와 Windows 운영체제의 공동 작업에 유용하다.

 

DispatcherServlet.java (Servlet)

package controller;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.net.*;
import java.util.*;

//Mac과 Windows를 호환할 수 있는 XML 읽기
/*
 * XML 파싱방법
 * - JAXP : DOM / SAX (MyBatis, Spring)
 * 		DOM : 메모리에 트리 형태로 저장 후 처리한다 (수정, 삭제, 추가)
 * 		SAX : 한 줄씩 태그의 값을 읽어 온다 (읽기 전용)
 * 			=> XML
 * 			데이터 저장 위치 -> <태그>데이터</태그> <태그 속성="데이터">
 * - JAXB : 빅데이터 (클래스 변수 == 태그명) ==> 1.8까지 지원
 */
@WebServlet("*.do")
public class DispatcherServlet extends HttpServlet {
  private static final long serialVersionUID = 1 L;
  private List < String > pkgList = new ArrayList < String > (); //XML에서 패키지를 읽어 옴
  private List < String > clsList = new ArrayList < String > (); //패키지 안의 클래스를 모은다
  public void init(ServletConfig config) throws ServletException {
    try {
      URL url = this.getClass().getClassLoader().getResource("."); //resource에 .을 주면 현재 폴더를 의미한다.

      File file = new File(url.toURI());
      System.out.println(file.getPath());
      //C:\webDev\webStudy\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\0727SpringMVCProject\WEB-INF\classes
      //현재 경로명을 읽어 오는 것.. 그래야 경로명 지금처럼 읽어 올 필요가 없음.

      String path = file.getPath();
      path = path.replace("\\", File.separator); //Mac은 /로 Windows는 \\로 바꿔준다!!!(공동작업용)
      System.out.println(path);
      //C:\webDev\webStudy\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\0727SpringMVCProject\WEB-INF\classes
      path = path.substring(0, path.lastIndexOf(File.separator));
      System.out.println(path);
      //C:\webDev\webStudy\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\0727SpringMVCProject\WEB-INF
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse(new File(path + File.separator + "application.xml")); //윈도우면 \\, 맥이면 /

      Element rootTag = doc.getDocumentElement();
      System.out.println(rootTag.getTagName());
      //beans -> XML을 읽었다~

      NodeList list = rootTag.getElementsByTagName("component-scan");
      for (int i = 0; i < list.getLength(); i++) {
        Element cs = (Element) list.item(i); //cs:component-scan
        String value = cs.getAttribute("base-package");
        pkgList.add(value);
      }
      for (String s: pkgList) {
        System.out.println(s); //패키지명이 출력됨
        path = path.substring(0, path.lastIndexOf(File.separator));
        System.out.println(path);
        //C:\webDev\webStudy\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\0727SpringMVCProject
        String ss = path + File.separator + "WEB-INF" + File.separator + "classes" + File.separator + s.replace(".", File.separator);
        File dir = new File(ss);
        File[] files = dir.listFiles();
        for (File f: files) {
          //					System.out.println(f.getName());
          String sss = s + "." + f.getName().substring(0, f.getName().lastIndexOf("."));
          //model.ListModel.class에서 .class를 떼려구
          System.out.println(sss);
        }
      }

    } catch (Exception ex) {}
  }
  //Model 등록
  //Model을 찾아서 요청 수행 => JSP찾기 => request, session으로 전송
  protected void service(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
    try {
      // 사용자 URL - http://localhost:8080/SpringMVCProject/main/main.do
      String uri = request.getRequestURI(); // /SpringMVCProject/main/main.do
      uri = uri.substring(request.getContextPath().length() + 1); // main/main.do

      //Model 클래스 찾기
      for (String strCls: clsList) {
        Class clsName = Class.forName(strCls);
        if (clsName.isAnnotationPresent(Controller.class) == false)
          continue; //클래스 위에 @Controller 있는지 확인하고 없으면 제외
        //메모리 할당
        Object obj = clsName.getDeclaredConstructor().newInstance();
        //요청 처리
        Method[] methods = clsName.getDeclaredMethods(); //Model클래스에 선언된 모든 메서드를 가져 온다.
        for (Method m: methods) {
          RequestMapping rm = m.getAnnotation(RequestMapping.class);
          //메서드 위에 @RequestMapping 이 있는지 확인
          if (uri.equals(rm.value())) { //처리 메서드를 찾아서 수행
            String jsp = (String) m.invoke(obj, request, response);
            /*
             * Model 메서드는 앞으로 이렇게 만들것임
             * @RequestMapping("uri")
             * public String main_main(HttpServletRequest request, HttpServletResponse response){
             * 		return "출력할 JSP";
             * request : 요청값을 받아 처리해서 setAttribute()로 넘겨줌
             * response : Cookie, 파일 업로드 등의 응답
             * }
             */
            //이동은 sendRedirect, forward로 진행
            //sendRedirect : 기존에 만들어진 파일로 이동/재호출 , request를 초기화 
            //forward : 화면 출력, request 보존해서 전송
            if (jsp.startsWith("redirect")) {
              //return "redirect:../main/main.do" 이렇게 보내주고
              response.sendRedirect(jsp.substring(jsp.indexOf(":") + 1)); //../main/main.do
            } else {
              // return "../main/main.jsp" 이렇게 보내주기로 약속합시다(사유:스프링에서 이렇게 함)
              RequestDispatcher rd = request.getRequestDispatcher(jsp);
              rd.forward(request, response); //jsp 한테 request와 response를 보내라~
            }
            return;
          }
        }

      }
    } catch (Exception ex) {}
  }
}

 

 

더보기
⑴아래 DispatcherServlet.java, RequestMapping.java, Controller.java를 하나의 패키지에 넣고
⑵해당 패키지를 jar 파일로 export해서
⑶다른 프로젝트에서 lib에 추가해 주면
→ 간단하게 MVC 구조를 사용할 수 있게 된다.
같은 내용의 코드를 일일이 작성하지 않아도 되어 굉장히 편리하다!

***물론 import한 jar을 구성하는 코드들에서 지정한 양식을 지켜 프로그래밍해야 한다.

 

Controller.java (Annotation)

package controller;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
//Controller 어노테이션이 들어간다 = Model이다.
@Retention(RUNTIME)
@Target(TYPE)
public @interface Controller {}

 

RequestMapping.java (Annotation)

package controller;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
//@ReuqestMapping("list.do");
@Retention(RUNTIME)
@Target(METHOD)
//메서드를 찾아준다.
public @interface RequestMapping {
  //이 안에 들어가는 문자열로 구분할 것이다.
  public String value();
}

 

DispatcherServlet.java (Servlet)

package controller;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.net.*;
import java.util.*;

//Mac과 Windows를 호환할 수 있는 XML 읽기
/*
 * XML 파싱방법
 * - JAXP : DOM / SAX (MyBatis, Spring)
 * 		DOM : 메모리에 트리 형태로 저장 후 처리한다 (수정, 삭제, 추가)
 * 		SAX : 한 줄씩 태그의 값을 읽어 온다 (읽기 전용)
 * 			=> XML
 * 			데이터 저장 위치 -> <태그>데이터</태그> <태그 속성="데이터">
 * - JAXB : 빅데이터 (클래스 변수 == 태그명) ==> 1.8까지 지원
 */
@WebServlet("*.do")
public class DispatcherServlet extends HttpServlet {
  private static final long serialVersionUID = 1 L;
  private List < String > pkgList = new ArrayList < String > (); //XML에서 패키지를 읽어 옴
  private List < String > clsList = new ArrayList < String > (); //패키지 안의 클래스를 모은다
  public void init(ServletConfig config) throws ServletException {
    try {
      URL url = this.getClass().getClassLoader().getResource("."); //resource에 .을 주면 현재 폴더를 의미한다.

      File file = new File(url.toURI());
      System.out.println(file.getPath());
      //C:\webDev\webStudy\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\0727SpringMVCProject\WEB-INF\classes
      //현재 경로명을 읽어 오는 것.. 그래야 경로명 지금처럼 읽어 올 필요가 없음.

      String path = file.getPath();
      path = path.replace("\\", File.separator); //Mac은 /로 Windows는 \\로 바꿔준다!!!(공동작업용)
      System.out.println(path);
      //C:\webDev\webStudy\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\0727SpringMVCProject\WEB-INF\classes
      path = path.substring(0, path.lastIndexOf(File.separator));
      System.out.println(path);
      //C:\webDev\webStudy\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\0727SpringMVCProject\WEB-INF
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse(new File(path + File.separator + "application.xml")); //윈도우면 \\, 맥이면 /

      Element rootTag = doc.getDocumentElement();
      System.out.println(rootTag.getTagName());
      //beans -> XML을 읽었다~

      NodeList list = rootTag.getElementsByTagName("component-scan");
      for (int i = 0; i < list.getLength(); i++) {
        Element cs = (Element) list.item(i); //cs:component-scan
        String value = cs.getAttribute("base-package");
        pkgList.add(value);
      }
      for (String s: pkgList) {
        System.out.println(s); //패키지명이 출력됨
        path = path.substring(0, path.lastIndexOf(File.separator));
        System.out.println(path);
        //C:\webDev\webStudy\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\0727SpringMVCProject
        String ss = path + File.separator + "WEB-INF" + File.separator + "classes" + File.separator + s.replace(".", File.separator);
        File dir = new File(ss);
        File[] files = dir.listFiles();
        for (File f: files) {
          //					System.out.println(f.getName());
          String sss = s + "." + f.getName().substring(0, f.getName().lastIndexOf("."));
          //model.ListModel.class에서 .class를 떼려구
          System.out.println(sss);
        }
      }

    } catch (Exception ex) {}
  }
  //Model 등록
  //Model을 찾아서 요청 수행 => JSP찾기 => request, session으로 전송
  protected void service(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
    try {
      // 사용자 URL - http://localhost:8080/SpringMVCProject/main/main.do
      String uri = request.getRequestURI(); // /SpringMVCProject/main/main.do
      uri = uri.substring(request.getContextPath().length() + 1); // main/main.do

      //Model 클래스 찾기
      for (String strCls: clsList) {
        Class clsName = Class.forName(strCls);
        if (clsName.isAnnotationPresent(Controller.class) == false)
          continue; //클래스 위에 @Controller 있는지 확인하고 없으면 제외
        //메모리 할당
        Object obj = clsName.getDeclaredConstructor().newInstance();
        //요청 처리
        Method[] methods = clsName.getDeclaredMethods(); //Model클래스에 선언된 모든 메서드를 가져 온다.
        for (Method m: methods) {
          RequestMapping rm = m.getAnnotation(RequestMapping.class);
          //메서드 위에 @RequestMapping 이 있는지 확인
          if (uri.equals(rm.value())) { //처리 메서드를 찾아서 수행
            String jsp = (String) m.invoke(obj, request, response);
            /*
             * Model 메서드는 앞으로 이렇게 만들것임
             * @RequestMapping("uri")
             * public String main_main(HttpServletRequest request, HttpServletResponse response){
             * 		return "출력할 JSP";
             * request : 요청값을 받아 처리해서 setAttribute()로 넘겨줌
             * response : Cookie, 파일 업로드 등의 응답
             * }
             */
            //이동은 sendRedirect, forward로 진행
            //sendRedirect : 기존에 만들어진 파일로 이동/재호출 , request를 초기화 
            //forward : 화면 출력, request 보존해서 전송
            if (jsp.startsWith("redirect")) {
              //return "redirect:../main/main.do" 이렇게 보내주고
              response.sendRedirect(jsp.substring(jsp.indexOf(":") + 1)); //../main/main.do
            } else {
              // return "../main/main.jsp" 이렇게 보내주기로 약속합시다(사유:스프링에서 이렇게 함)
              RequestDispatcher rd = request.getRequestDispatcher(jsp);
              rd.forward(request, response); //jsp 한테 request와 response를 보내라~
            }
            return;
          }
        }

      }
    } catch (Exception ex) {}
  }
}

 

 

'부트캠프(END) > Web' 카테고리의 다른 글

MyBatis : 기초  (0) 2022.07.29
MVC (1)  (0) 2022.07.27
EL/JSTL  (0) 2022.07.25

댓글()