본문 바로가기

카테고리 없음

Spring 01. 기본 구조 및 설정, 의존성주입, parameter 받는 방법

 

// WEB-INF/web.xml

DispatcherServlet : 요청/응답을 나눠주는 서블릿

[Front Controller]
 -> 모든 요청을 앞에서 받은 후 알맞은 Controller에게 연결해주고
Controller의 반환결과에 따라서 알맞는 화면을 선택해 클라이언트에게 응답해주는 역할을 한다.

	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
    


* 필터(서블릿보다 먼저 실행됨)
  -> 모든 요청처리 전 공통적으로 필요로 하는 기능들을 클라이언트의 요청을 Controller가 받기 전에 먼저 수행하게 함
		
* 스프링에서 제공해주는 인코딩 필터 등록
- class : org.springframework.web.filter.CharacterEncodingFilter

	 <!-- web.xml -> root-context.xml -> servlet-context.xml 순으로 실행됨 -->
	 <filter>
	 	<filter-name>encodingFilter</filter-name>
	 	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
	 	
	 	<init-Param>
	 		<param-name>encoding</param-name>
	 		<param-value>UTF-8</param-value>
	 	</init-Param>
	 	
	 	<init-Param>
	 		<param-name>forceEncoding</param-name>
	 		<param-value>true</param-value>
	 	</init-Param>
	 </filter>
	
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

 

// pom.xml


groupId : 2번째 레벨까지의 패키지 구조
artifactId : 3번째 레벨의 패키지명(프로젝트명)
packaging : 배포시 압축형식(.zip 과 비슷함)

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.kh</groupId>
	<artifactId>spring</artifactId>
	<name>spring</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>


properties : 이 문서에서 사용할 환경설정 내용들을 담은 변수(태그명이 변수명)
			 현재 문서 내부에서 ${변수명}으로 사용

	<properties>
		<java-version>11</java-version>
		<org.springframework-version>5.3.20</org.springframework-version>
		<org.aspectj-version>1.9.4</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
		<org.springframework.security-version>5.7.5</org.springframework.security-version>
	</properties>
    
repositories : 저장소

	<repositories>
		<repository>
			<id>Datanucleus</id>
			<url>https://www.datanucleus.org/downloads/maven2/</url>
		</repository>
	</repositories>

dependencies : 프로젝트에서 사용할 라이브러리들을 담는 곳

	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
        
        ....
        
        //필요한 라이브러리 추가(환경에 따라 버전 다름 유의!)
		<!--  1. DB관련 라이브러리 추가 -->
		<!--  1) ojdbc6 라이브러리 추가 -->
		<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc6 -->
		<!-- C:\dev\apache-maven-3.9.6\repository\com\oracle\database\jdbc\ojdbc6\11.2.0.4 -->
		<dependency>
		    <groupId>com.oracle.database.jdbc</groupId>
		    <artifactId>ojdbc6</artifactId>
		    <version>11.2.0.4</version>
		</dependency>
		
		<!--  2) mybatis 라이브러리 -->
		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis</artifactId>
		    <version>3.5.15</version>
		</dependency>
		
		<!--  3) mybatis-spring 라이브러리(spring에서 mybatis를 사용하기 위함) -->
		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
		<dependency>
		    <groupId>org.mybatis</groupId>
		    <artifactId>mybatis-spring</artifactId>
		    <version>2.0.7</version>
		</dependency>
		
		<!-- 4) spring에서 jdbc를 사용하기 위한 라이브러리 -->
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-jdbc</artifactId>
		    <version>${org.springframework-version}</version>
		</dependency>
		 
		 <!-- 5) 커넥션풀 라이브러리 -->
		<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
		<dependency>
		    <groupId>commons-dbcp</groupId>
		    <artifactId>commons-dbcp</artifactId>
		    <version>1.4</version>
		</dependency>
		<!--  DB 끝 -->
		
		<!-- 롬복 라이브러리 -->
		<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
		<dependency>
		    <groupId>org.projectlombok</groupId>
		    <artifactId>lombok</artifactId>
		    <version>1.18.30</version>
		    <scope>provided</scope>
		</dependency>
		
		<!-- spring-security -->
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-core</artifactId>
		    <version>${org.springframework.security-version}</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-web</artifactId>
		    <version>${org.springframework.security-version}</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-config</artifactId>
		    <version>${org.springframework.security-version}</version>
		</dependency>        
	</dependencies>

 

 

