Spring06_복습(MVC)

4 minute read



  • 이 게시물은 처음 시작하는 스프링 프레임워크 - 허진경 지음 책을 공부하며 작성한 글입니다.
    • 교수님! 좋은 책 주셔서 감사합니다:)

MVC

Model

  • 비즈니스 로직 실행결과를 저장하는 도메인 객체

View

  • 출력되어야할 데이터들이 모델에 저장되고 출력
  • 프레젠테이션 로직
  • 주로 JSP파일을 이용하여 결과를 보여줌

Controller

  • 제어로직
  • URL요청에 알맞은 비즈니스 로직을 실행




Spring Web MVC

  • DispatcherServlet을 중심으로 구성
    • 설정가능한 핸들러 매핑을 이용하여 요청을 처리
    • 뷰를 찾아 처리
    • 지역, 시간대를 인식하고 파일 업로드 기능까지 지원
  • 기본 핸들러는 @Controller 및 @RequestMapping 아노테이션 기반
  • Spring 3.0에 소개된 @Controller매커니즘을 사용하면 @PathVariable Annotation 및 기타 기능을 통해 RESTful 웹사이트 및 애플리케이션을 만들 수 있다.
  • Open-close-priciple : SW요소는 확장을 위해 개방되어야 하지만 수정을 위해서는 폐쇄되어야 한다.
    • 핵심 클래스에 있는 일부 메서드를 final로 표기
    • 자신의 행동을 제공하기 위해 이러한 메소드를 재정의 할 수 없음



1. DispatcherServlet

  • 스프링 IoC컨테이너와 완벽하게 통합되어 스프링이 가지고 있는 다른 모든 기능을 사용할 수 있다.
  • 웹 애플리케이션에 선언된 HttpServlet 클래스를 상속받은 Serlvet
  • URL매핑을 사용하여 DispatcherServlet에서 처리할 요청을 매핑해야함
  • web.xml에 URL매핑을 사용하여 처리할 요청을 매핑
<servlet>
  <servlet-name>dispatcher</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
      classpath:config/spring/spring-mvc.xml
    </param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>  
</servlet-mapping>

<servlet-mapping>
  <servlet-name>dispatcher</servlet-name>
<url-pattern>*.json</url-pattern>  
</servlet-mapping>



2. Spring 설정 파일

2-1. web.xml

  • WEB-INF폴더 하위에 위치
  • 공통컴포넌트 설정파일 위치와 웹 컴포넌트 설정파일의 위치 지정
    • 공통컴포넌트 설정파일 : 데이터소스, 트랜잭션, 서비스, 리포지토리 등 애플리케이션 전반에 걸쳐 사용되는 bean
    • 웹 컴포넌트 설정파일 : 컨트롤러, 뷰, 리졸버 등 웹과 관련된 bean 설정
  • 설정파일이 클래스패스 경로에 존재한다면 classpath: 접두어를 사용


2-2. application-config.xml (공통컴포넌트 파일)

  • web.xml에서 <context-param>태그에 의해 설정된 파일
  • 웹 컨테이너가 로드되기 전 로드됨


2-3. mvc-config.xml (웹 컴포넌트 설정파일)

  • web.xml에서 DispatcherServlet 클래스의 <init-param>태그를 이용해 설정한 파일



3. Controller구현

  • 컨트롤러는 POJO 클래스로 구현
  • 클래스를 bean으로 등록해주는 것과 비즈니스 객체에 의존성을 주입하는 것은 DI, AOP 개념 참고
  • 컨트롤러는 요청 URL을 매핑시켜주기 위한 설정이 필요
  • @Controller@RequestMapping 사용
@Controller
public class EmpController{

  // Controller는 1개이상 요청 매핑 설정을 갖는다.
  @RequestMapping(value="/hr/count")
  public String empCount(@RequestParam(value="deptid", required=false, defaultValue="0") int deptid, Model) {
    // ,,, 
  }
}
  • 실행 로직
    1. URL이 /hr/count일 경우 empCount()메소드 실행
    2. empCount()메소드가 “hr/count”를 리턴
    3. Spring Framework는 리턴한 문자열 앞에 /WEB-INF/views/를 붙이고 뒤에 .jsp를 붙여 WEB-INF/views/hr/count.jsp파일로 응답(forward response)



