For a database-related Spring MVC project, we typically configure the transaction at the service layer, and the service layer throws a run-time exception when the database operation fails, and the spring things manager rolls back.
As a result, our Controller layer will have to try-catch the Service layer exception, otherwise it will return some unfriendly error message to the client.
However, each method body of the Controller layer writes some templated Try-catch code, which is difficult to see and maintenance, especially when different exceptions to the Service layer are handled differently.
/** * Manual handling of Service layer exceptions and data check exceptions * @param dog * @param errors * @return*/@PostMapping (Value="") appresponse Add (@Validated (Add.class) @RequestBody dog Dog, Errors Errors) {Appresponse resp=NewAppresponse (); Try { //Data Validationbsutil.controllervalidate (Errors); //Perform businessDog Newdog =Dogservice.save (dog); //Return DataResp.setdata (Newdog); }Catch(businessexception e) {logger.error (E.getmessage (), E); Resp.setfail (E.getmessage ()); }Catch(Exception e) {logger.error (E.getmessage (), E); Resp.setfail ("operation failed! "); } returnresp;}
This article explains the use of @ControllerAdvice + @ExceptionHandler for the global controller layer exception handling, as long as the design is correct, you can no longer do try-catch in the controller layer!
Moreover, the @Validated validator annotations of the exception, can also be processed together, no need to manually determine the binding check results Bindingresult/errors!
[Email protected] Annotations Define global exception handling classes
// Uniform handles exceptions in this class, global interception of specified exceptions @ControllerAdvice Public class Exceptionhandle {
[email protected] Annotation declaration exception handling method
//Uniform handles exceptions in this class, global interception of specified exceptions@ControllerAdvice Public classExceptionhandle {Private StaticFinal Logger Logger = Loggerfactory.getlogger (exceptionhandle.class); @ExceptionHandler (Value= Exception.class)//assert that the exception class was captured@ResponseBody//returned to the browser is a JSON format, there is no @restcontroller, so this statement @responsebody PublicResult handle (Exception e) {return ' ERROR! "; }}
Method HandleException () handles the exception of the Exception and its subclasses thrown by all Controller layers.
Examples of implementing unified exception Management:
1. Encapsulate the returned result information and create a new result class
Public classResult<t> { /** * ERROR code*/ PrivateInteger Code; /** * Prompt information*/ PrivateString msg; /** * Specific content*/ PrivateT data; PublicResult () {} PublicResult (Integer code, String msg) { This(Code, MSG,NULL); } PublicResult (Integer code, String msg, T data) { This. Code =Code; This. msg =msg; This. data =data; } //。。。 }
2. To facilitate the processing of results information, the new result Information tool class: Resultutils
Public classResultutil { Public StaticResult Success (ObjectObject) { return NewResult (0,"Success",Object); } Public StaticResult Success () {returnSuccessNULL); } Public StaticResult Error (Integer code, String msg) {return NewResult (code, MSG); }}
3. To facilitate the processing of exception information, the custom exception information class: Girlexception
Public classGirlexception extends RuntimeException {//This place does not write exception, because spring is a transaction rollback only for runtime exceptions,//If the exception is thrown, the transaction is not rolled back. PrivateInteger Code; Publicgirlexception (Resultenum resultenum) { This(Resultenum.getmsg (), Resultenum.getcode ()); } Publicgirlexception (String message, Integer code) {super (message); This. Code =Code; } PublicInteger GetCode () {returnCode; } Public voidSetcode (Integer code) { This. Code =Code; }}
4. To facilitate the unified management of the relationship between the exception code and information, create an enumeration class
Public enumresultenum {unkown_error (-1,"Unknown error"), SUCCESS (0,"Success"), Primary_school (Ten,"you may still be in elementary school."), Middle_school ( -,"you may still be in junior high."), ; PrivateInteger Code; PrivateString msg; Privateresultenum (Integer code,string msg) { This. msg =msg; This. Code =Code; } PublicString getmsg () {returnmsg; } PublicInteger GetCode () {returnCode; } }
5. Throwing exceptions at the service layer
Public voidgetage (Integer id) throws Exception {Girl Girl=Girlrepository.getone (ID); Integer Age=Girl.getage (); if(Age <Ten) { Throw Newgirlexception (Resultenum.primary_school); } Else if(Age >Ten&& Age < -) { Throw Newgirlexception (Resultenum.middle_school); } }
6. Continue throwing exceptions at the controller layer
// Unified exception handling, in the controller layer of the exception to Exceptionhandler to deal with " Girls/getage/{id} " ) publicvoid getage (@PathVariable ("ID") Integer ID) throws Exception { girlservice.getage (ID); }
7. Handling Exceptions in Exceptionhandler
//Uniform handles exceptions in this class, global interception of specified exceptions@ControllerAdvice Public classExceptionhandle {Private StaticFinal Logger Logger = Loggerfactory.getlogger (exceptionhandle.class); @ExceptionHandler (Value= Exception.class)//assert that the exception class was captured@ResponseBody//returned to the browser is a JSON format, there is no @restcontroller, so this statement @responsebody PublicResult handle (Exception e) {if(e instanceof girlexception) {girlexception girlexception=(girlexception) e; returnResultutil.error (Girlexception.getcode (), Girlexception.getmessage ()); } logger.error (""System Exception"", E); returnResultutil.error (ResultEnum.UNKOWN_ERROR.getCode (), RESULTENUM.UNKOWN_ERROR.GETMSG ()); }}
Springboot Uniform exception handling