Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the problems encountered in global exception handling of springboot projects

2025-03-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces what problems will be encountered in the global exception handling of the springboot project, which has a certain reference value, and interested friends can refer to it. I hope you will gain a lot after reading this article.

Question 1: after the global exception is extracted, how to define the business error code?

The previous definition of the team's business error code is: business service prefix + business module + error code. If it is an exception that cannot be recognized, use the business prefix + fixed module code + fixed error code.

The previous global exception pseudocode is as follows

@ RestControllerAdvice@Slf4jpublic class GlobalExceptionBaseHandler {@ ExceptionHandler (Exception.class) @ ResponseStatus (HttpStatus.INTERNAL_SERVER_ERROR) public AjaxResult handleException (Exception e) {String servicePrifix = "U"; String moudleCode = "0001"; String code = "0001"; String errorCode = servicePrifix + moudleCode + code; String msg = e.getMessage (); if (StringUtils.isEmpty (msg)) {msg = "server exception" } log.error (msg, e); return AjaxResult.error (msg, errorCode);}} now that the global exception is extracted, how can the business service prefix be identified? When the business service is not removed before, the business service prefixes each business service directly in the code.

At that time, our temporary solution was to solve it through spring.application.name. Because after the global exception code block is extracted, it will eventually be introduced by the service. So the pseudo code that gets the business service prefix can be obtained as follows

