- 이 게시물은
처음 시작하는 스프링 프레임워크 - 허진경 지음
책을 공부하며 작성한 글입니다.
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) {
// ,,,
}
}
- 실행 로직
- URL이 /hr/count일 경우 empCount()메소드 실행
- empCount()메소드가 “hr/count”를 리턴
- Spring Framework는 리턴한 문자열 앞에 /WEB-INF/views/를 붙이고 뒤에 .jsp를 붙여
WEB-INF/views/hr/count.jsp
파일로 응답(forward response)
4. Controller와 요청처리
- Spring Controller는 bean으로 등록되어야함.
- 비즈니스 로직이 수행되기 위해서는 비즈니스 객체를 의존성 주입해야함.
- 웹 컴포넌트 설정파일에서 등록해야함(mvc-config.xml)
<!-- 아래처럼 쓰면 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가지 방법
- HttpServletRequest의 getParameter()메소드
- @RequestParam Annotation이용
- 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
java.io.OutputStream / java.io.Writer
@PathVariable
- URI템플릿 변수에 접근하기 위한 Annotation
- {}를 이용하여 URI에 설정
@RequestParam
- 파라미터 값을 받을 때 사용
- 선언된 타입으로 형변환 불가 시 400에러 발생
- 필수 파라미터가 아닌 경우 required=false, 기본 값 지정은 defaultValue로 지정 (=”1”)
@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. 예외처리
- HTTP 상태코드를 사용한 예외처리
- @ExceptionHandler을 이용한 컨트롤러 기반의 예외처리
- @ControllerAdvice를 이용한 글로벌 예외처리
- HandlerExceptionResolver bean을 XML파일에 설정하는 방법의 예외처리
4-8. 인터셉터
- Spring의 HandlerMapping 매커니즘은 특정 요청에 어떤 기능을 적용하기를 원할 때 유용한 handler Interceptor를 포함한다.
- 요청 경로마다 권한을 확인하여 접근제어를 다르게 해야할때
- 사용자가 특정 URL을 요청할 때마다 접근내역을 기록하고 싶을 때
- 로그인 체크를 해야할 때 사용
- 예시
- 로그인 되어있는지 확인
- 만일 로그인 사용자가 아니라면 현재 요청한 URL과 파라미터를 세션에 저장한 다음 로그인 페이지로 Redirect
- 사용자가 로그인한 후에는 세션에 저장한 URL과 파라미터를 이용하여 로그인한 다음 처음 요청한 페이지로 되돌리기 위해 사용
<mvc:interceptors>
태그로 등록가능