포워딩(전송)을 하게되면 오류가 발생할 수 있는데 이 오류를 두 가지로 나눌 수 있다. 컴파일오류와 실행오류이다. 컴파일오류는 오타를 쳤을때고 Java에서 알려준다.
실행오류는 예를 들어 무한 for문이다. 내가 생각한 결과물과 다른 결과물이 나올때다.
서버는 잘뜨나 실행이 되지 않는다.
다루어볼 것은 실행오류에 대한 처리이다. 오류는 시스템 오류와 예외가 있다. 시스템 오류는 잡을 수 없다.
예외는 내가 생각한 거와 다른 결과물로 프로그래밍으로 제어(제거)할 수가 있다.
모든 오류의 부모는 Throwable이다. 우리가 제어 할 수 있는 예외의 부모는 Exception이고, 우리가 제어할 수 없는 시스템 오류의 부모는 error이다.
실무에서 사용하는 ExceptionHandling이다.
Exception오류는 콘솔에 안 뜬다. 왜냐하면 자바컴파일러는 오류로 생각하지 않기 때문이다.
실행오류예외처리 (RuntimeException) try catch문을 사용해서 콘솔에 오류가 뜨게 만든다. try catch는 try구문 안에서 RuntimeException같은 종류의 오류가 발생하면 무조건 catch문을 타게된다.
++실무에서 운영서버나 test서버에 프로젝트를 올리게 되면 Java파일을 올리는 것이 아니라 class파일을 올리게 된다. 오류가 나게 되면 의지할 수 있는 곳은 콘솔 밖에 없다. 그러면 콘솔과 내 로컬 서버를 비교하면서 오류를 찾게 된다. 그렇기 때문에 어떠한 오류가 났는지 확인 하도록 값을 같이 찍어준다.
@Controller
public class WelcomeWebController {
@Resource
private WelcomeWebService welcomeWebService;
@RequestMapping(value = "/welcomeWeb.do")
public String welcomeWeb(ModelMap model) {
try {
//String nulls = null;
//System.out.println(nulls.toString());
List<EgovMap> welcomeWebList = welcomeWebService.selectWelcomeWebServiceList();
System.out.println(welcomeWebList);
//List를 Map에 담아 출력해보기
HashMap<String, Object> exceptionMap = new HashMap<String, Object>();
//여기서 오류냄
for (int i = 0; i < welcomeWebList.size()+2; i++) {
exceptionMap.put((String) welcomeWebList.get(i).get("seqNo"), welcomeWebList.get(i).getValue(1));
}
System.out.println("exceptionMap : " + exceptionMap);
//담은 Map의 데이터를 배열로 출력해보기
String[] arrStr = new String[exceptionMap.size()];
for (int i = 0; i < exceptionMap.size(); i++) {
arrStr[i] = (String) exceptionMap.get(String.valueOf(i+1));
}
System.out.println("arrStr : " + Arrays.toString(arrStr));
List<EgovMap> pieChartList = welcomeWebService.selectPieChartList();
System.out.println(pieChartList);
model.addAttribute("welcomeWebList", welcomeWebList);
model.addAttribute("pieChartList", pieChartList);
} catch (Exception e) {
System.out.println(e + "그 외 모든 오류들");
}
return "welcomeWeb/welcomeWeb.tiles";
}
}
보통 array오류와 nullpoint오류가 많이 난다. 팀프로젝트에서는 test서버에서는 확인하기 힘들어서 꼭 예외 처리해준다.
일단, try문에 String 변수에다가 null을 넣어준다.
@Controller
public class WelcomeWebController {
@Resource
private WelcomeWebService welcomeWebService;
@RequestMapping(value = "/welcomeWeb.do")
public String welcomeWeb(ModelMap model) {
try {
String nulls = null;
System.out.println(nulls.toString());
List<EgovMap> welcomeWebList = welcomeWebService.selectWelcomeWebServiceList();
System.out.println(welcomeWebList);
//List를 Map에 담아 출력해보기
HashMap<String, Object> exceptionMap = new HashMap<String, Object>();
for (int i = 0; i < welcomeWebList.size(); i++) {
exceptionMap.put((String) welcomeWebList.get(i).get("seqNo"), welcomeWebList.get(i).getValue(1));
}
System.out.println("exceptionMap : " + exceptionMap);
//담은 Map의 데이터를 배열로 출력해보기
String[] arrStr = new String[exceptionMap.size()];
for (int i = 0; i < exceptionMap.size()+2; i++) {
arrStr[i] = (String) exceptionMap.get(String.valueOf(i+1));
}
System.out.println("arrStr : " + Arrays.toString(arrStr));
List<EgovMap> pieChartList = welcomeWebService.selectPieChartList();
System.out.println(pieChartList);
model.addAttribute("welcomeWebList", welcomeWebList);
model.addAttribute("pieChartList", pieChartList);
} catch (ArrayIndexOutOfBoundsException ae) {
System.out.println(ae + "배열의 길이를 확인해!");
} catch (NullPointerException ne) {
System.out.println(ne + "null있다.");
return "welcomeWeb/welcomeWeb.tiles";
}
}
변수를 참조해서 실행하는데 우리가 변수에 null을 했기 때문에 참조할 수 없다. 그래서 콘솔에 nullpoint오류가 난다.
여러 오류가 발생한다면, 앞에 오류가 나오면 그 뒤에 오류는 안나온다.
그래서 무슨 오류가 나오는지 여러 오류처리를 해야한다. 어디 controller에서 나온 오류인지 확인할 수 있도록 controller명도 같이 찍어준다.
@Controller
public class WelcomeWebController {
@Resource
private WelcomeWebService welcomeWebService;
@RequestMapping(value = "/welcomeWeb.do")
public String welcomeWeb(ModelMap model) throws Exception{
try {
String nulls = null;
System.out.println(nulls.toString());
List<EgovMap> welcomeWebList = welcomeWebService.selectWelcomeWebServiceList();
System.out.println(welcomeWebList);
//List를 Map에 담아 출력해보기
HashMap<String, Object> exceptionMap = new HashMap<String, Object>();
for (int i = 0; i < welcomeWebList.size(); i++) {
exceptionMap.put((String) welcomeWebList.get(i).get("seqNo"), welcomeWebList.get(i).getValue(1));
}
System.out.println("exceptionMap : " + exceptionMap);
//담은 Map의 데이터를 배열로 출력해보기
String[] arrStr = new String[exceptionMap.size()];
for (int i = 0; i < exceptionMap.size()+2; i++) {
arrStr[i] = (String) exceptionMap.get(String.valueOf(i+1));
}
System.out.println("arrStr : " + Arrays.toString(arrStr));
List<EgovMap> pieChartList = welcomeWebService.selectPieChartList();
System.out.println(pieChartList);
model.addAttribute("welcomeWebList", welcomeWebList);
model.addAttribute("pieChartList", pieChartList);
} catch (ArrayIndexOutOfBoundsException ae) {
System.out.println(ae + "배열의 길이를 확인해!");
System.out.println("welcomeWeb Controller에서 오류");
} catch (NullPointerException ne) {
System.out.println(ne + "null있다.");
System.out.println("welcomeWeb Controller에서 오류");
}
return "welcomeWeb/welcomeWeb.tiles";
}
}
오류가 나던 안 나던 무조건 타게 만드는 메서드는 finally이다. try catch문에서만 실행이 된다.
@Controller
public class WelcomeWebController {
@Resource
private WelcomeWebService welcomeWebService;
@RequestMapping(value = "/welcomeWeb.do")
public String welcomeWeb(ModelMap model) throws Exception{
try {
String nulls = null;
System.out.println(nulls.toString());
List<EgovMap> welcomeWebList = welcomeWebService.selectWelcomeWebServiceList();
System.out.println(welcomeWebList);
//List를 Map에 담아 출력해보기
HashMap<String, Object> exceptionMap = new HashMap<String, Object>();
for (int i = 0; i < welcomeWebList.size(); i++) {
exceptionMap.put((String) welcomeWebList.get(i).get("seqNo"), welcomeWebList.get(i).getValue(1));
}
System.out.println("exceptionMap : " + exceptionMap);
//담은 Map의 데이터를 배열로 출력해보기
String[] arrStr = new String[exceptionMap.size()];
for (int i = 0; i < exceptionMap.size()+2; i++) {
arrStr[i] = (String) exceptionMap.get(String.valueOf(i+1));
}
System.out.println("arrStr : " + Arrays.toString(arrStr));
List<EgovMap> pieChartList = welcomeWebService.selectPieChartList();
System.out.println(pieChartList);
model.addAttribute("welcomeWebList", welcomeWebList);
model.addAttribute("pieChartList", pieChartList);
} catch (ArrayIndexOutOfBoundsException ae) {
System.out.println(ae + "배열의 길이를 확인해!");
} catch (NullPointerException ne) {
System.out.println(ne + "null있다.");
} finally {
System.out.println("welcomeWeb Controller에서 오류");
System.out.println("오류가 나던 안 나던 출력");
}
return "welcomeWeb/welcomeWeb.tiles";
}
}
모든 실행오류를 적어줄 수 없지만 어떤 오류인지 알수 없기 때문에 최상위 Exception를 적어준다. 이 최상위를 위에 적어주면 나머지 오류는 실행되지 않기 때문에 최상위 Exception을 맨 아래에 넣는다.
이 오류는 꼭 있어야 하는 처리문이다.
@Controller
public class WelcomeWebController {
@Resource
private WelcomeWebService welcomeWebService;
@RequestMapping(value = "/welcomeWeb.do")
public String welcomeWeb(ModelMap model) throws Exception{
try {
String nulls = null;
System.out.println(nulls.toString());
List<EgovMap> welcomeWebList = welcomeWebService.selectWelcomeWebServiceList();
System.out.println(welcomeWebList);
//List를 Map에 담아 출력해보기
HashMap<String, Object> exceptionMap = new HashMap<String, Object>();
for (int i = 0; i < welcomeWebList.size(); i++) {
exceptionMap.put((String) welcomeWebList.get(i).get("seqNo"), welcomeWebList.get(i).getValue(1));
}
System.out.println("exceptionMap : " + exceptionMap);
//담은 Map의 데이터를 배열로 출력해보기
String[] arrStr = new String[exceptionMap.size()];
for (int i = 0; i < exceptionMap.size()+2; i++) {
arrStr[i] = (String) exceptionMap.get(String.valueOf(i+1));
}
System.out.println("arrStr : " + Arrays.toString(arrStr));
List<EgovMap> pieChartList = welcomeWebService.selectPieChartList();
System.out.println(pieChartList);
model.addAttribute("welcomeWebList", welcomeWebList);
model.addAttribute("pieChartList", pieChartList);
} catch (ArrayIndexOutOfBoundsException ae) {
System.out.println(ae + "배열의 길이를 확인해!");
} catch (NullPointerException ne) {
System.out.println(ne + "null있다.");
} catch (Exception e) {
System.out.println(e + "그 외 모든 오류들");
} finally {
System.out.println("welcomeWeb Controller에서 오류");
System.out.println("오류가 나던 안 나던 출력");
}
return "welcomeWeb/welcomeWeb.tiles";
}
}
try catch는 내가 책임지겠다는 것이고 throws exception는 나를 호출한 놈한테 책임을 주는 것이다. 책임회피다. try랑 throw를 같이 적어주면 안된다. controller에는 throw exception을 적어주지 않는 것을 추천한다.
throw Exception의 controller에 적어주면 Java 뒷단에 책임을 지게 한다.
애초에 데이터를 올릴 때 jsonObject가 아닌 jsonObjectString으로 올려본다.
var form = {"param" : thisParam} ; 이렇게 변수에 담고 ajax data에 문자열을 올려본다.
JSON.stringify( )메서드가 jsonObject를 jsonObjectString로 바꾸는데 완벽한 문자열로 바꿔준다.
크롬 - network 에서 All로 열어서 확인해본다. error가 나오는데 인코딩이 잘못 되었기 때문이다. jsonObjectString이 더블코테이션(")을 읽지 못했기 때문이다. 왜냐하면 ajax는 아무것도 안써주면 자동으로 get방식이다. get방식은 특수문자를 읽지 못한다.
post방식으로 적어주면 error부분이 사라졌다.
post방식으로 바뀌면 개발자도구에 있는 Form Data(body)부분에 더블코테이션과 문자열이 적혀있다. Form Data는 body부분이다.
Form data는 키를 보고 벨류가 안 넘어가고 있다. 벨류를 받게 하려면 어떻게 할까? controller에 getParameterNames를 사용해준다. Emumeration name = request.getParameterNames; 라고 적어주면 name으로 키를 사용해 벨류 값을 뽑을 수 있다. 그리고 while문을 통해서 키를 뽑아낸다. 마치 키를 벨류처럼 사용해준다.
jsonObject는 데이터 포맷 중에 하나다. (예를 들어 html포맷, json포맷처럼) childSelectBox가 void타입인 이유는 리턴타입이 필요없기 때문이다.
AJAX는 호출한 곳에서 호출한 곳으로 데이터를 전달하기 때문에 특정 주소가 있는 리턴을 보낼 필요가 없다.
1번. hashMap인스턴스를 생성해서 원하는 값을 뺄 수 있게 했다.
2번. submit( )방식이 get방식이면 한글처리가 안되서 server.xml에서 한글처리를 해줬다. json은 톰켓 쪽이 아니여서 한글처리를 따로 해주어야 한다. utf-8세팅은 항상 위쪽에 있어야 한다.
3번. resquest는 화면에서 보내는 것이고 response는 화면에 파라미터를 내린다(받는다).
submit통신은 뷰가 모델과 논리적 주소를 받아서 처리하지만 ajax는 모델이 아닌 response가 내려준다. 예를들어, 모델로 받을때 model.addAttribute를 사용한 것처럼 response 메서드를 사용한 것이다.
PrintWriter out = response.getWriter( ); PrintWriter는 리턴타입이다.
콘솔에 resultMap에서 put( )로 뽑은 값은 AJAX전처리때문에 쿼리스트링 형식으로 나온다.
*response로 내려주면 View가 아니라 mappingJacksonHttpMessageConverter가 받는다. mappingJacksonHttpMessageConverter는 종류가 많다. 우리가 response를 이용해서 내리면 수많은 if문이 있다. 예를 들어, http만 받는 애도 있고
if문에 모델이면 뷰가 받고 또 if else해서 response는 mappingJacksonHttpMessageConverter이 받는다.
Java는 배열을 쓸때 [ ]대괄호를 사용한다. String[ ] arr = srt.split(","); Java처럼 변수 앞에 타입을 적어주는 것을 정적타입언어라고 한다. JavaScript처럼 타입을 안 적고 var를 쓰는 것을 동적타입언어라고 한다.
전체 배열을 출력하는 방법
for (String a : arr) { System.out.println(a); }
: 을 기준으로 왼쪽(a)은 변수, 오른쪽(arr)은 배열이다.
for문 돌때마다 배열의 0번째부터 순서대로 변수에 값을 넘겨준다. 배열의 타입과 변수를 담을 타입은 같아야한다.
그리고 내가 마음대로 for문을 중간에서 멈출 수 없다.
배열을 콘솔에 찍으면 주소값이 찍힌다.
int는 기본타입이라고 한다. 기본타입은 stack에 변수와 값이 쌓인다. 반면에, 배열이나 String타입을 참조타입이라고 하는데, 참조하는 것을 가리키는 역할을 한다 얘네는 heap에 쌓인다. heap이라는 공간에 값이 있고 그 값을 stack이 가리킨다. 즉, heap 안에 있는 참조타입은 콘솔에 주소값이 찍힌다. 주소값이 아닌 값을 나오게 하려면 Arrays클래스에 toString( )를 사용한다.
주소창에 http://localhost:8080/arrayInit/main.do?arr=a%2Cb%2Cc&pageName=main 라고 되어있는데 ?뒤에는 콤마(,)가 인코딩 되서 이상하게 보인다. 보안상 이상한 문자열로 출력한다.
저 부분을 지우면 에러가 뜬다. arr이란 키를 화면에서 보내지 않았기 때문이다.
Null Exception이 발생한다.
에러의 발성원인은 값이 null이 아니라 split를 썼기 때문이다.
null을 split한다는 것은 split할 것이 없기때문에 에러가 난다. String[ ] arr = srt.split(","); <- 이거때문!!
그래서 split을 쓸때에는 null처리를 해야한다. 해당 결과를 null인지 아닌지 체크를 꼭 해야한다.
화면에 데이터를 내릴 때는 @ModelMap타입을 사용한다. (ModelMap을 파라미터로 적어준다.) controller에 model.addattribute("A", B); 라고 적어주는데 A는 키 B는 벨류다.
Enumeration은 객체들의 집합에서 각각의 객체들을 한순간에 하나씩 처리할 수 있는 메소드를 제공하는 켈렉션이다.
getParameterNames가 화면에서 올린 키를 여기에 다 넣어준다 (벨류X 키만!!)
열거형 인터페이스엔 커서가 하나씩 다 있다 열거형에서 화면에서 올린 키는 data이다. 자신의 데이터(벨류)인것이다. 열거형 인터페이스는 암묵적으로 while문을 사용한다. 커서의 오른쪽에 있는 데이터를 준다(for문 돌고 주고 ...) 자기 데이터를 주면서 커서가 이동하는 형식이다.
화면에서 올린 키를 적어주면 값도 뽑아 낼 수도 있다.
checkbox는 name들이 같다. 같은 키(name)에 다른 값이 들어간다.
첫 번째, 체크박스를 클릭하고 submit하면 주소창에 내가 클릭한 체크박스의 값이 나온다.
이후에 여러 개의 체크박스를 클릭해도 콘솔창에 하나의 값만 출력된다.
request.getParameter( )때문이다. 얘는 하나의 키가 하나의 값을 가져온다.
reuqest.getParameterValues( )는 여러 개의 값을 가져올 수 있다.
리턴타입은 string이다.
한개든 여러개든 배열에 다 때려 박지 말고 하나일 때는 String으로 여러 개 일때는 배열로 담아 보낸다.
@Controller을 쓰는 이유는 @Controller 하위에 있는 어노테이션(@)을 쓰기 위해서다. 하위 어노테이션 중에 @RequestMapping이 있다. @RequestMapping은 @Controller이 적혀있지 않으면 사용할 수 없다.
@Service과 @Mapper도 마찬가지다 .
mvc패턴은
컨트롤러 -> 서비스 -> 서비스임플 -> 맵퍼 -> DB -> 서비스임플 -> 서비스 -> 컨트롤러
순으로 데이터가 이동한다.
controller -> service -> serviceImpl -> mapper -> db(sql)로 갔다가 다시 와서 논리적주소와 모델을 내려준다.
이 MVC패턴에서의 데이터이동을 더 자세하게 보면
@Controller를 읽어들이는 애가 있는데 dispatcher-servlet이다. dispatcher-servlet은 화면(view)과 Controller사이에 있다. (dispatcher-servlet가 데이터를 들고 컨트롤러로 이동하는데 컨트롤러가 받고 이동)
View에서 Controller로 바로 보내는 것이 아니라 dispatch-servlet에 있는 Adaptor가 보낸다. 이 어댑터는 RequestMappingHandlerAdaptor다.
이 Adaptor가 키와 벨류를 받는다. 참고로, Spring은 어댑터 방식이다. 어댑터가 다 이동시킨다.
이Adaptor가 @RequestMapping을 찾아가는데 다짜고짜 찾아가지 않는다.
++참고 : DI는 DI컨테이너(context.~.xml)에 등록되어있다. 여기에 등록되려면 자격이 있어야 한다. @Conponent이 적혀있는 DI만 등록할 수 있다. @Controller를 눌러보면 @Conponent이 적혀져 있는 것을 볼 수 있다.
@Service, @Mapper에도 다 @Conponent가 적혀져 있다.
이런 애들을 다 긁어서 bean으로 등록(DI)시켜주는 애가 dispatcher-servlet에 살고있는 ConponentScan이란 애다.
mvc패턴은 Controller에서 DB까지 데이터가 이동했다가 논리적주소와 모델을 내려준다고 했다. 논리적주소와 모델을 내리는 애는 dispatcher-servlet에 살고있는 JstlView다. 얘는 화면을 그리는 애다.
이 JstlView는 화면(html)을 그리다가 동적으로 생성되는 부분(C태그)을 만나면
Controller에서 받은 모델을 바라보고 내린다. (JSTL을 말함) 모델을 참고해서 내리기 때문에 JstlView이다.
JstlView가 dispatcher-servlet한테 주는데 사람의 눈으로 볼 수 있는 상태가 아니기 때문에
servletContainer 한테 주고 이 컨테이너는 브라우저 통신(HTTP통신)으로 파싱해서 브라우져에 뿌려준다. 그냥 뿌리는 것이 아니라 논리적주소를 참고해서 브라우져에 뿌려준다.
http통신(화면요청)에서 톰캣서버가 일어나서 dispatcher-servlet로 가고
dispatcher-servlet에서 RequestMappingHandlerAdaptor가 받는다.
RequestMappingHandlerAdaptor가 컨트롤러에 @requestMapping을 찾아간다. 모델이랑 뷰를 생성해서 dispatcher-servlet한테 주고
dispatcher-servlet에 있는 JstlView가 화면을 생성하는데 c를 만나면 모델을 참고하는데 dispatcher-servlet가 이것을 다시 받아 servletContainer가 http통신을 통해서 파싱해서 사람눈으로 보여준다.
정리 : dispatcher-servlet한테 http요청을 하면 dispatcher-servlet는 Controller한테 요청을 해서 모델을 생성한다. Controller는 dispatcher-servlet한테 모델과 뷰를 반환한다. dispatcher-servlet는 뷰한테 모델을 주고 뷰는 생성을해서 dispatcher-servlet한테 준다. dispatcher-servlet는 http응답을 한다.