[SPRING] SpringMVC 홈페이지만들기 6 [ 자료실 복습하기]

🐷Jinie (juniorDeveloper)·2020년 12월 8일
1

JSP/MVC/SPRING

목록 보기
69/81

1. 테이블만들기

  • 자료실 복습을 위한 간단한 테이블을 만든다.
CREATE TABLE table_psd(
    idx NUMBER NOT NULL PRIMARY KEY,
    NAME NVARCHAR2(10),
    fname NVARCHAR2(50),
    sdate DATE DEFAULT sysdate
);

SELECT * FROM table_psd;

CREATE SEQUENCE TABLE_SQ
MAXVALUE 99999
START WITH 10000
INCREMENT BY 1;

INSERT INTO table_psd (idx, NAME, fname) 
    VALUES (table_sq.NEXTVAL, '찐이' , 'test.jpg');

2. Spring 프로젝트 만들기

  • test JSP파일
  • test .do주소 확인

3. 프로젝트 설정하고 테스트페이지 확인하기

  • 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>classpath:applicationContext.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>
	
	<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>*.do</url-pattern>
	</filter-mapping>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>DispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/config/presentation-layer.xml</param-value>
		</init-param>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>DispatcherServlet</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

</web-app>
  • 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 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.psd</groupId>
	<artifactId>biz</artifactId>
	<name>Psd1208</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.8</java-version>
		<org.springframework-version>4.2.4.RELEASE</org.springframework-version>
		<org.aspectj-version>1.6.10</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
	</properties>
	<repositories>
		<repository>
			<id>public</id>
			<url>https://repo1.maven.org/maven2/</url>
		</repository>
	</repositories>
	<dependencies>
	<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc8 -->
		<dependency>
		    <groupId>com.oracle.database.jdbc</groupId>
		    <artifactId>ojdbc8</artifactId>
		    <version>12.2.0.1</version>
		</dependency>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
		</dependency>
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.1</version>
		</dependency>
		<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>	
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.8.8</version>
		</dependency>	
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjtools</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.7</version>
			<scope>test</scope>
		</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>2.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>

4. 패키지 구성하기

  • presentation-layer.xml (자료실정보 포함)
    : Controller가 있는 파일과 파일을 주고받을 수 있는 mutipartResolver객체를 설정한다.
<?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"
	xsi:schemaLocation="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.2.xsd">

<context:component-scan base-package="com.psd.biz.controller"/>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
</beans>
  • applicationContext.xml (SpringJDBC, AOP를 이용한 트랜잭션처리 등 포함)
    : 서버실행시 실행해둘 로직
    즉, 비즈니스단이 실려있는 패키지를 스캔한다.
<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="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.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

<context:component-scan base-package="com.psd.biz.member" />

<!-- DataSource 설정하기 -->
<context:property-placeholder location="classpath:config/database.properties" />
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}"/>
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
      <property name="dataSource" ref="dataSource" />
</bean>

<!--  트랜잭션 설정하기  -->
<bean  id="txManager"  class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
   <property name="dataSource"   ref="dataSource" />
</bean>

<tx:advice  id="txAdvice"  transaction-manager="txManager" >
	<tx:attributes>
		<tx:method name="get*"  read-only="true" />
		<tx:method name="*" />
	</tx:attributes>
</tx:advice>
<aop:config>
	<aop:pointcut id="txPointcut"  expression="execution(* com.psd.biz..ServiceImpl.*(..) )"   />
	<aop:advisor  pointcut-ref="txPointcut"  advice-ref="txAdvice"/>
</aop:config>
</beans>
  • DB 연결정보 넣기 (database.properties)
jdbc.driver=oracle.jdbc.OracleDriver
jdbc.url=jdbc:oracle:thin:@//localhost:1521/xe
jdbc.username=system
jdbc.password=1234

5. JSP파일 만들기

  • form.jsp
    : enctype 과 method 방식에 주의해서 필수설정!
    ★ method="POST" enctype="multipart/form-data"
    이때, input type file 부분은 multipartFile 형의 변수로 Vo매핑이 될 수 있도록 이름을 설정한다.
 <td><input  type=file  name=uploadFile size=20> </td>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div align="center">
