Spring Boot has become an essential skill for interviews, so it’s not too late to learn Spring Boot!

foreword

Since its release in 2014, Spring Boot's search index has soared. That's right, Spring Boot is getting more and more popular. As a front-line Java programmer, you may feel the fire of Spring Boot in all aspects.

Now there are more and more Spring Boot articles in major technical communities, more and more Spring Boot-related graphic and video tutorials, and more and more Internet companies using Spring Boot; Java programmers are now going out for interviews, and Spring Boot has already became a must-ask.

Everything is proving that Spring Boot has become an essential skill for Java programmers. And it is foreseeable that the development of Spring Boot will be better in the future. Learn Spring Boot without further ado!

Spring Boot2 Tutorial

In the Spring Boot project, there is normally no XML configuration. This is because Spring Boot does not recommend the use of XML. Note that it is not unsupported. Spring Boot recommends that developers use Java configuration to build the framework. In Spring Boot, a large number of automation The configuration is all implemented through Java configuration. We can also do this set of implementation solutions by ourselves, that is, we can also use pure Java to build an SSM environment, that is, there is no XML configuration in the project, including web.xml .

Environmental requirements:

To use pure Java to build the SSM environment, the version of Tomcat must be above 7.

1. Create a project

Create an ordinary Maven project (note that there is no need to create a Web project here), and add SpringMVC dependencies. At the same time, the environment here needs to use Servlet, so we also need to introduce Servlet dependencies (must not use lower version Servlets ), the final pom.xml file is as follows:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.1.6.RELEASE</version>
</dependency>
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.1</version>
  <scope>provided</scope>
</dependency>

2. Add Spring configuration

After the project is successfully created, first add the Spring configuration file, as follows:

@Configuration
@ComponentScan(basePackages = "org.javaboy", useDefaultFilters = true,
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes =
Controller.class)})
public class SpringConfig {
}

Regarding this configuration, I say the following:

The @Configuration annotation indicates that this is a configuration class. In our case, this configuration is similar to applicationContext.xml

The @ComponentScan annotation indicates configuration package scanning, and the attributes inside and the attributes in the xml configuration are all in one-to-one correspondence. useDefaultFilters indicates the use of the default filter, and then removes the Controller annotation, that is, scans other than the Controller in the Spring container All beans.

3. Add SpringMVC configuration

Next, create a configuration file for springmvc:

@Configuration
@ComponentScan(basePackages = "org.javaboy",useDefaultFilters =
false,includeFilters = {@ComponentScan.Filter(type =
FilterType.ANNOTATION,classes = Controller.class)})
public class SpringMVCConfig {
}

Note that if you don't need to add other additional configurations in SpringMVC, this is fine. That is, view parser, JSON parsing, file uploading, etc., if no configuration is required, this is fine.

4. Configure web.xml

At this time, we do not have a web.xml file. At this time, we can use Java code to replace the web.xml file. Here we will use WebApplicationInitializer, which is defined as follows:

public class WebInit implements WebApplicationInitializer {
  public void onStartup(ServletContext servletContext) throws ServletException
{
    //首先来加载 SpringMVC 的配置文件
    AnnotationConfigWebApplicationContext ctx = new
AnnotationConfigWebApplicationContext();
    ctx.register(SpringMVCConfig.class);
    // 添加 DispatcherServlet
    ServletRegistration.Dynamic springmvc =
servletContext.addServlet("springmvc", new DispatcherServlet(ctx));
    // 给 DispatcherServlet 添加路径映射
    springmvc.addMapping("/");
    // 给 DispatcherServlet 添加启动时机
    springmvc.setLoadOnStartup(1);
 }
}

The function of WebInit is similar to web.xml. This class needs to implement the WebApplicationInitializer interface and implement the methods in the interface. When the project starts, the onStartup method will be executed automatically. We can do some project initialization operations in this method, such as loading SpringMVC Container, add filter, add Listener, add Servlet, etc.

Notice:

Since we only added the configuration of SpringMVC in WebInit, the project will only load the SpringMVC container when it starts, but not the Spring container. If we must load the Spring container, we need to modify the configuration of SpringMVC, which is configured in SpringMVC The @Configuration annotation is also scanned during package scanning, and then the Spring container is loaded. There is another solution to this problem, which is to directly discard the Spring configuration in the project and directly put all the configurations into the SpringMVC configuration. This is integrated in SSM In actual development, the second option is often used. The configuration of SpringMVC for the second option is as follows:

@Configuration
@ComponentScan(basePackages = "org.javaboy")
public class SpringMVCConfig {
}

In this scheme, all annotations are scanned in SpringMVC. If this scheme is adopted, the Spring configuration file can be deleted.

5. Test

Finally, add a HelloController and start the project for testing:

@RestController
public class HelloController {
  @GetMapping("/hello")
  public String hello() {
    return "hello";
 }
}

Start the project and access the interface, the results are as follows:

Spring Boot global exception handling

In the Spring Boot project, exceptions are handled uniformly. You can use @ControllerAdvice in Spring to handle them uniformly, or you can define your own exception handling scheme. In Spring Boot, there are some default strategies for exception handling, let's look at them separately.

By default, exception pages in Spring Boot look like this:

We can also see from this exception prompt that the reason why the user sees this page is because the developer did not explicitly provide a /error path. If the developer provides the /error path, this page will not be displayed, but In Spring Boot, providing the /error path is actually a bad idea. When Spring Boot itself handles exceptions, it will only look for the /error path when all conditions are not met. So let's take a look first, how to customize the error page in Spring Boot, generally speaking, it can be divided into two types, one is a static page and the other is a dynamic page.

static exception page

There are two types of custom static exception pages. The first is to use HTTP response codes to name pages, such as 404.html, 405.html, 500.html.... The other is to directly define a 4xx. html, indicating that the status of 400-499 displays this abnormal page, and 5xx.html indicates that the status of 500-599 displays this abnormal page.

By default, relevant pages are defined under the classpath:/static/error/ path:

At this point, start the project, if the project throws a 500 request error, the 500.html page will be displayed automatically, and the 404.html page will be displayed if 404 occurs. If there are both 5xx.html and 500.html in the exception display page, at this time, when a 500 exception occurs, the 500.html page will be displayed first.

Dynamic exception page

The dynamic exception page definition method is basically the same as the static one, and the page templates that can be used include jsp, freemarker, and thymeleaf.

Dynamic exception pages also support 404.html or 4xx.html, but generally speaking, since dynamic exception pages can directly display exception details, there is no need to enumerate errors one by one, directly define 4xx.html (thymeleaf template is used here ) or 5xx.html.

Note that the dynamic page template does not require the developer to define the controller himself, just define the exception page directly, and the exception handler that comes with Spring Boot will automatically find the exception page.

The page is defined as follows:

The content of the page is as follows:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<h1>5xx</h1>
<table border="1">
  <tr>
    <td>path</td>
    <td th:text="${path}"></td>
  </tr>
  <tr>
    <td>error</td>
    <td th:text="${error}"></td>
  </tr>
  <tr>
    <td>message</td>
    <td th:text="${message}"></td>
  </tr>
  <tr>
    <td>timestamp</td>
    <td th:text="${timestamp}"></td>
  </tr>
  <tr>
    <td>status</td>
    <td th:text="${status}"></td>
  </tr>
</table>
</body>
</html>

By default, the complete exception information is these 5 pieces, and the display effect is as follows:

If both dynamic pages and static pages define exception handling pages, for example, when classpath:/static/error/404.html and classpath:/templates/error/404.html exist at the same time, dynamic pages are used by default. That is, the complete error page search method should be as follows:

A 500 error occurred --> Find dynamic 500.html page --> Find static 500.html --> Find dynamic 5xx.html --> Find static 5xx.html.

Custom exception data

By default, in Spring Boot, all exception data is actually the 5 pieces of data shown above. These 5 pieces of data are defined in the org.springframework.boot.web.reactive.error.DefaultErrorAttributes class, specifically defined in In the getErrorAttributes method:

@Override
public Map<String, Object> getErrorAttributes(ServerRequest request,
        boolean includeStackTrace) {
    Map<String, Object> errorAttributes = new LinkedHashMap<>();
    errorAttributes.put("timestamp", new Date());
    errorAttributes.put("path", request.path());
    Throwable error = getError(request);
    HttpStatus errorStatus = determineHttpStatus(error);
    errorAttributes.put("status", errorStatus.value());
    errorAttributes.put("error", errorStatus.getReasonPhrase());
    errorAttributes.put("message", determineMessage(error));
    handleException(errorAttributes, determineException(error),
includeStackTrace);
    return errorAttributes;
}

The DefaultErrorAttributes class itself is in the

