728x90
Mapper
이제 URL 을 통한 요청이 들어올 경우 Method 와 URL 을 사용해 필요한 요청을 각각 수행할 수 있도록 해주어야한다.
- 결국 라우팅을 해주는 객체가 필요하다
- 확장성을 위해 컨트롤러를 한 번 등록하면 이후에 요청이 들어왔을 때 찾을 수 있도록 하고 싶다.
- 모든 컨트롤러들은 인터페이스를 구현해 하나의 메서드를 실행할 수 있게 한다.
HttpMapper
public interface HttpMapper {
MyHttpResponse handle(MyHttpRequest httpRequest) throws IOException;
}
가장 기본이 되는 인터페이스를 하나 생성하자.
이전에 만들었던 요청 객체를 파라미터로 받아 handle 메서드 내에서 이를 실행하고 응답 객체를 반환한다.
큰 틀을 유지하며 일단 Mapper 객체를 몇 개 만들어보자.
public class GETHomeMapper implements HttpMapper {
private final FileContentReader fileContentReader = FileContentReader.getInstance();
@Override
public MyHttpResponse handle(MyHttpRequest httpRequest) throws IOException {
MyHttpResponse response = fileContentReader.readStaticResource("/index.html");
return response;
}
}
...
public MyHttpResponse readStaticResource(String uri) throws IOException {
String path = "src/main/resources/static";
File file = new File(path + uri);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
byte[] byteArray = new byte[(int) file.length()];
int bytesRead = 0;
int offset = 0;
while (offset < byteArray.length
&& (bytesRead = fis.read(byteArray, offset, byteArray.length - offset)) >= 0) {
offset += bytesRead;
}
if (offset < byteArray.length) {
throw new IOException("Could not completely read the file " + file.getName());
}
String extension = uri.substring(uri.lastIndexOf(".") + 1);
String contentType = ContentType.valueOf(extension).getContentType();
return new MyHttpResponse(200, "OK", new HashMap<>() {
{
put(CONTENT_TYPE, contentType);
put(CONTENT_LENGTH, String.valueOf(byteArray.length));
}
}, byteArray);
}
}
홈 요청 시 정적파일을 읽어내고 이를 반환한다. 물론 응답 객체에 넣어서 반환하면 Parser 가 클라이언트에게 Response 형식에 맞게 잘 파싱하여 보내준다.
3 번은 해결한 것 같다.
MappingHandler
이제 1, 2번을 해결하자.
public class MappingHandler {
private static final Map<String, HttpMapper> getHandlers = new HashMap<>();
private static final Map<String, HttpMapper> postHandlers = new HashMap<>();
private static MappingHandler instance = new MappingHandler();
private MappingHandler() {
}
public static MappingHandler getInstance() {
return instance;
}
static {
getHandlers.put("/", new GETHomeMapper());
getHandlers.put("/registration", new GETRegistrationFormMapper());
// getHandlers.put("/user/create", new GETCreateUserMapper());
postHandlers.put("/user/create", new POSTCreateUserMapper());
}
public MyHttpResponse mapping(MyHttpRequest httpRequest) throws IOException {
String method = httpRequest.getMethod();
String path = httpRequest.getPath();
return switch (method) {
case "GET" -> getHandlers.get(path).handle(httpRequest);
case "POST" -> postHandlers.get(path).handle(httpRequest);
default -> null;
};
}
}
위와 같이 MappingHandler 를 구현하였다.
우선 url 이 같아도 method 가 다르면 다른 처리를 해주어야하기에 각 method 별로 컨트롤러를 등록할 수 있는 Map 을 생성해주었다. (현재는 Get, Post만 생성해줬다.)
의존성 주입을 위해 해당 객체를 싱글톤 객체로 생성하는 모습이다.
이후 static 블록을 사용해 사용할 객체들을 Map 에 알맞게 넣어준다! 이 과정이 컨트롤러를 등록하는 과정이라 생각하면 된다.
이후 mapping 메서드를 사용해서 method, path 를 통해 특정 컨트롤러(Mapper)를 찾아낸다. 모든 Mapper 들은 handle() 이라는 메서드를 구현하고 있기 때문에 request 를 넘겨주며 handle 을 실행시켜 response 를 받아 그대로 반환한다.
728x90
'Programming > JAVA' 카테고리의 다른 글
[JAVA] 정적 파일 위치 설정 및 src/main/resource 경로 ClassLoader 로 읽기 및 Java Reflection 살펴보기 (0) | 2024.07.11 |
---|---|
[JAVA] JVM 구조 총정리 (0) | 2024.07.10 |
[JAVA] Spring 없이 웹 서버 구축! (3) HTTP Request, Response 객체 (0) | 2024.07.09 |
[Java] String 과 Byte[] 의 차이 by 인코딩! 바이트 파일을 String 으로 읽으면? (1) | 2024.07.05 |
[JAVA] Spring 없이 웹 서버 구축! (2) 다양한 컨텐츠 타입 지원 (0) | 2024.07.04 |