GDJ 24/06/17 (Ajax, chart.js)

kimuki·2024년 6월 17일
post-thumbnail
# $.ajax 를 사용한 유효성 검사

Controller > Service > Mapper 를 통해
입력받은 id, pw의 중복을 검사하고

결과값을 Controller에서 받아
중복이 있으면 1, 없으면 0을 리턴한다

리턴한 값은 $.ajax에서 json 값으로 들어오며

$.ajax에서 function(json)의 형태로 json의 값에 따라

html(view)에서 어떤 결과를 보여줄지 작성하면 된다

이 때 $.ajax의 url 은 Controller의 Mapping 주소가 되고
method는 post, data값은 id 혹은 pw가 된다 
$('#id').val() > id의 value값을 이용하는 $.ajax 문법
success : function(~~)


# chart.js 사용
w3school chart.js 에서 예시코드 가져와서 틀만 가져오고
사용할 데이터만 가공해서 넘기기

ex) List<Map>형태로 컬럼명과 COUNT(*) cnt 값을 가져와서

const xValues = [];
const yValues = [];

json.forEach(function(item){
	xValues.push(item.컬럼명);
	yValues.push(item.cnt);
});
처럼 데이터 넣어서 차트로 데이터 출력하기


# $.ajax의 동기식 방식
$.ajax는 비동기 방식으로 동작하는것이 default이지만
때에 따라 동기식 방식으로 사용하는 경우가 있다

비동기 방식 : 프로그램 실행과 동시에 동작하는것이 아닌
특정 조건에 따라 이벤트가 발생할 때
ex) 버튼 누르기, 이벤트 발생(alert)

동기 방식 : 프로그램 실행과 동시에 동작하는 방식
ex) 그래프 출력, 차트 출력 등

$.ajax를 동기 방식으로 동작시키게 하기 위해서
$.ajax의 속성에 async : false 속성을 추가하면 된다.
(jQuery의 ajax호출은 async : true 가 기본이다 (비동기 방식))


# 405 not allowed method 발생
차트 만들기 프로젝트 진행 중 위 에러 발생

원인 : $.ajax의 method가 post로 되어있는데
url에 적은 /chart/rest/getCountGender RestController의
Mapping 방식이 @GetMapping 으로 되어 있어
$.ajax의 method(Post)와 RestController의(Get)이 충돌하여 발생

해결 : RestController의 Mapping명을
GetMapping에서 PostMapping으로 변경 후 정상 작동


# AWS Lightsail Docker 설치
https://cafe.naver.com/jjdev/16139

HomeController.java (Controller)

package com.gd.chart.controller;

import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;

import lombok.extern.slf4j.Slf4j;

@Controller
@Transactional
@Slf4j
public class HomeController {
	
	@GetMapping("/home")
	public String home() {
		
		return "home";
	}
	
	@GetMapping("/chart2")
	public String chart2() {
		
		return "chart2";
	}
	
	@GetMapping("/chart3")
	public String chart3() {
		
		return "chart3";
	}
	
	@GetMapping("/chart4")
	public String chart4() {
		
		return "chart4";
	}
}

HomeRest.java (RestController 데이터 전달용)

package com.gd.chart.rest;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.gd.chart.mapper.EmployeesMapper;

@RestController
public class HomeRest {
	
	@Autowired
	EmployeesMapper employeesMapper;

	@PostMapping("/rest/getCountGender")
	public List<Map<String, Object>> getCountGender(){
		
		return employeesMapper.selectCountGender();
	}
	
	@PostMapping("/rest/getCountYear")
	public List<Map<String, Object>> getCountYear(){
		
		return employeesMapper.selectCountYear();
	}
	
	@PostMapping("/rest/getCountDname")
	public List<Map<String, Object>> getCountDname(){
		
		return employeesMapper.selectCountDname();
	}
	
	@PostMapping("/rest/getSalaryByDname")
	public List<Map<String, Object>> getSalaryByDname(){
		
		return employeesMapper.selectSalaryByDname();
	}
}

EmployeesMapper.java (Mapper)

package com.gd.chart.mapper;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface EmployeesMapper {
	
	List<Map<String, Object>> selectCountGender();
	
	List<Map<String, Object>> selectCountYear();
	
	List<Map<String, Object>> selectCountDname();

	List<Map<String, Object>> selectSalaryByDname();
}

