// The subclass method did not throw an exception @Override public List<String> readFromFile(String filePath){ return null; }
}
1.3. 2. Method overload
Java method overloading involves only method names and parameter lists. Method return value and exception list are used as the basis for method overloading.
1 |
2
3
4
5
6
7
8
9
10
public List<String> readFromFile(String path) throws IOException{
return null;
}
/**
Compile but
public List<String> readFromFile(String path) throws FileNotFoundException{
return null;
}
*/
1.3. 3. Constructor
Exception restriction has no effect on the constructor. The subclass constructor can throw any exception, regardless of the exception thrown by the base class constructor. However, because the base class constructor must be called in some form, the exception description of the derived class constructor must contain the exception description of the base class constructor.
The constructor will set the object to a safe initialization state. If there is other work, such as opening a file, such an action can only be cleaned up after the object is used and the user calls the cleaning method. If an exception is thrown in the constructor, these cleanup actions will not work properly, so pay special attention when writing the constructor.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Parent{
Parent() throws IOException{ }
}
class Child extends Parent{
Child() throws IOException { super(); //Exception thrown this time } /** Child() throws IOException { // super Must be the first statement, exception cannot be caught try { super(); //Exception thrown this time }catch (Exception e){ } } */
}
1.4 inspected abnormality
Exceptions that are forced to be checked at compile time are called checked exceptions. That is, the exception declared in the declaration of the method.
The checked exception requires that the method caller must handle the exception. In a way, the checked exception violates the original intention of Java exception handling.
1 |
2
3
4
private List<String> readFromFile(String filePath) throws IOException {
Path path = Paths.get(filePath); return Files.readAllLines(path, Charset.defaultCharset());
}
You cannot ignore the handling of the 'IOException' when calling the 'readFromFile' method.
In general, we usually handle the checked exceptions as follows:
-
Modify your own method signature and add a new exception declaration;
-
Use try catch to wrap exception calls (most of the time, we don't know how to recover);
-
Convert the checked exception into a runtime exception;
1 |
2
3
4
5
6
7
8
9
private void printFile2(String filePath){
try { List<String> lines = readFromFile(filePath); lines.forEach(System.out::println); }catch (IOException e){ // Use the exception chain to convert checked exceptions to runtime exceptions throw new RuntimeException(e); }
}
1.4.1 Spring DAO Support
There are a large number of checked exceptions in the JDBC interface. When operating the database, a large number of try catch template codes will appear, burying the core logic in the code sea.
Therefore, Spring optimizes it. The specific optimization measures are as follows:
-
On the basis of runtime exceptions, a set of exception system (DataAccessException and subclasses) is established;
-
Convert the checked exception in jdbc into a runtime exception;
-
Use template method to reduce redundant code.
The JDBC tempalt code snippet is as follows:
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null"); Connection con = DataSourceUtils.getConnection(obtainDataSource()); Statement stmt = null; try { stmt = con.createStatement(); applyStatementSettings(stmt); T result = action.doInStatement(stmt); handleWarnings(stmt); return result; } catch (SQLException ex) { // Release Connection early, to avoid potential connection pool deadlock // in the case when the exception translator hasn't been initialized yet. String sql = getSql(action); JdbcUtils.closeStatement(stmt); stmt = null; DataSourceUtils.releaseConnection(con, getDataSource()); con = null; // Complete the conversion from checked exception to runtime exception throw translateException("StatementCallback", sql, ex); } finally { JdbcUtils.closeStatement(stmt); DataSourceUtils.releaseConnection(con, getDataSource()); }
}
2. Custom exception
You don't have to be limited to the exception types provided by Java. We can customize exception classes to represent specific problems that may be encountered in the program.
To customize an exception class, you must inherit from an existing exception class. The best way is to select an exception class with similar meaning.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//Business exception
class BizException extends RuntimeException{
public BizException() { super(); } public BizException(String message) { super(message); } public BizException(String message, Throwable cause) { super(message, cause); } public BizException(Throwable cause) { super(cause); }
}
Exceptions are usually named to represent the problem, and the name of the exception should be known by text.
2.1. Abnormal inheritance system
Exceptions themselves are classes, and there is a complete inheritance system.
2.2. Throwable
Throwable is used to represent any class that can be thrown as an exception.
Throwable objects can be divided into two types (inherited from throwable):
-
Error is used to indicate compile time and system errors. Except in special cases, developers do not need to have a relationship
-
Exception indicates the base type that can be thrown. Exceptions can be thrown in Java class libraries, user methods, and runtime faults. This is the most relevant exception for developers.
throwable is mainly used to maintain the exception stack. The core methods are as follows:
Method | meaning
—|—
printStackTrace | print call stack information and output it to standard error output (System.error)
printStackTrace(PrintStream) | specifies the Stream print call stack information
printStackTrace(PrintWriter) | specifies the Print call stack information
getStackTrace() | get call stack sequence information
fillInStackTrace() | records the current state of the stack frame
The exception stack records the method call sequence of "taking you to the exception throw point", which is one of the main information for troubleshooting.
1 |
2
3
4
5
6
7
8
9
10
11
public static void main(String... arg){
try { // Normal processing flow, correct implementation of the process, what to do Path path = Paths.get("var", "error"); List<String> lines = Files.readAllLines(path, Charset.defaultCharset()); System.out.println(lines); } catch (IOException e) { // Exception handling process. What if something goes wrong e.printStackTrace(); }
}
Run the program and get the results. The exception stack is as follows:
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
java.nio.file.NoSuchFileException: var/error
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86) at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102) at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107) at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214) at java.nio.file.Files.newByteChannel(Files.java:361) at java.nio.file.Files.newByteChannel(Files.java:407) at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:384) at java.nio.file.Files.newInputStream(Files.java:152) at java.nio.file.Files.newBufferedReader(Files.java:2781) at java.nio.file.Files.readAllLines(Files.java:3199) at com.geekhalo.exception.Demo.main(Demo.java:15) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
2.3. Exception
Exception is the base class of all exception classes related to programming.
|Method | meaning|
| — | — |
|getMessage | get details|
|getLocaliedMessage | get the details of the local language representation|
2.4. RuntimeException
The exception derived from RuntimeException becomes an unchecked exception. This exception is automatically thrown by the Java virtual machine, so it does not have to be listed in the exception description of the method.
1 |
2
3
private void throwRuntimeException(){
throw new RuntimeException();
}
RuntimeException and its subclasses} do not need to be declared in the method.
3. Common exception handling strategies
After the custom exception is completed, the next key point is how to handle the exception.
3.1. Abnormal recovery
The purpose of the exception handler is to handle the exception that occurs. Therefore, the first exception handling strategy is to handle exceptions and recover exceptions.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
private void recoveryException(String filePath){
try { List<String> lines = readFromFile(filePath); lines.forEach(System.out::println); }catch (IOException e){ // Print the log and recover the program from the exception LOGGER.error("failed to read from file {}", filePath, e); }
}
private List<String> readFromFile(String filePath) throws IOException {
Path path = Paths.get(filePath); return Files.readAllLines(path, Charset.defaultCharset());
}
3.2. Re throw exception
When you can't get enough information to recover the exception. You can re throw the exception just caught. The reference to the current exception object has been obtained in the catch clause and can be thrown directly.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void printFile(String filePath) throws IOException{
try { List<String> lines = readFromFile(filePath); lines.forEach(System.out::println); }catch (IOException e){ // Re throw exception throw e; }
}
//Method exception description
private List<String> readFromFile(String filePath) throws IOException {
Path path = Paths.get(filePath); return Files.readAllLines(path, Charset.defaultCharset());
}
Throwing the exception again will throw the exception to the previous call, and the catch clause after the same try will be ignored. If only the current exception is thrown, printStackTrace displays the call chain information of the original exception throwing point rather than the information of the re throwing point. If you want to update the invocation information, you can call the fillInStackTrace method to return another Throwable object, which will fill the current call stack information into the original exception object.
3.3. Abnormal chain
If you want to throw another new exception after catching an exception and want to keep the original exception information, this is called exception concatenation.
The subclass of Throwable can accept a cause object in the constructor to represent the original exception. In this way, the original exception is passed to the new exception, so that the new exception created and thrown in the current position can be traced to the original position of the exception through the exception chain.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void printFile2(String filePath){
try { List<String> lines = readFromFile(filePath); lines.forEach(System.out::println); }catch (IOException e){ // Abnormal chain throw new BizException(e); }
}
//Method exception description
private List<String> readFromFile(String filePath) throws IOException {
Path path = Paths.get(filePath); return Files.readAllLines(path, Charset.defaultCharset());
}
In the Throwable subclass, only Error, Exception and RuntimeException provide the cause parameter in the constructor. If you want to chain other exceptions, you can use the initCause method.
4. Abnormal actual combat
Exception is an indispensable point in frame design.
The exception handling in the framework also follows the fixed operation process:
-
Customize exceptions according to requirements;
-
Provide exception handler to handle exceptions uniformly;
4.1. Spring MVC unified exception handling
Spring MVC is the most common Web framework. It is easy to start and develop quickly.
Follow the separation strategy of normal process and exception handling. The R & D personnel only need to care about the normal logic, and the framework handles the abnormal process uniformly. How should I operate it?
4.1. 1. Define business exceptions
First, you need to define your own business exceptions.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public abstract class BusinessException extends RuntimeException{
/** * Exception handling code */ private final int code; /** * Exception message */ private final String msg; private final String timestamp = String.valueOf(System.currentTimeMillis()); protected BusinessException(int code, String msg){ this.code = code; this.msg = msg; } protected BusinessException(int code, String msg, Exception e) { super(e); this.code = code; this.msg = msg; }
}
4.1. 2. Exception handling
Exceptions can be customized using the HandlerExceptionResolver extension.
RestHandlerExceptionResolver , handles the service exception requested by , Rest ,. Uniformly convert the exception into JSON and return it to the user.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Component
public class RestHandlerExceptionResolver implements HandlerExceptionResolver {
private static final Logger LOGGER = LoggerFactory.getLogger(RestHandlerExceptionResolver.class); @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // It is a Rest request and can handle it if(isRestRequest(handler) && isAcceptException(ex)){ // Pass exception to RestResVo object RestResVo<Void> restResVo = RestResVo.error((BusinessException)ex); try { // Writeback in Json format response.getWriter().println(JSON.toJSONString(restResVo)); }catch (Exception e){ LOGGER.error("failed to write json {}", restResVo, e); } // empty ModelAndView description has been processed return new ModelAndView(); } return null; } private boolean isRestRequest(Object handler) { if (handler instanceof HandlerMethod){ HandlerMethod handlerMethod = (HandlerMethod) handler; return AnnotationUtils.findAnnotation(handlerMethod.getMethod(), ResponseBody.class) !=null || AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), ResponseBody.class) != null; } return false; } private boolean isAcceptException(Exception ex) { return ex instanceof BusinessException; }
}
PageHandlerExceptionResolver: handles exceptions in page requests. Uniformly forward exceptions to the error view.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Component
public class PageHandlerExceptionResolver implements HandlerExceptionResolver {
@Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // Is a page request and can handle the current exception if(isPageRequest(handler) && isAcceptException(ex)){ // Return to the error view ModelAndView mv = new ModelAndView("error"); mv.addObject("error", ex); return mv; } return null; } private boolean isPageRequest(Object handler) { if (handler instanceof HandlerMethod){ HandlerMethod handlerMethod = (HandlerMethod) handler; return AnnotationUtils.findAnnotation(handlerMethod.getMethod(), ResponseBody.class) == null && AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), ResponseBody.class) == null; } return true; } private boolean isAcceptException(Exception ex) { return ex instanceof BusinessException; }
}
4.2. Spring Cloud exception penetration
When using Spring Cloud for microservices, if an exception occurs on the Server side, the client will receive a 5xx error, thus interrupting the current normal request logic. However, the business information contained in the exception is also lost. How to keep the exception information to the greatest extent?
4.2. 1. Define business exceptions
First, you still define your own business exception class.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Data
public class CodeBasedException extends RuntimeException {
private Integer code; private String msg; private Object data; public CodeBasedException(){ super(); } public CodeBasedException(String msg) { super(msg); this.msg = msg; } public CodeBasedException(Integer code, String msg, Object data) { this.code = code; this.msg = msg; this.data = data; } public CodeBasedException(String message, Integer code, String msg, Object data) { super(message); this.code = code; this.msg = msg; this.data = data; }
}
4.2.2. Server side processing
On the Server side, business exceptions are captured and the information is written back through the Header.
Handlerinterceptorbasedexception binder: after the business processing is completed, catch the CodeBasedException exception and write the exception information back to the Header through the Response object.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class HandlerInterceptorBasedExceptionBinder implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(HandlerInterceptorBasedExceptionBinder.class); @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { if (ex == null){ return; } if (ex instanceof CodeBasedException){ CodeBasedException codeBasedException = (CodeBasedException) ex; response.addHeader(SoaConstants.HEADER_ERROR_CODE, String.valueOf(codeBasedException.getCode())); response.addHeader(SoaConstants.HEADER_ERROR_MSG, encode(codeBasedException.getMsg())); response.addHeader(SoaConstants.HEADER_ERROR_EXCEPTION_MSG, encode(codeBasedException.getMessage())); return; } response.setHeader(SoaConstants.HEADER_ERROR_CODE, "500"); response.setHeader(SoaConstants.HEADER_ERROR_MSG, encode(ex.getMessage())); response.setHeader(SoaConstants.HEADER_ERROR_EXCEPTION_MSG, encode(String.valueOf(ex.getStackTrace()))); LOGGER.error("failed to handle request.", ex); }
}
If it is a Spring Boot project, we need to complete the registration of handlerinterceptorbasedexception binder.
1 |
2
3
4
5
6
7
@Configuration
public class SoaWebMvcConfigurer implements WebMvcConfigurer{
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HandlerInterceptorBasedExceptionBinder()).addPathPatterns("/**"); }
}
4.2.3. Client side processing
After obtaining the request result, the client extracts the exception information from the Header, reassembles and throws an exception.
Feignerroderbasedexception converter: extract the exception information from the Header, reassemble and throw a SoaRemoteCallException.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
last
Authoritative guide - the first Docker book
Lead the installation, deployment, management and expansion of Docker, let it go through the whole development life cycle from test to production, and deeply understand what scenarios Docker is suitable for. In addition, this authoritative guide to Docker introduces the basic knowledge of its components, and then uses Docker to build containers and services to complete various tasks: use Docker to establish a test environment for new projects, demonstrate how to integrate Docker using continuously integrated workflow, how to build application services and platforms, how to use Docker's API, and how to extend Docker.
It includes nine chapters: introduction, installing Docker, getting started with Docker, using Docker image and warehouse, using Docker in testing, using Docker to build services, using Fig to configure Docker, using Docker API, getting help and improving Docker.
The "K8S+Docker learning guide" strongly recommended by Ali - Kubernetes in simple terms: Theory + practice and authoritative guide - the first Docker book are described in two words after reading. I love it!
);
LOGGER.error("failed to handle request.", ex); }
}
If it is a Spring Boot project, we need to complete the registration of handlerinterceptorbasedexception binder.
1 |
2
3
4
5
6
7
@Configuration
public class SoaWebMvcConfigurer implements WebMvcConfigurer{
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HandlerInterceptorBasedExceptionBinder()).addPathPatterns("/**"); }
}
4.2.3. Client side processing
After obtaining the request result, the client extracts the exception information from the Header, reassembles and throws an exception.
Feignerroderbasedexception converter: extract the exception information from the Header, reassemble and throw a SoaRemoteCallException.
1 |
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
last
Authoritative guide - the first Docker book
Lead the installation, deployment, management and expansion of Docker, let it go through the whole development life cycle from test to production, and deeply understand what scenarios Docker is suitable for. In addition, this authoritative guide to Docker introduces the basic knowledge of its components, and then uses Docker to build containers and services to complete various tasks: use Docker to establish a test environment for new projects, demonstrate how to integrate Docker using continuously integrated workflow, how to build application services and platforms, how to use Docker's API, and how to extend Docker.
It includes nine chapters: introduction, installing Docker, getting started with Docker, using Docker image and warehouse, using Docker in testing, using Docker to build services, using Fig to configure Docker, using Docker API, getting help and improving Docker.
[external chain picture transferring... (img-6T7C6sfb-1630462751591)]
[external chain picture transferring... (img-p8321CtP-1630462751593)]
[external chain picture transferring... (img-T1qxnMJz-1630462751595)]
[external chain picture transferring... (img-dtV4gT47-1630462751598)]
The "K8S+Docker learning guide" strongly recommended by Ali - Kubernetes in simple terms: Theory + practice and authoritative guide - the first Docker book are described in two words after reading. I love it!