카이옌 2020. 12. 17. 11:16

키워드 : Spring Legacy Project / 애자일 개발과 스크럼

 

 

****

 

 

0. Spring Legacy Project 와 Dynamic Web Project 의 디렉토리 구조 차이

 

 

 


 

1. 스프링MVC 실습

 

gWebBoard.zip
0.02MB

 

 

 

(1) 새 프로젝트 gWebBoard 생성 후 실습 파일 붙여넣기

    ① pom.xml 에서 Java 1.8버전으로, Spring 5.0.8 버전으로 변경

    ② junit 4.12 버전으로 변경

 

(2) 프로젝트명 우클릭 - Properties

    ① Project facets 에서 버전 변경 후 Apply

    ② Server 에서 Tomcat 선택 후 Apply

 

(3) web.xml 에서 서블릿 url-pattern을 * . do 로 변경

 

(4) 불필요한 com.javassem.basic 패키지 삭제

 

(5) servlet-context.xml 에서 2라인을 보면 xmlns에서 mvc만 이름 생략 가능함을 확인할 수 있다. 

    이전 프로젝트에서는 xmlns에서 이름 생략 가능한 태그는 beans 였다. 

    이름 생략 가능한 태그는 단 하나 뿐이므로 보다 많이 사용할 것 같은 태그로 지정하면 된다. 

    

     <context> 태그에서는 스캔할 패키지를 "com.javassem"으로 변경해준다.

 

<!-- 해당 패키지를 스캔하여 지정된 @를 찾아서 실행 -->
<context:component-scan base-package="com.javassem" />

 

 

(6) <resources> 태그에서 location 속성값에 해당하는 경로에만 클라이언트가 접근할 수 있다. 

    이 경로에는 이후 css, js, jquery, image, files 가 오게 된다. 

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<!-- 클라이언트가 접근할 수 있는 부분 : css, js, jquery, image, files -->
<resources mapping="/resources/**" location="/resources/" />

 

(7) mybatis-config.xml 에서 com.javassem.domain 패키지의 BoardVO 클래스에

    별칭으로 board를 주었음을 확인할 수 있다. 

<!-- Alias 설정 -->
<typeAliases>
    <typeAlias alias="board" type="com.javassem.domain.BoardVO" />		
</typeAliases>

 

(8) rootContext.xml 에서 localhost 변경

<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
    <property name="url" value="jdbc:oracle:thin:@192.168.0.17:1521:orcl"></property>
    <property name="username" value="scott"></property>
    <property name="password" value="tiger"></property>
</bean> 

 

(9) index.jsp 에서 작성된 getBoardList.do 요청을 받기 위해

    com.javassem.controller 패키지의 BoardController.java 가 컨트롤러 역할을 하고

    해당 요청을 받도록 애노테이션을 붙인다.  

@Controller
public class BoardController {
	
    @RequestMapping("getBoardList.do")
    public void getBoardList() {

    }
}

 

(10) getBoardList( ) 메소드에서 boardService클래스의 getBoardList( ) 메소드를 수행하도록 작성한다. 

      이 메소드는 BoardVO 타입을 인자로 받는다. 

@Autowired
private BoardService boardService;
	
@RequestMapping("getBoardList.do")
public void getBoardList(BoardVO vo) {
    // BoardVO vo 현재는 필요 업음
    boardService.getBoardList(vo);
}

 

(11) getBoardList( ) 메소드 수행 결과를 List로 받은 뒤 HashMap에 담고 리턴해준다. 

@RequestMapping("getBoardList.do")
public Map getBoardList(BoardVO vo) {
    List<BoardVO> list = boardService.getBoardList(vo);
    Map map = new HashMap();
    map.put("boardList", list);
    return map;
}

 

(12) getBoardList.jsp 에서 아래 태그는 컨트롤러에서 넘겨준 데이터를 가리킨다. 

<c:forEach items="${boardList }" var="board">
    <tr>
        <td>${board.seq }</td>
        <td align="left"><a href="getBoard.do?seq=${board.seq }">
            ${board.title }</a></td>
        <td>${board.writer }</td>
        <td><fmt:formatDate value="${board.regDate }" pattern="yyyy-MM-dd"/></td>
        <td>${board.cnt }</td>
    </tr>
</c:forEach>

 

(13) 서비스 역할을 할 BoardServiceImpl.java 에 boardService 라는 이름으로 빈을 생성하여

      컨트롤러에서 찾아올 수 있도록 애노테이션을 붙인다. 

@Service("boardService")
public class BoardServiceImpl implements BoardService {

 

(14) 클래스 내의 BoardDAOImpl 에 대해서도 스프링 컨테이너에서 객체를 찾아서 연결해주도록 애노테이션을 붙인다. 

@Service("boardService")
public class BoardServiceImpl implements BoardService {

    @Autowired
    private BoardDAOImpl boardDAO;

 

(15) 서비스에서 수행하는 getBoardList( ) 메소드는 BoardDAOImpl 의 getBoardList( ) 메소드를 호출한다. 

public List<BoardVO> getBoardList(BoardVO vo) {
    return boardDAO.getBoardList(vo);
}

 

(16) BoardDAOImpl.java 에서 Repository 역할을 하도록 애노테이션을 붙인다. 

@Repository("boardDAO")
public class BoardDAOImpl implements BoardDAO{

 

(17) 클래스 안의 SqlSessionTemplate 이 DB와 연결해주는 커넥션 역할을 한다. 

      해당 클래스의 객체를 스프링 컨테이너에서 연결해주도록 애노테이션을 붙인다. 

@Autowired
private SqlSessionTemplate mybatis;

 

( 실행결과 )

 

 

 

 

(18) 글 제목을 클릭했을 때 게시글을 확인하기 위해서는

      getBoard.do 요청이 수행되어야 하며 파라미터로 글 번호를 가져간다. 

<td align="left"><a href="getBoard.do?seq=${board.seq }">${board.title}</a></td>

 

(19) BoardController 에서 getBoard.do 요청을 받는 메소드를 작성하고

      글번호 데이터를 파라미터로부터 받을 수 있도록 BoardVO를 인자로 지정한다. 

@RequestMapping("getBoard.do")
public void getBoard(BoardVO vo) {
		
}

 

(20) BoardService로부터 vo를 받아와서 변수 result에 담는다.

      데이터를 뷰로 넘기기 위해 ModelAndView 방식을 채택했으므로

      setViewName( ) 함수로 다음 페이지를 getBoard.jsp로 지정하고,

      addObject( ) 함수로 변수에 담긴 데이터를 넘겨주는 스크립트를 작성한다. 

