괴발개발/Spring Framework

에이젝스 $.ajax

moonday 2021. 8. 11. 16:14

- $.ajax()는 이벤트 아래에 같이 쓰는 것, 이벤트 없으면 안됨

 

- dataType :  success에 들어가는 결과값 result에 대한 타입임-> "json", "text", ...등
- data속성에 JSON.stringify(보낼값) 이라고했을때는 보낼값이 1개가아니라 여러개일때
(data에 정보 하나만 보낼때는 data가 담긴 변수하나만 쓰고 contentType지우고 컨트롤러 @RequestBody도지움)
- contentType은 data타입에 대한 것

- 컨텐츠타입 : 화면->서버로 보내는 data속성 => data는 속성 data항목을 말함, 컨텐츠타입은 생략가능
- 데이터 타입: 서버->화면으로 보내는 정보의 속성 => success function(   )괄호 안에 있는거 //노란색말하는거
- 데이터타입은 int String과 같이 문자열 문자의 갯수가 1개일때는 데이터 타입을 안쓰고 VO처럼 여러개를 담아서 보낼땐 씀

- aysnc : false, 를 추가하면 에이젝스의 success파트에 있는 변수를 전역변수로 사용할 수 있음

 


-$('태그종류[속성=속성값]').val()
- 에이젝스할때 컨트롤러에 @PathVariable("변수명")  이거는 경로에 값을 보낼때만쓰는거, 아니면 안씀
- data 타입은 VO랑 <>컬렉션프레임워크(?) 일때 씀 => 값여러개일때
- 콘텐츠타입이 없으면 컨트롤러에서 @RequestBody 를 빼야돼

- 리퀘스트바디있으면 "" 까지 다들어가게됨. 없으면 원하는 값만 딱 들어갈 수 있음

- ajax안에서는 $(this)를 사용할 수 없으므로 ajax시작 바로전에  변수타입 변수명 = $(this) 를 넣어둘 것. 

 

- submitHandler같은경우, 앞서서 위에 submit을 변수&값선언해주고 +  
- submitHandler를 이용해서 정보를 하나로 합치는 코드를 사용하면 됨(근데 써밋핸들러는 써밋하기전에 실행되는 코드라던데)

 


-$(function){} 아래에다가 변수를 바로 설정한다음에 해당 값을 예를들어,

var nickname = $('input[name=teacher_nickname]').val(); 일경우, 문서가 준비되고 바로 그 값을가져오기때문에, 입력한 값이 아니라 초기상태에서 더는 값을 불러오지 않아서 null인채로 계속 있게되니 이벤트 안에 넣어줄것

 

 

- ajax로 서버에있는 정보를 송수신하는 거니까, form태그가 굳이 필요하지 않음. + 만약 form태그가 있다면 action에 입력된 링크로 input창 입력하는 공간이 있으면 enter쳤을때 거기로 넘어가버림. (+내용이 text로 화면에 출력됨)


에러

- ajax안에 있는 data 속성을 적을 때, 변수명이 _ 은가능하지만 -는 에러가 남

 

에러

-JSON parse error: Unrecognized token => data : JSON.stringify(data), 

=>이런식으로 써줘야 객체로 변환시켜서 읽을 수 있는 값으로 됨

 

- success안에 location.href='/가고싶은링크' 이걸 success안에다가 넣어주면 됨

 

- ajax안에서  ajax를 발동시킨 이벤트의 트리거였던 것을 this로 쓸 수없음

(예를들면,  $('.grade').click(function(){ ~~~~~~}) 여기서 $(this) 는 grade를 클래스로 가진 걸 말하는데,

ajax안에들어가서 success안에 $(this)를쓰게되면 더이상 .grade가 아니라는 것. 따라서, ajax들어가기 전에 해당 값을 변수로 넣어놓고 ajax안에서 변수를 이용해 this를 대체해서 써야 함)

 

에러

- Required String parameter '변수명' is not present

 controller로 값을 보내고 json에 담아 ajax로 받아오는 과정에서 에러가 발생했습니다. 