EmployeesMapper.xml (Mapper.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gd.chart.mapper.EmployeesMapper">
	<select id="selectCountGender" resultType="Map">
		SELECT
			gender, COUNT(*) cnt
		FROM
			employees
		GROUP BY
			gender
	</select>
	
	<select id="selectCountYear" resultType="Map">
		SELECT
			YEAR(hire_date) hireYear, COUNT(*) cnt
		FROM
			employees
		GROUP BY
			YEAR(hire_date)
		ORDER BY
			YEAR(hire_date)
	</select>
	
	<select id="selectCountDname" resultType="Map">
		SELECT
			t.dept_name dname, COUNT(*) cnt
		FROM
			(SELECT emp_no, dept_name
			FROM dept_emp de INNER JOIN departments d
			ON de.dept_no = d.dept_no
			WHERE to_date = '9999-01-01') t
		GROUP BY
			t.dept_name
	</select>
	
	<select id="selectSalaryByDname" resultType="Map">
		SELECT
			t.dept_name dname, SUM(t.salary) salSum, ROUND(AVG(t.salary)) salAvg, MAX(t.salary) salMax, MIN(t.salary) salMin
		FROM
			(SELECT s.emp_no emp_no, s.salary salary, d.dept_name dept_name
			FROM
				(SELECT emp_no, salary
				FROM salaries
				WHERE to_date = '9999-01-01') s
					INNER join
					(SELECT emp_no, dept_no
					FROM dept_emp
					WHERE to_date = '9999-01-01') de
					ON s.emp_no = de.emp_no
						INNER JOIN departments d
						ON de.dept_no = d.dept_no) t
		GROUP BY
			t.dept_name
		ORDER BY
			t.dept_name;
	</select>
</mapper>

home.jsp (view)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</head>
<body>
	<h1>HOME</h1>
	<canvas id="myChart" style="width:100%;max-width:700px"></canvas>
	
	<script>
		const xValues = [];
		const yValues = [];
		const barColors = ["blue", "red"];
		
		$.ajax({
			async:false,	// 동기로 요청 (default는 비동기)
			url:'/chart/rest/getCountGender',
			method:'post',
			success:function(json){
				console.log("json : " + json);
				// [{'M':179973}, {'F':120051}]
				json.forEach(function(item){
					xValues.push(item.gender);
					yValues.push(item.cnt);
				});
				console.log("xValues : " + xValues);
				console.log("yValues : " + yValues);
			}
		});
		
		new Chart("myChart", {
		  type: "bar",
		  data: {
		    labels: xValues,
		    datasets: [{
		      backgroundColor: barColors,
		      data: yValues
		    }]
		  },
		  options: {
		    legend: {display: false},
		    title: {
		      display: true,
		      text: "World Wine Production 2018"
		    },
		  scales : {
				yAxes : [ {
					ticks : {
						beginAtZero : true // 0부터 시작하게 합니다.
					}
				} ]
			}
		  }

		});
	</script>
</body>
</html>

home.jsp 출력결과


chart2.jsp (view)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</head>
<body>
	<h1>chart 2</h1>
	
	<canvas id="myChart" style="width:100%;max-width:700px"></canvas>
	
	<script>
		const xValues = [];
		const yValues = [];
		const barColors = ["red", "green","blue","orange", "red", "green","blue","orange", "red", "green","blue","orange", "red", "green","blue","orange"];
		
		$.ajax({
			async:false,	// $.ajax 를 동기식으로 바꿔주기
			url:'/chart/rest/getCountYear',	// RestController 를 이용하여 차트에 사용할 데이터 가져오기
			method:'post',	// 데이터를 가져올 RestController의 Mapping 방식과 맞춰주기 (post)
		//	data : // 데이터를 가져와서 단순히 출력하는 것이므로 data: 속성은 불필요
			success:function(json){
				console.log("json : " + json);
				
				json.forEach(function(item){
					xValues.push(item.hireYear);
					yValues.push(item.cnt);
				});
				console.log("xValues : " + xValues);
				console.log("yValues : " + yValues);
			}
		});
		
		new Chart("myChart", {
		  type: "bar",
		  data: {
		    labels: xValues,
		    datasets: [{
		      backgroundColor: barColors,
		      data: yValues
		    }]
		  },
		  options: {
		    legend: {display: false},
		    title: {
		      display: true,
		      text: "Employees Count By Hire Year"
		    },
		    scales : {
				yAxes : [ {
					ticks : {
						beginAtZero : true
					}
				} ]
			}
		  }
		});
	</script>
</body>
</html>

chart2.jsp 출력결과


chart3.jsp (view)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</head>
<body>
	<h1>Count Employees By Department Name</h1>
	
	<canvas id="myChart" style="width:100%;max-width:700px"></canvas>
	
	<script>
		const xValues = [];
		const yValues = [];
		const barColors = ["red", "green","blue","orange","brown", "red", "green","blue","orange"];
		
		$.ajax({
			async:false,
			url:'/chart/rest/getCountDname',
			method:'post',
		//	data:	데이터 가져와서 출력하는 것 뿐이므로 data 속성 필요없음
			success:function(json){
				console.log("json : " + json);
				
				json.forEach(function(item){
					xValues.push(item.dname);
					yValues.push(item.cnt);
				});
				console.log("xValues : " + xValues);
				console.log("yValues : " + yValues);
				
			}
		});
		
		new Chart("myChart", {
		  type: "horizontalBar",
		  data: {
		    labels: xValues,
		    datasets: [{
		      backgroundColor: barColors,
		      data: yValues
		    }]
		  },
		  options: {
		    legend: {display: false},
		    title: {
		      display: true,
		      text: "Count Employees By Department Name"
		    },
		    scales : {
				yAxes : [ {
					ticks : {
						beginAtZero : true
					}
				} ]
			}
		  }
		});
	</script>
</body>
</html>

chart3.jsp 출력결과


chart4.jsp (view)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Total Salaries By DepartMent Name</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</head>
<body>
	<h1>Salaries By Grouping</h1>
	
	<canvas id="myChart" style="width:100%;max-width:700px"></canvas>
	<canvas id="myChart2" style="width:100%;max-width:700px"></canvas>
	<canvas id="myChart3" style="width:100%;max-width:700px"></canvas>
	<canvas id="myChart4" style="width:100%;max-width:700px"></canvas>
	
	<script>
		const xValues = [];
		const yValues = [];
		const xAvgValues = [];
		const yAvgValues = [];
		const xMaxValues = [];
		const yMaxValues = [];
		const xMinValues = [];
		const yMinValues = [];
		const barColors = ["red", "green","blue","orange","brown", "red", "green","blue","orange"];
		
		$.ajax({
			async:false,	// 비동기방식 ajax를 동기식으로 작동하도록 설정
			url:'/chart/rest/getSalaryByDname',
			method:'post',
		//	data:	// select 한 데이터를 출력할 뿐이라 data 속성은 필요없음
			success:function(json){
				console.log("json : " + json);
				
				json.forEach(function(item){
					xValues.push(item.dname);
					yValues.push(item.salSum);
					xAvgValues.push(item.dname);
					yAvgValues.push(item.salAvg);
					xMaxValues.push(item.dname);
					yMaxValues.push(item.salMax);
					xMinValues.push(item.dname);
					yMinValues.push(item.salMin);
				});
				console.log("xValues : " + xValues);
				console.log("yValues : " + yValues);
			}
		});
		
		new Chart("myChart", {
		  type: "horizontalBar",
		  data: {
		    labels: xValues,
		    datasets: [{
		      backgroundColor: barColors,
		      data: yValues
		    }]
		  },
		  options: {
		    legend: {display: false},
		    title: {
		      display: true,
		      text: "Sum of Salary By Department"
		    },
		    scales : {
				yAxes : [ {
					ticks : {
						beginAtZero : true
					}
				} ]
			}
		  }
		});
		
		new Chart("myChart2", {
			  type: "doughnut",
			  data: {
			    labels: xAvgValues,
			    datasets: [{
			      backgroundColor: barColors,
			      data: yAvgValues
			    }]
			  },
			  options: {
			    legend: {display: false},
			    title: {
			      display: true,
			      text: "Avg of Salary By Department"
			    },
			    scales : {
					yAxes : [ {
						ticks : {
							beginAtZero : true
						}
					} ]
				}
			  }
			});
		
		new Chart("myChart3", {
			  type: "pie",
			  data: {
			    labels: xMaxValues,
			    datasets: [{
			      backgroundColor: barColors,
			      data: yMaxValues
			    }]
			  },
			  options: {
			    legend: {display: false},
			    title: {
			      display: true,
			      text: "Max of Salary By Department"
			    },
			    scales : {
					yAxes : [ {
						ticks : {
							beginAtZero : true
						}
					} ]
				}
			  }
			});
		
		new Chart("myChart4", {
			  type: "bar",
			  data: {
			    labels: xMinValues,
			    datasets: [{
			      backgroundColor: barColors,
			      data: yMinValues
			    }]
			  },
			  options: {
			    legend: {display: false},
			    title: {
			      display: true,
			      text: "Min of Salary By Department"
			    },
			    scales : {
					yAxes : [ {
						ticks : {
							beginAtZero : true
						}
					} ]
				}
			  }
			});
	</script>
</body>
</html>

chart4.jsp 출력결과

profile
Road OF Developer

0개의 댓글