      mv를 리턴해야 하므로, 리턴형을 void에서 ModelAndView로 수정한다. 

@RequestMapping("getBoard.do")
public MpdelAndView getBoard(BoardVO vo) {
    BoardVO result = boardService.getBoard(vo);
    ModelAndView mv = new ModelAndView();
    mv.setViewName("getBoard");
    mv.addObject("", result);
    return mv;
}

 

(21) getBoard.jsp 를 확인하면 board라는 이름으로 데이터를 전달받고 있음을 확인할 수 있으므로, 

      mv에 추가되는 오브젝트명을 board로 작성해준다. 

<input name="seq" type="hidden" value="${board.seq}" />

 

@RequestMapping("getBoard.do")
public void getBoard(BoardVO vo) {
    BoardVO result = boardService.getBoard(vo);
    ModelAndView mv = new ModelAndView();
    mv.setViewName("getBoard");
    mv.addObject("board", result);
}

 

( 실행결과 )

 

 

 

(22) 새 글 작성을 클릭했을 때 글 작성 페이지로 이동하기 위해 insertBoard.do 요청을 수행하도록 

<a href="insertBoard.do">글등록</a>

 

(23) 컨트롤러에서 

@RequestMapping("insertBoard.do")
public void insertBoard() {
		
}

 

(24) insertBoard.jsp 에서 새 글 등록 버튼을 클릭했을 때 글이 등록되려면

     saveBoard.do 요청이 수행되어야 함을 확인할 수 있다. 

<form action="saveBoard.do" method="post"> 

 

(25) <form>의 요소들에 name 속성이 없으면 데이터가 전송되지 않으므로 VO와 동일한 이름을 부여해준다. 

<input type="text" name='title' />
<input type="text" size="10" name='writer' />
<textarea cols="40" rows="10" name='content' >

 

(26) 컨트롤러에서 saveBoard.do 요청을 수행할 수 있도록 save( ) 메소드를 작성하는데 

      이 때, name과 BoardVO의 변수명을 동일하게 부여했으므로,

      인자에 BoardVO를 기술하면 정보를 알아서 가져온다. 

      받아온 데이터 vo로 DB에 입력하려면

      BoardService 의 insertBoard( ) 메소드를 수행하는 스크립트를 작성한다. 

@RequestMapping("saveBoard.do")
public void save(BoardVO vo) {
    boardService.insertBoard(vo);
}	

 

( 실행결과 )

 

 

 

(27) 글 저장은 되었으나 목록 보기 페이지로 자동 전환이 되지 않기 때문에

      글 저장시 리다이렉트가 함께 수행되도록 save( ) 메소드를 수정한다. 

@RequestMapping("saveBoard.do")
public String save(BoardVO vo) {
    boardService.insertBoard(vo);
    return "redirect:/getBoardList.do";
}	

 

( 실행결과 )

    : 글 작성 후 정상적으로 저장되고, 목록으로 페이지 자동 전환됨

 

 

 

 

(28) 글 상세 페이지 getBoard.jsp 에서 글 수정 버튼을 클릭했을 때 수행될 요청을 확인한다. 

<form action="updateBoard.do" method="post">

 

(29) 컨트롤러에서 요청을 수행할 함수를 작성한다. 

@RequestMapping("updateBoard.do")
public void update() {
		
}

 

(30) 글 수정 페이지에 기존 글 내용을 가져와서 화면에 표시하도록 메소드의 인자로 받아와야 한다. 

      작성한 내용은 updateBoard( ) 메소드로 DB까지 전달되고, 

      완료 후 글 상세 페이지로 자동 전환되도록 리다이렉트 시켜주되, 글 번호를 가져가도록 작성한다. 

@RequestMapping("updateBoard.do")
public String update(BoardVO vo) {
    boardService.updateBoard(vo);
    return "redirect:getBoard.do?seq=" + vo.getSeq() + "";
}

 

( 실행결과 )

   : 작성한 글 변경 후 "글 수정" 버튼 클릭시 DB에 반영된다.

    수정된 글을 바로 보기 때문에 사용자 입장에서는 페이지 전환이 눈에 보이진 않는다. 

 

 

(31) 삭제 버튼을 클릭했을 때 해당 글이 DB에서도 지워지고 목록보기로 페이지 전환되도록

      컨트롤러에서 스크립트를 작성한다. 

@RequestMapping("deleteBoard.do")
public String delete(BoardVO vo) {
    boardService.deleteBoard(vo);
    return "redirect:getBoardList.do";
}

 

( 실행결과 )

 

 

 

(32) 요청을 수행할 때마다 내용이 비어있는 함수를 매번 작성해야 하는 번거로움을 줄이려면,

      다음과 같은 함수를 한 번 작성하고 나면 비슷한 코드 작성을 하지 않아도 알아서

      변수명에 해당되는 페이지로 뷰 페이지를 지정한다. 

//  @RequestMapping("insertBoard.do")
//  public void insert() {
//
//  }		
	
    @RequestMapping("{step}.do")
    public String insert(@PathVariable String step) {
        return step;
    }

 

 

< pom.xml 전체 소스 코드 >

더보기
<?xml version="1.0" encoding="UTF-8"?>
<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.javassem</groupId>
   <artifactId>basic</artifactId>
   <name>gWebMybatis</name>
   <packaging>war</packaging>
   <version>1.0.0-BUILD-SNAPSHOT</version>
   <properties>
      <!-- ### 버전 변경 ### -->
      <java-version>1.8</java-version>
      <org.springframework-version>5.0.8.RELEASE</org.springframework-version>
      <org.aspectj-version>1.6.10</org.aspectj-version>
      <org.slf4j-version>1.6.6</org.slf4j-version>
   </properties>
   <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>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version>${org.springframework-version}</version>
      </dependency>
            
      <!-- AspectJ -->
      <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjrt</artifactId>
         <version>${org.aspectj-version}</version>
      </dependency>   
      
      <!-- Logging -->
      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
         <version>${org.slf4j-version}</version>
      </dependency>
      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>jcl-over-slf4j</artifactId>
         <version>${org.slf4j-version}</version>
         <scope>runtime</scope>
      </dependency>
      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-log4j12</artifactId>
         <version>${org.slf4j-version}</version>
         <scope>runtime</scope>
      </dependency>
      <dependency>
         <groupId>log4j</groupId>
         <artifactId>log4j</artifactId>
         <version>1.2.15</version>
         <exclusions>
            <exclusion>
               <groupId>javax.mail</groupId>
               <artifactId>mail</artifactId>
            </exclusion>
            <exclusion>
               <groupId>javax.jms</groupId>
               <artifactId>jms</artifactId>
            </exclusion>
            <exclusion>
               <groupId>com.sun.jdmk</groupId>
               <artifactId>jmxtools</artifactId>
            </exclusion>
            <exclusion>
               <groupId>com.sun.jmx</groupId>
               <artifactId>jmxri</artifactId>
            </exclusion>
         </exclusions>
         <scope>runtime</scope>
      </dependency>