<h2>입력하기</h2>
<form action="insert.do" method="POST" enctype="multipart/form-data">
	<table border=1 width=600>
		<tr>
			<td  align=center>회원성명 </td>
			<td> <input  type=text  name=name size=10></td>
		</tr>
		<tr>
			<td  align=center>사진첨부</td>
			<td><input  type=file  name=uploadFile size=20> </td>
		</tr>
		<tr>
			<td colspan=2  align=center>
				<input  type=submit  value="등록"> &emsp;
				<input  type=reset   value="다시입력">
			</td>
		</tr>
	</table>
</form>
</div>
</body>
</html>

  • list.jsp
    : 입력한 정보를 목록으로 볼 수 있는 jsp 페이지를 만든다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
  <div align="center">
  <br><br>
  <h2>목록보기</h2>
  <table border=1  width=800  height=250>
    <tr><td>회원번호</td><td>회원성명</td><td>가입일자</td><td>사진</td></tr>
      <c:forEach items="${list}" var="m">
        <tr>
            <td>${m.getIdx()}</td>
            <td>${m.getName()}</td>
            <td>${m.getSdate()}</td>
            <td><img src="./psd/${m.getFname()}" width=50 height=50></td>
        </tr>
      </c:forEach>
  </table>
  </div>
</body>
</html>

6. DTO/VO 만들기

package com.psd.biz.member.common;

import org.springframework.web.multipart.MultipartFile;

public class PsdVo {
	private int idx;
	private String name;
	private String fname;
	private MultipartFile uploadFile;
	private String sdate;
	public int getIdx() {
		return idx;
	}
	public void setIdx(int idx) {
		this.idx = idx;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getFname() {
		return fname;
	}
	public void setFname(String fname) {
		this.fname = fname;
	}
	public MultipartFile getUploadFile() {
		return uploadFile;
	}
	public void setUploadFile(MultipartFile uploadFile) {
		this.uploadFile = uploadFile;
	}
	public String getSdate() {
		return sdate;
	}
	public void setSdate(String sdate) {
		this.sdate = sdate.substring(0,10);
	}
	@Override
	public String toString() {
		return "PsdVo [idx=" + idx + ", name=" + name + ", fname=" + fname + ", uploadFile=" + uploadFile + ", sdate="
				+ sdate + "]";
	}	
}
  • sdate 칼럼은 String으로 잡고 뒤에 시간 분 초를 표기하는 부분을 떼고 사용하기 위해서 .substring 메서드를 사용했다.
  • file은 파일이름정보만 있는 String형의 fname과 실제 파일이 들어있는 MultipartFile형의 uploadFile이 있다.
    반드시 두가지를 다 만들어줘야 db에서 파일이름을 받아오고 넘겨주고
    실제파일을 지정한 폴더에 저장할 수 있다.

7. Service, Dao, Controller

  • serviceImpl
package com.psd.biz.member.service;

import java.util.List;

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

import com.psd.biz.member.common.PsdVo;
import com.psd.biz.member.dao.PsdDAO;
@Service
public class PsdServiceImpl implements PsdService{
	@Autowired
	PsdDAO dao;
	@Override
	public void insert(PsdVo vo) {
		dao.insert(vo);
	}
	@Override
	public List<PsdVo> list() {
		return dao.list();
	}
}
  • DAOImpl
package com.psd.biz.member.dao;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.psd.biz.member.common.PsdVo;
@Repository
public class PsdDAOImpl implements PsdDAO{
	@Autowired
	JdbcTemplate jdbcTemplate;
	String insert_sql="insert into table_psd (idx, name, fname) values (table_sq.NEXTVAL, ? , ?) ";
	String select_sql="select * from table_psd order by idx desc ";
	@Override
	public void insert(PsdVo vo) {
		Object[] args = {vo.getName(), vo.getFname()};
		jdbcTemplate.update(insert_sql, args);
	}

