관리 메뉴

거니의 velog

(18) 스프링 애너테이션 기능 1 본문

Java_Spring Framework part1

(18) 스프링 애너테이션 기능 1

Unlimited00 2023. 11. 11. 15:40

1. 스프링 애너테이션이란?

* 앞에서 살펴봤듯이, 스프링 2.5까지는 DI나 AOP 같은 기능은 따로 XML 파일로 설정한 후 애플리케이션에서 사용했다. 그러나, 애플리케이션의 기능이 복잡해짐에 따라 XML 설정 파일의 내용도 복잡해졌고 관리에도 문제가 생기기 시작했다.

* 따라서 스프링 3.0 부터는 DI와 같은 자바 코드와 관련된 설정은 직접 코드에서 할 수 있게 애너테이션(Annotation)이라는 기능을 제공한다. 현재 스프링 기반 애플리케이션에서는 XML에서 설정하는 방법과 애너테이션 기능을 사용하는 방법 두 가지를 혼합해서 사용하고 있다.


(1) 스프링 애너테이션 제공 클래스

* 스프링에서 애너테이션을 사용하려면 먼저 스프링에서 제공하는 애너테이션 관련 클래스를 XML 설정 파일에서 빈으로 설정해야 한다.

< 브라우저 URL 요청 처리 애너테이션 관련 클래스 >

클래스 기능
DefaultAnnotationHandlerMapping 클래스 레벨에서 @RequestMapping을 처리한다.
AnnotationMethodHandlerAdapter 메서드 레벨에서 @RequestMapping을 처리한다.

(2) <content:component-scan> 태그 기능

* <content:component-scan> 태그를 사용해 패키지 이름을 지정하면 애플리케이션 실행 시 해당 패키지에서 애너테이션으로 지정된 클래스를 빈으로 만들어 준다.

<content:component-scan base-package="패키지이름" />

* 다음 표는 <content:component-scan> 태그로 지정한 패키지에 위치하는 클래스에 지정하는 여러 가지 애너테이션이다.

< 여러 가지 스테레오 타입 애너테이션 >

애너테이션 기능
@Controller 스프링 컨테이너가 component-scan에 의해 지정한 클래스를 컨트롤러 빈으로 자동 변환한다.
@Service 스프링 컨테이너가 component-scan에 의해 지정한 클래스를 서비스 빈으로 자동 변환한다.
@Repository 스프링 컨테이너가 component-scan에 의해 지정한 클래스를 DAO 빈으로 자동 변환한다.
@Component 스프링 컨테이너가 component-scan에 의해 지정한 클래스를 빈으로 자동 변환한다.

* 이러한 클래스들은 스프링 실행 시 자동으로 빈으로 생성된다. 자세한 것은 실습을 통해 알아보자.


2. 스프링 애너테이션 이용해 URL 요청 실습하기

* 그럼 스프링 애너테이션 기능을 이용해 실습해 보자.

1. 새 프로젝트 pro26을 만들고 스프링 애너테이션 기능을 실습하기 위한 XML 설정 파일인 action-servlet.xml 을 다음과 같이 추가한다.

2. action-servlet.xml을 다음과 같이 작성한다. 스프링에서 제공하는 DefaultAnnotationHandlerMapping과 AnnotationMethodHandlerAdapter 클래스의 빈을 설정한다.

[web.xml]

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">
	
	<servlet>
		<servlet-name>action</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

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

</web-app>

* <context:component-scan base-package="com.spring" /> 태그를 이용해 com.spring 하위 패키지에 애너테이션이 적용되도록 설정한다.

[action-servlet.xml]

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans   
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/test/" />
        <!--   <property name="prefix" value="/WEB-INF/views/member/" /> -->
        <property name="suffix" value=".jsp" />
    </bean>

	<!-- 클래스 레벨에 @RequestMapping을 처리한다. -->
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
	<!-- 메서드 레벨에 @RequestMapping을 처리한다. -->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
    <!-- com.spring 패키지에 존재하는 클래스에 애너테이션이 적용되도록 설정한다. -->
    <context:component-scan base-package="com.spring" />
</beans>

3. 애너테이션 기능을 수행하는 자바 클래스와 JSP 파일을 추가한다.

4. MainController 클래스가 하는 일은 다음과 같다. @Controller("mainController") 애너테이션은 주로 Controller 클래스에 위치해 빈을 만든다. @RequestMapping("/test")은 URL 요청 시 첫 번째 단계의 요청이 /test이면 mainController 빈에게 요청을 전달한다. 그리고 @RequestMapping(value="/main1.do" , method=RequestMethod.GET)을 메서드에 위치시킨 후 각 요청을 구분하여 메서드를 호출한다.

package com.spring.ex01; // 애너테이션이 적용되도록 하려면 해당 클래스가 반드시 <component-scan>에서 설정한 패키지나 하위 패키지에 존재해야 한다.

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller("mainController") // @Controller 애너테이션을 이용해 MainController 클래스를 빈으로 자동 변환한다. 빈 id는 mainController이다.
@RequestMapping("/test") // @RequestMapping을 이용해 첫 번째 단계의 URL 요청이 /test 이면 mainController 빈을 요청한다.
public class MainController {
	
   // @RequestMapping을 이용해 두 번째 단계의 URL 요청이 /main1.do이면 mainController 빈의 main1() 메서드에게 요청한다.
   // method=RequestMethod.GET으로 지정하면 GET 방식으로 요청시 해당 메서드가 호출된다.
   @RequestMapping(value="/main1.do" , method=RequestMethod.GET)
   public ModelAndView main1(HttpServletRequest request, HttpServletResponse response)  throws Exception{
      ModelAndView mav = new ModelAndView();
      mav.addObject("msg","main1");
      mav.setViewName("main");
      return mav;
   }

   // @RequestMapping을 이용해 두 번째 단계의 URL 요청이 /main2.do이면 mainController 빈의 main2() 메서드에게 요청한다.
   // method=RequestMethod.GET으로 지정하면 GET 방식으로 요청시 해당 메서드가 호출된다.
   @RequestMapping(value="/main2.do" , method=RequestMethod.GET)
   public ModelAndView main2(HttpServletRequest request, HttpServletResponse response) throws Exception{
      ModelAndView mav = new ModelAndView();
      mav.addObject("msg","main2");
      mav.setViewName("main");
      return mav;
   }
   
}

5. 다음은 컨트롤러에서 ModelAndView 에 뷰이름으로 설정한 main.jsp이다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" 
    isELIgnored="false"  %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"  %>


<%
  request.setCharacterEncoding("UTF-8");
%>

<!DOCTYPE html>
<html lang="ko">

    <head>
        <meta charset="UTF-8">
        <title>결과창</title>
    </head>

    <body>
        <h1>안녕하세요!!</h1>
        <h1>${msg} 페이지입니다!!</h1> <!-- 컨트롤러에서 넘긴 메시지를 출력한다. -->
    </body>

</html>

6. 다음의 주소들로 각각 요청하여 결과를 확인한다.

- http://localhost:8090/pro26/test/main1.do

- http://localhost:8090/pro26/test/main2.do