org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration is defined in the abnormal automatic configuration class. If the developer does not provide an instance of ErrorAttributes himself, Spring Boot will automatically provide an instance of ErrorAttributes, which is DefaultErrorAttributes.

Based on this, there are two ways for developers to customize ErrorAttributes:

1. Directly implement the ErrorAttributes interface

2. Inherit DefaultErrorAttributes (recommended), because the processing of exception data in DefaultErrorAttributes has been completed, and developers can use it directly.

The specific definition is as follows:

@Component
public class MyErrorAttributes  extends DefaultErrorAttributes {
  @Override
  public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean
includeStackTrace) {
    Map<String, Object> map = super.getErrorAttributes(webRequest,
includeStackTrace);
    if ((Integer)map.get("status") == 500) {
      map.put("message", "服务器内部错误!");
   }
    return map;
 }
}

The defined ErrorAttributes must be registered as a Bean, so that Spring Boot will not use the default DefaultErrorAttributes, and the operation effect is as follows:

Custom exception view

The default exception view is the static or dynamic page mentioned above, which can also be customized. First, the default exception view loading logic is in the errorHtml method of the org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController class. This method is used to return the abnormal page + data, and there is another error method, which is used to return the abnormal data (if it is an ajax request, this method will be triggered).

@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView errorHtml(HttpServletRequest request,
        HttpServletResponse response) {
    HttpStatus status = getStatus(request);
    Map<String, Object> model =
Collections.unmodifiableMap(getErrorAttributes(
            request, isIncludeStackTrace(request,
MediaType.TEXT_HTML)));
    response.setStatus(status.value());
    ModelAndView modelAndView = resolveErrorView(request, response, status,
model);
    return (modelAndView != null) ? modelAndView : new ModelAndView("error",
model);
}

In this method, the getErrorAttributes method will first be used to obtain the exception data (actually, the getErrorAttributes method of the instance of ErrorAttributes will be called), and then resolveErrorView will be called to create a ModelAndView. If the creation fails here, the user will see the default error prompt page.

Normally, the resolveErrorView method will come to the resolveErrorView method of the DefaultErrorViewResolver class:

@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus
status,
        Map<String, Object> model) {
    ModelAndView modelAndView = resolve(String.valueOf(status.value()),
model);
    if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
        modelAndView = resolve(SERIES_VIEWS.get(status.series()),
model);
   }
    return modelAndView;
}

Here, first use the exception response code as the view name to search for dynamic pages and static pages respectively, if not found, then use 4xx or 5xx as the view name to search for dynamic or static pages respectively.

It is also very easy to customize exception view parsing. Since DefaultErrorViewResolver is an instance provided in the ErrorMvcAutoConfiguration class, that is, when the developer does not provide a relevant instance, the default DefaultErrorViewResolver will be used. After the developer provides his own ErrorViewResolver instance, the default configuration will fail, therefore, to customize the exception view, you only need to provide an instance of ErrorViewResolver:

@Component
public class MyErrorViewResolver extends DefaultErrorViewResolver {
  public MyErrorViewResolver(ApplicationContext applicationContext,
ResourceProperties resourceProperties) {
    super(applicationContext, resourceProperties);
 }
  @Override
  public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus
status, Map<String, Object> model) {
    return new ModelAndView("/aaa/123", model);
 }
}

In fact, developers can also define abnormal data here (directly redefine a model in the resolveErrorView method, copy and modify the model data in the parameter, note that the model type in the parameter is UnmodifiableMap, that is, it cannot be directly modified), and No need to customize MyErrorAttributes. After the definition is complete, provide a view named 123, as shown in the figure below:

After that, the wrong attempt is considered to be a successful definition.

Summarize

In fact, you can also customize the exception controller BasicErrorController, but I feel that this is too much trouble, and it is unnecessary. The previous methods can already meet most of our development needs. If it is a front-end and back-end separation architecture, there are other solutions for exception handling, which I will talk to you later.

The space is limited, and other content will not be shown here one by one. This Spring Boot practical tutorial has been compiled into a PDF document with a total of more than 200 pages.

Pay attention to the public account: programmer chasing the wind, reply 005 to get this organized Spring Boot practical tutorial.

at last

Everyone is welcome to communicate together. If you like the article, remember to follow me and give me a thumbs up. Thank you for your support!

Guess you like

Origin blog.csdn.net/Design407/article/details/107406325