4. Controller와 요청처리

  • Spring Controller는 bean으로 등록되어야함.
  • 비즈니스 로직이 수행되기 위해서는 비즈니스 객체를 의존성 주입해야함.
  • 웹 컴포넌트 설정파일에서 등록해야함(mvc-config.xml)
    • <context:component-scan>

<!-- 아래처럼 쓰면 http://localhost:8080/hr/count가 호출되어 404에러뜸 -->
<a href="/hr/count">사원의 수 </a>

<!-- 절대경로를 사용한 url을 지정하려면 Core태그 사용 -->
<a href="<c:url value='/hr/count'/>">사원의 수</a>


4-1. 요청방식에 따른 처리 (GET / POST)

  • GET
    • @RequestMapping(value=”/hr/count”, method=RequestMethod.GET)
    • Spring 4부터 @GetMapping(value="/hr/count") 가 가능해짐
  • POST
    • @RequestMapping(value=”/hr/count”, method=RequestMethod.POST)
    • Spring 4부터 @PostMapping(value="/hr/count") 가 가능해짐


4-2. 다중요청처리

  • @RequestMapping의 value값을 String배열로 지정하면 여러 URL을 동일한 메소드로 처리할 수있다.
@RequestMapping(value={"/hr/count", "/hr/cnt"})


4-3. 파라미터 전송받기

  • HTTP요청 파라미터 가져올 때 지원하는 3가지 방법
    1. HttpServletRequest의 getParameter()메소드
    2. @RequestParam Annotation이용
    3. Command 객체 이용

01. request.getParameter()

  • 컨트롤러 메소드의 파라미터에 HttpServletRequest타입 변수 선언하면 요청 파라미터 값을 읽을 수 있음
  • getParameter()의 리턴타입은 String
@RequestMapping(value="/hr/count", method=RequestMethod.GET)
public String empCount(HttpServletRequest request, Model model) {
  String param = request.getParameter("deptid");
  //...
  }
}

02. @RequestParam

  • URL이 http://localhost:8080/myapp/hr/count?deptid=50 일때
@RequestMapping(value="/hr/count", method=RequestMethod.GET)
public String empCount(@RequestParam("deptid") int deptid, Model model) { }


  • 요청 파라미터와 컨트롤러 메소드의 파라미터 이름이 같을 경우
    • @RequestParam을 생략해도 스프링이 자동으로 요청 파라미터 값을 메소드 파라미터에 매핑
@RequestMapping(value="/hr/count", method=RequestMethod.GET)
public String empCount(int deptid, Model model) { }
  • 속성값
    • value
      • 요청 파라미터의 이름 지정
      • 컨트롤러메소드의 파라미터 이름과 요청 파라미터 이름이 다를 경우 사용
    • required
      • true(기본값)일 경우 요청 파라미터를 반드시 지정해야함
      • 만일 요청 파라미터가 반드시 필요하지 않을 경우 false로 설정
    • defaultValue
      • 요청 파라미터가 없이 요청되었을 경우 갖게 되는 기본 값
      • 기본값은 컨트롤러의 메소드 파라미터 Type과 무관하게 항상 “ “로 둘러싸야함.
@RequestMapping(value="/hr/count", method=RequestMethod.GET)
public String empCount(@RequestParam(value="deptid", required=false, defaultValue="0") int deptid, Model model) { }

03. Command객체

  • form태그로부터 파라미터를 전송받기 위해 Command 메소드에 파라미터를 나열하여 요청 파라미터를 개별적으로 처리할 수 있음.
  • 다른 모델 객체에 넣어야할 때 setter메소드를 하나하나 지정해서 사용한 후 저장해야하는 불편함이 있음
@RequestMapping(value="/hr/insert", method=RequestMethod.POST)
public String empInsert(@RequestParam("emplyeeId")    int employeeId,
                        @RequestParam("firstName")    String firstName,
                        @RequestParam("lastName")     String lastName,
                        @RequestParam("email")        String email,
                        @RequestParam("phoneNumber")  int phoneNumber,
                        @RequestParam("salary")       int salary
                        //...
                        ) { }
  • 스프링에서는 Command객체로 쉽게 해결할 수 있다.
    • Value Object (VO) 클래스를 이용
    • Command객체는 파라미터의 이름과 동일한 변수를 갖는 클래스이다.
    • 입력양식의 name속성의 값이 Command클래스의 이름과 같다면 컨트롤러 메소드 파라미터에 Command객체를 선언하는 것만으로 입력양식 데이터를 Command객체에 매핑시킬 수 있다.
