728x90
- 총 10개의 숫자1 * 숫자2 = 답 이 출력되는 칸을 만든다.
- client -> server 에게로 n개의 요청이 가면 n개의 응답이 오는 방식으로 구현한다.
- 빈 곳은 제외하고 서버로 전송되어야 하고 제외된 상태로 응답을 받아야 한다.
- ajax를 통해 이루어지도록 한다.
- 입력값 또는 결과값이 int 범위를 넘어가는 경우 예외처리를 해준다.
1단계 : M(Model) 역할의 MultiplicationService.java 파일 만들기
@Service
public class MultiplicationServiceImpl implements MultiplicationService {
private MultiplicationServiceImpl() {}
public String generateProductResult(String inputValue) {
List<Map<String, Object>> product = createProductList(inputValue);
Gson gson = new Gson();
String gsonString = gson.toJson(product);
return gsonString;
}
private List<Map<String, Object>> createProductList(String inputValue) {
JSONArray jsonArray = new JSONArray(inputValue);
List<Map<String, Object>> productList = new ArrayList<Map<String, Object>>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
try {
productList.add(createProductMap(jsonObject.getInt("firstFactor"), jsonObject.getInt("secondFactor"), jsonObject.getString("product")));
} catch(Exception e) {
productList.add(exceptionProductMap(jsonObject.getString("product")));
}
}
return productList;
}
private Map<String, Object> exceptionProductMap(String product) {
Map<String, Object> exceptionProductMap = new HashMap<String, Object>();
exceptionProductMap.put(product, "계산 가능 범위 초과");
return exceptionProductMap;
}
// product1=10 형태로 맵에 저장한다.
private Map<String, Object> createProductMap(int firstFactor, int secondFactor, String product) {
Map<String, Object> productMap = new HashMap<String, Object>();
productMap.put(product, generateProduct(firstFactor, secondFactor));
return productMap;
}
// firstFactor와 secondFactor 를 인수로 받아서 두 수의 곱의 결과(product)를 리턴한다.
// 2, 5 -> 10
private Object generateProduct(int firstFactor, int secondFactor) {
int product = firstFactor * secondFactor;
String productExcess = "계산 가능 범위 초과";
if (firstFactor == 0 || secondFactor == 0) {
return 0;
} else {
// 두 수의 부호가 같은 경우
if (firstFactor > 0 && secondFactor > 0 ||
firstFactor < 0 && secondFactor < 0) {
// 곱이 int의 최대값보다 클 경우
if(Math.abs(firstFactor) > (Integer.MAX_VALUE / Math.abs(secondFactor))) {
return productExcess;
} else {
return product;
}
} else {
// 곱이 int 최소값보다 작을 경우
if(-Math.abs(firstFactor) < (Integer.MIN_VALUE / Math.abs(secondFactor))) {
return productExcess;
} else {
return product;
}
}
}
}
}
- generateProductResult(String inputValue)
- 컨트롤러를 통해 inputValue를 인자로 받는다.
- 이를 Gson을 이용하여 json 문자열 형태로 변환하여 리턴한다.
- createProductList(String inputValue)
- generateProductResult() 메서드를 통해 inputValue를 인자로 받아 이를 JSONArray 형태로 받는다.
- jsonArray의 값을 반복문을 통해 jsonObject로 하나씩 꺼낸다.
- 숫자1의 값을 jsonObject.getInt("firstFactor")로, 숫자2의 값을 jsonObject.getInt("secondFactor")로, 답의 칸의 값을 jsonObject.getString("product")로 꺼냈다.
- 꺼낸 값을 List<map<string, object>> 형태의 productList에 넣어주었다.
- 이 때, 꺼낸 값이 int 범위를 초과하는 경우 예외가 발생하기 때문에 try/catch 문을 사용하였다.
- 예외가 발생하지 않는 경우 createProductMap() 메서드로 연결하였다.
- 예외가 발생하는 경우 exceptionProductMap() 메서드로 연결하였다.
- createProductMap(int firstFactor, int secondFactor, String product)
- Map<String, Object> 형태의 productMap을 만든다.
- 만들어진 productMap에 키 값으로 product 를 사용한다.
- product 키에 대한 값으로 generateProduct(firstFactor, secondFactor)를 넣어주었다.
- exceptionProductMap(String product)
- 예외가 발생한 경우 product의 값을 인자로 받아 이를 key로 넣어 "계산 가능 범위 초과" 라는 문자열을 값으로 담았다.
- generateProduct(int firstFactor, int secondFactor)
- 인자로 받은 firstFactor와 secondFactor를 곱한 값인 product를 리턴한다.
- 이 때, product의 값이 int 범위를 초과하는 경우가 있어 이를 위해 여러개의 if-else 문을 통해 처리해주었다.
- firstFactor가 0이거나 secondFactor 0일 때, 혹은 두 수 모두 0일 때 0을 리턴한다.
- 두 수 모두 0이 아닐 때
- 두 수의 부호가 같은 때 곱의 결과가 int의 최대값보다 클 경우 "계산 가능 범위 초과" 문자열을 리턴하고, 그 밖의 경우 결과값을 리턴한다.
- 그 외의 경우 곱의 결과가 int의 최소값보다 작을 경우 "계산 가능 범위 초과" 문자열을 리턴하고, 그 밖의 경우 결과값을 리턴한다.
2단계 : V(View) 역할의 multiplication.jsp 파일 만들기
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>곱셈</title>
</head>
<body>
<div id="formDiv"></div>
<script src="http://code.jquery.com/jquery-3.5.1.min.js"></script>
<script type="text/javascript">
/* formDiv 구성 */
for (var i = 1; i <= 10; i++) {
var firstFactorTag = document.createElement('input');
firstFactorTag.setAttribute('id', 'firstFactor'+i);
firstFactorTag.setAttribute('placeholder', '숫자1');
firstFactorTag.setAttribute('onKeyup', "this.value=this.value.match(/^(-?)[0-9]*/g);");
var secondFactorTag = document.createElement('input');
secondFactorTag.setAttribute('id', 'secondFactor'+i);
secondFactorTag.setAttribute('placeholder', '숫자2');
secondFactorTag.setAttribute('onKeyup', "this.value=this.value.match(/^(-?)[0-9]*/g);");
var productTag = document.createElement('input');
productTag.setAttribute('id', 'product'+i);
productTag.setAttribute('readonly', true); // readonly 지정 방법
productTag.setAttribute('placeholder', '답');
$("#formDiv").append(firstFactorTag, ' × ', secondFactorTag, ' = ', productTag, '<br>');
}
$("#formDiv").append("<button type='button'>계산하기</button>");
/* 결과 구성 */
$('button').on('click', function() {
// 배열 선언
var dataArr = new Array();
for (var i = 1; i <= 10; i++) {
// 객체 생성
var dataObj = new Object();
// 객체에 input 값을 담는다.
dataObj.firstFactor = $('#firstFactor' + i).val();
dataObj.secondFactor = $('#secondFactor' + i).val();
dataObj.product = 'product' + i;
// 둘 중 하나만 입력했을 때 "두 수 모두 입력하세요" 출력
if (dataObj.firstFactor != '' && dataObj.secondFactor == '' ||
dataObj.firstFactor =='' && dataObj.secondFactor != '') {
alert("두 수 모두 입력하세요");
}
// firstFactor가 '' 이거나 secondFactor가 '' 인 경우 factor 객체를 null로 만든다.
if (dataObj.firstFactor == '' || dataObj.secondFactor == '') {
dataObj = null;
}
// 배열에 생성된 객체를 삽입한다. ('null'이 포함된 상태)
dataArr.push(dataObj);
}
// null을 필터링하여 제거한 배열을 만든다.
var removeNullDataArr = dataArr.filter((element) => element != null);
// 배열을 json 형태의 문자열로 만든다.
var jsonData = JSON.stringify(removeNullDataArr);
// 클라이언트에서 Content-type을 application/json으로 세팅해서 송신, 서버에서 @RequestBody로 받으면
// Json 데이터를 송수신할 수 있다.
$.ajax({
url: "/getProduct.do",
contentType: "application/json; charset=UTF-8",
data: jsonData,
method: "POST"
}).done(function(returnValue) { // 호출 성공하면 product 출력
printProducts(returnValue);
});
});
function printProducts(returnValue) {
var value = JSON.parse(returnValue);
value.forEach(function(item) {
for (var key in item) { // value의 key를 모두 열거.
$('#' + key).attr('value',item[key]);
}
})
}
</script>
</body>
</html>
- id="formDiv"의 div 태그를 하나 만든다.
- 자바스크립트를 이용하여 div 태그에 □ × □ = □ 형태의 칸을 10개 만들고 각각 firstFactor1~10, secondFactor1~10, product1~10 의 id 값을 준다.
- 이를 위해 1 ~ 10까지 반복문을 돌면서 input 태그를 만들고 id 속성, placeholder 속성, onKeyup 속성을 추가해주었다.
- type="button"의 button을 하나 만든다.
- button을 클릭했을 때 함수가 호출된다.
- dataArr 배열을 선언하였다.
- 1~10까지 반복하며 firstFactor1~10의 값, secondFactor1~10의 값, product1~10을 dataObj 객체에 각각 firstFactor, secondFactor, product 이름의 키에 담았다.
- firstFactor와 secondFactor 중 하나에만 입력될 경우 "두 수 모두 입력하세요" 라는 알람이 뜨도록 하였다.
- 또한 두개의 수 중 하나라도 빈칸인 경우 이 때의 객체 자체를 null로 만들어주었다.
- 생성된 dataObj 객체를 dataArr 배열에 담았다.
- dataArr 배열에서 null 값을 필터링한 배열 removeNullDataArr 를 만들었다.
- removeNullDataArr를 json 형태의 문자열 jsonData 로 만들었다.
- ajax 를 통해 jsonData를 contentType: "application/json; charset=UTF-8"로 송신하였다.
- 호출이 성공할 경우 returnValue를 받아서 이를 printProducts() 메서드로 연결되도록 하였다.
- dataArr 배열을 선언하였다.
- printProducts(returnValue)
- returnValue를 json 형태로 받은 후에 forEach 문을 사용하여 값들을 꺼내주었다.
- 꺼낸 값을 key에 value 속성으로 넣어주었다.
3단계 : C(Controller) 역할의 MultiplicationController.java 파일 만들기
728x90
@Controller
public class MultiplicationController {
@Autowired
MultiplicationService multiplicationService;
@RequestMapping(value = "/home", method = RequestMethod.GET)
public String home() {
return "multiplication";
}
@ResponseBody
@RequestMapping(value = "/getProduct.do", method = RequestMethod.POST, produces = "application/text; charset=utf8")
public String getProduct(@RequestBody String inputValue) {
String gsonString = multiplicationService.generateProductResult(inputValue);
return gsonString;
}
}
- @Autowired 애너테이션을 이용하여 MultiplicationService 객체를 주입하였다.
- 첫번째 @RequestMapping 을 통해 메인 화면과 연결하였다.
- 두 번째 @RequestMapping 을 통해 결과 화면과 연결하였다.
- 문자열의 한글이 깨지는 것을 방지하기 위해 produces 속성에 값을 "application/text; charset=utf8"로 주었다.
- return 되는 값을 그대로 json 문자열로 사용하기 위해 @ResponseBody 애너테이션을 사용하였다.
- View에서 application/json 형태로 받은 inputValue를 사용하기 위해 @RequestBody 애너테이션을 사용하였다.
- inputValue를 서비스 객체의 메서드와 연결하여 문자열 형태로 받은 후 이를 리턴해준다.
728x90
'Project' 카테고리의 다른 글
스프링 MVC로 구구단 출력 프로그램 만들기 - 도메인(vo), JUnit 테스트 (0) | 2021.10.25 |
---|---|
자바스크립트 MVC 형태로 구구단 출력 프로그램 만들기 (0) | 2021.10.22 |
자바스크립트로 빈도 top10 문자 카운터 만들기 (0) | 2021.10.21 |
자바스크립트로 입력값 모음 개수 카운터 프로그램 만들기 (0) | 2021.10.20 |
자바스크립트로 문자의 개수를 카운트해주는 프로그램 만들기 (0) | 2021.10.19 |