      <!-- @Inject -->
      <dependency>
         <groupId>javax.inject</groupId>
         <artifactId>javax.inject</artifactId>
         <version>1</version>
      </dependency>
            
      <!-- Servlet -->
      <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>servlet-api</artifactId>
         <version>2.5</version>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>javax.servlet.jsp</groupId>
         <artifactId>jsp-api</artifactId>
         <version>2.1</version>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>jstl</artifactId>
         <version>1.2</version>
      </dependency>
   
      <!-- ### Test 버전 변경 ###-->
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.12</version>
         <scope>test</scope>
      </dependency> 
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-test</artifactId>
         <version>${org.springframework-version}</version>
      </dependency>
      
            
      
      <!-- 마이바티스 추가  -->
      <!-- mybatis -->
      <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>3.4.6</version>
      </dependency>
      
      <!-- mybatis-spring -->
      <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis-spring</artifactId>
          <version>1.3.2</version>
      </dependency>
      
        <!--  SPRING JDBC 필요 --> 
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>${org.springframework-version}</version>
      </dependency>   
      
      <!-- 트랜잭션 필요 -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
          <version>${org.springframework-version}</version>
      </dependency>
                
   </dependencies>
   
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
               <!-- ### 버전 변경 ### -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

<web.xml 전체 소스 코드 >

더보기
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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 https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<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>*.do</url-pattern>
	</servlet-mapping>
	
	<!-- 한글 인코딩 -->
<filter>
    <filter-name>characterEncoding</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>
<filter-mapping>
    <filter-name>characterEncoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

</web-app>

< servlet-context.xml 전체 소스 코드 >

더보기
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<!-- 클라이언트가 접근할 수 있는 부분 : css, js, jquery, image, files -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<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>
	
	<!-- 해당 패키지를 스캔하여 지정된 @를 찾아서 실행 -->
	<context:component-scan base-package="com.javassem" />
	
	
	
</beans:beans>

< mybatis-config.xml 전체 소스 코드 >

더보기
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

	<!-- Alias 설정 -->
	<typeAliases>
		<typeAlias alias="board" type="com.javassem.domain.BoardVO" />		
	</typeAliases>


</configuration>

< root-context.xml 전체 소스 코드 >

더보기
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
   xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
   
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
   <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
   <property name="url" value="jdbc:oracle:thin:@192.168.0.17:1521:orcl"></property>
   <property name="username" value="scott"></property>
   <property name="password" value="tiger"></property>
</bean>   
   
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
  <property name="configLocation" value="classpath:/mybatis-config.xml"></property>
  <property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"></property>
 </bean>
 
 <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
   <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
 </bean>
 

          
</beans>

< BoardMapper.xml 전체 소스 코드 >

더보기
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="BoardDAO">

	
	<insert id="insertBoard" parameterType="board">
		<![CDATA[
		INSERT INTO BOARD(SEQ, TITLE, WRITER, CONTENT, REGDATE, CNT)
		VALUES(board_seq.nextval,
			#{title}, #{writer}, #{content}, 
			sysdate, 0)
		]]>
	</insert>
	
	<update id="updateBoard" parameterType="board">
		<![CDATA[
		UPDATE BOARD SET
		TITLE = #{title},
		CONTENT = #{content}
		WHERE SEQ = #{seq}
		]]>
	</update>
	
	<delete id="deleteBoard" parameterType="board">
		<![CDATA[
		DELETE BOARD
		WHERE SEQ = #{seq}
		]]>
	</delete>
	
	<select id="getBoard" parameterType="board" resultType="board">
		<![CDATA[
		SELECT *
		FROM BOARD
		WHERE SEQ = #{seq}
		]]>
	</select>
	
	<select id="getBoardList" resultType="board">
		<![CDATA[
		SELECT *
		FROM BOARD
		ORDER BY SEQ DESC
		]]>
	</select>
</mapper>

< BoardController.java 전체 소스 코드 >

더보기
package com.javassem.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.javassem.domain.BoardVO;
import com.javassem.service.BoardService;

@Controller
public class BoardController {
	
	@Autowired
	private BoardService boardService;
	
	@RequestMapping("getBoardList.do")
	public Map getBoardList(BoardVO vo) {
		
		// BoardVO vo 현재는 필요 업음
		List<BoardVO> list = boardService.getBoardList(vo);
		Map map = new HashMap();
		map.put("boardList", list);
		return map;
	}
	
	@RequestMapping("getBoard.do")
/*	public ModelAndView getBoard(BoardVO vo) {
		BoardVO result = boardService.getBoard(vo);
		ModelAndView mv = new ModelAndView();
		mv.setViewName("getBoard");
		mv.addObject("board", result);
		return mv;
	} */
	
	public void getBoard(BoardVO vo, Model m) {
		m.addAttribute("board", boardService.getBoard(vo));
	}
	


//	@RequestMapping("insertBoard.do")
//	public void insert() {
//	}		
	
	@RequestMapping("{step}.do")
	public String insert(@PathVariable String step) {
		return step;
	}
	
	
	@RequestMapping("saveBoard.do")
	public String save(BoardVO vo) {
		boardService.insertBoard(vo);
		return "redirect:/getBoardList.do";
	}
	
	@RequestMapping("updateBoard.do")
	public String update(BoardVO vo) {
		boardService.updateBoard(vo);
		return "redirect:getBoard.do?seq=" + vo.getSeq();
	}
	
	@RequestMapping("deleteBoard.do")
	public String delete(BoardVO vo) {
		boardService.deleteBoard(vo);
		return "redirect:getBoardList.do";
	}

}

< BoardServiceImpl.java 전체 소스 코드 >

더보기
package com.javassem.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.javassem.dao.BoardDAOImpl;
import com.javassem.domain.BoardVO;


@Service("boardService")
public class BoardServiceImpl implements BoardService {
	
	@Autowired
	private BoardDAOImpl boardDAO;

	public void insertBoard(BoardVO vo) {
		boardDAO.insertBoard(vo);
	}

	public void updateBoard(BoardVO vo) {
		boardDAO.updateBoard(vo);
	}