	@Override
	public List<PsdVo> list() {
		return jdbcTemplate.query(select_sql, new rowMapper());
	}
}
class rowMapper implements RowMapper<PsdVo>{
	@Override
	public PsdVo mapRow(ResultSet rs, int rowNum) throws SQLException {
		PsdVo vo = new PsdVo();
		vo.setIdx(rs.getInt("idx"));
		vo.setName(rs.getString("name"));
		vo.setFname(rs.getString("fname"));
		vo.setSdate(rs.getString("sdate"));
		return vo;
	}	
}
  • Controller ★★
    : 1. 실제파일을 저장하고 insert쿼리를 실행해야한다.
    1. 파일이름 중복을 방지하기 위해서 동일한 파일명이 있을경우 난수처리로직을 작성한다.
package com.psd.biz.controller;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

import com.psd.biz.member.common.PsdVo;
import com.psd.biz.member.service.PsdService;

@Controller
public class PsdController {
	@Autowired
	PsdService s;
	@RequestMapping(value="/insert.do", method=RequestMethod.POST)
	public String insert(PsdVo vo, HttpServletRequest request) {
		// 1. 파일 저장경로 설정하기    		
		String realPath = request.getSession().getServletContext().getRealPath("/psd/");
		System.out.println(realPath);
        // 2. 업로드된 파일 MultipartFile형의 변수에 받아두기
		MultipartFile uploadFile = vo.getUploadFile();
		// 3. 업로드한 파일이 있다면!
		if(!uploadFile.isEmpty()) {
        		//4. 그 업로드한 파일명은 getOriginalFilename 메서드를 이용해서 String변환
				String originalFileName = uploadFile.getOriginalFilename();
                //5. 파일저장경로/실제파일이름이
				File file = new File(realPath+originalFileName);
				String fileName = originalFileName.substring(0, originalFileName.lastIndexOf("."));
				String extension = FilenameUtils.getExtension(originalFileName);
                //7. 아니면 난수빼고 그냥쓸게
				String saveFileName = fileName + "." + extension;
                //6. 만약에 존재한다면
				if(file.isFile()) {
                	// 7. 난수를 발생해서 saveFileName을 설정할거고
					String ranId = UUID.randomUUID().toString();
					saveFileName = fileName + ranId.substring(0,3) + "." + extension;
				}
				try {
                // 8.정해진 저장이름으로 Fname칼럼에 파일명 DB에 Insert하고 파일 지정폴더저장
					vo.setFname(saveFileName);
					uploadFile.transferTo(new File(realPath+saveFileName));
				} catch (IllegalStateException | IOException e) {
					e.printStackTrace();
				}
		}else {
        //9. 혹시 만약에 파일업로드를 안했다면 empty.jpg로 일괄 insert
			vo.setFname("empty.jpg");
		}
		s.insert(vo);
		return "list.do";
	}
	@RequestMapping(value="/list.do", method=RequestMethod.POST)
	public String list(PsdVo vo, Model model) {
		model.addAttribute("list", s.list());
		return "list.jsp";
	}
}

[ 참고자료 : File형의 메서드]

  1. exists 함수
    파일이 존재하는지 여부를 알 수 있다.
  2. length 함수
    file의 사이즈를 측정하는 함수 ->long반환
  3. isFile 함수
    파일이 존재하지 않거나 디렉토리이면 false, 파일이고 존재하면 true 반환
  4. isDirectory 함수
    디렉토리이고 존재하면 true를 반환 ,파일이거나 존재하지 않으면 false
  5. isHidden 함수
    숨김파일인지를 검사하는 함수
  6. getName 함수
    파일에 이름을 반환하는 함수. 앞에 파일 경로를 제외하고 파일이름만 String 타입으로 반환
  7. getPath 함수
    파일의 전체 경로와 이름을 반환

8. 처리결과 확인하기

  • 파일이름이 중복되지 않게 잘 업로드 되었는지 확인한다.
  1. 중복테스트라는 이름으로 동일한 사진파일을 여러개 업로드한다.
  2. 저장하기 페이지에서 저장완료 후 목록보기로 잘 전달되는지 확인한다.
  3. 파일저장지정폴더에 업로드한 파일이 잘 업로드 되었는지 확인한다.
    C:\Users\602-07\eclipse-workspace.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\Psd1208\psd\
  • 파일명을 확인해보면 중복파일이 없었을 때는 oo.jpg로 난수없이 이름 그대로 저장이 되었고,
    중복되는 파일이 확인되어 이후 저장된 동일한 사진은 난수3글자가 생성되어 같이 저장되었다.
  1. DB확인
  • 데이터베이스에도 의도한대로 잘 입력된 것을 확인했다.
profile
ᴘᴇᴛɪᴛs ᴅᴇ́ᴠᴇʟᴏᴘᴘᴇᴜʀ. ᴘʀᴏɢʀᴀᴍᴍᴀᴛɪᴏɴ = ᴘʟᴀɪsɪʀ 💕

0개의 댓글