GlobalExceptionAdvisor.java 11.3 KB
Newer Older
liqin's avatar
liqin committed
1
package cn.chnmuseum.party.common.mvc;
liqin's avatar
liqin committed
2

liqin's avatar
liqin committed
3 4
import cn.chnmuseum.party.common.enums.RESPONSE_CODE_ENUM;
import cn.chnmuseum.party.common.enums.RESULT_INFO_ENUM;
liqin's avatar
liqin committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
import com.google.common.base.Splitter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
liqin's avatar
liqin committed
27
import org.springframework.web.multipart.support.MissingServletRequestPartException;
liqin's avatar
liqin committed
28 29 30 31

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.sql.SQLIntegrityConstraintViolationException;
liqin's avatar
liqin committed
32
import java.util.LinkedHashMap;
liqin's avatar
liqin committed
33
import java.util.List;
liqin's avatar
liqin committed
34
import java.util.Map;
liqin's avatar
liqin committed
35 36 37 38 39
import java.util.stream.Collectors;

/**
 * 全局异常处理
 *
liqin's avatar
liqin committed
40
 * @author Danny Lee
liqin's avatar
liqin committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
 * @date 2019/8/1
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionAdvisor {

    /**
     * 捕获全局异常,处理所有不可知的异常
     *
     * @param exception 异常对象
     */
    @ExceptionHandler(Exception.class)
    public Object handleException(Exception exception) {
        log.error("\r\n ************** 操作出现异常:{}", ExceptionUtils.getStackTrace(exception));
        Class<?> eClass = exception.getClass();
liqin's avatar
liqin committed
56
        cn.chnmuseum.party.common.validator.HttpResult httpResult = new cn.chnmuseum.party.common.validator.HttpResult();
liqin's avatar
liqin committed
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
        if (eClass.equals(HttpRequestMethodNotSupportedException.class)) {
            addResCodeToMap(RESPONSE_CODE_ENUM.METHOD_NOT_SUPPORTED, httpResult);
        } else if (eClass.equals(HttpMediaTypeNotAcceptableException.class)) {
            addResCodeToMap(RESPONSE_CODE_ENUM.MEDIA_TYPE_NOT_ACCEPT, httpResult);
        } else if (eClass.equals(HttpMediaTypeNotSupportedException.class)) {
            addResCodeToMap(RESPONSE_CODE_ENUM.MEDIA_TYPE_NOT_SUPPORTED, httpResult);
        } else if (eClass.equals(ConversionNotSupportedException.class)) {
            addResCodeToMap(RESPONSE_CODE_ENUM.SERVER_ERROR, httpResult);
        } else if (eClass.equals(HttpMessageNotWritableException.class)) {
            addResCodeToMap(RESPONSE_CODE_ENUM.SERVER_ERROR, httpResult);
        } else {
            addResCodeToMap(RESPONSE_CODE_ENUM.SERVER_ERROR, httpResult);
        }
        return httpResult;
    }

    @ExceptionHandler(BindException.class)
    @ResponseBody
liqin's avatar
liqin committed
75
    public cn.chnmuseum.party.common.validator.HttpResult handle(BindException ex) {
liqin's avatar
liqin committed
76
        String message = ex.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(" \n "));
liqin's avatar
liqin committed
77 78 79 80 81 82 83 84 85 86
        //        BindingResult bindingResult = ex.getBindingResult();
        //        StringBuilder errMsg = new StringBuilder(bindingResult.getFieldErrors().size() * 16);
        //        errMsg.append("Invalid request:");
        //        for (int i = 0; i < bindingResult.getFieldErrors().size(); i++) {
        //            if (i > 0) {
        //                errMsg.append(",");
        //            }
        //            FieldError error = bindingResult.getFieldErrors().get(i);
        //            errMsg.append(error.getField()).append(":").append(error.getDefaultMessage());
        //        }
liqin's avatar
liqin committed
87 88 89 90 91

//        String message1 = Splitter.onPattern("\r\n|\n|\r").trimResults().splitToList(ex.getLocalizedMessage()).get(1);
//        if (message1 != null) {
//            String substring = message1.substring(message1.indexOf("on field"), message1.indexOf("rejected value"));
//            if (substring.toUpperCase().contains("REMARKS")) {
liqin's avatar
liqin committed
92
//                return new cn.chnmuseum.party.common.validator.HttpResult("400", "备注字数超过" + message1, "");
liqin's avatar
liqin committed
93 94
//            }
//        }
liqin's avatar
liqin committed
95
        return new cn.chnmuseum.party.common.validator.HttpResult("400", message, "");
