Spring Framrwork

[Spring Boot] Exception Resolver

gregorio 2018. 8. 14. 12:00

Spring Boot 사용 시 Exception이 발생하면 Exception을 사용자에게 보내기 위해 SimpleMappingExceptionResolver를 상속받아 Exception을 처리할 수 있다.



SimpleMappingExceptionResolver를 상속받으면 doResolveException 메소드를 재정의하여 Exception 발생 시 메세지를 JSON Format으로 클라이언트에게 전달한다.


doResolverException 메소드에서 Exception의 Type에 따라 메세지를 처리할 수 있다.


Spring Boot에서는 해당 Class를 Component Annotation을 이용하여 bean으로 설정한다.


■JsonExceptionResolver.java


import java.util.HashMap;

import java.util.Map;

import java.util.regex.Matcher;

import java.util.regex.Pattern;


import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import org.apache.ibatis.exceptions.PersistenceException;

import org.mybatis.spring.MyBatisSystemException;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.dao.DataAccessException;

import org.springframework.stereotype.Component;

import org.springframework.web.servlet.ModelAndView;

import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;


import dymn.demo.base.BaseConstants;

import dymn.demo.util.MessageUtil;

import dymn.demo.util.NullUtil;


//@Configuration


/** This class should used @Component annotation */

/** If you want to declare as a bean, create bean in WebConfig class **/

@Component

public class JsonExceptionResolver extends SimpleMappingExceptionResolver {

private static final Logger LOGGER = LoggerFactory.getLogger(JsonExceptionResolver.class);

    private final  String exceptionCodeAttribute = "exception";


@Override

    protected ModelAndView getModelAndView(String viewName, Exception ex) {

ModelAndView mv = super.getModelAndView(viewName,ex);

Map<String, Object> model = mv.getModel();

String code = model.get(this.exceptionCodeAttribute)!=null ?

        (String)model.get(this.exceptionCodeAttribute):  BaseConstants.DEFAULT_ERROR_CODE;

       

        String message = ex.getMessage();

        try {

            message = message == null ? MessageUtil.getMessage(code) : message;       

        }

        catch(Exception exception) {

        message = "";

        }


        model.put("message", message);

        model.put("error", "true");

        model.put("errortype", ex.getClass().getSimpleName());

        model.put("code",code);


return mv;

    }

 

    @Override

    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

    String msgCode = null;

    String msgValue = null;

   

    ex.printStackTrace();

 

    if (ex instanceof BizException) {

    BaseException be = (BaseException)ex; 

    msgCode = be.getCode();

    msgValue = be.getMessage();

    if (msgValue == null) {

            try {

              msgValue = MessageUtil.getMessage(msgCode);

              msgValue = msgCode + "<BR>" + msgValue; 

            }

            catch(Exception exception) {

              msgValue = "";

            }   

    }

    }

    /** Mybatis Or Database Exception **/

    else if (ex instanceof MyBatisSystemException || ex instanceof PersistenceException || ex instanceof DataAccessException ) {

    msgCode = BaseConstants.DEFAULT_DB_ERROR_CODE;

   

    if (ex.getCause() instanceof java.sql.SQLException) {

        /*-------------------------------------------------------------

        * 오라클의 경우 모든 오류를 SQLException으로 날립니다.

        * 이에 해당 오류메세지를 구분하여 메세지를 설정해야합니다.

        * 민자영업소의 요청에 따라 Oracle Exception ID 정보를 출력합니다.

        *-------------------------------------------------------------*/

        msgCode = BaseConstants.DEFAULT_DB_ERROR_CODE;

        String oraErrMsg = ex.getCause().getMessage();

       

        // 오라클 오류메세지 여부를 판단합니다.

        if (oraErrMsg != null && oraErrMsg.length() > 0) {

        String oraCode = null;

        Pattern pattern = Pattern.compile("ORA-\\d+");

       

        Matcher matcher = pattern.matcher(oraErrMsg);

       

        if (matcher.find()) {

        oraCode = matcher.group();

        }

        try {

        msgValue = MessageUtil.getMessage( msgCode, new Object[] {oraCode});

        msgValue = msgCode + "<BR>" + msgValue;

        }

        catch(Exception exception) {

        msgValue = "";

        }

        }

    }

    else {

    try {

    msgValue = MessageUtil.getMessage( msgCode);

    msgValue = msgCode + "<BR>" + msgValue;

    }

    catch(Exception exception) {

    msgValue = "";

    }       

    }

       

    }

    else {

    /** Set Default Message Code **/

    msgCode =  BaseConstants.DEFAULT_ERROR_CODE;

            try {

            msgValue = MessageUtil.getMessage( msgCode);

            msgValue = msgCode + "<BR>" + msgValue; 

            }

            catch(Exception exception) {

            msgValue = "";

            } 

    }

   


    /** Set error code and message for client **/

        Map<String, Object> retMsg = new HashMap<String, Object>();

        

      retMsg.put("message", msgValue);

      msgCode = !NullUtil.isNone(msgCode) ? msgCode : BaseConstants.DEFAULT_ERROR_CODE;

        retMsg.put("status", BaseConstants.STATUS_ERROR);


        if (LOGGER.isDebugEnabled()) {

            LOGGER.debug("Error Message to clinet :: {}", retMsg.toString());       

        }

       

       ModelAndView mav = new ModelAndView();

       mav.setViewName("jsonView");


       mav.addObject("message", retMsg);

       return mav;

    }

}

 



Exception에 에러코드만 있는 경우에는 메세지 파일에 정의되어 있는 메세지를 읽어서 JSON으로 생성하고, 에러코드와 메세지가 있는 경우 오류 코드와 메세지를 Json형식으로 만들어 화면에 전달한다.


Spring MVC에서는 mvc-servlet-context.xml에 bean으로 정의하면 된다.


  <!-- Exception Resolver -->

<bean id="exceptionResolver" class="cmn.deploy.exception.JsonExceptionResolver">

<property name="maxLength" value="1000" />

</bean>