@RequestParam이나 기타 Prameter 값을 받아올 때 null이거나 Type이 맞지 않는 경우 이 에러가 발생

 

=>해결1

(@RequestParam(value="checkbox",required=false) 부분에 checkbox뒤 [] 배열표시를 뺌. 

=> 배열이더라도 스프링은 배열 및 Collection 계열의 파라미터로 지정 시 타입만 맞으면 알아서 가공

*,required=false 는 해결2 참고 // 꼭 1, 2동시에 해주길

	@ResponseBody
	@PostMapping("/list/checklistDeletion") //checkbox[]에 student_id가 담겨있음
	public String studentChecklistDeletion(@RequestParam(value="checkbox",required=false) List<Integer> student_id, HttpServletRequest request) {
		System.out.println("컨트롤러1 student_id : "+ student_id);
		TeacherVO loginUser = teacherService.getTeacherInfoByRequest(request);
		System.out.println("컨트롤러2 loginUser:"+loginUser);
		return studentService.deleteStudentList(student_id, loginUser)? "SUCCESS" : "FAIL";
	}

 

해결2

아래에서 (@RequestParam(value="checkbox",required=false) 부분에 required=false추가.

=> ajax에서 null값을 넘겨줄 수 도 있기때문에 처리해줘야 함

(선택박스체크안하고 삭제하기버튼누른 경우 컨트롤러에 넘어온 값이 null)

	@ResponseBody
	@PostMapping("/list/checklistDeletion") //checkbox는[]이고 student_id가 담겨있음
	public String studentChecklistDeletion(@RequestParam(value="checkbox",required=false) List<Integer> student_id, HttpServletRequest request) {
		System.out.println("컨트롤러1 student_id : "+ student_id);
        	if(student_id == null) {
			return "FAIL";
		}
		TeacherVO loginUser = teacherService.getTeacherInfoByRequest(request);
		System.out.println("컨트롤러2 loginUser:"+loginUser);
		return studentService.deleteStudentList(student_id, loginUser)? "SUCCESS" : "FAIL";
	}

얘도 같이 넣어줘야 함

if(student_id == null) {
	return "FAIL";
}

jsp ajax에서 controller로 배열값 넘기기  (참고하면좋은블로그)

 

jsp에서 ajax부분

traditional : true, 를 넣으면 지금 상태에서는 배열로값넘어오는 컨트롤러일때 null이 아닌 원하는 값이 들어옴
dataType : 'text', 는 컨트롤러에서 SUCCESS, FAIL과 같은 반환값을 TEXT타입으로 받겠다는 이야기
*(여기서 dataType: "json"은 먹히지 않더군) 
$.ajax({
  type : 'post',
  url : contextPath + '/student/list/checklistDeletion',
  data : data,						
  dataType : 'text',
  traditional : true,
  success : function(result){
  	if(result == 'SUCCESS'){ //화면에서 실시간으로 해당 리스트를 제거하기 + 모달창 삭제알림
  		console.log('success');
 		var msg = "선택된 학생들의 정보를 삭제했습니다.";
  		$('.modalContent').text(msg);
  		$('#staticBackdrop').modal('show');
  	}
  	else{ //모달창으로 삭제 실패 알림
  		console.log('fail');
  		var msg = "선택된 학생 정보 삭제에 실패했습니다.";
  		$('.modalContent').text(msg);
 		$('#staticBackdrop').modal('show');
  	}
  }
});

 

컨트롤러

value="checkbox" checkbox는 jsp에서 input태그 type=checkbox의 지정된 name을 말함.

@ResponseBody
@PostMapping("/list/checklistDeletion") //checkbox[]에 student_id가 담겨있음
  public String studentChecklistDeletion(@RequestParam(value="checkbox") List<Integer> student_id, HttpServletRequest request) {
  System.out.println("컨트롤러1 student_id : "+ student_id);
  TeacherVO loginUser = teacherService.getTeacherInfoByRequest(request);
  System.out.println("컨트롤러2 loginUser:"+loginUser);
  return studentService.deleteStudentList(student_id, loginUser)? "SUCCESS" : "FAIL";
}

 


 

@RestController는 Spring MVC Controller에 @ResponseBody가 추가된 것입니다.
(@RestController = @Controller + @ResponseBody)

당연하게도 RestController의 주용도는 Json 형태로 객체 데이터를 반환하는 것입니다.
@Controller와 @RestController는 용도의 차이
예전에 프로그래밍을 할 때에는 jsp나 html과 같은 뷰를 전달해 주었기 때문에 @Controller를 사용해왔었지만,
최근에는 프론트엔드와 백엔드를 따로 두고, 백엔드에서는 REST API를 통해 json으로 데이터만 전달하기 때문에 편리성을 위해 @RestController를 사용
단점:
(하나의 컨트롤러 코드에서 같은 작업을 여러번 수행시킬때) @RestController 를 구성하는 것은 좋지 못한 습관
매번 클라이언트로 부터 요청을 받을 때마다, 매번 새로운 List 를 생성하기 때문이다.메모리 낭비가 상당히 심해질 수 있는 코드이다

 

 


에이젝스로 첨부파일 보내기

jsp에서 ajax를 data가 아니라 form형식으로 보내주고, 

var file_id = $('input[name=file_id]').val();
				var form = new FormData();
				form.append("studentImage", $('input[name=studentImage]')[0].files[0]);
				form.append("student_id",student_id);
				form.append("student_name",student_name);
				form.append("student_gender",student_gender);
				form.append("student_school",student_school);
				form.append("student_phone",student_phone);
				form.append("student_birthdate",student_birthdate);
				form.append("student_registration_date",student_registration_date);
				form.append("student_note",student_note);
				form.append("student_zipcode",student_zipcode);
				form.append("student_reference_address",student_reference_address);
				form.append("student_detail_address",student_detail_address);
				form.append("student_road_address",student_road_address);
				form.append("student_number_address",student_number_address);
				form.append("fild_id", file_id);
				
				$.ajax({
					type: 'post',
					aysnc : false,
					enctype: 'multipart/form-data',
					contentType:false,
					processData : false,
					url : contextPath + '/student/editStudentInfo',
					data : form,
					success : function(result){ 
						if(result == "SUCCESS"){
							$('.modalContent').text('학생정보가 수정되었습니다.');
							$('#staticBackdrop').modal('show');
							var newBirth = student_birthdate.slice(0,4);
							$('.studentAge').text('생년월일 ( 나이: '+(thisYear-newBirth+1)+' )');
						}else{
							$('.modalContent').text('학생정보 수정을 실패했습니다. 다시시도해주세요.');
							$('#staticBackdrop').modal('show');
						}
					}
				});
			})
		})

컨트롤러에서 RequestBody빼고 첨부파일은 꼭 MultiPartFile을 붙여준다음 앞에 @RequestParam써주기

required=false를 안써주면 (*따옴표없음), 파일없을때 기존의 기능들이 실행안하게되니깐 꼭 써줄 것

	@ResponseBody
	@PostMapping("/editStudentInfo")
	public String editStudentInfoPost(
			StudentVO studentInfo, 
			@RequestParam(value="studentImage", required = false)MultipartFile studentImage, Integer file_id,
			HttpServletRequest request, Criteria cri, ModelAndView mv) throws Exception {
		TeacherVO loginUser = teacherService.getTeacherInfoByRequest(request);
		if(loginUser == null) {
			return null;
		}
		mv.addObject("cri",cri);
		return studentService.updateStudentInfo(studentInfo, loginUser, studentImage, file_id)? "SUCCESS":"FAIL";
	}

 

 

 

 

 

 

 

참고한 내용들: 

https://mangkyu.tistory.com/49

https://sdy-study.tistory.com/241

https://dondons.tistory.com/19

https://okky.kr/article/836844