	public void deleteBoard(BoardVO vo) {
		boardDAO.deleteBoard(vo);
	}

	public BoardVO getBoard(BoardVO vo) {
		return boardDAO.getBoard(vo);
	}

	public List<BoardVO> getBoardList(BoardVO vo) {
		return boardDAO.getBoardList(vo);
	}
}

< BoardDAOImpl.java 전체 소스 코드 >

더보기
package com.javassem.dao;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.javassem.domain.BoardVO;

@Repository("boardDAO")
public class BoardDAOImpl implements BoardDAO{

	@Autowired
	private SqlSessionTemplate mybatis;

	public void insertBoard(BoardVO vo) {
		System.out.println("===> Mybatis insertBoard() 호출");
		mybatis.insert("BoardDAO.insertBoard", vo);
	}

	public void updateBoard(BoardVO vo) {
		System.out.println("===> Mybatis updateBoard() 호출");
		mybatis.update("BoardDAO.updateBoard", vo);
	}

	public void deleteBoard(BoardVO vo) {
		System.out.println("===> Mybatis deleteBoard() 호출");
		mybatis.delete("BoardDAO.deleteBoard", vo);
	}

	public BoardVO getBoard(BoardVO vo) {
		System.out.println("===> Mybatis getBoard() 호출");
		return mybatis.selectOne("BoardDAO.getBoard", vo);
	}

	public List<BoardVO> getBoardList(BoardVO vo) {
		System.out.println("===> Mybatis getBoardList() 호출");
		return mybatis.selectList("BoardDAO.getBoardList", vo);
	}
}

<BoardVO.java 전체 소스 코드 >

더보기
package com.javassem.domain;

import java.util.Date;

//VO(Value Object)

public class BoardVO {

	private int seq;
	private String title;
	private String writer;
	private String content;
	private Date regDate;
	private int cnt;


	public int getSeq() {
		return seq;
	}

	public void setSeq(int seq) {
		this.seq = seq;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getWriter() {
		return writer;
	}

	public void setWriter(String writer) {
		this.writer = writer;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public Date getRegDate() {
		return regDate;
	}

	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}

	public int getCnt() {
		return cnt;
	}

	public void setCnt(int cnt) {
		this.cnt = cnt;
	}

}

< index.jsp 전체 소스 코드 >

더보기
<%@page contentType="text/html; charset=EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Main Page</title>
</head>
<body>

		<h1>게시판 프로그램</h1>
		<hr>
		<br> <a href="getBoardList.do">글 목록 바로가기</a>
		<hr>
		<br>

</body>
</html>

< getBoardList.jsp 전체 소스 코드 >

더보기
<%@ page contentType="text/html; charset=EUC-KR"%>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>글 목록</title>
</head>
<body>
		<h1>게시글 목록</h1>

		
	<table border="1">
			<tr>
				<th bgcolor="orange" width="100">번호</th>
				<th bgcolor="orange" width="200">제목</th>
				<th bgcolor="orange" width="150">작성자</th>
				<th bgcolor="orange" width="150">등록일</th>
				<th bgcolor="orange" width="100">조회수</th>
			</tr>
			<!-- boardList : 컨트롤러에서 넘겨준 데이터 -->
			<c:forEach items="${boardList }" var="board">
				<tr>
					<td>${board.seq }</td>
					<td align="left"><a href="getBoard.do?seq=${board.seq }">
							${board.title }</a></td>
					<td>${board.writer }</td>
					<td><fmt:formatDate value="${board.regDate }" pattern="yyyy-MM-dd"/></td>
					<td>${board.cnt }</td>
				</tr>
			</c:forEach>
		</table>
		<br> <a href="insertBoard.do">새글 등록</a>
</body>
</html>

< getBoard.jsp 전체 소스 코드 >

더보기
<%@page contentType="text/html; charset=UTF-8"%>

<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>글 상세</title>
</head>
<body>
		<h1>글 상세</h1>		
		<hr>
		<form action="updateBoard.do" method="post">
			<input name="seq" type="hidden" value="${board.seq}" />
			<table border="1" cellpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange" width="70">제목</td>
					<td align="left"><input name="title" type="text"
						value="${board.title }" /></td>
				</tr>
				<tr>
					<td bgcolor="orange">작성자</td>
					<td align="left">${board.writer }</td>
				</tr>
				<tr>
					<td bgcolor="orange">내용</td>
					<td align="left"><textarea name="content" cols="40" rows="10">
						${board.content }</textarea></td>
				</tr>
				<tr>
					<td bgcolor="orange">등록일</td>
					<td align="left">${board.regDate }</td>
				</tr>
				<tr>
					<td bgcolor="orange">조회수</td>
					<td align="left">${board.cnt }</td>
				</tr>
				<tr>
					<td colspan="2" align="center"><input type="submit"
						value="글 수정" /></td>
				</tr>
			</table>
		</form>
		<hr>
		<a href="insertBoard.do">글등록</a>&nbsp;&nbsp;&nbsp; 
		<a href="deleteBoard.do?seq=${board.seq }">글삭제</a>&nbsp;&nbsp;&nbsp;
		<a href="getBoardList.do">글목록</a>
</body>
</html>

< insertBoard.jsp 전체 소스 코드 >

더보기
<%@page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>새글등록</title>
</head>
<body>
		<h1>글 등록</h1>		
		<hr>
		<form action="saveBoard.do" method="post"> <!--  enctype="multipart/form-data" -->
			<table border="1" cellpadding="0" cellspacing="0">
				<tr>
					<td bgcolor="orange" width="70">제목</td>
					<td align="left"><input type="text" name='title' /></td>
				</tr>
				<tr>
					<td bgcolor="orange">작성자</td>
					<td align="left"><input type="text" size="10" name='writer' /></td>
				</tr>
				<tr>
					<td bgcolor="orange">내용</td>
					<td align="left"><textarea cols="40" rows="10" name='content' ></textarea></td>
				</tr>
				<tr>
					<td colspan="2" align="center"><input type="submit"	value=" 새글 등록 " /></td>
				</tr>
			</table>
		</form>
		<hr>
		<a href="getBoardList.do">글 목록 가기</a>
</body>
</html>

 

 


 

2. Spring Legacy Project 실습 (2)

 

gWebBoard1.zip
0.02MB

 

 

 

(1) 실습파일 gWebBoard1.zip 다운로드한다.

 

(2) hWebBoard라는 이름의 Spring Legacy Project 생성시 com.javaclass.basic 이라 입력했다면,

    자동으로 생성된 com.javaclass.basic 패키지를 삭제한다.

