1)한줄요약 : 멜론과 같은 음원 결제 및 다운로드 사이트를 제작
2)본인 역할 : 프로젝트리더.선행개발 및 본 개발로 MVC구조에 기반한 웹 서버 구조 설계 및 개발.
+선행개발: 검색 가능한 웹화면, 로그인,파일업로드 기능같이 부수적인 것들 미리 제작. Jsp와 BLOB 자료형 사용.
+팀원:ㄱㄱㅂ,ㅂㅊㅁ
3)본인이 사용한 스킬 : Java,Oracle Database,Spring,Jsp
+팀원스킬: JAVA,Oracle Database,Spring
4)힘들었던 점: 기술 이해의 불균형. 개발기간이 5일이어서 곧바로 분업했지만 수업에 완전히 참석하지 못한 팀원들이 이해에 어려움을 겪었다.
->2일이라도 스터디 제안,스터디에 가기 전 최대한 많은 내용을 공부하고 팀원의 이해를 도울 수 있는 자료를 만듬.
[주제를 정하기 위해서 SWOT 분석을 활용]
[구조도]
Main - 사용자가 원하는 기능을 선택하면 필요한 Controller의 메소드를 호출한다.
Controller - 각 기능에 필요한 서비스를 호출하고 관리한다.
Service
- UserServise : 사용자메뉴에 필요한 서비스를 포함한다.
- MusicService : 음원서비스에 필요한 서비스를 포함한다.
DAO
- UserRepository : 사용자 서비스에 필요한 insert,delete,find를 포함한다.
- MusicRepository : 음원 서비스에 필요한 insert,delete,find를 포함한다.
Database - 사용자데이터를 userdata에, 음원데이터를 musicdata에 저장한다.
[흐름도]
[본개발 시연 (DI구조를 선행개발과 합치지 못해서 콘솔창 구현)]
[주요 코드]
package com.watermelon.controller;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import com.watermelon.dao.IRepository;
public class RepositoryController {// ICustomerService custService = new CustomerService();
public IRepository repository;
//AbstractApplicationContext context=new GenericXmlApplicationContext("application-config.xml");
public RepositoryController(IRepository repository) {
this.repository = repository;
} //원래는 여기서 서비스 선택해야됨
public void run_insert() {
repository.insert();
}
}
package com.watermelon.dao;
public interface IRepository { //같은 리포지터리로 많이 만들거니까 인터페이스
void insert();
void update();
void print();
void delete();
}
package com.watermelon.dao;
import java.util.Scanner;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import com.watermelon.model.Artist;
public class ArtistRepository implements IRepository { //실체화된 리포지터리
Scanner scan = new Scanner(System.in);
//AbstractApplicationContext context = new GenericXmlApplicationContext("application-config.xml");
JdbcTemplate jdbcTemplate;
@Override
public void insert() {
System.out.print("번호 : ");
int artist_num = scan.nextInt();
System.out.print("이름 : ");
String name = scan.next();
System.out.print("날짜 : ");
String create_date = scan.next();
System.out.print("점수 : ");
int score = scan.nextInt();
Artist a = new Artist(artist_num, name, create_date, score);
String sql = "insert into artist (artist_num, name, create_date, score)" + "values ('" + artist_num + "','"
+ name + "','" + create_date + "','" + score + "')";
jdbcTemplate.update(sql); //모델인 테이블에서 가져올거임
}
public void update() {
}
public void print() {
}
public void delete() {
}
public void setMethod(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
package com.watermelon.main;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import com.watermelon.dao.ArtistRepository;
public class WatermelonMain {
public static void main(String[] arg) {
AbstractApplicationContext context = new GenericXmlApplicationContext("application-config.xml"); //컨테이너 등록
ArtistRepository a = context.getBean(ArtistRepository.class); //컨테이너에선 손쉽게 생성하고 빈객체까지 취할수있음
a.setMethod(context.getBean("jdbcTemplate",JdbcTemplate.class)); //jdbc도 빈객체로 설정되있을때 a빈객체에 넣어서 해당 과정 수행한다.
a.insert(); //사실 여기 메인에선 컨트롤러 만들어서 걔가 컨테이너 만들어서 위의 두줄 넣고 빈빼서 실행해야됐음
}
}
<?xml version="1.0" encoding="UTF-8"?>
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">
<!-- 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>/</url-pattern>
</servlet-mapping>
</web-app>
//그리고 위처럼 음악파일도 똑같이 만들어서 뷰 파일로 결과 보내줘야함. jsp든 서블릿이든. 즉, 뷰와 컨트롤러 부분을 못만든 것이다.
[선행개발-논리적 데이터 모델]
[선행개발 시연]
[주요 코드]
메인 jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ page import="java.sql.*,javax.naming.*,javax.sql.*" %>
http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<script language='javascript'>
function wrong_input(){
alert("잘못된 정보를 입력하셨습니다.");
history.back();
}
function no_exist_result(){
alert("원하시는 결과가 없습니다");
history.back();
}
</script>
<%
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/sec");
Connection conn = ds.getConnection();
String keyword = request.getParameter("keyword");
if (keyword == null) {
%><script>
wrong_input();
</script>
<%
}
String sqlQuery = "select * from attachment where file_name='";
sqlQuery +=keyword;
sqlQuery += "'";
System.out.println("SQL: "+sqlQuery);
PreparedStatement ps =conn.prepareStatement(sqlQuery);
ResultSet rs = ps.executeQuery();
while(rs.next()){
%>
<tr> <li><td><a href="file_down.jsp?file_id=<%=rs.getInt("id")%>">
<td><%=rs.getString("file_name")%>
</tr>
<%
}
//예외처리 만들어줘야
conn.commit();
rs.close();
ps.close();
conn.close();
%>
</body>
</html>
파일업로드 jsp
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="utf-8"%>
<%@ page import="java.sql.*,javax.naming.*,javax.sql.*" %>
<!DOCTYPE >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Upload files</title>
</head>
<body>
<script language='javascript'>
function wrong_input(){
alert("로그인 하셔야죠!");
window.location.href="login.html"; //history.back();
}
</script>
<%
String user_id=request.getParameter("user_id");
System.out.println(user_id);
if(user_id.equals("null"))
{%>
<scripts>
wrong_input();
</scripts><%
}%>
<div style="padding:5px; color:red;font-style:italic;">
${errorMessage}
</div>
<h2>Upload Files</h2>
<form method="post" action="${pageContext.request.contextPath}/uploadToDB"
enctype="multipart/form-data">
Select file to upload:
<br />
<input type="file" name="file" />
<br />
<input type="file" name="file" />
<br />
Description:
<br />
<input type="text" name="description" size="100" />
<br />
<br />
<input type="submit" value="Upload" />
</form>
</body>
</html>
클릭한 파일 다운로드
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<%
String file_id=request.getParameter("file_id");
String str="http://localhost:8080/WaterMelon/downloadAttachment?id=";
str+=file_id;
System.out.println(str);
response.sendRedirect(str);
%>
<script>
wrong_input();
</script>
</body>
</html>
BLOB 자료형으로 파일 클래스
import java.sql.Blob;
public class Attachment {
private Long id;
private Blob FileData;
private String FileName;
public Attachment(Long id,Blob FileData, String FileName) {
this.id = id;
this.FileData = FileData;
this.FileName = FileName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Blob getFileData() {
return FileData;
}
public void setFileData(Blob FileData) {
this.FileData = FileData;
}
public String getFileName() {
return FileName;
}
public void setFileName(String FileName) {
this.FileName = FileName;
}
}
import java.io.IOException;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
@WebServlet("/downloadAttachment")
public class DownloadAttachmentServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) //다운로드는 빨라야 돼
throws ServletException, IOException {
Connection conn = null;
try {
// Get Database Connection.
// (See more in JDBC Tutorial).
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/sec");
conn = ds.getConnection();
conn.setAutoCommit(false);
Long id = null;
try {
id = Long.parseLong(request.getParameter("id"));
} catch (Exception e) {
}
Attachment atc = getAttachmentFromDB(conn, id);
if (atc == null) {
// No record found.
response.getWriter().write("No data found");
return;
}
// file1.zip, file2.zip
String fileName = atc.getFileName();
System.out.println("File Name: " + fileName);
// abc.txt => text/plain
// abc.zip => application/zip
// abc.pdf => application/pdf
String contentType = this.getServletContext().getMimeType(fileName);
System.out.println("Content Type: " + contentType);
response.setHeader("Content-Type", contentType);
response.setHeader("Content-Length", String.valueOf(atc.getFileData().length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + atc.getFileName() + "\"");
// For big BLOB data.
Blob fileData = atc.getFileData();
InputStream is = fileData.getBinaryStream();
byte[] bytes = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(bytes)) != -1) {
// Write image data to Response.
response.getOutputStream().write(bytes, 0, bytesRead);
}
is.close();
} catch (Exception e) {
throw new ServletException(e);
} finally {
this.closeQuietly(conn);
}
}
private Attachment getAttachmentFromDB(Connection conn, Long id) throws SQLException {
String sql = "Select a.Id,a.File_Name,a.File_Data,a.Description "//
+ " from Attachment a where a.id = ?";
PreparedStatement pstm = conn.prepareStatement(sql);
pstm.setLong(1, id);
ResultSet rs = pstm.executeQuery();
if (rs.next()) {
String fileName = rs.getString("File_Name");
Blob fileData = rs.getBlob("File_Data");
String description = rs.getString("Description");
return new Attachment(id, fileData, description);
}
return null;
}
private void closeQuietly(Connection conn) {
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) {
}
}
}
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.naming.Context;
import java.sql.*;
import javax.sql.*;
import javax.naming.InitialContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import javax.sql.DataSource;
파일 업로드 DB 연동 클래스
@WebServlet("/uploadToDB")
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, // 2MB
maxFileSize = 1024 * 1024 * 10, // 10MB
maxRequestSize = 1024 * 1024 * 50) // 50MB
public class UploadToDBServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher dispatcher = request.getServletContext().getRequestDispatcher("/WebContent/uploadToDB.jsp");
dispatcher.forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) //올리는건 ㄷ ㅓ신중히
throws ServletException, IOException {
Connection conn = null;
try {
// Connection to Database
// (See more in JDBC Tutorial).
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/sec");
conn = ds.getConnection();
conn.setAutoCommit(false);
String description = request.getParameter("description");
// Part list (multi files).
for (Part part : request.getParts()) {
String fileName = extractFileName(part);
if (fileName != null && fileName.length() > 0) {
// File data
InputStream is = part.getInputStream();
// Write to file
this.writeToDB(conn, fileName, is, description);
}
}
conn.commit();
// Upload successfully!.
response.sendRedirect(request.getContextPath() + "/uploadToDBResults");
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("errorMessage", "Error: " + e.getMessage());
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WebContent/uploadToDB.jsp");
dispatcher.forward(request, response);
} finally {
this.closeQuietly(conn);
}
}
private String extractFileName(Part part) {
// form-data; name="file"; filename="C:\file1.zip"
// form-data; name="file"; filename="C:\Note\file2.zip"
String contentDisp = part.getHeader("content-disposition");
String[] items = contentDisp.split(";");
for (String s : items) {
if (s.trim().startsWith("filename")) {
// C:\file1.zip
// C:\Note\file2.zip
String clientFileName = s.substring(s.indexOf("=") + 2, s.length() - 1);
clientFileName = clientFileName.replace("\\", "/");
int i = clientFileName.lastIndexOf('/');
// file1.zip
// file2.zip
return clientFileName.substring(i + 1);
}
}
return null;
}
private Long getMaxAttachmentId(Connection conn) throws SQLException {
String sql = "Select max(a.id) from Attachment a";
PreparedStatement pstm = conn.prepareStatement(sql);
ResultSet rs = pstm.executeQuery();
if (rs.next()) {
long max = rs.getLong(1);
return max;
}
return 0L;
}
private void writeToDB(Connection conn, String fileName, InputStream is, String description) throws SQLException {
String sql = "Insert into Attachment(Id,File_Name,File_Data,Description) " //
+ " values (?,?,?,?) ";
PreparedStatement pstm = conn.prepareStatement(sql);
Long id = this.getMaxAttachmentId(conn) + 1;
pstm.setLong(1, id);
pstm.setString(2, fileName);
pstm.setBlob(3, is);
pstm.setString(4, description);
pstm.executeUpdate();
}
private void closeQuietly(Connection conn) {
try {
if (conn != null) {
conn.close();
}
} catch (Exception e) {
}
}
}