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( ) 메소드는 한번만 실행한다.
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;
}
}
추상 클래스를 통해 핵심적인 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);
}
}
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로 사용할 수 없는 문자(예약어, 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/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"로 바꾸게 된다면 정상적인 값이 나오게 된다.