    (JavaEE 모드에서는 src/main/java 안의 폴더 및 views 안의 home.jsp를 삭제한다.)

 

(3) root-context.xml 에서 DB 연결 정보를 수정한다. 

<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
    <property name="url" value="jdbc:oracle:thin:@192.168.0.17:1521:orcl"></property>
    <property name="username" value="scott"></property>
    <property name="password" value="tiger"></property>
</bean>	

 

(4) 데이터베이스.txt 참고하여 DB를 생성한다. 

create table upLoadtemp(
    b_id number(5) primary key,     -- 글번호 
    b_name varchar2(20),            -- 글쓴이 
    b_email varchar2(50),           -- 글쓴이 메일 주소 
    b_title varchar2(80),           -- 글 제목 
    b_content varchar2(3000),       -- 글 내용 
    b_pwd varchar2(12),             -- 비밀번호 
    b_date date,                    -- 글쓴날짜 
    b_count number(5) default 0,    -- 조회횟수 
    b_ip varchar2(15),              -- 글쓴이 아이피주소 
    b_fname varchar2(100),          -- 파일이름
    b_fsize number                  -- 파일용량
);

create sequence uploadtemp_bid_seq ;

 

(5) insertBoard.jsp 에서 <form>에 name이 없으므로 VO를 참고하여 작성한다. 

    단, file의 name은 file로 작성해야 한다. 

<form action="saveBoard.do">
....
<input type="text" name='b_title'/>
<input type="text" size="10" name='b_name'/>
<textarea cols="40" rows="10" name='b_content'>
<input type="text" name='b_email'/>
<input type="text" name='b_pwd'/>
<input type="hidden" name='b_ip' value="<%=request.getRemoteAddr()%>"> 
<input type="file" name='file' maxlength="60" size="40">

 

(6) 파일업로드.txt 참고하여 pom.xml에 파일업로드를 위한 <dependency> 태그를 작성한다. 

<!-- 파일업로드 -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3</version>
</dependency>

 

(7) 파일업로드.txt 참고하여 servlet-context.xml 에 <beans> 태그 작성한다.

<!-- 파일업로드 하려면 MultipartResolver를 등록해야 함 -->
<beans:bean id="multipartResolver"  
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

 

(8) 파일업로드.txt 참고하여 insertBoard.jsp 에 <form>태그에서 전송방식을 post로 작성해야 데이터가 전송될 수 있다. 

<form action="saveBoard.do" method='post' enctype="multipart/form-data"> 

 

(9) 파일업로드.txt 참고하여 BoardVO.java를 수정 (File 경로 수정)

MultipartFile file;	// write.jsp에 파일첨부시 name="file"과 동일한 변수명
	
