springmvc请求参数异常统一处理,结合钉钉报告信息定位bug位置

Posted xy-ouyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springmvc请求参数异常统一处理,结合钉钉报告信息定位bug位置相关的知识,希望对你有一定的参考价值。

参考之前一篇博客:springmvc请求参数异常统一处理

1、ExceptionHandlerController

package com.oy.controller;

import java.text.MessageFormat;
import java.util.ResourceBundle;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;

import com.alibaba.fastjson.JSONObject;

import com.oy.exception.ForbiddenException;
import com.oy.exception.JwebException;
import com.oy.utils.ErrCode;
import com.oy.utils.Response;
import com.oy.utils.UtilFunctions;

@ControllerAdvice
public class ExceptionHandlerController {

    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public JSONObject runtimeExceptionHandler(RuntimeException ex) {
        UtilFunctions.log.error("runtimeExceptionHandler, msg: {}, exception: {}", ex.toString(), ex);
        UtilFunctions.reportError("runtimeExceptionHandler: " + ex.toString(), ex);
        JSONObject response = new JSONObject();
        response.put("message", "Internal Server Error");
        return response;
    }

    @ExceptionHandler(NullPointerException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public JSONObject nullPointerExceptionHandler(NullPointerException ex) {
        UtilFunctions.log.error("nullPointerExceptionHandler, msg: {}, exception: {}", ex.toString(), ex);
        UtilFunctions.reportError("runtimeExceptionHandler: " + ex.toString(), ex);
        JSONObject response = new JSONObject();
        response.put("message", "Internal Server Error");
        return response;
    }

    /*----- REQUEST ERROR -----*/
    @ExceptionHandler({ ForbiddenException.class })
    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ResponseBody
    public JSONObject requestForbidden(ForbiddenException ex) {
        UtilFunctions.log.error("ForbiddenExceptionHandler, msg: {}, exception: {}", ex.toString(), ex);
        JSONObject response = new JSONObject();
        response.put("message", ex.getMessage());
        return response;
    }

    @ExceptionHandler({ TypeMismatchException.class })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public JSONObject requestTypeMismatch(TypeMismatchException ex) {
        UtilFunctions.log.error("TypeMismatchExceptionHandler, msg: {}, exception: {}", ex.toString(), ex);
        JSONObject response = new JSONObject();
        // response.put("message", "Bad Request");
        // response.put("message", "Bad Request,  parameter type of " + ex.getPropertyName() + " need be " + ex.getRequiredType());
        
        if (Double.class.equals(ex.getRequiredType()) ||  Integer.class.equals(ex.getRequiredType())) {
            response.put("message", "Bad Request, " +  ex.getValue() + " not a number");
        } else {
            String strTemplate = "Bad Request, {0} is invalid, a type of {1} is needed";
            response.put("message", MessageFormat.format(strTemplate, ex.getValue(), ex.getRequiredType().getName()));
        }
        return response;
    }

    @ExceptionHandler({ MissingServletRequestParameterException.class })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public JSONObject requestMissingServletRequest(MissingServletRequestParameterException ex) {
        UtilFunctions.log.error("MissingServletRequestParameterExceptionHandler, msg: {}, exception: {}", ex.toString(), ex);
        JSONObject response = new JSONObject();
        // response.put("message", "Bad Request");
        String strTemplate = "Bad Request, param:{0} is required, type:{1}";
        response.put("message", MessageFormat.format(strTemplate, ex.getParameterName(), ex.getParameterType()));
        return response;
    }
    
    @ExceptionHandler({ NoSuchRequestHandlingMethodException.class })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public JSONObject NoSuchRequestHandlingMethodExceptionHandler(NoSuchRequestHandlingMethodException ex) {
        UtilFunctions.log.error("NoSuchRequestHandlingMethodExceptionHandler, msg: {}, exception: {}", ex.toString(), ex);
        JSONObject response = new JSONObject();
        response.put("message", "Not Found");
        return response;
    }
    
    /*----- REQUEST ERROR -----*/
    @ExceptionHandler({ HttpMessageNotReadableException.class })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public JSONObject requestNotReadable(HttpMessageNotReadableException ex) {
        UtilFunctions.log.error("HttpMessageNotReadableExceptionHandler, msg: {}, exception: {}", ex.toString(), ex);
        JSONObject response = new JSONObject();
        response.put("message", "Bad Request");
        return response;
    }

    @ExceptionHandler({ HttpRequestMethodNotSupportedException.class })
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ResponseBody
    public JSONObject request405(HttpRequestMethodNotSupportedException ex) {
        UtilFunctions.log.error("HttpRequestMethodNotSupportedExceptionHandler, msg: {}, exception: {}", ex.toString(), ex);
        JSONObject response = new JSONObject();
        // response.put("message", "Method Not Allowed");
        response.put("message", ex.getMessage());
        return response;
    }
    
    @ExceptionHandler({ JwebException.class })
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public JSONObject jwebExceptionHandler(JwebException ex, HttpServletRequest request) {
        UtilFunctions.log.error("jwebExceptionHandler, info: {}, exception: {}", ex.getMessage(), ex);
        UtilFunctions.reportError("jwebExceptionHandler, " + ex.toString(), null);
        //JSONObject response = new JSONObject();
        //response.put("code", ErrCode.SER_INTERNAL_ERR);
        //response.put("message", ex.getMessage());
        //response.put("message", "The system is busy. Please try again later.");
        ResourceBundle resourceBundle = (ResourceBundle) request.getAttribute("resourceBundle");
        String message = UtilFunctions.getMessage(resourceBundle, "SYSTEM_BUSY");
        return new Response(ErrCode.SER_INTERNAL_ERR, message).toJson();
    }
}

 

2、springmvc全局异常捕获,整合钉钉打印异常相关信息