liqin's avatar
liqin committed
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
    }

    //处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是javax.validation.ConstraintViolationException
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public String constraintViolationExceptionHandler(ConstraintViolationException e) {
        return e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
    }

    /**
     * 处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常。
     *
     * @param exception 错误信息集合
     * @return 错误信息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
liqin's avatar
liqin committed
112
    public cn.chnmuseum.party.common.validator.HttpResult validationBodyException(MethodArgumentNotValidException exception) {
liqin's avatar
liqin committed
113 114 115 116 117 118 119 120 121 122 123 124 125
        BindingResult result = exception.getBindingResult();
        String msg = null;
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            for (ObjectError objectError : errors) {
                FieldError fieldError = (FieldError) objectError;
                if (fieldError.getDefaultMessage() != null) {
                    log.info("Data check failure : object{" + fieldError.getObjectName() + "},field{" + fieldError.getField() +
                            "},errorMessage{" + fieldError.getDefaultMessage() + "}");
                    msg = fieldError.getDefaultMessage();
                }
            }
        }
liqin's avatar
liqin committed
126
        return new cn.chnmuseum.party.common.validator.HttpResult("400", msg);
liqin's avatar
liqin committed
127 128 129
    }

    @ExceptionHandler(DataAccessException.class)
liqin's avatar
liqin committed
130 131
    public cn.chnmuseum.party.common.validator.HttpResult dataAccessException(DataAccessException exception) {
        return new cn.chnmuseum.party.common.validator.HttpResult("400", exception.getLocalizedMessage());
liqin's avatar
liqin committed
132 133 134 135
    }

    @ExceptionHandler(DuplicateKeyException.class)
    @ResponseBody
liqin's avatar
liqin committed
136
    public cn.chnmuseum.party.common.validator.HttpResult duplicateKeyException(DuplicateKeyException e) {
liqin's avatar
liqin committed
137 138 139 140
        String localizedMessage = e.getLocalizedMessage();
        String message = Splitter.on(System.lineSeparator()).trimResults().splitToList(localizedMessage).get(1);
        String substring = message.substring(message.indexOf("Exception:"));
        if (substring.toUpperCase().contains("NAME")) {
liqin's avatar
liqin committed
141
            return new cn.chnmuseum.party.common.validator.HttpResult("400", "名称已存在,请修改名称", "");
liqin's avatar
liqin committed
142
        } else if (substring.toUpperCase().contains("CODE")) {
liqin's avatar
liqin committed
143
            return new cn.chnmuseum.party.common.validator.HttpResult("400", "编码已存在", "");
liqin's avatar
liqin committed
144
        }
liqin's avatar
liqin committed
145
        return new cn.chnmuseum.party.common.validator.HttpResult("400", message, "");
liqin's avatar
liqin committed
146 147 148 149
    }

    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    @ResponseBody
liqin's avatar
liqin committed
150
    public cn.chnmuseum.party.common.validator.HttpResult sqlIntegrityConstraintViolationException(SQLIntegrityConstraintViolationException e) {
liqin's avatar
liqin committed
151 152 153 154
        String localizedMessage = e.getLocalizedMessage();
        String message = Splitter.on(System.lineSeparator()).trimResults().splitToList(localizedMessage).get(1);
        String substring = message.substring(message.indexOf("Exception:"));
        if (substring.toUpperCase().contains("NAME")) {
liqin's avatar
liqin committed
155
            return new cn.chnmuseum.party.common.validator.HttpResult("400", "名称已存在,请修改名称", "");
liqin's avatar
liqin committed
156
        } else if (substring.toUpperCase().contains("CODE")) {
liqin's avatar
liqin committed
157
            return new cn.chnmuseum.party.common.validator.HttpResult("400", "编码已存在", "");
liqin's avatar
liqin committed
158
        }
liqin's avatar
liqin committed
159
        return new cn.chnmuseum.party.common.validator.HttpResult("400", message, "");
liqin's avatar
liqin committed
160 161 162 163 164 165 166 167 168
    }

    /**
     * 参数类型转换错误
     *
     * @param exception 错误
     * @return 错误信息
     */
    @ExceptionHandler(HttpMessageConversionException.class)