// resources/mybatis-config.xml
// DB와 연결할 정보를 파일에 담아둔다.

datasource.driverClassName=oracle.jdbc.driver.OracleDriver
datasource.url = jdbc:oracle:thin:@localhost:1521:xe
datasource.username = SPRING
datasource.password = SPRING

 

// root-context.xml
// 서버구동과 동시에 web.xml파일을 거쳐서 로딩되는 문서
// 서버구동과 동시에 셋팅해야 하는 내용들을 작성한다. ex) DB연결정보(mybatice)


	 <!-- datasource.properties 파일 읽어오기  -->
	 <!-- context:  : 하단 Namespace에서 체크하기  -->
	 <context:property-placeholder location="classpath:datasource.properties" />
     
     
         <!-- DB연결 설정 -->
	 <!-- 1) DB연결을 위한 도구 설정 -->
	 <bean class="org.apache.commons.dbcp.BasicDataSource" id="realDataSource" destroy-method="close">
	 	<property name="driverClassName" value="${datasource.driverClassName}" />	
	 	<property name="url" value="${datasource.url}" />	
	 	<property name="username" value="${datasource.username}" />	
	 	<property name="password" value="${datasource.password}" />	
	 </bean>
	 
	 
	 <!-- 2) Mybatic Spring에서 제공하는 sql명령어 실행을 위한 도구 등록 -->
	 <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
	 	<!-- mybatic 설정파일 위치 지정 -->
	 	<property name="configLocation" value="classpath:mybatis-config.xml" />
	 	
	 	<!-- DB연결을 위한 도구 등록 -->
	 	<property name="dataSource" ref="realDataSource" />
	 	
	 	<!--  매퍼 등록 : 앞으로 생성할 모든 mapper파일을 한 번에 읽어올 예정 -->
	 	<property name="mapperLocations" value="classpath*:mapper/**/*.xml" />
	 </bean>
	 
	 
	 <!-- 3) SQL구문을 실행하기 위한 탬플릿을 제공하는 도구(Bean) 등록 -->
	 <!-- SqlSessionTemplate : SqlSession을 구현한 구현클래스 -->
	 <bean class="org.mybatis.spring.SqlSessionTemplate" id="sqlSession">
	 	<constructor-arg ref="sqlSessionFactory" /> <!-- 매개변수들 -->
	 </bean>
	 
	 
	 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	 	<property name="dataSource" ref="realDataSource" />
	 </bean>

 

 

// WEB-INF/spring/appServlet/servlet-context.xml


	<!-- /resources/** : /resources/a.jpg, /resources/img/b.jpg ..등 
		 /resources/모든 폴더 또는 파일 매핑을 의미(정적인 파일들에 대한 요청을 mapping )-->
	<resources mapping="/resources/**" location="/resources/" />


	<!-- 
		* 주소 자동완성 도구 
		- 매번 같은 주소를 추가해야 하는 불편함 때문에 주소자동완성기능이 기본적으로 등록되었다.
		  ex) (/WEB-INF/views/)
		- ViewResolver라는 도구를 등록(spring에서 제공)
		- class : InternalResourceViewResolver
		- prefix : 접두어 
		- suffix : 접미어
		- 컨트롤러에서 문자열(String)값을 리턴할때 해당 문자열에 앞에는 접두어, 뒤에는 접미어를 붙여서 포워딩시켜준다.
		ex) /WEB-INF/views/..... .jsp
	-->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" /> 
	</beans:bean>
	
	<!-- 
		base-package에 등록된 패키지와 그 하위에 존재하는 모든 패키지를 scan해서 
		bean으로 등록가능한 클래스가 있다면 모두 등록시키겠다.. (Beans Graph에서 확인가능)
		
		bean ? 스프링프레임워크에서 관리하는 자바객체. 딱 1개만 생성해서 관리
	 -->
	<context:component-scan base-package="com.kh.spring" />

 

 


 

의존성 주입 ? 아래 예시를 보자..

// MemberController.java

	/*
	 * 기본 객체 생성방식
	   private MemberService mService = new MemberServiceImpl();
	   => 다형성에 의해 MemberServiceImpl가 업캐스팅됨
		
	   Spring의 DI(Dependency Injection) : 의존성주입
	   -> 객체를 개발자가 생성하는 것이 아니라 스프링이 생성한 객체를 주입받아서 사용하는 방식
		
	   new 연산자를 쓰지 않고 선언만 한 후 @Autowird어노테이션을 붙여서 주입을 받음
	*/
    
    
    @Controller
    public class MemberController {
    	
      /*  
        * 의존성 주입 방식 3가지
        1) 필드방식
          -> 장점 : 이해하기 편하다. 사용하기 편하다.
	 	  -> 단점 : 1)순환 의존성 문제가 발생할 수 있다. 
	 		   2)무분별한 주입시 의존관계 확인이 어렵다.
        2) 생성자방식(권장)
          : 생성자에 참조할 클래스를 인자(매개변수)로 받아서 필드에 매핑시킨다.
          -> 장점 : 현재 클래스에서 내가 주입시킬 객체들을 모아서 관리할 수 있기 때문에 한 눈에 알아보기 편함
        3) setter방식
          -> setter메서드로 빈을 주입받는 방식
      */  
        
        // 2) 생성자방식 예)
        private MemberService mService;
        
        public MemberController() {
		 // 기본생성자
        }

        @Autowired
        public MemberController(MemberService mService) {
            this.mService = mService;
        }
        
        // 3) setter방식 예)
        @Autowired
	public void setMemberSerview(MemberService mService) {
	    this.mService = mService;
	}
       
    }

 

 

