• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

    • About
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Java EE 정리 38

19 Apr 2019

Reading time ~3 minutes

Java EE 정리 38 - Controller에서 예외처리, 응답시에 JSP가 아닌 다른 do를 다시 요청할 때


Controller에서 예외처리

  • 요청을 처리하는 메소드에서 throws로 예외를 날림(예외 발생!)
    • 예외처리하는 메소드위에 @ExceptionHandler 정의
      • 한번에 하나의 예외만 처리한다
    • 예외처리 메소드의 반환형은 반드시 ModelAndView
    • 매개변수로 예외처리클래스명의 객체를 받는다
@ExceptionHandler(예외처리클래스명.class)
public ModelAndView 예외처리메소드명(예외처리클래스명 예외처리클래스객체명) {
    // 예외가 발생하면 발생한 예외객체를 전달받아 사용

    ModelAndView mav = new ModelAndView();

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

    return mav;
}

Controller에서 예외처리 예

<!-- main_menu.jsp -->
...
<li><a href="exception/exception.do">Controller에서 예외처리</a></li>
...
@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";
      }
...
<!-- 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

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

02

  • ExceptionHandler로 예외처리하는 메소드는 ModelAndView를 반환한다
    • ModelAndView에 이동할 예외처리 JSP명과 예외 메시지를 저장 후 반환
// 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;
      }
...
<!-- exception/error.jsp -->
...
<img src="http://localhost:8080/spring_mvc/common/images/err.png"/>
<br/>
문제가 발생했습니다.<br/>
간단한 메세지: ${ msg }<br/>
예외처리객체와 메세지: ${ requestScope.exception }
...

03

  • 다른 예외처리 예, ClassNotFoundException
// 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

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

  • methodA에서 작업을 처리 후 methodB에 이동해서 나머지 작업을 처리해야 할 때
    • return에 JSP명이 아닌 요청을 처리하는 “~.do”가 나와야 한다.
      • return에 forward를 붙이면 ViewResolver를 거치지 않고 정의된 URL을 직접 호출하게 된다.
@RequestMapping("a.do")
public String methodA() {
    // 작업...
    
    // return "view명";
    return "forward:b.do";
}

@RequestMapping("b.do")
public String methodB() {
    // 나머지 작업 ...
    return "view명";
}
<!-- main_menu.jsp -->
...
<li><a href="chain/chain_a.do">chain_a.do요청</a></li>
...
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

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

06

  • chainA에서 햄버거 정보를 추가하는 작업을 추가
@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";
      }
}
<!-- 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



Java EESpring