  UtilFunctions#reportError()方法:

public static void reportError(String msg, Exception err) {
    if (err != null) {
        log.error("msg:{}, err:{}", msg, err);
    }
    
    JSONObject content = new JSONObject();
    //content.put("content", "hostname:" + Config.HOSTNAME + "\\n" + "errMsg:" + msg);
    content.put("content", "hostname:" + Config.HOSTNAME + "\\n" + "errMsg:" + msg + "\\n" + getStackTraceInfo(err));
    
    JSONObject obj = new JSONObject();
    obj.put("msgtype", "text");
    obj.put("text", content.toString());
    String query = obj.toString();
    try {
        URL url = new URL("https://oapi.dingtalk.com/robot/send?access_token=" + Config.DINGTOKEN);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setRequestMethod("POST");
        connection.setUseCaches(false);
        connection.setInstanceFollowRedirects(true);
        connection.setRequestProperty("Content-Type", "application/json");
        connection.connect();
        try (OutputStream os = connection.getOutputStream()) {
            os.write(query.getBytes("UTF-8"));
        }
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {

        }
        connection.disconnect();

    } catch (Exception e) {
        e.printStackTrace();
    }
}
public static String printStackTraceToString(Throwable t) {
//        StringWriter sw = new StringWriter();
//        t.printStackTrace(new PrintWriter(sw, true));
//        return sw.getBuffer().toString();
    
    StringWriter sw = null;
    PrintWriter pw = null;
    try {
        sw = new StringWriter();
        pw =  new PrintWriter(sw);
        t.printStackTrace(pw);
        pw.flush();
        sw.flush();
        return sw.getBuffer().toString();
    } finally {
        if (sw != null) {
            try {
                sw.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
        if (pw != null) {
            pw.close();
        }
    }
}
public static String getStackTraceInfo(Throwable t) {
    String stackTraceInfo = "";
    
    String stackTrace = printStackTraceToString(t);
    String regex = "at amberai.jweb(\\\\S*)";
    Pattern pattern = Pattern.compile(regex);
    
    Matcher matcher = pattern.matcher(stackTrace);
    while (matcher.find()) {
        stackTraceInfo += matcher.group() + "\\n";
        // UtilFunctions.log.info("=====matcher.group:{}" + matcher.group());
    }
    return stackTraceInfo;
}

 

3、测试

  3.1、手动抛出JwebException

TradeOrder tradeOrder = tradeService.getOrderByHashId(hashId);
if (tradeOrder == null) {
    String errMsg = MessageFormat.format("TradeController#getOrder error, tradeOrder:{0}, uid:{1}", tradeOrder, uid);
    throw new JwebException(errMsg);
}
UtilFunctions.log.info("grpc getOrder info, uid:{}, tradeOrder.getUserid:{}", tradeOrder, uid,
        tradeOrder.getUserid());
if (!uid.equals(tradeOrder.getUserid())) {
    String errMsg = MessageFormat.format("TradeController#getOrder error, uid:{0}, tradeOrder.getUserid:{0}", uid, tradeOrder.getUserid());
    throw new JwebException(errMsg);
}

  

  3.2、代码出现RuntimeException,比如

  int a = 1/0;

 

以上是关于springmvc请求参数异常统一处理,结合钉钉报告信息定位bug位置的主要内容,如果未能解决你的问题,请参考以下文章

javaweb异常提示信息统一处理(使用springmvc,附源码)

SpringMvc,Springboot统一校验自定义异常全局异常处理

SpringMvc,Springboot统一校验自定义异常全局异常处理

spring MVC实践

SpringMVC学习07SpringMVC中的统一异常处理

统一异常处理