[Spring 3일차] Maven + Spring

이경영·2022년 10월 14일
0
post-custom-banner

Maven의 핵심기능

장점

  1. pom.xml에서 디펜던시로 라이브러리 쉽게 추가/삭제 가능
  2. 빌드/서버 배포시 자동화 지원
  3. 빌드시 플러그인 지원
  4. repository에 없는 경우 scope system으로 수동으로 라이브러리 추가 가능

단점

  1. 원하는 라이브러리를 repository서버에서 등록되어있어야 다운로드 가능
  2. repository서버를 구축해서 사용
  3. 가끔 원인 모를 빌드 에러가 발생하여 구글링으로 해결해야함.

SpringFramework구조

  • 2.0.8 version 으로 진행
  • web.xml에 DispatchServlet의 역할 : 모든 요청/응답 받고 처리함
  • ContextLoaderListener : 초기정보, 서비스, dao, 트랜잭션, db등 모든 정보를 로드한 뒤 사용 가능하게 하는 역할

장점

  • web.xml에 의존했던 부분이 dispatch-servlet, application-context로 분리되어 관리에 좋음
  • 자원을 공유하는 구조이므로 다수의 개발자가 공통으로 개발하기 좋음
  • 확장성과 유지보수에 최적화되어있어 좋음
  • 오픈소스 라이브러리 spring 빈 설정을 통해서 쉽게 사용 및 공유가 좋음

단점

  • 서로 연결하고 공유하는 구조이므로 초기 분석 및 설계가 중요함.


: dependency들은 이 위치에 저장해서 컴파일해서 사용함.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.example</groupId>
	<artifactId>java-web-03-spring2x</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>java-web-03-spring2x Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>2.0.8</version>
			<exclusions>
				<exclusion>
					<groupId>javax.servlet</groupId>
					<artifactId>servlet-api</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>2.0.8</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>2.0.8</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>2.0.8</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>2.0.8</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>2.0.8</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>1.2.9</version>
		</dependency>	

		<!-- https://mvnrepository.com/artifact/org.apache.ibatis/ibatis-core -->
		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-core</artifactId>
			<version>3.0</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.apache.ibatis/ibatis-sqlmap -->
		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-sqlmap</artifactId>
			<version>2.3.0</version>
		</dependency>		
		
		<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.49</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/log4j/log4j -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.16</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.2.2</version>
		</dependency>
		
		<!-- https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-impl -->
		<dependency>
			<groupId>org.apache.taglibs</groupId>
			<artifactId>taglibs-standard-impl</artifactId>
			<version>1.2.1</version>
			<scope>runtime</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>		
		
		
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>java-web-03-spring2x</finalName>
		<pluginManagement><!-- lock down plugins versions to avoid using Maven 
				defaults (may be moved to parent pom) -->
			<plugins>
				<plugin>
					<artifactId>maven-clean-plugin</artifactId>
					<version>3.1.0</version>
				</plugin>
				<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
				<plugin>
					<artifactId>maven-resources-plugin</artifactId>
					<version>3.0.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.8.0</version>
				</plugin>
				<plugin>
					<artifactId>maven-surefire-plugin</artifactId>
					<version>2.22.1</version>
				</plugin>
				<plugin>
					<artifactId>maven-war-plugin</artifactId>
					<version>3.2.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-install-plugin</artifactId>
					<version>2.5.2</version>
				</plugin>
				<plugin>
					<artifactId>maven-deploy-plugin</artifactId>
					<version>2.8.2</version>
				</plugin>
			</plugins>
		</pluginManagement>		
	</build>
</project>

web.xml

<web-app
	xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5"
>

  <display-name>Archetype Created Web Application</display-name>
  
  	
  	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:config/spring/application-context.xml</param-value>
	</context-param>
	
	<!-- spring ContextLoaderListener -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
		<context-param>
		<param-name>log4jConfigLocation</param-name>
		<param-value>classpath:config/log4j.xml</param-value>
	</context-param>

	<!-- log4j 등록 -->
	<listener>
		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
	</listener>
	
	<!-- encoding -->
	<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>
	</filter>

	<!-- spring DispatcherServlet -->
	<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/dispatcher-servlet.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>
	
</web-app>

코드 관련 이해하기

  1. Request가 오면 DispatcherServlet이 작동함. 이 서블렛은 web.xml에서 매핑되어있음
  • Servlet class 태그에 있는 것이 패키지 명부터 클래스명까지
  • servlet-mapping 태그 안에 있는 servlet-name 태그servlet 태그 안에 있는 servlet-name 태그를 같게 설정함.
  1. url-pattern 태그로 들어오는 uri 주소에 맞춰 servlet-class 태그에 있는 파일을 실행시켜줌