@RequestMapping(value="/hr/insert", method=RequestMethod.POST)
public String empInsert(EmpVO emp, Model model){
  try{
    empService.insertEmp(emp);
  }catch(Exception e){
    model.addAttribute("msg", e.getMessage());
    return "hr/error";
  }
  return "hr/ok";
}

4-4. Path Variable과 URI Template Variable

  • @PathVariable
  • 파라미터가 URL에 포함되도록 하는 형태 /hr/count/50
  • URI템플릿 변수의 이름을 지정할 수 있다.
  • required속성과 defaultValue속성이 없으므로 템플릿변수는 반드시 URL에 포함되어야함.
@RequestMapping(value="/hr/{employeeId}")
public String empInsert(@PathVariable int employeeId, Model model){ }


4-5. Controller 메소드의 파라미터 타입

  • HttpServletRequest, HttpServletResponse
    • HTTP request객체와 response객체
    • 직접 request객체를 다룰 때 사용

HttpSession

  • 사용자 인증처리에 사용

java.util.Locale

  • 현재 요청에 대한 Locale을 알 수 있음

java.io.InputStream / java.io.Reader

  • 요청 컨텐츠에 직접 접근

java.io.OutputStream / java.io.Writer

  • 응답 컨텐츠를 생성. (파일 다운로드)

@PathVariable

  • URI템플릿 변수에 접근하기 위한 Annotation
  • {}를 이용하여 URI에 설정

@RequestParam

  • 파라미터 값을 받을 때 사용
  • 선언된 타입으로 형변환 불가 시 400에러 발생
  • 필수 파라미터가 아닌 경우 required=false, 기본 값 지정은 defaultValue로 지정 (=”1”)

@RequestHeader

  • 요청 헤더 매핑

@CookieValue

  • 쿠키 매핑

@RequestBody

  • 요청 몸체 내용에 접근

HttpEntity<?>

  • Servlet요청 request Http헤더와 컨텐츠 사용할 수 있음

java.util.Map, org.springframework.ui.Model, org.springframework.ui.ModelMap

  • 뷰에 전달한 모델 데이터를 설정

org.springframework.web.servlet.mvc.support.RedirectAttributes

  • redirect할 페이지에 데이터를 저장하기 위해 사용
  • redirect: 접두어가 붙을 때 사용

VO객체

  • 요청 파라미터 저장객체
  • 클래스 이름을 모델명으로 사용
  • @ModelAttribute로 모델명 설정가능

org.springframework.validation.Errors, org.springframework.validatin.BindingResult

  • VO 또는 form객체의 유효성 검증 결과를 저장.


4-6. Static 파일(Css, js, image)

  • <mvc:resources>태그를 이용하여 location과 mapping설정
  • 웹 컴포넌트 파일(mvc-config.xml)에 리소스를 설정
<mvc:resources location="/WEB-INF/resources/" mapping="/**" />
<mvc:resources location="/WEB-INF/resources/images" mapping="/images/**" />
<mvc:resources location="/WEB-INF/resources/js" mapping="/js/**" />
<mvc:resources location="/WEB-INF/resources/css" mapping="/css/**" />


4-7. 예외처리

  1. HTTP 상태코드를 사용한 예외처리
  2. @ExceptionHandler을 이용한 컨트롤러 기반의 예외처리
  3. @ControllerAdvice를 이용한 글로벌 예외처리
  4. HandlerExceptionResolver bean을 XML파일에 설정하는 방법의 예외처리


4-8. 인터셉터

  • Spring의 HandlerMapping 매커니즘은 특정 요청에 어떤 기능을 적용하기를 원할 때 유용한 handler Interceptor를 포함한다.
  • 요청 경로마다 권한을 확인하여 접근제어를 다르게 해야할때
  • 사용자가 특정 URL을 요청할 때마다 접근내역을 기록하고 싶을 때
  • 로그인 체크를 해야할 때 사용
  • 예시
    • 로그인 되어있는지 확인
    • 만일 로그인 사용자가 아니라면 현재 요청한 URL과 파라미터를 세션에 저장한 다음 로그인 페이지로 Redirect
    • 사용자가 로그인한 후에는 세션에 저장한 URL과 파라미터를 이용하여 로그인한 다음 처음 요청한 페이지로 되돌리기 위해 사용
  • <mvc:interceptors>태그로 등록가능