스프링에서 parameter를 받는 방법들.

  1. HttpServletRequest를 이용해서 전달받기(기존방식)
  => 해당 메서드의 매개변수로 HttpServletRequest를 작성해 놓으면 
     스프링컨테이너가 해당 메서드를 호출 할 때 자동으로 request객체를 생성해서 매개변수에 주입해준다.

  2. @RequestParam 어노테이션을 이용하는 방법
  servlet의 request.getParameter("키")로 뽑는 역할을 대신 수행해주는 어노테이션
  RequestParam속성의 value로 jsp에서 작성했던 name값을 입력해주면 알아서 매개변수로 값을 담아옴
  넘어온 값이 비어있다면 기본값도 지정 가능하다.

  3. @RequestParam을 생략하는 방법
  단, 기본값(defaultValue)은 사용불가!

  4. 커맨드 객체 방식
  해당 메서드의 매개변수로 요청시 전달하고자 하는 VO클래스타입의 변수를 셋팅하고
  요청시 전달값의 name속성을 VO클래스의 필드명과 일치시켜서 작성(userId, userPwd)
 
  스프링컨테이너에서 해당 객체를 "기본생성자"를 호출해서 객체를 생성한 후
  내부적으로 전달받은 key값에 해당하는 setter메서드를 찾아서 전달한 값을 생성된 객체의 필드에 담아준다.
  따라서 반드시 name속성값과 필드명이 일치해야 한다.

 

 

// 예시) userId, userPwd 전달받은 값 꺼내기


1. HttpServletRequest를 이용해서 전달받기(기존방식)
	@RequestMapping(value="login.me", method=RequestMethod.POST)
	public String loginMember(HttpServletRequest request) {

		System.out.println("userId : " + request.getParameter("userId"));
		System.out.println("userPwd : " + request.getParameter("userPwd"));
		return "main";
	}
    
2. @RequestParam어노테이션을 이용하는 방법
	@RequestMapping(value="login.me", method=RequestMethod.POST)
	public String loginMember(@RequestParam(value="userId", defaultValue = "mmm") String userId,
				@RequestParam(value="userPwd") String userPwd
			) {
		System.out.println(userId + "," + userPwd);
		return "main";
	}
    
3. @RequestParam을 생략하는 방법
	@RequestMapping(value="login.me", method=RequestMethod.POST)
	public String loginMember(
			String userId,
			String userPwd
			) {
		System.out.println(userId + "," + userPwd);
		return "main";
	}
    
4. 커맨드 객체 방식
    @RequestMapping(value="login.me", method=RequestMethod.POST)
	public String loginMember(Member m) {
		System.out.println(m.getUserId() + "," + m.getUserPwd());
		System.out.println(m.getUserNo() );
		return "main";
	}