java/kotlin/spring引导发生异常时,如何自动检索参数值?

gijlo24d  于 2021-07-12  发布在  Java
关注(0)|答案(3)|浏览(314)

考虑到我们正在使用 Kotlin , Spring Boot 注解和其他相关库。
如果我们的代码抛出了一个异常,那么我们如何在异常发生时自动检索方法参数值呢?
我们可以使用aop、spring拦截器或其他技术来实现这一点吗?
我们希望它能丰富我们的错误信息,这样我们就可以从错误发生的地方复制错误。
请注意,我们正在寻找一种解决方案,它不需要注解所有可能的方法,而是在发生异常时处理代码的方法。我们可以使用javastacktrace元素来检索一些有用的信息,比如发生异常的方法、行和文件,但是那里没有参数值。
在spring中,我们有控制器通知功能,可以用来处理所有异常,因此我们希望为此目的在那里放置一些东西,例如。
编辑
添加一些示例代码:

fun exceptionHandler(throwable: Throwable) {
    logger.severe("""
        Error ${throwable.message}
        File: ${throwable.stackTrace[2].fileName}
        Class: ${throwable.stackTrace[2].className}
        Method: ${throwable.stackTrace[2].methodName}
        Line: ${throwable.stackTrace[2].lineNumber}
        Parameters: ## Somehow get the parameters values here, in this case "Hello, 1, false"
    """.trimIndent())
    }

fun myController() {
    myMethodWithErrors("Hello", 1, false)
}

fun myMethodWithErrors(param1: String, param2: Int, param3: Boolean) {
    throw RuntimeException("Some bad thing happened here when executing this code.")
}
6qfn3psc

6qfn3psc1#

我假设您讨论的是restapi参数,而不是每个java方法参数。您可以实现捕获restapi调用中所有异常的控制器建议。

@ControllerAdvice
public class ExceptionHandler {

    @ExceptionHandler(value = [Exception::class])
    @ResponseBody
    fun onException(exception: Exception, request: WebRequest): ResponseEntity<ErrorDetailsClass> {
         log.error("error when request with parameters ${request.parameterMap} ")
         return buildDetails(request)
    }
}

通过这种方式,您既可以检索正确的错误消息,也可以在内部记录一些用于错误跟踪的内容。

3xiyfsfu

3xiyfsfu2#

使用spring aop,可以通过@afterhrowing建议来满足这一要求。
下面的示例方面将截获包下的所有方法调用 org.aop.bean.impl 有一个例外。我们可以使用 throwing 属性。给定的示例过滤掉了使用 IllegalArgumentException .
方法调用期间的参数可以通过 joinpoint.getArgs() 方法。

@Aspect
@Component
public class ExceptionLoggerAspect {

    @Pointcut("execution(* org.aop.bean.impl..*(..))")
    public void allExceptions() {

    }

    @AfterThrowing(pointcut = "allExceptions()",throwing="ex")
    public void logException(JoinPoint jp , IllegalArgumentException ex) {
        Object[] args= jp.getArgs();
        for(Object obj:args) {
            System.out.println(obj);
        }
    }
}

从文件中
通常,您希望通知仅在抛出给定类型的异常时运行,并且还经常需要访问通知正文中抛出的异常。可以使用抛出属性来限制匹配(如果需要) — 使用throwable作为异常类型(否则),并将抛出的异常绑定到advice参数

qlckcl4x

qlckcl4x3#

我正在编写的示例是在springboot中使用org.springframework.web.bind.annotation.exceptionhandler注解
它对我来说非常好
假设我请求https://example.com/user-api/users/a535c777-c906-45e2-b1c3-940965a507f2q ,然后我们的api验证该用户id是否存在,如果不存在,则抛出正确的消息,包括哪些参数无效或有错误。
响应示例1:

{
"apierror": {
    "dateTime": "2020-02-13T06:24:14.985",
    "timestamp": "1581603854985",
    "status": 404,
    "error": "Not Found",
    "message": "User not found",
    "debugMessage": null,
    "errors": [
        {
            "field": "userId",
            "rejectedValue": "a535c777-c906-45e2-b1c3-940965a507f2q",
            "message": "User not found with userId:a535c777-c906-45e2-b1c3-940965a507f2q"
        }
    ]
}

}
响应ex2:

{
      "apierror": {
        "dateTime": "2020-02-13T06:43:23.377",
        "timestamp": "1581605003377",
        "status": 400,
        "error": "Bad Request",
        "message": "Validation error",
        "debugMessage": null,
        "errors": [
          {
            "field": "userName",
            "rejectedValue": "Ash",
            "message": "Username should have at least 6 characters"
          },
          {
            "field": "userName",
            "rejectedValue": "Ash",
            "message": "Invalid username"
          },
          {
            "field": "password",
            "rejectedValue": "shutosh@",
            "message": "Invalid password"
          }
        ]
      }
    }

异常消息“找不到用户”userid:a535c777-c906-45e2-b1c3-940965a507f2q“符合api。下面是用例。
控制器:

@PrivilegeMapper.HasPlaceUserPrivilege
@GetMapping(value = "/{userId}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<?> getUserProfile(@NotBlank @PathVariable String userId) {
 return myService.buildUserProfile(userId);
}

服务:

@Override
public ResponseEntity<?> buildUserProfile(final String userId) {

    ApiUser apiUser = userRepository.findById(userId)
            .orElseThrow(() -> new ApiUserNotFoundException("userId",userId));

    return ResponseEntity.ok(sirfUser);
}

异常类:

@Getter
    @Setter
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    public class ApiUserNotFoundException extends NotFoundException {

        public ApiUserNotFoundException(String msg, Throwable t) {
            super(msg, t);
        }

        public ApiUserNotFoundException(String msg) {
            super(msg);
        }

        public ApiUserNotFoundException(String key, String value) {
            super(key, value);
        }

        public ApiUserNotFoundException(String key, String value, List<Error> errors) {
            super(key, value, errors);
        }
    }   

    @Getter
    @Setter
    @ResponseStatus(code = HttpStatus.NOT_FOUND)
    public class NotFoundException extends RuntimeException {

        private String key;
        private String value;
        private List<Error> errors;

        public NotFoundException(String msg, Throwable t) {
            super(msg, t);
        }

        public NotFoundException(String msg) {
            super(msg);
        }

        public NotFoundException(String key, String value) {
            this.key = key;
            this.value = value;
        }

        public NotFoundException(String key, String value, List<Error> errors) {
            this.key = key;
            this.value = value;
            this.errors = errors;
        }

    }

异常处理程序:

@ExceptionHandler(ApiUserNotFoundException.class)
protected ResponseEntity<Object> handleSirfUserNotFound(ApiUserNotFoundException ex) {
    log.error(String.format("User not found with %s:%s",ex.getKey(),ex.getValue()));
    ApiError apiError = new ApiError(NOT_FOUND);
    apiError.setMessage("User not found");
    List<Error> errors = new ArrayList<>();
    Error error = new ApiValidationError(SirfUser.class.getSimpleName());
    ((ApiValidationError) error).setMessage(String.format("User not found with %s:%s",ex.getKey(),ex.getValue()));
    ((ApiValidationError) error).setField(ex.getKey());
    ((ApiValidationError) error).setRejectedValue(ex.getValue());
    errors.add(error);
    apiError.setErrors(errors);
    return buildResponseEntity(apiError);
}

就是这样。你完了。这种类型的处理对于日志记录和ui透视总是有用的。

相关问题