Giter Club home page Giter Club logo

my-own-mvc-framework's Introduction

My-own-MVC-framework ๐ŸŽž

FastCampus

Environment

  • springframework '2.7.4'
  • embed:tomcat '8.5.42'
  • servlet '4.0.1'
  • slf4j-api '2.0.3'
  • spring-jdbc: '5.3.22'
  • junit-jupiter-api: '5.8.1'
  • junit-jupiter-params: '5.9.0'
  • assertj-core: '3.22.0'
  • h2database:h2: '2.1.214'
  • reflections: '0.10.2'

my-own-mvc-framework's People

Contributors

sungwon-097 avatar

Watchers

 avatar

Forkers

constwon111

my-own-mvc-framework's Issues

stream() ์—์„œ์˜ map()

stream().map() : ์ŠคํŠธ๋ฆผ๋‚ด ์š”์†Œ๋“ค์— ๋Œ€ํ•ด ํ•จ์ˆ˜๊ฐ€ ์ ์šฉ๋œ ๊ฒฐ๊ณผ์˜ ์ƒˆ๋กœ์šด ์š”์†Œ๋กœ ๋งคํ•‘ํ•ด์ค€๋‹ค.

// My-own-MVC-framework/src/test/src/main/java/com/example/test/arithmeticCalculator.java

public static int calculate(PositiveNumber operand1, String operator, PositiveNumber operand2) {
        return arithmeticOperators.stream()
                .filter(arithmeticOperator -> arithmeticOperator.supports(operator))
                .map(arithmeticOperator -> arithmeticOperator.calculate(operand1, operand2)) // << issue
                .findFirst()
                .orElseThrow(()-> new IllegalArgumentException("์˜ฌ๋ฐ”๋ฅธ ์—ฐ์‚ฐ์ด ์•„๋‹™๋‹ˆ๋‹ค"));
    }

// My-own-MVC-framework/src/test/src/main/java/com/example/test/arithmeticCalculator.java

public static int calculate(int operand1, String operator, int operand2) {
        ArithmeticOperator arithmeticOperator = Arrays.stream(values())
                .filter(v -> v.operator.equals(operator))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("์˜ฌ๋ฐ”๋ฅธ ์—ฐ์‚ฐ์ด ์•„๋‹™๋‹ˆ๋‹ค"));

        return arithmeticOperator.arithmeticCalculate(operand1, operand2);
    }
  • arithmeticOperators.stream() ๋‚ด์˜ ๊ฐ์ฒด๋ฅผ arithmeticOperator.calculate() ๋ฉ”์†Œ๋“œ๋กœ ๋งคํ•‘ํ•ด์ค€๋‹ค.
    1. filter() : ๋งค๊ฐœ๋ณ€์ˆ˜ operator์˜ ๊ฐ’์„ ์ฐพ์Œ
    2. map() : ๋งค๊ฐœ๋ณ€์ˆ˜ operand 1, 2์˜ ๊ฐ’์„ ๋งคํ•‘
    3. findFirst() : ๋งคํ•‘๋œ ์ŠคํŠธ๋ฆผ ์ƒ์œ„์˜ ๊ฐ’์„ ์ฐพ์Œ
    4. orElseThrow() : ๋งคํ•‘๋œ ๋‚ด์šฉ์ด ์—†๋‹ค๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง

์ฐธ๊ณ ์ž๋ฃŒ

Flow of SpringBoot Framework

SpringBoot Framework ๋™์ž‘ ์›๋ฆฌ