Public enum ServicePrefixEnum {USER_SERVICE ("U", "user Center"); private final String servicePrefix; private final String serviceDesc; ServicePrefixEnum (String servicePrefix,String serviceDesc) {this.servicePrefix = servicePrefix; this.serviceDesc = serviceDesc;} public String getServicePrefix () {return servicePrefix;} public String getServiceDesc () {return serviceDesc } public String getServicePrefix (@ Value ("${spring.application.name}") String serviceName) {return ServicePrefixEnum.valueOf (serviceName) .getServicePrefix ();}

But this scheme actually has its drawbacks.

Disadvantage one: through enumerating hard-coding, the current micro-service name is preset. Once the project changes the micro-service name, the service prefix cannot be found.

Disadvantage 2: if the business service module is newly online, this enumeration class will have to be changed.

Later, we added a custom service code configuration to the global exception jar. Business personnel only need to configure it in the springboot configuration file, as follows

Lybgeek: bizcode: prefix: U

At this point, the example of a global exception modification is as follows

@ RestControllerAdvice@Slf4jpublic class GlobalExceptionBaseHandler {@ Autowired private ServiceCodeProperties serviceCodeProperties; @ ExceptionHandler (Exception.class) @ ResponseStatus (HttpStatus.INTERNAL_SERVER_ERROR) public AjaxResult handleException (Exception e) {String servicePrifix = serviceCodeProperties.getPrifix (); String moudleCode = "001"; String code = "0001"; String errorCode = servicePrifix + moudleCode + code; String msg = e.getMessage () If (StringUtils.isEmpty (msg)) {msg = "server exception";} log.error (msg, e); return AjaxResult.error (msg, errorCode);} problem 2: the global exception introduces the same dependency jar as the business, but the version of jar is different.

If the global exception is written directly as follows, there is no problem. Examples are as follows

@ RestControllerAdvice@Slf4jpublic class GlobalExceptionBaseHandler {@ Autowired private ServiceCodeProperties serviceCodeProperties; @ ExceptionHandler (Exception.class) @ ResponseStatus (HttpStatus.INTERNAL_SERVER_ERROR) public AjaxResult handleException (Exception e) {String servicePrifix = serviceCodeProperties.getPrifix (); String moudleCode = "001"; String code = "0001"; String errorCode = servicePrifix + moudleCode + code; String msg = e.getMessage () If (StringUtils.isEmpty (msg)) {msg = "server exception";} log.error (msg, e); return AjaxResult.error (msg, HttpStatus.INTERNAL_SERVER_ERROR.value ());} @ ExceptionHandler (BizException.class) public AjaxResult handleException (BizException e) {return AjaxResult.error (e.getMessage (), e.getErrorCode ());}}

That is, global exceptions are directly divided into business exceptions and Execption. The disadvantage of this division is that there is no way to subdivide exceptions, and it also makes it impossible to subdivide the module code and business code defined by the project team. Therefore, we also list commonly predictable system exceptions, as shown in the following example

/ * * Parameter verification failed * @ param e * @ return * / @ ExceptionHandler (ConstraintViolationException.class) @ ResponseStatus (HttpStatus.BAD_REQUEST) public AjaxResult handleException (ConstraintViolationException e) {log.error ("parameter verification failed", e); return AjaxResult.error ("parameter verification failed", HttpStatus.BAD_REQUEST.value ()) Database exception * @ param e * @ return * / @ ExceptionHandler ({SQLException.class, MybatisPlusException.class, MyBatisSystemException.class, org.apache.ibatis.exceptions.PersistenceException.class, BadSqlGrammarException.class}) @ ResponseStatus (HttpStatus.BAD_REQUEST) public AjaxResult dbException (Exception e) {String msg = ExceptionUtil.getExceptionMessage (e) Log.error (msg, e); return AjaxResult.error (msg,HttpStatus.BAD_REQUEST.value ());} / * the record already exists in the database * @ param e * @ return * / @ ExceptionHandler (DuplicateKeyException.class) @ ResponseStatus (HttpStatus.CONFLICT) public AjaxResult handleException (DuplicateKeyException e) {log.error ("the record already exists in the database", e) Return AjaxResult.error ("the record already exists in the database", HttpStatus.CONFLICT.value ();}

However, this leads to a problem, that is, the global exception and the business side use the same dependency jar, but when there is a version difference, there may be dependency conflicts, resulting in business project startup errors. So the solution is to add the optional tag to the pom file. Examples are as follows

Com.baomidou mybatis-plus-boot-starter true

The label means that the jar coordinates are optional, so if you already have coordinates in the project that introduce the jar, use the jar coordinates directly.

Problem 3: after the introduction of the maven optional tag, the jar required by the global exception is not introduced into the business, resulting in a project startup error report.

The cause of this problem: for example, our business microservice project has an aggregation layer, and some aggregation layers do not need to rely on storage media, such as mysql. Therefore, these aggregation layer projects pom do not introduce mybatis-related dependencies. However, our global exception requires mybatis-related dependencies, which leads to additional jar that is not needed by the business side if we want to reference the global exception module.

So springboot's conditional annotations come in handy, using @ ConditionalOnClass annotations. Examples are as follows

@ RestControllerAdvice@Slf4j@ConditionalOnClass ({SQLException.class, MybatisPlusException.class, MyBatisSystemException.class, org.apache.ibatis.exceptions.PersistenceException.class, BadSqlGrammarException.class, DuplicateKeyException.class}) public class GlobalExceptionDbHandler {/ * Database exception * @ param e * @ return * / @ ExceptionHandler ({SQLException.class, MybatisPlusException.class, MyBatisSystemException.class, org.apache.ibatis.exceptions.PersistenceException.class BadSqlGrammarException.class}) @ ResponseStatus (HttpStatus.BAD_REQUEST) public AjaxResult dbException (Exception e) {String msg = ExceptionUtil.getExceptionMessage (e) Log.error (msg, e); return AjaxResult.error (msg,HttpStatus.BAD_REQUEST.value ());} / * the record already exists in the database * @ param e * @ return * / @ ExceptionHandler (DuplicateKeyException.class) @ ResponseStatus (HttpStatus.CONFLICT) public AjaxResult handleException (DuplicateKeyException e) {log.error ("the record already exists in the database", e) Return AjaxResult.error ("the record already exists in the database", HttpStatus.CONFLICT.value ());}}

The purpose of the @ ConditionalOnClass annotation is that if the specified class exists in classpath, the class on that annotation will take effect.

At the same time, there is a detail node here, that is, global exceptions may have to be subdivided, that is, the original unified global exceptions are separated according to business scenarios, such as storage media-related storage exceptions and web-related exceptions.

Thank you for reading this article carefully. I hope the article "what problems will be encountered in the global exception handling of the springboot project" shared by the editor will be helpful to everyone? at the same time, I also hope that you will support and pay attention to the industry information channel, and more related knowledge is waiting for you to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report