-
Notifications
You must be signed in to change notification settings - Fork 309
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[톰캣 구현하기 - 3,4단계] 도기(김동호) 미션 제출합니다. #449
Changes from all commits
963a0dc
d2e9fa4
4a8d3dc
37e1c0c
667378f
6ffafc4
646d2a8
6847697
f97b1c2
7e5589a
b7037c8
538a250
4ed631d
68494e8
6c13871
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package nextstep.jwp.application; | ||
|
||
import static nextstep.jwp.db.InMemoryUserRepository.findByAccount; | ||
|
||
import nextstep.jwp.exception.InvalidPasswordException; | ||
import nextstep.jwp.model.User; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class LoginService { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(LoginService.class); | ||
|
||
public User login(String account, String password) { | ||
User user = findByAccount(account).orElseThrow(); | ||
|
||
if (!user.checkPassword(password)) { | ||
log.debug("비밀번호 틀림! - 입력={}", password); | ||
throw new InvalidPasswordException(); | ||
} | ||
log.info("로그인 성공! - {}", user); | ||
return user; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package nextstep.jwp.application; | ||
|
||
import nextstep.jwp.db.InMemoryUserRepository; | ||
import nextstep.jwp.model.User; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class RegisterService { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(RegisterService.class); | ||
|
||
public void register(String account, String email, String password) { | ||
User user = new User(account, password, email); | ||
InMemoryUserRepository.save(user); | ||
log.info("회원가입 성공! - {}", user); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package nextstep.jwp.controller; | ||
|
||
import static org.apache.coyote.HttpStatus.OK; | ||
import static org.apache.coyote.header.HttpHeaders.CONTENT_LENGTH; | ||
import static org.apache.coyote.header.HttpHeaders.CONTENT_TYPE; | ||
|
||
import org.apache.coyote.HttpRequest; | ||
import org.apache.coyote.HttpResponse; | ||
import org.apache.coyote.http11.handler.AbstractController; | ||
|
||
public class HelloController extends AbstractController { | ||
|
||
@Override | ||
protected void doGet(HttpRequest request, HttpResponse response) { | ||
String message = "Hello world!"; | ||
|
||
response.setVersion(request.protocolVersion()); | ||
response.setStatus(OK); | ||
response.addHeader(CONTENT_TYPE, "text/html;charset=utf-8"); | ||
response.addHeader(CONTENT_LENGTH, String.valueOf(message.length())); | ||
response.setBody(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package nextstep.jwp.controller; | ||
|
||
import static org.apache.coyote.HttpStatus.FOUND; | ||
import static org.apache.coyote.HttpStatus.OK; | ||
import static org.apache.coyote.header.HttpHeaders.CONTENT_LENGTH; | ||
import static org.apache.coyote.header.HttpHeaders.CONTENT_TYPE; | ||
import static org.apache.coyote.header.HttpHeaders.LOCATION; | ||
import static org.apache.coyote.header.HttpHeaders.SET_COOKIE; | ||
|
||
import java.util.Map; | ||
import nextstep.jwp.application.LoginService; | ||
import nextstep.jwp.model.User; | ||
import nextstep.jwp.util.ResourceLoaderUtil; | ||
import org.apache.coyote.HttpRequest; | ||
import org.apache.coyote.HttpResponse; | ||
import org.apache.coyote.header.ContentType; | ||
import org.apache.coyote.header.HttpCookie; | ||
import org.apache.coyote.http11.handler.AbstractController; | ||
import org.apache.coyote.session.Session; | ||
import org.apache.coyote.session.SessionManager; | ||
|
||
public class LoginController extends AbstractController { | ||
|
||
private final LoginService loginService = new LoginService(); | ||
|
||
@Override | ||
protected void doGet(HttpRequest request, HttpResponse response) throws Exception { | ||
response.setVersion(request.protocolVersion()); | ||
if (request.getSession() != null) { | ||
response.setStatus(FOUND); | ||
response.addHeader(LOCATION, "index.html"); | ||
return; | ||
} | ||
|
||
String content = ResourceLoaderUtil.loadContent(request.requestUrl()); | ||
response.setStatus(OK); | ||
response.addHeader(CONTENT_TYPE, ContentType.negotiate(request.requestUrl())); | ||
response.addHeader(CONTENT_LENGTH, String.valueOf(content.getBytes().length)); | ||
response.setBody(content); | ||
} | ||
|
||
@Override | ||
protected void doPost(HttpRequest request, HttpResponse response) throws Exception { | ||
Map<String, String> requestBody = request.getRequestBody(); | ||
|
||
response.setVersion(request.protocolVersion()); | ||
response.setStatus(FOUND); | ||
try { | ||
User user = loginService.login(requestBody.get("account"), requestBody.get("password")); | ||
response.addHeader(LOCATION, "index.html"); | ||
|
||
Session session = new Session(); | ||
session.setAttribute(user.getAccount(), user); | ||
SessionManager.add(session); | ||
HttpCookie cookie = new HttpCookie(); | ||
cookie.addSessionId(session.id()); | ||
response.addHeader(SET_COOKIE, cookie.toString()); | ||
} catch (RuntimeException e) { | ||
response.addHeader(LOCATION, "401.html"); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package nextstep.jwp.controller; | ||
|
||
import static org.apache.coyote.HttpStatus.FOUND; | ||
import static org.apache.coyote.HttpStatus.OK; | ||
import static org.apache.coyote.header.HttpHeaders.CONTENT_LENGTH; | ||
import static org.apache.coyote.header.HttpHeaders.CONTENT_TYPE; | ||
import static org.apache.coyote.header.HttpHeaders.LOCATION; | ||
|
||
import java.util.Map; | ||
import nextstep.jwp.application.RegisterService; | ||
import nextstep.jwp.util.ResourceLoaderUtil; | ||
import org.apache.coyote.HttpRequest; | ||
import org.apache.coyote.HttpResponse; | ||
import org.apache.coyote.header.ContentType; | ||
import org.apache.coyote.http11.handler.AbstractController; | ||
|
||
public class RegisterController extends AbstractController { | ||
|
||
private final RegisterService registerService = new RegisterService(); | ||
|
||
@Override | ||
protected void doGet(HttpRequest request, HttpResponse response) throws Exception { | ||
String content = ResourceLoaderUtil.loadContent(request.requestUrl()); | ||
response.setVersion(request.protocolVersion()); | ||
response.setStatus(OK); | ||
response.addHeader(CONTENT_TYPE, ContentType.negotiate(request.requestUrl())); | ||
response.addHeader(CONTENT_LENGTH, String.valueOf(content.getBytes().length)); | ||
response.setBody(content); | ||
} | ||
|
||
@Override | ||
protected void doPost(HttpRequest request, HttpResponse response) throws Exception { | ||
Map<String, String> requestBody = request.getRequestBody(); | ||
registerService.register( | ||
requestBody.get("account"), | ||
requestBody.get("email"), | ||
requestBody.get("password") | ||
); | ||
|
||
response.setVersion(request.protocolVersion()); | ||
response.setStatus(FOUND); | ||
response.addHeader(LOCATION, "index.html"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package nextstep.jwp.controller; | ||
|
||
import static org.apache.coyote.HttpStatus.OK; | ||
import static org.apache.coyote.header.HttpHeaders.CONTENT_LENGTH; | ||
import static org.apache.coyote.header.HttpHeaders.CONTENT_TYPE; | ||
|
||
import nextstep.jwp.util.ResourceLoaderUtil; | ||
import org.apache.coyote.HttpRequest; | ||
import org.apache.coyote.HttpResponse; | ||
import org.apache.coyote.header.ContentType; | ||
import org.apache.coyote.http11.handler.AbstractController; | ||
|
||
public class ResourceController extends AbstractController { | ||
|
||
@Override | ||
protected void doGet(HttpRequest request, HttpResponse response) throws Exception { | ||
String content = ResourceLoaderUtil.loadContent(request.requestUrl()); | ||
response.setVersion(request.protocolVersion()); | ||
response.setStatus(OK); | ||
response.addHeader(CONTENT_TYPE, ContentType.negotiate(request.requestUrl())); | ||
response.addHeader(CONTENT_LENGTH, String.valueOf(content.getBytes().length)); | ||
response.setBody(content); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package nextstep.jwp.exception; | ||
|
||
public class InvalidPasswordException extends RuntimeException { | ||
|
||
public InvalidPasswordException() { | ||
super("비밀번호가 틀렸습니다."); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package nextstep.jwp.util; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.net.URL; | ||
import java.nio.file.Files; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class ResourceLoaderUtil { | ||
kdkdhoho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
private static final Logger log = LoggerFactory.getLogger(ResourceLoaderUtil.class); | ||
private static final String DEFAULT_ROOT_PATH = "static"; | ||
|
||
private ResourceLoaderUtil() { | ||
} | ||
|
||
public static String loadContent(String path) { | ||
if (!path.contains(".")) { | ||
path += ".html"; | ||
} | ||
|
||
URL resourcePath = ResourceLoaderUtil.class.getClassLoader().getResource(DEFAULT_ROOT_PATH + path); | ||
String content = ""; | ||
try { | ||
content = new String(Files.readAllBytes(new File(resourcePath.getFile()).toPath())); | ||
} catch (IOException e) { | ||
log.error(e.getMessage()); | ||
} | ||
return content; | ||
} | ||
|
||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,10 @@ | |
import java.io.UncheckedIOException; | ||
import java.net.ServerSocket; | ||
import java.net.Socket; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import org.apache.coyote.http11.Http11Processor; | ||
import org.apache.coyote.http11.adaptor.ControllerMapping; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
|
@@ -14,23 +17,27 @@ public class Connector implements Runnable { | |
|
||
private static final int DEFAULT_PORT = 8080; | ||
private static final int DEFAULT_ACCEPT_COUNT = 100; | ||
private final ControllerMapping controllerMapping; | ||
private final ExecutorService executorService; | ||
|
||
private final ServerSocket serverSocket; | ||
private boolean stopped; | ||
|
||
public Connector() { | ||
this(DEFAULT_PORT, DEFAULT_ACCEPT_COUNT); | ||
public Connector(ControllerMapping controllerMapping, int maxThreads) { | ||
this(controllerMapping, DEFAULT_PORT, DEFAULT_ACCEPT_COUNT, maxThreads); | ||
} | ||
|
||
public Connector(final int port, final int acceptCount) { | ||
public Connector(ControllerMapping controllerMapping, int port, int acceptCount, int maxThreads) { | ||
this.controllerMapping = controllerMapping; | ||
this.serverSocket = createServerSocket(port, acceptCount); | ||
this.stopped = false; | ||
this.executorService = Executors.newFixedThreadPool(maxThreads); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A이건 그냥 참고사항인데요!
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 감사합니다!! 해당 방법에 대해 생각해보고 적용까지 한번 해볼게요 :) |
||
} | ||
|
||
private ServerSocket createServerSocket(final int port, final int acceptCount) { | ||
private ServerSocket createServerSocket(int port, int acceptCount) { | ||
try { | ||
final int checkedPort = checkPort(port); | ||
final int checkedAcceptCount = checkAcceptCount(acceptCount); | ||
int checkedPort = checkPort(port); | ||
int checkedAcceptCount = checkAcceptCount(acceptCount); | ||
return new ServerSocket(checkedPort, checkedAcceptCount); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
|
@@ -60,12 +67,12 @@ private void connect() { | |
} | ||
} | ||
|
||
private void process(final Socket connection) { | ||
private void process(Socket connection) { | ||
if (connection == null) { | ||
return; | ||
} | ||
var processor = new Http11Processor(connection); | ||
new Thread(processor).start(); | ||
var processor = new Http11Processor(connection, controllerMapping); | ||
executorService.submit(processor); | ||
} | ||
|
||
public void stop() { | ||
|
@@ -77,17 +84,17 @@ public void stop() { | |
} | ||
} | ||
|
||
private int checkPort(final int port) { | ||
final var MIN_PORT = 1; | ||
final var MAX_PORT = 65535; | ||
private int checkPort(int port) { | ||
var MIN_PORT = 1; | ||
var MAX_PORT = 65535; | ||
|
||
if (port < MIN_PORT || MAX_PORT < port) { | ||
return DEFAULT_PORT; | ||
} | ||
return port; | ||
} | ||
|
||
private int checkAcceptCount(final int acceptCount) { | ||
private int checkAcceptCount(int acceptCount) { | ||
return Math.max(acceptCount, DEFAULT_ACCEPT_COUNT); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A
단순 질문입니다!
저 같은 경우는 로그인/혹은 회원가입 로직이 비대하지 않다고 판단해 컨트롤러 영역에 위치시켰는데, 서비스 클래스를 도입하신 이유가 있을까요??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
물론 하마드 말씀대로 로직 자체는 비대하지 않지만, 습관적으로 분리한 것 같아요 🤣