@WebServlet("/")
public class DispatcherServlet extends HttpServlet {
    ...
    @Override
    public void service(HttpServletRequest req, HttpServletResponse res){
    ...
    Controller handler = requestMappingHandlerMapping.findHandler(req.getRequestURI());
  • ๋ชจ๋“  Request๋Š” DispatcherServlet์„ ํ†ตํ•ด ๋“ค์–ด์˜ค๊ณ  handler์— mapping์‹œํ‚ด
public class RequestMappingHandlerMapping {
    // key : users/, value : userController
    private Map<String, Controller> mappings = new HashMap<>();

    public void init(){
        mappings.put("/", new HomeController());
        mappings.put("/users", new UserListController());
    }

    public Controller findHandler(String uriPath){
        return mappings.get(uriPath);
    }
}
  • uriPath์— ๋งž๋Š” Controller๋ฅผ ๋ฐ˜ํ™˜
public class HomeController implements Controller{
    @Override
    public String handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        return "home.jsp";
    }
}
  • Controller์—์„œ๋Š” viewName์„ ๋‹ค์‹œ handlerAdapter์—๊ฒŒ ์ „๋‹ฌ
@WebServlet("/")
public class DispatcherServlet extends HttpServlet {
    ...
    @Override
    public void service(HttpServletRequest req, HttpServletResponse res){
    ...
        View view = viewResolver.resolveViewname(ModelAndView, getViewName());
        view.render(ModelAndView.getModel(), req, res);
  • viewResolver๋Š” ํ•ด๋‹น๋˜๋Š” view์˜ ์ด๋ฆ„์„ ์ฐพ์•„ ๋ฆฌํ„ดํ•ด์ฃผ๊ณ  ๋ฆฌํ„ด๋œ ๋ทฐ๋ฅผ ๋‹ค์‹œ DispatcherServlet์—์„œ ๋ Œ๋”๋ง ํ•ด์คŒ์œผ๋กœ์„œ Responseํ•จ

Flow

img

MVC Framework

  • createProject
  • Controller mapping
  • implement Get, Post

TDD ์ „๋žต์œผ๋กœ ์Œ์‹์ฃผ๋ฌธ ํ”„๋กœ์„ธ์Šค ๋งŒ๋“ค๊ธฐ

  1. ๋„๋ฉ”์ธ์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฐ์ฒด : ์†๋‹˜, ๋ฉ”๋‰ดํŒ, ์š”๋ฆฌ, ์š”๋ฆฌ์‚ฌ ...
  2. ๊ฐ์ฒด๋“ค๊ฐ„์˜ ๊ด€๊ณ„
  • ์†๋‹˜ <-> ๋ฉ”๋‰ดํŒ
  • ์†๋‹˜ <-> ์š”๋ฆฌ์‚ฌ
  • ์š”๋ฆฌ์‚ฌ <-> ์š”๋ฆฌ
  1. ๋™์ ์ธ ๊ฐ์ฒด๋ฅผ ์ •์ ์ธ ํƒ€์ž…์œผ๋กœ ์ถ”์ƒํ™”ํ•ด์„œ ๋„๋ฉ”์ธ ๋ชจ๋ธ๋ง
  2. ํ˜‘๋ ฅ์„ ์„ค๊ณ„
  3. ๊ฐ์ฒด๋“ค์„ ํฌ๊ด„ํ•˜๋Š” ํƒ€์ž…์— ์ ์ ˆํ•œ ์ฑ…์ž„์„ ํ• ๋‹น
  4. ๊ตฌํ˜„

์‹œ์ž‘ํ•˜๊ธฐ

  • ๊ฐ•์˜ ๋ชฉํ‘œ ์†Œ๊ฐœ
  • ๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ค์ •
    • Tomcat(~Ch01)
    • Docker
    • mySQL(~Ch02)

์ ˆ์ฐจ์ง€ํ–ฅ๊ณผ ๊ฐ์ฒด์ง€ํ–ฅ

ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ์ข…๋ฅ˜๊ฐ€ ์•„๋‹ˆ๋ผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ์ข…๋ฅ˜์ด๋‹ค. ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€๋กœ ๋‚˜๋‰˜๊ณ , ๊ฐ์ฒด์ง€ํ–ฅ๊ณผ ์ ˆ์ฐจ์ง€ํ–ฅ์€ ์„œ๋กœ ๋Œ€๋ฆฝ๋˜๋Š” ๊ฐœ๋…์€ ์•„๋‹ˆ๋‹ค.

๊ฐ์ฒด์ง€ํ–ฅ ์ ˆ์ฐจ์ง€ํ–ฅ
ํŠน์ง• ์‹ค์ œ ์„ธ๊ณ„๋ฅผ ๋ชจ๋ธ๋งํ•˜์—ฌ ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ๋ฐฉ๋ฒ• ์ˆœ์ฐจ์ ์ธ ์ฒ˜๋ฆฌ๋กœ ํ”„๋กœ๊ทธ๋žจ ์ „์ฒด๊ฐ€ ์œ ๊ธฐ์ ์œผ๋กœ ์—ฐ๊ฒฐ๋˜๋„๋ก ํ•˜๋Š” ๋ฐฉ๋ฒ•
์ดˆ์  ๊ฐ์ฒด๊ฐ„์˜ ๊ด€๊ณ„์™€ ์กฐ์ง(๊ธฐ๋Šฅ ์ค‘์‹ฌ) ์ˆœ์ฐจ์ ์ธ ์‹คํ–‰(๋ฐ์ดํ„ฐ ์ค‘์‹ฌ)
์žฅ์  ์ฝ”๋“œ์˜ ์žฌํ™œ์šฉ์„ฑ์ด ๋†’์Œ
์ฝ”๋”ฉ์ด ์ ˆ์ฐจ์ง€ํ–ฅ๋ณด๋‹ค ๊ฐ„ํŽธํ•จ
๋””๋ฒ„๊น…์ด ์‰ฌ์›€
์ปดํ“จํ„ฐ์˜ ์ฒ˜๋ฆฌ๊ตฌ์กฐ์™€ ์œ ์‚ฌํ•ด ์‹คํ–‰์†๋„๊ฐ€ ๋น ๋ฆ„
๋‹จ์  ์ฒ˜๋ฆฌ์†๋„๊ฐ€ ์ ˆ์ฐจ์ง€ํ–ฅ๋ณด๋‹ค ๋Š๋ฆผ
์„ค๊ณ„์— ๋งŽ์€ ์‹œ๊ฐ„์†Œ์š”๊ฐ€ ๋“ค์–ด๊ฐ
์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›€
์ฝ”๋“œ์˜ ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์žฅํ•˜๊ธฐ ์–ด๋ ค์›€
๋””๋ฒ„๊น…์ด ์–ด๋ ค์›€

์ฐธ๊ณ ์ž๋ฃŒ

TDD ์ „๋žต์œผ๋กœ ํ•™์  ๊ณ„์‚ฐ๊ธฐ ๋งŒ๋“ค๊ธฐ

  • ํ•™์ ๊ณ„์‚ฐ๊ธฐ ๋„๋ฉ”์ธ : ์ด์ˆ˜ํ•œ ๊ณผ๋ชฉ, ํ•™์  ๊ณ„์‚ฐ๊ธฐ
  • ๊ณผ๋ชฉ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๋Š” ํด๋ž˜์Šค๋กœ ํ‘œํ˜„
  • ์ด์ˆ˜ํ•œ ๊ณผ๋ชฉ์„ ์ „๋‹ฌํ•˜์—ฌ ํ‰๊ท ํ•™์  ๊ณ„์‚ฐ ์š”์ฒญ --> ํ•™์  ๊ณ„์‚ฐ๊ธฐ

์ƒˆ๋กœ์šด Thread์—์„œ ์ž‘์—…์„ ์‹คํ–‰

// CustomWebApplicationServer
public class CustomWebApplicationServer {

    private final int port;

    private static final Logger logger = LoggerFactory.getLogger(CustomWebApplicationServer.class);
    public CustomWebApplicationServer(int port) {
        this.port = port;
    }

    public void start() throws IOException {
      while((clientSocket = serverSocket.accept()) != null){
                      logger.info("[CustomWebApplicationServer] client connected.");
                      new Thread(new ClientRequestHandler(clientSocket)).start(); // [1]

// ClientRequestHandler
public class ClientRequestHandler implements Runnable {

    @Override
    public void run() {
//      [2]
   }
  • ๊ธฐ์กด์—๋Š” [1]์— ํ–‰๋™์„ ๊ธฐ์ˆ  ํ•˜์˜€์ง€๋งŒ ๊ทธ ๋ถ€๋ถ„์„ [2]๋กœ ์˜ฎ๊น€
  • Runnable์„ implementํ•œ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ธฐ์กด์— main thread์—์„œ ํ•˜๋˜ ์ž‘์—…์„ run() ์žฌ์ •์˜ํ•ด ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•จ
  1. ์žฅ์  : ๋™์‹œ์„ฑ ํ–ฅ์ƒ
  2. ๋‹จ์  : ๋ฉ”๋ชจ๋ฆฌ์™€ ํ”„๋กœ์„ธ์„œ ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€
    • new Thread().start() ๋Š” ๊ฐ๊ฐ์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„(stack)์„ ํ• ๋‹นํ•˜๋ฉฐ ํ”„๋กœ์„ธ์„œ์—์„œ Context Switch ํ•˜๋Š” ํšŸ์ˆ˜ ๋˜ํ•œ ๋งŽ์•„์ง€๊ธฐ ๋•Œ๋ฌธ
  3. ํ•ด๊ฒฐ์ฑ… : Thread pool์„ ์ ์šฉํ•œ๋‹ค

about tomcat path setting

ํ†ฐ์บฃ ์„œ๋ฒ„๋Š” ์ปดํŒŒ์ผ์ด ์™„๋ฃŒ๋œ ์„œ๋ธ”๋ฆฟ ํด๋ž˜์ŠคํŒŒ์ผ์„ ์ฐพ๊ธฐ ์œ„ํ•ด WEB-INF ํด๋”์˜ ํ•˜์œ„ ํด๋”์ธ classes ํด๋”๋ฅผ ๋’ค์ง€๋Š” ๊ทœ์น™์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด ์—ฌ๋Ÿฌ ํ”„๋กœ์ ํŠธ์—์„œ ์ปดํŒŒ์ผ ๊ฒฐ๊ณผ ํŒŒ์ผ์˜ ์ƒ์„ฑ์œ„์น˜๋ฅผ ์ž„์˜๋กœ ์ง€์ •ํ•ด์ฃผ์—ˆ๋Š”๋ฐ(๊ฐ•์˜ ์˜์ƒ์—์„œ),
ํ•ด๋‹น ๊ฒฝ๋กœ๋Š” gradle ํŒŒ์ผ(build.gradle)์— ์˜์กด ํ•˜๋ฏ€๋กœ gradle ๋กœ ์žฌ๋นŒ๋“œ ํ•˜๊ฑฐ๋‚˜ ์ธํ…”๋ฆฌ์ œ์ด๊ฐ€ ํ”„๋กœ์ ํŠธ ์ธ๋ฑ์‹ฑ์„ ์ƒˆ๋กœํ•˜๋Š” ๊ฒฝ์šฐ, ๊ฒฝ๋กœ๊ฐ€ ์ดˆ๊ธฐํ™” ๋ฉ๋‹ˆ๋‹ค.

์œ„์˜ ๊ฒฝ์šฐ, ๋‹ค์‹œ ์ปดํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ด ์ฃผ์–ด์•ผ ํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, build.gradle ์— ๊ฒฝ๋กœ ์„ค์ •์„ ๋ช…์‹œํ•ด์ฃผ๋ฉด ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

plugins {
    id 'java'
    id 'idea'
}

idea {
    module {
        inheritOutputDirs = false
        outputDir = file('/{your}/{project}/{path}/{project-name}/webapps/WEB-INF/classes')
    }
}

์ต๋ช…ํด๋ž˜์Šค๋ฅผ ๋žŒ๋‹ค์‹์œผ๋กœ

// annonymous Class
public void create(User user) throws SQLException {

        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        String sql = "INSERT INTO USERS VALUES (?,?,?,?)";
        jdbcTemplate.executeUpdate(user, sql, new PreparedStatementSetter() {
            @Override
            public void Setter(PreparedStatement pstamt) throws SQLException {
                pstamt.setString(1, user.getUserid());
                pstamt.setString(2, user.getPassword());
                pstamt.setString(3, user.getName());
                pstamt.setString(4, user.getEmail());
            }
        });
    }

// lambda
public void create(User user) throws SQLException {

        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        String sql = "INSERT INTO USERS VALUES (?,?,?,?)";
        jdbcTemplate.executeUpdate(user, sql, pstamt -> {
            pstamt.setString(1, user.getUserid());
            pstamt.setString(2, user.getPassword());
            pstamt.setString(3, user.getName());
            pstamt.setString(4, user.getEmail());
        });
    }

intelliJ์—์„œ ๊ตฌํ˜„ํ•˜๋ ค๋Š” ๋ฉ”์†Œ๋“œ์— option(alt)+Enter ํ•˜๋ฉด ๋žŒ๋‹ค์‹์œผ๋กœ ๋ณ€ํ™˜.

Spring Framework์—์„œ์˜ Reflection

  • Spring Framework๋Š” @service, @repository, @component์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋“ฑ๋ก์‹œํ‚จ Bean๋“ค์„ Spring Container์•ˆ์˜ BeanFactory์— ๋“ฑ๋ก์‹œ์ผœ ๋Ÿฐํƒ€์ž„์‹œ ๋™์ ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
  • SpringContainer.of(beanFactory(@service, @repository, @component... any other beans ...)) -> Runtime

Refelction์ด๋ž€

  • ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค ํƒ€์ž…์„ ์•Œ์ง€ ๋ชปํ•ด๋„ ๊ทธ ํด๋ž˜์Šค์˜ ์ •๋ณด(๋ฉ”์„œ๋“œ, ํƒ€์ž…, ๋ณ€์ˆ˜ ๋“ฑ๋“ฑ)์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์ž๋ฐ” API๋‹ค.
  • ํด๋ž˜์Šค์˜ ์ด๋ฆ„๋งŒ์œผ๋กœ ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค
private Set<Class<?>> getTypesAnnotatedWith(List<Class<? extends Annotation>> annotations) {
        Reflections reflections = new Reflections("com.example");

        Set<Class<?>> beans = new HashSet<>();
        annotations.forEach(annotation -> beans.addAll(reflections.getTypesAnnotatedWith(annotation)));
        
        return beans;
    }
// annotationd์˜ List๋กœ ๋“ค์–ด์˜จ ์ธ์ž๋“ค์„ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด reflection์˜ prefix์— ์กด์žฌํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋ชจ๋‘ beans์— ์ถ”๊ฐ€ํ•ด์ค€๋‹ค

Thread Pool ์ ์šฉ

// CustomWebApplicationServer
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CustomWebApplicationServer {
  private final ExecutorService executorService = Executors.newFixedThreadPool(10); // Thread 10๊ฐœ๋ฅผ ์šด์šฉํ•˜๋Š” Pool

  //   new Thread(new ClientRequestHandler(clientSocket)).start();
  executorService.execute(new ClientRequestHandler(clientSocket));
}
  • new Thread ๋ฅผ ๋ฌด์ œํ•œ์œผ๋กœ ์‹คํ–‰ ํ•˜๊ฒŒ ๋˜๋ฉด ์ž์›์ด ๋ถ€์กฑํ•ด ์‹œ์Šคํ…œ์ด ๋‹ค์šด ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ฌธ์ œ์ ์ด ๋ฐœ์ƒํ•œ๋‹ค.
  • Thread Pool์€ ์ž‘์—… ์ฒ˜๋ฆฌ์— ์‚ฌ์šฉ๋˜๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ์ œํ•œ๋œ ๊ฐœ์ˆ˜๋งŒํผ ์ •ํ•ด ๋†“๊ณ  ์ž‘์—… ํ์— ๋“ค์–ด์˜ค๋Š” ์ž‘์—…๋“ค์„ ํ•˜๋‚˜์”ฉ ์Šค๋ ˆ๋“œ๊ฐ€ ๋งก์•„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

SLF4J ๊ตฌํ˜„์ฒด ๋ฌธ์ œ

// >Run

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". 
SLF4J: Defaulting to no-operation (NOP) logger implementation 
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
  • ๋นŒ๋“œ๋Š” ์ •์ƒ์ ์œผ๋กœ ์ง„ํ–‰์ด ๋˜๋‚˜ ๋กœ๊ทธ๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š์Œ
// build.gradle

    implementation 'ch.qos.logback:logback-classic:0.9.26'
    implementation 'org.slf4j:slf4j-api:2.0.1'
    implementation 'org.slf4j:slf4j-simple:2.0.1'
  • ์˜์กด์„ฑ ์ถ”๊ฐ€๋กœ ํ•ด๊ฒฐ

Modifiy compiler output module

  • Command + // Project Structure ์ง„์ž…
  • Modules / main / Path /use module compile output path
  • [REPOSITORY]/src/[PROJECT_NAME]/webapp/WEB-INF/classes ๋กœ ์ปดํŒŒ์ผ ๊ฒฝ๋กœ ์ˆ˜์ •

JDBC์˜ ์ดํ•ด

  • ์‹ค์Šตํ™˜๊ฒฝ ๊ตฌ์ถ•
  • jdbc ์—ฐ๊ฒฐ
  • ํ…Œ์ด๋ธ” ์ƒ์„ฑ
  • ์ปค๋„ฅ์…˜ํ’€ ์ ์šฉ

@GetMapping()์˜ ๋™์ž‘

  1. Tomcat์ด Servlet์˜ service() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•จ
  2. service() ๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€์—์„œ doGet(req, resp) ์„ ํ˜ธ์ถœ
  3. HTTP GET์œผ๋กœ ๋“ค์–ด์˜จ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•จ(POST, PUT, PATCH, DELETE๋“ฑ๋„ ๋™์ผ)
@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        log.info("service");
        int operand1 = Integer.parseInt(request.getParameter("operand1"));
        String operator = request.getParameter("operator");
        int operand2 = Integer.parseInt(request.getParameter("operand2"));

        int result = Calculator.calculate(new PositiveNumber(operand1),operator ,new PositiveNumber(operand2));

        PrintWriter writer = response.getWriter();
        writer.println(result);
    }

Race Condition ๋ฐœ์ƒ

  • Singleton Pattern : ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์ž‘ ๋  ๋•Œ ์ตœ์ดˆ ํ•œ ๋ฒˆ๋งŒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๊ณ  ๊ทธ ๋ฉ”๋ชจ๋ฆฌ์— ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด
  • Servlet Container๋Š” Servlet ๊ฐ์ฒด๋ฅผ Singleton Pattern์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— statefulํ•˜๊ฒŒ ์„ค๊ณ„ํ•˜๋ฉด ์•ˆ๋œ๋‹ค
    • Multi Thread ํ™˜๊ฒฝ์—์„œ Race Condition ๋ฐœ์ƒ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ

+ ์ถ”๊ฐ€๋กœ ์ฝ”๋“œ์—์„œ ๋™๊ธฐํ™” ๋ฐฉ์‹์œผ๋กœ Race Condition์„ ๋ฐฉ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด Synchronized Block์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค

public class Counter implements Runnable{

    @Override
    public void run() {
        synchronized (this) { // ๋™๊ธฐํ™” ์‚ฌ์šฉ
            this.increment();
            System.out.println("value for Thread After increment " 
                        + Thread.currentThread().getName() + " " + this.getValue()); // 1
            this.decrement();
            System.out.println("value for Thread at last "
                        + Thread.currentThread().getName() + " " + this.getValue()); // 0
        }
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.