지금까지는 각 패키지마다 controller를 만들어줘서 servlet을 만들어줬는데 오늘은 하나의 파일에서 관리하는 법을 배웠다.
.do 로 끝나는 모든 파일이 dispatcherServlet으로 들어간다.
package req;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import javax.servlet.RequestDispatcher;
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 handler.Handler;
import handler.member.JoinHandler;
import handler.member.LoginHandler;
/**
* Servlet implementation class DispatcherServlet
*/
@WebServlet("*.do")
public class DispatcherServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Map<String, Handler> map = new HashMap<>();
// commands.properties 파일의 url과 명령어를 읽어서 저장할 map
/**
* @see HttpServlet#HttpServlet()
*/
public DispatcherServlet() {
super();
// TODO Auto-generated constructor stub
}
// 서블릿 생성시 딱 한 번 실행되는 메서드.
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
Properties prop = new Properties();
String path = this.getServletContext().getRealPath("/WEB-INF/commands.properties");
try {
prop.load(new FileReader(path));
Iterator iter = prop.keySet().iterator();
while (iter.hasNext()) {
String url = (String) iter.next(); // member/join.do
try {
String className = prop.getProperty(url); // handler.member.JoinHandler
Class<?> handlerClass = Class.forName(className);
Constructor<?> cons = handlerClass.getConstructor(null);
Handler handler = (Handler) cons.newInstance();
map.put(url, handler);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String url = request.getServletPath(); // 요청 url 반환 join.do
String view = null;
Handler handler = map.get(url); // 업캐스팅
if (handler != null) {
view = handler.process(request, response);
if (view.startsWith("redirect")) {
String[] path = view.split(":");
response.sendRedirect(request.getContextPath() + path[1]);
} else {
RequestDispatcher dis = request.getRequestDispatcher(view);
dis.forward(request, response);
}
} else {
response.getWriter().append("404 not found url");
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
private Map<String, Handler> map = new HashMap<>();
commands.properties 파일의 url과 명령어를 읽어서 저장할 map을 만들어준다.
init 메소드는 경로를 가져와서(load) prop에 저장을 한다.
그래서 로드한 데이터의 키를 하나씩 꺼내서 String url
과 String className
에 값을 넣어준다.
public void init() throws ServletException {
// TODO Auto-generated method stub
Properties prop = new Properties();
// Properties 생성자 생성
String path = this.getServletContext().getRealPath("/WEB-INF/commands.properties");
// commands.properties에 있는 실제 경로를 가져온다.
try {
prop.load(new FileReader(path));
Iterator iter = prop.keySet().iterator();
// 키만 가져온다.
while (iter.hasNext()) {
String url = (String) iter.next();
// "member/join.do" 이런 식으로 url을 가져온다.
try {
String className = prop.getProperty(url);
// handler.member.JoinHandler
Class<?> handlerClass = Class.forName(className);
// 클래스에 대한 정보를 알아야하기 때문에
// 해당 클래스에 대한 정보를 수집한다.
Constructor<?> cons = handlerClass.getConstructor(null);
Handler handler = (Handler) cons.newInstance();
// => "JoinHandler h = new JoinHandler();" (얜 하드코딩)
// 생성을 해주기
map.put(url, handler);
// url과 만든 handler을 map에 저장
// 맵에는 "url"과 "url이 왔을 때 실행될 친구"를 넣기 위해서 생성 Handler에는 객체를 생성해서 넣어주는 것이다.
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String url = request.getServletPath();
// 요청 url 반환 "join.do"
String view = null;
Handler handler = map.get(url); // 업캐스팅
// map.put(url, handler); 여기서 넣은 걸 가져오는 것
if (handler != null) {
view = handler.process(request, response);
if (view.startsWith("redirect")) { // redirect로 시작한다면
String[] path = view.split(":");
response.sendRedirect(request.getContextPath() + path[1]);
} else {
RequestDispatcher dis = request.getRequestDispatcher(view);
dis.forward(request, response);
}
} else {
response.getWriter().append("404 not found url");
}
}
package "handler" 만들어주고
handler.java 생성
그리고 handler 패키지 밑에 handler.member 패키지를 만들어주고
class 파일로 JoinHandler.java를 만들어준다.
이런식으로 만들어준다.
package handler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 모든 요청 처리 클래스의 부모
public interface Handler {
String process(HttpServletRequest request, HttpServletResponse response);
}
서버에 있는 파일을 클라이언트에게 복사하는것
//다운로드 폴더
String downDir = "C:\\down\\";
//사용자가 클릭한 파일명
String fname = request.getParameter("fname");
// 다운로드할 파일 전체 경로
String path = downDir + fname;
//파일에 대한 정보. 파일크기, 읽기, 쓰기, 실행 가능, 존재하는지 유무
File file = new File(path);
//다운로드 파일의 내용을 읽을 스트림 생성
FileInputStream in = new FileInputStream(path);
//파일명 인코딩
fname = new String(fname.getBytes("euc-kr"), "8859_1");
//다운로드 응답을 보내기 위한 response 설정
//setContentType(): 파일의 마임설정. 파일의 종류.
//octet-stream: 바이너리 파일 한 종류
response.setContentType("application/octet-stream");
//헤더 설정. 패킷의 중요 정보를 설정. 첨부파일 전송 설정
response.setHeader("Content-Disposition", "attachment; filename=" + fname);
//다운로드 파일 내용을 response에 출력할 출력 스트림 획득
OutputStream os = response.getOutputStream();
int length;
//다운로드 파일에서 읽은 내용을 담을 byte배열을 파일 크기와 동일하게 생성
byte[] b = new byte[(int) file.length()];
//파일에서 읽은 내용을 response에 출력
while ((length = in.read(b)) > 0) {
os.write(b, 0, length);
}
//강제출력
os.flush();
//스트림 닫기
os.close();
in.close();
create table filedown(
num number primary key,
writer varchar2(20) references member(id) on delete cascade,
w_date date,
title varchar2(50),
content varchar2(100),
fname varchar2(100),
cnt number
);
create sequence seq_filedown;