liqin's avatar
liqin committed
169
    public cn.chnmuseum.party.common.validator.HttpResult httpMessageConversionException(HttpMessageConversionException exception) {
liqin's avatar
liqin committed
170
        log.error(exception.getCause().getLocalizedMessage());
liqin's avatar
liqin committed
171
        return new cn.chnmuseum.party.common.validator.HttpResult("400", exception.getCause().getLocalizedMessage());
liqin's avatar
liqin committed
172 173 174 175 176 177 178 179 180
    }

    /**
     * 捕获业务异常
     *
     * @param exception 自定义接口异常类
     * @return 返回的异常信息map
     */
    @ExceptionHandler(InterfaceException.class)
liqin's avatar
liqin committed
181 182
    public cn.chnmuseum.party.common.validator.HttpResult handleInterfaceException(InterfaceException exception) {
        cn.chnmuseum.party.common.validator.HttpResult httpResult = new cn.chnmuseum.party.common.validator.HttpResult();
wzp's avatar
wzp committed
183
        httpResult.setResultCode(exception.getErrorCode());
wzp's avatar
wzp committed
184
        httpResult.setMessage(exception.getErrorMsg());
liqin's avatar
liqin committed
185 186 187 188 189 190 191 192 193 194 195
        return httpResult;
    }

    /**
     * 捕获Shiro无权限异常 未授权异常
     *
     * @param exception 无权限异常
     * @return 返回的异常信息map
     */
    @ExceptionHandler(UnauthorizedException.class)
    public Object handleUnauthorizedException(UnauthorizedException exception) {
liqin's avatar
liqin committed
196
        cn.chnmuseum.party.common.validator.HttpResult httpResult = new cn.chnmuseum.party.common.validator.HttpResult();
liqin's avatar
liqin committed
197
        // 无权限
wzp's avatar
wzp committed
198
        addResCodeToMap(RESPONSE_CODE_ENUM.ACCOUNT_AUTHENTICATION_FAILED, httpResult);
liqin's avatar
liqin committed
199 200 201 202 203 204 205 206 207 208 209
        return httpResult;
    }

    /**
     * 捕获Shiro无权限异常 未认证异常
     *
     * @param exception 无权限异常
     * @return 返回的异常信息map
     */
    @ExceptionHandler(UnauthenticatedException.class)
    public Object handleUnauthenticatedException(UnauthenticatedException exception) {
liqin's avatar
liqin committed
210
        cn.chnmuseum.party.common.validator.HttpResult httpResult = new cn.chnmuseum.party.common.validator.HttpResult();
liqin's avatar
liqin committed
211
        // 无权限
wzp's avatar
wzp committed
212
        addResCodeToMap(RESPONSE_CODE_ENUM.ACCOUNT_AUTHENTICATION_FAILED, httpResult);
liqin's avatar
liqin committed
213 214 215
        return httpResult;
    }

liqin's avatar
liqin committed
216 217 218 219 220 221 222 223
    @ExceptionHandler(MissingServletRequestPartException.class)
    public Object handleServletRequestPartException(MissingServletRequestPartException exception) {
        Map<String, Object> map = new LinkedHashMap<>();
        map.put(RESULT_INFO_ENUM.RESULT_CODE.getKey(), "400");
        map.put(RESULT_INFO_ENUM.RESULT_MSG.getKey(), "请选择文件后点击上传");
        return map;
    }

liqin's avatar
liqin committed
224 225 226 227 228 229
    /**
     * 添加异常信息到map中
     *
     * @param responseCodeEnum 错误响应编码枚举类对象
     * @param httpResult       响应对象
     */
liqin's avatar
liqin committed
230
    private void addResCodeToMap(RESPONSE_CODE_ENUM responseCodeEnum, cn.chnmuseum.party.common.validator.HttpResult httpResult) {
wzp's avatar
wzp committed
231
        httpResult.setResultCode(responseCodeEnum.getResultCode());
wzp's avatar
wzp committed
232
        httpResult.setMessage(responseCodeEnum.getMessage());
liqin's avatar
liqin committed
233
    }
liqin's avatar
liqin committed
234
}