---
title: "Java EE 정리 38"
date: "2019-04-19"
tags: ["Java EE","Spring"]
status: archived
verified: false
---

---

## Controller에서 예외처리

* **요청을 처리하는 메소드에서 throws로 예외를 날림(예외 발생!)**
  * 예외처리하는 메소드위에 **@ExceptionHandler** 정의
    * **한번에 하나의 예외만 처리한다**
  * **예외처리 메소드의 반환형은 반드시 ModelAndView**
  * **매개변수로 예외처리클래스명의 객체를 받는다**

```java
@ExceptionHandler(예외처리클래스명.class)
public ModelAndView 예외처리메소드명(예외처리클래스명 예외처리클래스객체명) {
    // 예외가 발생하면 발생한 예외객체를 전달받아 사용

    ModelAndView mav = new ModelAndView();

    mav.setViewName("예외페이지 JSP명");
    mav.addObject("msg", 예외처리클래스객체명.getMessage()); // 간단한 에러메시지
    mav.addObject("exception", 예외처리클래스객체명.toString());
    // 예외처리클래스 객체와 간단한 에러 메시지

    return mav;
}
```

## Controller에서 예외처리 예

```html
<!-- main_menu.jsp -->
...
<li><a href="exception/exception.do">Controller에서 예외처리</a></li>
...
```

```java
@Controller
public class ExceptionController {
      @RequestMapping(value = "/exception/exception.do", method = GET)
      public String exceptionForm() {
            return "exception/exception_form";
      }

      @RequestMapping(value = "/exception/number_format.do", method =  GET)
      public String numberFormat(int age, Model model) {
            // 입력받은 나이로 태어난 해 보여주기
            model.addAttribute("birth",  Calendar.getInstance().get(Calendar.YEAR) - age + 1);
            return "exception/view_age";
      }
...
```

```html
<!-- exception/exception_form.jsp -->
...
      <div>
            <form action="number_format.do" method="get">
                  <label>나이</label>
                  <input type="text" name="age" class="inputBox"/>
                  <input type="submit" value="전송" class="btn"/>
            </form>
            <br/>
            <form action="class_not_found.do" method="get">
                  <input type="submit" value="전송" class="btn"/>
            </form>
      </div>
...
```

![01](/md/legacy-assets/javaEe/38/01.webp)

```html
<!-- exception/view_age.jsp -->
...
나이: ${ param.age }<br/>
태어난해: ${ requestScope.birth }<br/>
<a href="javascript:history.back()">뒤로</a>
...
```

![02](/md/legacy-assets/javaEe/38/02.webp)

* **ExceptionHandler로 예외처리하는 메소드는 ModelAndView를 반환한다**
  * **ModelAndView에 이동할 예외처리 JSP명과 예외 메시지를 저장 후 반환**

```java
// ExceptionController
...
      @ExceptionHandler(NumberFormatException.class)
      public ModelAndView numberFormatProcess(NumberFormatException nfe)  {
            ModelAndView mav = new ModelAndView();
            mav.setViewName("exception/error");

            mav.addObject("msg", nfe.getMessage()); // 간단한 에러  메세지
            mav.addObject("exception", nfe.toString()); // 예외처리  객체와 간단한 에러 메세지

            return mav;
      }
...
```

```html
<!-- exception/error.jsp -->
...
<img src="http://localhost:8080/spring_mvc/common/images/err.png"/>
<br/>
문제가 발생했습니다.<br/>
간단한 메세지: ${ msg }<br/>
예외처리객체와 메세지: ${ requestScope.exception }
...
```

![03](/md/legacy-assets/javaEe/38/03.webp)

* **다른 예외처리 예, ClassNotFoundException**

```java
// ExceptionController
...
      @RequestMapping(value = "/exception/class_not_found.do", method = GET)
      public String classNotFound() throws ClassNotFoundException {
            if (new Random().nextBoolean()) { // 랜덤하게 강제 예외발생
                  throw new ClassNotFoundException("클래스 없는 상황");
            }
            return "exception/view_class";
      }
      
      @ExceptionHandler(ClassNotFoundException.class)
      public ModelAndView classNotFoundProcess(ClassNotFoundException cnfe) {
            ModelAndView mav = new ModelAndView();
            
            mav.setViewName("exception/error");
            mav.addObject("msg", cnfe.getMessage());
            mav.addObject("exception", cnfe.toString());
            
            return mav;
      }
}
```

![04](/md/legacy-assets/javaEe/38/04.webp)

## 응답시에 JSP가 아닌 다른 do를 다시 요청할 때 

* **methodA에서 작업을 처리 후 methodB에 이동해서 나머지 작업을 처리해야 할 때**
  * **return에 JSP명이 아닌 요청을 처리하는 "~.do"가 나와야 한다.**
    * return에 **forward**를 붙이면 ViewResolver를 거치지 않고 정의된 URL을 직접 호출하게 된다.

```java
@RequestMapping("a.do")
public String methodA() {
    // 작업...
    
    // return "view명";
    return "forward:b.do";
}

@RequestMapping("b.do")
public String methodB() {
    // 나머지 작업 ...
    return "view명";
}
```

```html
<!-- main_menu.jsp -->
...
<li><a href="chain/chain_a.do">chain_a.do요청</a></li>
...
```

```java
import static org.springframework.web.bind.annotation.RequestMethod.GET;
...
@Controller
public class ChainController {
      @RequestMapping(value="/chain/chain_a.do",method=GET)
      public String chainA() {
            System.out.println("------------chain_A");
            return "forward:/chain/chain_b.do";
      }
      
      @RequestMapping(value="/chain/chain_b.do",method=GET)
      public String chainB() {
            // 직접 호출될 수도 있고 A를 거쳐서 호출될 수도 있다.
            System.out.println("------------chain_B");
            
            return "chain/chain_b_result";
      }
}
```

![05](/md/legacy-assets/javaEe/38/05.webp)

```html
<!-- chain/chain_b_result.jsp -->
...
<strong>chain_b.do로 응답된 내용</strong><br/>
<a href="#" onclick="history.back()">뒤로</a>
...
```

![06](/md/legacy-assets/javaEe/38/06.webp)

* **chainA에서 햄버거 정보를 추가하는 작업을 추가**

```java
@Controller
public class ChainController {
      @RequestMapping(value="/chain/chain_a.do",method=GET)
      public String chainA(Model model) {
            
            String[] lunch = { "버거킹", "KFC", "맥날", "맘스터치",  "롯데리아" };
            model.addAttribute("lunch", lunch);
            
            return "forward:/chain/chain_b.do";
      }
      
      @RequestMapping(value="/chain/chain_b.do",method=GET)
      public String chainB() {
            return "chain/chain_b_result";
      }
}
```

```html
<!-- chain/chain_b_result.jsp -->
...
<strong>chain_b.do로 응답된 내용</strong><br/>
<c:choose>
      <c:when test="${ empty lunch }">
            햄버거 목록을 받아오세요<br/>
            (chain_a를 거쳐서 오세요.)<br/>
      </c:when>
      <c:otherwise>
            좋아하는 햄버거 선택<br/>
            <c:forEach var="menu" items="${ lunch }">
                  <input type="checkbox" name="menu" value="${ menu }"/>
                  <c:out value="${ menu }" escapeXml="false"/>
                  <!-- checkbox를 체크하고 value가 없이 전달하면 'on'이  넘어간다 -->
            </c:forEach>            
      </c:otherwise>          
</c:choose>
<br/>
<a href="#" onclick="history.back()">뒤로</a>
...
```

![07](/md/legacy-assets/javaEe/38/07.webp)