이걸 해결하기 위해 나온 방식이 어노테이션 방식임 @WebServlet

	<!-- spring DispatcherServlet -->
	<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/dispatcher-servlet.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>

BoardListController.java

package example.controller;

import java.sql.SQLException;

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

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.BaseCommandController;

import example.service.BoardService;

public class BoardListController extends BaseCommandController{
	
	final Logger logger = LogManager.getLogger(getClass());
	
	private BoardService boardService;
	
	
	@Override
	protected ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		//데이터 set, view 페이지 지정 
		
		ModelAndView view = new ModelAndView();
		try {
			//게시물 목록 조회를 boardService에 호출하고 결과값을 boarList key값으로 request에 저장한다.
			view.addObject("boardList", boardService.selectBoardList());
		} catch (SQLException e) {
			logger.error("boardListError",e);
		}
		
		//board/list.jsp를 호출한다
		view.setViewName("board/list");
		return view;
	}
	

	public BoardService getBoardService() {
		return boardService;
	}

	public void setBoardService(BoardService boardService) {
		this.boardService = boardService;
	}



}

출처 : BaseCommandController에 대해 더 알고싶은 경우 여기로!

스프링 프레임워크 웹 요청을 처리하기위한 초기 클래스 계층구조

  • BaseCommandController는 웹요청 기본 기능 + 파라미터 처리 기능을 확장하고 있음

    상속을 통한 기능 재사용은 몇가지 문제점이 생김

    1. 클래스 변경의 어려움 / 2. 클래스 증가 / 3. 상속 오용

ModelAndView

  • ModelAndView는 Controller의 처리결과를 보여줄 view와 view에서 사용할 값을 전달하는 클래스임.
  • ModelAndView는 컴포넌트 방식으로 ModelAndView 객체를 생성해서 객체형태로 리턴한다 MoelAndView는 말그대로 Model과 View를 합쳐놓은 것으로, 값을 넣을때 addObject()를 사용하고, setViewName()으로 보낼 곳 View를 세팅한다

** 참고 - Model은 파라미터 방식으로 메소드에 (Model model) 파라미터를 넣어주고 String형태로 리턴한다 Model은 값을 넣을 때 addAttribute()를 사용
출처: https://develop-im.tistory.com/10 [IsBerry:티스토리]

getter setter로 간접 접근 가하게

example.service.

BoardService.java

package example.service;

import java.sql.SQLException;
import java.util.List;

import example.dao.Board;
import example.dao.BoardDao;


public class BoardService {
	private BoardDao boardDao;
	
	/**
	 * @author oiio6
	 *
	 */
     //리스트 조회 불러오게 처리 
	public List<Board> selectBoardList() throws SQLException{
		return boardDao.selectBoardList();
	}

	public BoardDao getBoardDao() {
		return boardDao;
	}

	public void setBoardDao(BoardDao boardDao) {
		this.boardDao = boardDao;
	}
}

example.dao

BoardDao.java

package example.dao;

import java.sql.SQLException;
import java.util.List;

import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;


public class BoardDao extends SqlMapClientDaoSupport{

	@SuppressWarnings("unchecked")
	public List<Board> selectBoardList() throws SQLException {
		return getSqlMapClientTemplate().queryForList("selectBoardList");
	}

	
	public Board selectBoard(int boardSeq) throws SQLException {
		return (Board) getSqlMapClientTemplate().queryForObject("selectBoard", boardSeq);
	}
	
	
	public void insertBoard(Board board) throws SQLException {
		getSqlMapClientTemplate()
			.insert("insertBoard", board);
	}
	
	public void deleteBoard(int boardSeq) throws SQLException {
		getSqlMapClientTemplate()
			.insert("deleteBoard", boardSeq);
	}


	public void updateBoard(Board board) throws SQLException {
		getSqlMapClientTemplate()
		.update("updateBoard", board);
	}
	

	
}

sqlMapClientDaoSupport를 이용하여 iBatis와 연동

  • sqlMapClientDaoSupport를 상속받아서 Dao 구현 클래스를 작성함.
  • support클래스가 sqlMapClientTemplate 객체를 제공해줌
  • ibatis의 주 설정 파일 sqlmapconfig.xml

