계산기 서블릿 만들기

hyunwoo·2023년 1월 16일
0

Spring (fastcampus)

목록 보기
11/27

Javax.servlet.Servlet @Override

package org.example;

import javax.servlet.*;
import java.io.IOException;

public class CalculatorServlet implements Servlet {
    @Override
    public void init(ServletConfig config) throws ServletException {
    
    // init 메소드는 servlet container가 servlet 생성 후 초기화 작업을 수행하게 호출하는 메소드
    // servlet 인스턴스는 한번만 생성되기에 다음 사용자 요청시에 init 메소드는 호출되지 않고 service 메소드만 호출된다.

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void destroy() {
    
	// resource release
    
    }
    
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {

    }

    @Override
    public String getServletInfo() {
        return null;
    }

}

init( ) 메소드는 한번만 실행한다.


Javax.servlet.Servlet

package org.example;

import org.example.calculator.domain.Calculator;
import org.example.calculator.domain.PositiveNumber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/calculate")   //url path와 해당 servlet을 맵핑하기 위해서 어노테이션을 쓴다.

public class CalculatorServlet implements Servlet {
    private static final Logger log = LoggerFactory.getLogger(CalculatorServlet.class);
    private ServletConfig servleltConfig;

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        log.info("init");
        this.servleltConfig = servletConfig;
    }

    @Override
    public void service(ServletRequest request, ServletResponse 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);
    }

    @Override
    public void destroy() {
    
        // resource release
        
    }

    @Override
    public ServletConfig getServletConfig() {
        return this.servleltConfig;
    }

    @Override
    public String getServletInfo() {
        return null;
    }

}

javax.servlet.GenericServlet

추상 클래스를 통해 핵심적인 service 부분만 오버라이드를 통해 구현하고 나머지 필요없는 부분은 구현하지 않아도 된다.

package org.example;

import org.example.calculator.domain.Calculator;
import org.example.calculator.domain.PositiveNumber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/calculate")   //url path와 해당 servlet을 맵핑하기 위해서 어노테이션을 쓴다.

public class CalculatorServlet extends GenericServlet {
    private static final Logger log = LoggerFactory.getLogger(CalculatorServlet.class);


    @Override
    public void service(ServletRequest request, ServletResponse 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);
    }


}

Javax.servlet.http.HttpServlet

package org.example;

import org.example.calculator.domain.Calculator;
import org.example.calculator.domain.PositiveNumber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/calculate")   //url path와 해당 servlet을 맵핑하기 위해서 어노테이션을 쓴다.

public class CalculatorServlet extends HttpServlet {
    private static final Logger log = LoggerFactory.getLogger(CalculatorServlet.class);

    @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);
        }
}

URL 인코딩 (= 퍼센트 인코딩)

• URL로 사용할 수 없는 문자(예약어, Non-ASCII 문자(한글) 등)를 사용할 수 있도록
인코딩하는 것
• 인코딩 된 문자는 triplet(세 개가 한 세트)로 인코딩 되며 각각을 % 다음에 두 개의
16진수로 표현함
--- ex) "홍" -> "%ed%99%8d" 이렇게 세 개가 한 세트로 인코딩 된다.
• 예약 문자
https://ko.wikipedia.org/wiki/%ED%8D%BC%EC%84%BC%ED%8A%B8_%EC%9D%B8%EC%BD%94%EB%94%A9

+는 예약문자어로 url에서 중요한 문법을 가지고 있기 때문에 반드시 인코딩해서 사용해야한다.

(url 인코딩)
https://convertstring.com/ko/EncodeDecode/UrlEncode

그렇기에 바로 아래 test.http의 GET 을 실행하면

이러한 에러가 나게 된다.

GET http://localhost:8080/calculate?operand1=20&operator= &operand2=10

HTTP/1.1 500 
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 1715
Date: Mon, 16 Jan 2023 18:17:07 GMT
Connection: close

<!doctype html>
<html lang="en">
<head><title>HTTP Status 500 – Internal Server Error</title>
    <style type="text/css">h1 {
        font-family: Tahoma, Arial, sans-serif;
        color: white;
        background-color: #525D76;
        font-size: 22px;
    }

    h2 {
        font-family: Tahoma, Arial, sans-serif;
        color: white;
        background-color: #525D76;
        font-size: 16px;
    }

    h3 {
        font-family: Tahoma, Arial, sans-serif;
        color: white;
        background-color: #525D76;
        font-size: 14px;
    }

    body {
        font-family: Tahoma, Arial, sans-serif;
        color: black;
        background-color: white;
    }

    b {
        font-family: Tahoma, Arial, sans-serif;
        color: white;
        background-color: #525D76;
    }

    p {
        font-family: Tahoma, Arial, sans-serif;
        background: white;
        color: black;
        font-size: 12px;
    }

    a {
        color: black;
    }

    a.name {
        color: black;
    }

    .line {
        height: 1px;
        background-color: #525D76;
        border: none;
    }</style>
</head>
<body><h1>HTTP Status 500 – Internal Server Error</h1>
<hr class="line"/>
<p><b>Type</b> Exception Report</p>
<p><b>Message</b> 올바른 사칙연산이 아닙니다.</p>
<p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.</p>
<p><b>Exception</b></p>
<pre>java.lang.IllegalArgumentException: 올바른 사칙연산이 아닙니다.
	org.example.calculator.domain.Calculator.lambda$calculate$2(Calculator.java:28)
	java.base&#47;java.util.Optional.orElseThrow(Optional.java:408)
	org.example.calculator.domain.Calculator.calculate(Calculator.java:28)
	org.example.CalculatorServlet.doGet(CalculatorServlet.java:28)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
</pre>
<p><b>Note</b> The full stack trace of the root cause is available in the server logs.</p>
<hr class="line"/>
<h3>Apache Tomcat/8.5.42</h3></body>
</html>
응답 파일이 저장되었습니다.
> 2023-01-17T031707.500.html

Response code: 500; Time: 5022ms (5 s 22 ms); Content length: 1663 bytes (1.66 kB)

위와 같이 사칙연산이 되지 않으므로

GET http://localhost:8080/calculate?operand1=20&operator=%2b&operand2=10

이렇게 "+"를 "%2b"로 바꾸게 된다면 정상적인 값이 나오게 된다.

0개의 댓글