    public MultipartFile getFile() {
        return file;
    }
    public void setFile(MultipartFile file) {
        this.file = file;
		
        // 업로드 파일 접근
        if(! file.isEmpty()){
            this.b_fname = file.getOriginalFilename();
            this.b_fsize = file.getSize();
			
            //***********************************************
            // 해당 경로로 변경 (실제 경로임)
            File f = new File("C:\\java\\webwork\\Spring\\Junior\\hWebBoard\\src\\main\\webapp\\resources\\upload\\"+b_fname);
			
            try {
                file.transferTo(f);
            } catch (IllegalStateException e) {				
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

 

(10) webapp/resources 폴더 아래에 업로드한 파일이 저장될 upload 폴더 생성 

 

(11) BoardMapper.xml 에서 insertBoard가 호출되었을 때 수행할 SQL문을 작성한다. 

<insert id="insertBoard" parameterType="board">
    INSERT INTO upLoadTemp (
        b_id, b_name, b_email, b_title, b_content, 
        b_pwd, b_date, b_count, b_ip, b_fname, b_fsize
    ) VALUES (
        uploadtemp_bid_seq.NEXTVAL, #{b_name}, #{b_email}, 
        #{b_title}, #{b_content}, #{b_pwd}, sysdate, 0, 
        #{b_ip}, #{b_fname}, #{b_fsize} 
    )
</insert>

 

(12) 글 작성시 유효성 검사는 jQuery를 사용한다. 

 

(13) 파일을 등록하지 않더라도 글 작성이 가능하려면 파일 등록에 관한 SQL 부분이 조건문에 들어가야 한다. 

<insert id="insertBoard" parameterType="board">
    INSERT INTO upLoadTemp (
        b_id, b_name, b_email, b_title, b_content, 
        b_pwd, b_date, b_count, b_ip
        <if test="b_fname !=null">
        , 
        b_fname, b_fsize
        </if>
    ) VALUES (
        uploadtemp_bid_seq.NEXTVAL, #{b_name}, #{b_email}, 
        #{b_title}, #{b_content}, #{b_pwd}, sysdate, 0, 
        #{b_ip}
        <if test="b_fname !=null">
        , 
        #{b_fname}, #{b_fsize} 
        </if>
    )
</insert>

 

(14) upload 파일에 저장된 이미지 파일을 글 상세보기 페이지에서 확인할 수 있다. 

 

 

 

 

< root-context.xml 전체 소스 코드 >

더보기
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
    xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
	
<!-- Root Context: defines shared resources visible to all other web components -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
    <property name="url" value="jdbc:oracle:thin:@192.168.0.17:1521:orcl"></property>
    <property name="username" value="scott"></property>
    <property name="password" value="tiger"></property>
</bean>	
	
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:/mybatis-config.xml"></property>
    <property name="mapperLocations" value="classpath:mappers/**/*Mapper.xml"></property>
</bean>
 
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
 
<!--  <context:component-scan base-package="org.javassem"></context:component-scan> -->
    		
</beans>


< insertBoard.jsp 전체 소스 코드 >

더보기
<%@page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>새글등록</title>
</head>
<body>
    <h1>글 등록</h1>		
    <hr>
    <!-- 1. 폼태그에 속성 추가  -->
    <form action="saveBoard.do" method='post' enctype="multipart/form-data"> 
        <table border="1" cellpadding="0" cellspacing="0">
            <!-- 2. 각 항목에  name 맞추기 -->
            <tr>
                <td bgcolor="orange" width="70">제목</td>
                <td align="left"><input type="text" name='b_title'/></td>
            </tr>
            <tr>
                <td bgcolor="orange">작성자</td>
                <td align="left"><input type="text" size="10" name='b_name'/></td>
            </tr>
            <tr>
                <td bgcolor="orange">내용</td>
                <td align="left"><textarea cols="40" rows="10" name='b_content'></textarea></td>
            </tr>
            <!-- 추가항목 시작 -->
            <tr>
                <td bgcolor="orange">이메일</td>
                <td align="left"><input type="text" name='b_email'/></td>
            </tr>
            <tr>
                <td bgcolor="orange">비밀번호</td>
                <td align="left"><input type="text" name='b_pwd'/>
                <input type="hidden" name='b_ip' value="<%=request.getRemoteAddr()%>"></td>
            </tr>
            <tr>
                <td bgcolor="orange" width="70">파일추가</td><td align="left">
                <input type="file" name='file' maxlength="60" size="40"></td>
            </tr>
            <!-- 추가항목 끝 -->
            <tr>
                <td colspan="2" align="center"><input type="submit"	value=" 새글 등록 " /></td>
            </tr>
        </table>
    </form>
    <hr>
    <a href="getBoardList.do">글 목록 가기</a>
</body>
</html>

< BoardMapper.mxl 전체 소스 코드 >

더보기
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="BoardDAO">

    <insert id="insertBoard" parameterType="board">
        INSERT INTO upLoadTemp (
            b_id, b_name, b_email, b_title, b_content, 
            b_pwd, b_date, b_count, b_ip
            <if test="b_fname !=null">
            , 
            b_fname, b_fsize
            </if>
        ) VALUES (
            uploadtemp_bid_seq.NEXTVAL, #{b_name}, #{b_email}, 
            #{b_title}, #{b_content}, #{b_pwd}, sysdate, 0, 
            #{b_ip}
            <if test="b_fname !=null">
            , 
            #{b_fname}, #{b_fsize} 
            </if>
        )
    </insert>

    <select id="getBoardList" resultType="board">
    <![CDATA[
        SELECT * FROM uploadtemp ORDER BY b_id DESC
    ]]>
    </select>
	
    <update id="updateBoard"  parameterType="board">
    <![CDATA[
        UPDATE uploadtemp SET
        b_title = #{b_title},
        b_content = #{b_content}
        WHERE b_id = #{b_id}
    ]]>
    </update>
	
    <delete id="deleteBoard"  parameterType="board">
    <![CDATA[
        DELETE uploadtemp
        WHERE b_id = #{b_id}
    ]]>
    </delete>
	
    <select id="getBoard"  parameterType="board" resultType="board">
    <![CDATA[
        SELECT *
        FROM uploadtemp
        WHERE b_id = #{b_id}
    ]]>
    </select>
    
</mapper>

< BoardVO.java 전체 소스 코드 >

더보기
package com.javassem.domain;

import java.io.File;
import java.io.IOException;

import org.springframework.web.multipart.MultipartFile;

public class BoardVO {
    private int b_id;
    private String b_name;
    private String b_email;
    private String b_title;
    private String b_content;
    private String b_pwd;
    private String b_date;	
    private int b_count;
    private String b_ip;
    private String b_fname;
    private long b_fsize;
	
    //*************************************************
    MultipartFile file;	// write.jsp에 파일첨부시 name="file"과 동일한 변수명
	
    public MultipartFile getFile() {
        return file;
    }
    public void setFile(MultipartFile file) {
        this.file = file;
		
        // 업로드 파일 접근
        if(! file.isEmpty()){
            this.b_fname = file.getOriginalFilename();
            this.b_fsize = file.getSize();
			
            //***********************************************
            // 해당 경로로 변경 (실제 경로임)
            File f = new File("C:\\java\\webwork\\Spring\\Junior\\hWebBoard\\src\\main\\webapp\\resources\\upload\\"+b_fname);
			
            try {
                file.transferTo(f);
            } catch (IllegalStateException e) {				
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
	
    public int getB_id() {
        return b_id;
    }
    public void setB_id(int b_id) {
        this.b_id = b_id;
    }
    public String getB_name() {
        return b_name;
    }
    public void setB_name(String b_name) {
        this.b_name = b_name;
    }
    public String getB_email() {
        return b_email;
    }
    public void setB_email(String b_email) {
        this.b_email = b_email;
    }
    public String getB_title() {
        return b_title;
    }
    public void setB_title(String b_title) {
        this.b_title = b_title;
    }
    public String getB_content() {
        return b_content;
    }
    public void setB_content(String b_content) {
        this.b_content = b_content;
    }
    public String getB_pwd() {
        return b_pwd;
    }
    public void setB_pwd(String b_pwd) {
        this.b_pwd = b_pwd;
    }
    public String getB_date() {
        return b_date;
    }
    public void setB_date(String b_date) {
        this.b_date = b_date;
    }
    public int getB_count() {
        return b_count;
    }
    public void setB_count(int b_count) {
        this.b_count = b_count;
    }
    public String getB_ip() {
        return b_ip;
    }
    public void setB_ip(String b_ip) {
        this.b_ip = b_ip;
    }
    public String getB_fname() {
        return b_fname;
    }
    public void setB_fname(String b_fname) {
        this.b_fname = b_fname;
    }
    public long getB_fsize() {
        return b_fsize;
    }
    public void setB_fsize(long b_fsize) {
        this.b_fsize = b_fsize;
    }

}

< pom.xml 전체 소스 코드 >

더보기
<?xml version="1.0" encoding="UTF-8"?>
<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.javassem</groupId>
    <artifactId>basic</artifactId>
    <name>gWebMybatis</name>
    <packaging>war</packaging>
    <version>1.0.0-BUILD-SNAPSHOT</version>
    <properties>
        <!-- ### 버전 변경 ### -->
        <java-version>1.8</java-version>
        <org.springframework-version>5.0.8.RELEASE</org.springframework-version>
        <org.aspectj-version>1.6.10</org.aspectj-version>
        <org.slf4j-version>1.6.6</org.slf4j-version>
    </properties>
    <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>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
				
        <!-- AspectJ -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${org.aspectj-version}</version>
        </dependency>	
		
        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.mail</groupId>
                    <artifactId>mail</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>

        <!-- @Inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
				
        <!-- Servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
	
        <!-- ### Test 버전 변경 ###-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency> 
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
		
        <!-- 마이바티스 추가  -->
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
		
        <!-- mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
		
        <!--  SPRING JDBC 필요 --> 
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>	
		
        <!-- 트랜잭션 필요 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
		
        <!-- ################################################# -->
        <!-- 파일업로드 -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3</version>
        </dependency>


    </dependencies>
	
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <!-- ### 버전 변경 ### -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

< servlet-context.xml 전체 소스 코드 >

더보기
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <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>
	
    <context:component-scan base-package="com.javassem" />
	
    <!-- ##################################################### -->
    <!-- 파일업로드 하려면 MultipartResolver를 등록해야 함 -->
	
    <beans:bean id="multipartResolver"  
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

</beans:beans>

<BoardControll.java 전체 소스 코드 >

더보기
package com.javassem.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.javassem.domain.BoardVO;
import com.javassem.service.BoardService;

@Controller
public class BoardController {
	
    @Autowired
    private BoardService boardService;

        //
        @RequestMapping("/{step}.do")
        public String viewPage(@PathVariable String step) {
            return step;
        }
	
        // 글 목록 검색
        @RequestMapping("/getBoardList.do")
        public void getBoardList(BoardVO vo, Model model) {
			
            model.addAttribute("boardList", boardService.getBoardList(vo));
            // ViewResolver를 지정하지 않으면 아래처럼 페이지명 지정
            // return "views/getBoardList.jsp"; // View 이름 리턴
        }
	
        // 글 등록
        @RequestMapping(value = "/saveBoard.do")
        public String insertBoard(BoardVO vo) throws IOException {
            boardService.insertBoard(vo);
            return "redirect:/getBoardList.do";
        }

        // 글 수정
        @RequestMapping("/updateBoard.do")
        public String updateBoard(@ModelAttribute("board") BoardVO vo) {
            boardService.updateBoard(vo);
            return "redirect:/getBoardList.do";
        }

        // 글 삭제
        @RequestMapping("/deleteBoard.do")
        public String deleteBoard(BoardVO vo) {
            boardService.deleteBoard(vo);
            return "redirect:/getBoardList.do";
        }

        // 글 상세 조회
        @RequestMapping("/getBoard.do")
        public void getBoard(BoardVO vo, Model model) {
            model.addAttribute("board", boardService.getBoard(vo)); // Model 정보 저장			
        }

}

< BoardServiceImpl.java 전체 소스 코드 >

더보기
package com.javassem.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.javassem.dao.BoardDAOImpl;
import com.javassem.domain.BoardVO;


@Service("boardService")
public class BoardServiceImpl implements BoardService {

    @Autowired
    private BoardDAOImpl boardDAO;

    public void insertBoard(BoardVO vo) {
        boardDAO.insertBoard(vo);
    }

    public void updateBoard(BoardVO vo) {
        boardDAO.updateBoard(vo);
    }

    public void deleteBoard(BoardVO vo) {
        boardDAO.deleteBoard(vo);
    }

    public BoardVO getBoard(BoardVO vo) {
        return boardDAO.getBoard(vo);
    }

    public List<BoardVO> getBoardList(BoardVO vo) {
        return boardDAO.getBoardList(vo);
    }
}

< BoardDAOImplljava 전체 소스 코드 >

더보기
package com.javassem.dao;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.javassem.domain.BoardVO;


@Repository("boardDAO") 
public class BoardDAOImpl implements BoardDAO{

    @Autowired
    private SqlSessionTemplate mybatis;

    public void insertBoard(BoardVO vo) {
        System.out.println("===> Mybatis insertBoard() 호출");
        mybatis.insert("BoardDAO.insertBoard", vo);
    }

    public void updateBoard(BoardVO vo) {
        System.out.println("===> Mybatis updateBoard() 호출");
        mybatis.update("BoardDAO.updateBoard", vo);
    }

    public void deleteBoard(BoardVO vo) {
        System.out.println("===> Mybatis deleteBoard() 호출");
        mybatis.delete("BoardDAO.deleteBoard", vo);
    }

    public BoardVO getBoard(BoardVO vo) {
        System.out.println("===> Mybatis getBoard() 호출");
        return (BoardVO) mybatis.selectOne("BoardDAO.getBoard", vo);
    }

    public List<BoardVO> getBoardList(BoardVO vo) {
        System.out.println("===> Mybatis getBoardList() 호출");
        return mybatis.selectList("BoardDAO.getBoardList", vo);
    }
}

< index.jsp 전체 소스 코드 >

더보기
<%@page contentType="text/html; charset=EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Main Page</title>
</head>
<body>

    <h1>게시판 프로그램</h1>
    <hr>
    <br> <a href="getBoardList.do">글 목록 바로가기</a>
    <hr>
    <br>

</body>
</html>

< getBoard.jsp 전체 소스 코드 >

더보기
<%@page contentType="text/html; charset=UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>글 상세</title>
</head>
<body>

    <h1>글 상세</h1>		
    <hr>
    <form action="updateBoard.do" method="post">
        <input name="b_id" type="hidden" value="${board.b_id}" />
        <table border="1" cellpadding="0" cellspacing="0">
            <tr>
                <td bgcolor="orange" width="70">제목</td>
                <td align="left"><input name="b_title" type="text"
                    value="${board.b_title }" /></td>
            </tr>
            <tr>
                <td bgcolor="orange">작성자</td>
                <td align="left">${board.b_name }</td>
            </tr>
            <tr>
                <td bgcolor="orange">내용</td>
                <td align="left"><textarea name="b_content" cols="40" rows="10">${board.b_content }</textarea></td>
            </tr>
            <tr>
                <td bgcolor="orange">등록일</td>
                <td align="left">${board.b_date }</td>
            </tr>
            <tr>
                <td bgcolor="orange">조회수</td>
                <td align="left">${board.b_count }</td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                <input type="submit" value="글 수정" /></td>
            </tr>
        </table>
        
        <img src="resources/upload/icon_01.png"/>
        <img src="/hWebBoard/resources/upload/icon_02.png"/>
        
    </form>
    
    <hr>
    <a href="insertBoard.do">글등록</a>&nbsp;&nbsp;&nbsp; 
    <a href="deleteBoard.do?b_id=${board.b_id }">글삭제</a>&nbsp;&nbsp;&nbsp;
    <a href="getBoardList.do">글목록</a>
</body>
</html>

 


3. 애자일 개발과 스크럼

 

(1) 기본방식과의 비교

   - 애자일과 폭포수 방식은 대립구조는 아니다. 

   - 애자일은 사고방식과 변화를 수용하고자 하는 움직임을 따르고자 한다.

   - 애자일의 궁극적인 목적은 기술 조식, 비지니즈 조직 그리고 고객이

     상호 협력하여 해결책을 같이 고심하자는 것이다. 

 

Waterfall Agile
각 공정 단계 완료 후에는 이전 단계로 되돌아 갈 수 없다.  우선 순위가 높은 기능부터 개발
단계간 커뮤니케이션은 주로 문서로 수행 문서보다는 동작하는 소프트웨어 중심으로 대화
개발을 시작하여  완료될 쯤엔 이미 시장환경이 변화를 따라갈 수 없게 된다.  전체를 한 번에 만들지 않고 일부라도 동작하는 부분을 완성하여 고객에게 보여주고 피드백을 반영하여 발전시켜 나간다. 

 

요구사항 분석 - 무엇을 만들지 이해
설계 - 어떻게 만들지 검토
구현 - 실제 소프트웨어로 작성
테스트 - 만들어진 소프트웨어를 확인

 

(2) 폭포수 방법론

※ 소프트웨어 개발 현장에서 자주 일어나는 현상

1. 프로젝트 초기에 전체 설계를 하다 보니 전체 프로젝트에 대한 예측이 정홖하지 않을 수 있다. 
   - 개발 기간 부족으로 일정이 지연되기도 한다. 
   - 처음에 요구사항이 완성 시점에서 구식이 되기도 한다.
   - 개발 전체의 진척 사항을 정확히 판단하기 어렵다. 
2. 프로젝트의 마지막 단계에서 동작 기능이 완성되어 고객과 사용자는 마지막까지 실제 어떻게 동작되는지 알기 어렵다. 
   - 개발 막바지 단계에서 기능 수정이나 변경사항이 요구되는 경우가 발생한다. 
3. 각각 조직은 서로 문서로 주고 받다 보니 문서 이해에 대한 오해가 발생하기도 한다. 
   - 팀이 커질수록 생산성이 떨어진다.

 

(3) 애자일 프로젝트

※ 프로젝트가 실패하는 이유

   : 각자가 생각하는 프로젝트 성공의 의미가 다르게 해석되는 경우가 많다. 

   : 처음부터 의견이 일치되지 않은 상태에서 프로젝트가 시작된다. 

   : 현명한 선택을 하기 위해서는 다른 팀원들과 소통해야 한다. 

   : 고객과의 지속적인 피드백으로 소통해야 한다. 

 

(4) 용어정리

 - 스크럼 : 애자일 프로젝트를 관리하기 위한 프로젝트 관리 툴

 - XP : 애자일 프로젝트에 필요한 핵심 소프트웨어 엔지니어링 실천법

스크럼 XP
스프린트 이터레이션
제품 백로그 마스터 스토리 리스트
제품 책임자 고객

 

 - 스프린트 (iteration) 

   : 짧은 반복 주기를 계속하는 개발 프로세스

   : 1~4주 간격의 개발 기간

   : 애자일의 Iteration (반복)

   : 스프린트 계획 → 일일스크럼 → 스프린트 리뷰 → 회고

 

- 제품 백로그 (마스터 스토리 리스트)

   : 개발해야 할 제품의 기능 목록

   : 고객이 이해하는 언어로 작성

   : 후에는 '사용자 스토리' 형식으로 작성되는 경우가 많음

 

- 스프린트 백로그

   : 제품 백로그에서 스프린트 중 개발한 기능 목록

   : 이 목록은 한 번의 스프린트에서만 사용

   : 스프린트 계획을 수립할 때 제품 소유자가 결정한 순위와 개발팀이 결정한 공수 정보를 통합하여 논의한 후 만든다. 

 

- 일일스크럼

   : 스탠드업 미팅 (매일 15분 정도)

   : 팀원들은 '어제 한 일', '오늘 할 일', '장애가 되고 있는 일'을 말하고 스크럼 마스터는 그 장애를 제거한다. 

   : 일일스크럼의 상황은 제품 소유자가 공유한다. 

 

- 스프린트 (1~4주)

   : 큰 문제들은 작은 문제들로 세분화하라

   : 가장 중요한 것을 먼저 집중하고, 다른 것들은 잊어버려라

   : 소프트웨어가 제대로 작동하는지 확인하고 또 확인하라

   : 고객의 피드백을 구하라

   : 필요하다면 계획을 바꿔라

 

 

(5) Inception Deck (인셉션 덱)

   : 애자일의 도구 중 하나이다. 

 

※ Inception ?

   : 사전적 의미는 어떤 활동이나 단체를 시작, 설립하는 단계를 가리킴

   : 프로젝트 초기 단계에 고객과 개발팀이 서로 알아가는 과정을 갖는 일정한 기간으르 말한다. 

     (Agile samurai 저서의 Jonathan Rasmusson 저자의 정의)

 

※ [ Why? ] 왜 우리가 이 프로젝트를 하려는지 이해하기 위해 다음과 같은 질문을 한다. 

 (1) 우리는 왜 모였는가? (반드시 고객과 함께)

 (2) 이 프로젝트의 엘리베이터 피치는 무엇인가?

 (3) 우리 제품을 광고한다면 어떻게 표현할까?

 (4) 우리가 하지 말아야 하는 것은 무엇이 있을까?

 (5) 프로젝트 관계자 중 우리가 알아두어야 할 사람은 누구인가?

 

(1) 우리는 왜 모였는가? 
프로젝트의 주인은 고객이다. 고객의 의도가 무엇인지 파악한다. 

예를 들어 건설회사의 광산에 출입허가관리 프롲게트를 한다면, 직접 현장을 체험하고 실제 프로그램을 사용할 직원(고객)을 만나 소통한다. 

항공사 사장의 기내식단으로 의견을 좁히던 중 사장님의 취지는 비행기 요금인하라는 것을 알게 된다면, 메뉴를 추가하는 방식이 문제가 아니라 진짜 프로젝트의 목적을 파악한다. 
(2) 이 프로젝트의 엘리베이터 피치는 무엇인가?
투자자를 엘레베이터에서 만났다면 30초 안에 우리 회사의 아이디어를 어떻게 멋지게 소개하여 사업 구현까지 이루어지게 하는지를 가리킨다. 
즉, 짧은 시간 안에 핵심을 피력하는 것이다. 


[고객이 필요로 하는 사항]을
[목표로 하는 고객]에게
[제품의 카테고리]인
[제품의 이름]은
[제품이 주는 혜택이나 구매해야만 하는 이유]이다.
[경쟁사 제품의 기능과 다르게]
우리 제품은 [우리 제품이 가지는 특별한 점]이다.
(3) 우리 제품을 광고한다면 어떻게 표현할까?
만일 소프트웨어를 슈퍼마켓에서 판다면 소비자에게 어필할 광고를 만들어보자. 
 - 기능보다 혜택이 무엇인지
 - 기억에 남거나 느낌이 좋은 슬로건으로
 - 포장이나 이미지를 구상한다면
(4) 우리가 하지 말아야 하는 것은 무엇이 있을까?
해야 할 리스트 옆에, 다음 릴리즈에 해도 되는 목록은 적지 말아야 한다. 

 

 

 

반응형