board.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap>

 	<!-- 결과 맵 -->
	<resultMap id="selectBoardListResultMap" class="example.dao.Board">
		<result column="BOARD_SEQ" property="boardSeq" />
		<result column="BOARD_TYPE" property="boardType" />
		<result column="TITLE" property="title" />
		<result column="USER_NAME" property="userName" />
		<result column="REG_DATE" property="regDate" />
	</resultMap>
	
 	<!-- 상세 조회 결과 맵 -->
	<resultMap id="selectBoardResultMap" class="example.dao.Board">
		<result column="BOARD_SEQ" property="boardSeq" />
		<result column="BOARD_TYPE" property="boardType" />
		<result column="TITLE" property="title" />
		<result column="CONTENTS" property="contents" />
		<result column="REG_DATE" property="regDate" />
		<result column="USER_NAME" property="userName" />
	</resultMap>	
 
	<!-- 게시물 목록 쿼리 -->
	<select id="selectBoardList" resultMap="selectBoardListResultMap">
		SELECT BOARD_SEQ, BOARD_TYPE, TITLE, REG_DATE, USER_NAME
		FROM T_BOARD
		ORDER BY REG_DATE DESC
	</select>
	
	<!-- 게시물 목록 쿼리 -->
	<select id="selectBoard" resultMap="selectBoardResultMap">
		SELECT BOARD_SEQ, BOARD_TYPE, TITLE, CONTENTS, REG_DATE, USER_NAME
		FROM T_BOARD
		WHERE BOARD_SEQ = #boardSeq#
	</select>	
	
	<!-- 게시물 등록 쿼리 -->
	<insert id="insertBoard" parameterClass="example.dao.Board">
		INSERT INTO T_BOARD
		(
			BOARD_TYPE,
			TITLE,
			CONTENTS,
			REG_DATE,
			USER_NAME		
		)
		VALUES
		(
			#boardType#,
			#title#,
			#contents#,
			NOW(),
			#userName#
		)
	</insert>
	
	<!-- 게시물 업데이트 쿼리 -->
	<insert id="updateBoard" parameterClass="example.dao.Board">
		UPDATE T_BOARD SET 
			BOARD_TYPE = #boardType#,
			TITLE = #title#,
			CONTENTS = #contents#,
			REG_DATE = NOW(),
			USER_NAME = #userName#	
		WHERE BOARD_SEQ = #boardSeq#
	</insert>
	
	<!-- 게시물 삭제 쿼리 -->
	<delete id="deleteBoard" parameterClass="int">
		DELETE FROM T_BOARD
		WHERE BOARD_SEQ = #boardSeq#
	</delete>
	
</sqlMap>

sql-map-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

	<settings
		cacheModelsEnabled="true"
		enhancementEnabled="true"
		lazyLoadingEnabled="true"
		maxRequests="32"
		maxSessions="10"
		maxTransactions="5"
		useStatementNamespaces="false" />
        
	//spring과 연동하는 경우, sql구문이 정의된 xml파일을 등록함
	<sqlMap resource="./config/sqlmap/Board.xml" />

</sqlMapConfig>

config.properties

application-context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	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-2.0.xsd"
>
	<!-- 프로퍼티 -->
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="location" value="classpath:/config/properties/database.properties"/>
		<property name="fileEncoding" value="UTF-8" />
	</bean>

	<!-- dataSource bean 설정 -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
		<property name="driverClassName" value="${database.driverClassName}" />
		<property name="url" value="${database.url}" />
		<property name="username" value="${database.username}" />
		<property name="password" value="${database.password}" />
	</bean>
	
	<!-- ibatis -->
	<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
     		// sql-amp.config파일과연결
		<property name="configLocation" value="classpath:config/ibatis/sql-map-config.xml" />
		<property name="dataSource" ref="dataSource" /> // 위 데이터소스와 연결
	</bean>	
	
	<!-- 게시판 Service -->
	<bean name="boardService" class="example.service.BoardService">
		<property name="boardDao" ref="boardDao" />
	</bean>

	<!-- 게시판 Dao -->
	<bean name="boardDao" class="example.dao.BoardDao">
		<property name="sqlMapClient" ref="sqlMapClient" />
	</bean>

</beans>

config.spring

dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	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-2.0.xsd"
>
	<!-- JSP View resolver -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>

	<!-- URL 맵핑 컨트롤러 -->
	<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<prop key="/board/list.do">boardListController</prop>
			</props>
		</property>
	</bean>

	<!-- 게시판 목록 Controller -->
	<bean name="boardListController" class="example.controller.BoardListController">
		<property name="boardService" ref="boardService" />
	</bean>

</beans>
profile
꾸준히
post-custom-banner

0개의 댓글