Analysis of exception handling problems
How to Handle exceptions
Problem is introduced into
-
There are two ways to handle exceptions in code. One is throws directly, and the other is tries.. Catch caught.
-
In A Java project, there may be a man-made exception, or the second may be used to get the details of the exception, or to ensure that the program continues to execute in the event of an exception.
-
However, catching every exception in the code makes the code redundant and less maintainable.
solution
-
Define a global exception handling class, return a uniform specification of exception information;
-
The processing logic is to determine whether an exception occurs before executing subsequent services.
Business, for example,
In order to realize the logic of global exception handling, this paper only gives a simple business
If an employee needs to be added to a department of a company, perform the following steps: 1 Query the employee object based on the employee ID. 2 Check whether the employee object has information, that is, whether the information is not empty. 3 If the employee object has information, it indicates that the employee object exists, and you do not need to add it.
The code is as follows:
public class MyService {
// Inject the DAO layer
@Autowired
EmployeeecMapper employeeecMapper;
/** * Add employee information *@paramEmployee Indicates the employee object *@returnNumber of rows affected */
public int add(Employee employee) {
// Query the employee object by id
Employeeec emp = employeeecMapper.selectByPrimaryKey(employee.getId());
// Determine whether the employee already exists
if(emp ! =null) {// If yes, throw an exception. The exception indicates that the employee already exists
throw new RuntimeException("Exception code: 1201, error message: This employee already exists");
}
// Insert the employee
returnemployeeecMapper.insert(emp); }}Copy the code
Exception Handling Process
There are runtime exceptions and business logic exceptions in the business. The former is difficult to detect when it is not running, and the latter can be defined when it is throughout the business. Therefore, exceptions are classified into unpredictable exceptions and knowable exceptions. The process is as follows:
- Custom global exception class, using
@ControllerAdvice
, controller enhancement - Custom error code and error message, the two types of exceptions will eventually use the same message format, error code + error message.
- For predictable exceptions thrown by the programmer in the code, by
SpringMVC
Uniform capture. - An unpredictable exception is usually caused by a system bug or some external factors (such as network fluctuation and server breakdown). The type of the exception is
RuntimeException
Type (runtime exception).
Is abnormal
Define the exception information class, variables as error code and error information, to catch custom exceptions, directly return the object
Agnostic exception
Define a map where you store common exceptions and define error codes. For other unusual exceptions, which are not in the map, the same exception object is returned.
Exception handling code flow
Is abnormal
1. Define the interface between print exception information and return result
public interface ResultCode {
// Whether the operation succeeded
boolean success(a);
// Operation result code
long code(a);
// Prompt message
String message(a);
}
Copy the code
public interface Response {
public static final boolean SUCCESS = true;
public static final int SUCCESS_CODE = 10000;
}
Copy the code
2, define the enumeration class to print the exception information and return the result class
@ToString
public enum CommonCode implements ResultCode {
NO_PAGE(false.404."No information."),
FAIL(false.500."Operation failed!"),
SUCCESS(true.200."Operation successful!");
// The result information
boolean success;
long code;
String message;
// Structure with parameters
CommonCode(boolean success, long code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
@Override
public boolean success(a) {
return true;
}
@Override
public long code(a) {
return code;
}
@Override
public String message(a) {
returnmessage; }}Copy the code
@Data
@ToString
public class ResponseResult implements Response {
boolean success = SUCCESS;
long code = SUCCESS_CODE;
String message;
public ResponseResult(ResultCode resultCode){
this.success = resultCode.success();
this.code = resultCode.code();
this.message = resultCode.message(); }}Copy the code
3. Define error exception classes
public class CustomException extends RuntimeException{
@Autowired
ResultCode resultCode;
// Structure with parameters
public CustomException(ResultCode resultCode){
this.resultCode = resultCode;
}
// getter
public ResultCode getResultCode(a){
returnresultCode; }}Copy the code
4. Define an exception-throwing class
public class ExceptionCast {
// Static methods
public static void cast(ResultCode resultCode){
throw newCustomException(resultCode); }}Copy the code
5. Define an exception catching class, use the annotation enhanced by ControllerAdvice controller, and add ExceptionHandler annotation to the method that catches the CustomException exception to catch all exceptions of this class, and return JSON data.
@ControllerAdvice
public class ExceptionCatch {
/** * Catch the CustomException class exception *@param customException
* @returnResult information,json data */
@ExceptionHandler(CustomException.class)
@ResponseBody
public ResponseResult customException(CustomException customException){
ResultCode resultCode = customException.getResultCode();
return newResponseResult(resultCode); }}Copy the code
6. Throw an exception in the business
public class MyService {
@Autowired
EmployeeecMapper employeeecMapper;
public int add(Employee employee) {
Employeeec emp = employeeecMapper.selectByPrimaryKey(employee.getId());
if(emp ! =null){
ExceptionCast.cast(CommonCode.FAIL);
}
returnemployeeecMapper.insert(emp); }}Copy the code
Unknown exception handling
1. Add error code to CommonCode class
UNAUTHORISE(false.510."No access."),
Copy the code
2. Add the method of catching unknowable exceptions in the exception catching class. In this method, a read-only map is defined to store the mapping of error codes of the exception type. Elements not in the map are defined as error code 999.
UNKNOWNERROR(false.999."Unknown exception"),
Copy the code
@ControllerAdvice
public class ExceptionCatch {
// Define a map to store common error messages. This map cannot be modified
private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;
/ / build ImmutableMap
protected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();
@ExceptionHandler(CustomException.class)
@ResponseBody
public ResponseResult customException(CustomException customException){
ResultCode resultCode = customException.getResultCode();
return new ResponseResult(resultCode);
}
/** * Catch non-custom class exceptions *@param exception
* @return* /
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseResult exception(Exception exception){
// Record logs
LOGGER.error("catch exception ==> ",exception.getMessage());
if (EXCEPTIONS == null){
EXCEPTIONS = builder.build();
}
ResultCode resultCode = EXCEPTIONS.get(exception.getClass());
if(resultCode ! =null) {return new ResponseResult(resultCode);
}else {
return newResponseResult(CommonCode.UNKNOWNERROR); }}static{ builder.put(HttpMessageNotReadableException.class, CommonCode.INVALID_PARAM); }}Copy the code
Complete the ~ ~