乐趣区

互联网的寒冬下各大一线互联网公司还在用SpringBoot这是为什么

引言

当初各大技术社区 Spring Boot 的文章越来越多,Spring Boot 相干的图文、视频教程越来越多,应用 Spring Boot 的互联网公司也越来越多;Java 程序员当初进来面试,Spring Boot 曾经成了必问的内容。

一切都在证实,Spring Boot 曾经成为了 Java 程序员必备的技能。并且能够预感的是将来 Spring Boot 的倒退还会更好。

所以对 Java 程序员来说其中不乏说对 Spring Boot 十分相熟的,而后当问到一些 Spring Boot 外围性能和原理的时候,没人能说得上来,或者说不到点上,能够说一个问题就问趴下了!(问题:你能讲下为什么咱们要用 Spring Boot 吗?)

置信我,下面这些相似的问题,90% 有教训的 Java 程序员超都曾遇见过!但很少有系统化的答复。

因而,总结了这份 Spring Boot 外围知识点实战教程,通过这份教程,带你梳理 Spring Boot 技术体系。

文末有彩蛋~

Spring Boot2 教程
在 Spring Boot 我的项目中,失常来说是不存在 XML 配置,这是因为 Spring Boot 不举荐应用 XML,留神,并非不反对,Spring Boot 举荐开发者应用 Java 配置来搭建框架,Spring Boot 中,大量的自动化配置都是通过 Java 配置来实现的,这一套实现计划,咱们也能够本人做,即本人也能够应用纯 Java 来搭建一个 SSM 环境,即在我的项目中,不存在任何 XML 配置,包含 web.xml。

环境要求:

应用纯 Java 来搭建 SSM 环境,要求 Tomcat 的版本必须在 7 以上。

1、创立工程

创立一个一般的 Maven 工程(留神,这里能够不用创立 Web 工程),并增加 SpringMVC 的依赖,同时,这里环境的搭建须要用到 Servlet,所以咱们还须要引入 Servlet 的依赖(肯定不能应用低版本的 Servlet),最终的 pom.xml 文件如下:

<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、增加 Spring 配置

工程创立胜利之后,首先增加 Spring 的配置文件,如下:

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

对于这个配置,我说如下几点:

@Configuration 注解示意这是一个配置类,在咱们这里,这个配置的作用相似于 applicationContext.xml

@ComponentScan 注解示意配置包扫描,里边的属性和 xml 配置中的属性都是一一对应的,useDefaultFilters 示意应用默认的过滤器,而后又除去 Controller 注解,即在 Spring 容器中扫描除了 Controller 之外的其余所有 Bean。

3、增加 SpringMVC 配置

接下来再来创立 springmvc 的配置文件:

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

留神,如果不须要在 SpringMVC 中增加其余的额定配置,这样就能够了。即视图解析器、JSON 解析、文件上传 …… 等等,如果都不须要配置的话,这样就能够了。

4、配置 web.xml

此时,咱们并没 web.xml 文件,这时,咱们能够应用 Java 代码去代替 web.xml 文件,这里会用到 WebApplicationInitializer,具体定义如下:

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);
 }
}

WebInit 的作用相似于 web.xml,这个类须要实现 WebApplicationInitializer 接口,并实现接口中的办法,当我的项目启动时,onStartup 办法会被主动执行,咱们能够在这个办法中做一些我的项目初始化操作,例如加载 SpringMVC 容器,增加过滤器,增加 Listener、增加 Servlet 等。

留神:

因为咱们在 WebInit 中只是增加了 SpringMVC 的配置,这样我的项目在启动时只会去加载 SpringMVC 容器,而不会去加载 Spring 容器,如果肯定要加载 Spring 容器,须要咱们批改 SpringMVC 的配置,在 SpringMVC 配置的包扫描中也去扫描 @Configuration 注解,进而加载 Spring 容器,还有一种计划能够解决这个问题,就是间接在我的项目中舍弃 Spring 配置,间接将所有配置放到 SpringMVC 的配置中来实现,这个在 SSM 整合时是没有问题的,在理论开发中,较多采纳第二种计划,第二种计划,SpringMVC 的配置如下:

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

这种计划中,所有的注解都在 SpringMVC 中扫描,采纳这种计划的话,则 Spring 的配置文件就能够删除了。

5、测试

最初,增加一个 HelloController,而后启动我的项目进行测试:

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

启动我的项目,拜访接口,后果如下:

Spring Boot 全局异样解决

在 Spring Boot 我的项目中,异样对立解决,能够应用 Spring 中 @ControllerAdvice 来对立解决,也能够本人来定义异样解决计划。Spring Boot 中,对异样的解决有一些默认的策略,咱们别离来看。

默认状况下,Spring Boot 中的异样页面 是这样的:

咱们从这个异样提醒中,也能看进去,之所以用户看到这个页面,是因为开发者没有明确提供一个 /error 门路,如果开发者提供了 /error 门路,这个页面就不会展现进去,不过在 Spring Boot 中,提供 /error 门路实际上是下下策,Spring Boot 自身在解决异样时,也是当所有条件都不满足时,才会去找 /error 门路。那么咱们就先来看看,在 Spring Boot 中,如何自定义 error 页面,整体上来说,能够分为两种,一种是动态页面,另一种是动静页面。

动态异样页面

自定义动态异样页面,又分为两种,第一种 是应用 HTTP 响应码来命名页面,例如 404.html、405.html、500.html ….,另一种就是间接定义一个 4xx.html,示意 400-499 的状态都显示这个异样页面,5xx.html 示意 500-599 的状态显示这个异样页面。

默认是在 classpath:/static/error/ 门路下定义相干页面:

此时,启动我的项目,如果我的项目抛出 500 申请谬误,就会主动展现 500.html 这个页面,产生 404 就会展现 404.html 页面。如果异样展现页面既存在 5xx.html,也存在 500.html,此时,产生 500 异样时,优先展现 500.html 页面。

动静异样页面

动静的异样页面定义形式和动态的根本 统一,能够采纳的页面模板有 jsp、freemarker、thymeleaf。

动静异样页面,也反对 404.html 或者 4xx.html,然而一般来说,因为动静异样页面能够间接展现异样详细信息,所以就没有必要挨个枚举谬误了,间接定义 4xx.html(这里应用 thymeleaf 模板)或者 5xx.html 即可。

留神,动静页面模板,不须要开发者本人去定义控制器,间接定义异样页面即可,Spring Boot 中自带的异样处理器会主动查找到异样页面。

页面定义如下:

页面内容如下:

<!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>

默认状况下,残缺的异样信息就是这 5 条,展现 成果如下:

如果动静页面和动态页面同时定义了异样解决页面,例如 classpath:/static/error/404.html 和 classpath:/templates/error/404.html 同时存在时,默认应用动静页面。即残缺的谬误页面查找

形式应该是这样:

产生了 500 谬误 –> 查找动静 500.html 页面 –> 查找动态 500.html –> 查找动静 5xx.html–> 查找动态 5xx.html。

自定义异样数据

默认状况下,在 Spring Boot 中,所有的异样数据其实就是上文所展现进去的 5 条数据,这 5 条数据定义在 org.springframework.boot.web.reactive.error.DefaultErrorAttributes 类中,具体定义在 getErrorAttributes 办法中:

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;
}

DefaultErrorAttributes 类自身则是在

org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration 异样主动配置类中定义的,如果开发者没有本人提供一个 ErrorAttributes 的实例的话,那么 Spring Boot 将主动提供一个 ErrorAttributes 的实例,也就是 DefaultErrorAttributes。

基于此,开发者自定义 ErrorAttributes 有两种形式:

  1. 间接实现 ErrorAttributes 接口
  2. 继承 DefaultErrorAttributes(举荐),因为 DefaultErrorAttributes 中对异样数据的解决曾经实现,开发者能够间接应用。

具体定义如下:

@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;
 }
}

定义好的 ErrorAttributes 肯定要注册成一个 Bean,这样,Spring Boot 就不会应用默认的 DefaultErrorAttributes 了,运行成果如下图:

自定义异样视图

异样视图默认就是后面所说的动态或者动静页面,这个也是能够自定义的,首先,默认的异样视图加载逻辑在 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController 类的 errorHtml 办法中,这个办法用来返回异样页面 + 数据,还有另外一个 error 办法,这个办法用来返回异样数据(如果是 ajax 申请,则该办法会被触发)。

@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);
}

在该办法中,首先会通过 getErrorAttributes 办法去获取异样数据(实际上会调用到 ErrorAttributes 的实例 的 getErrorAttributes 办法),而后调用 resolveErrorView 去创立一个 ModelAndView,如果这里创立失败,那么用户将会看到默认的谬误提醒页面。

失常状况下,resolveErrorView 办法会来到 DefaultErrorViewResolver 类的 resolveErrorView 办法中:

@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;
}

在这里,首先以异样响应码作为视图名别离去查找动静页面和动态页面,如果没有查找到,则再以 4xx 或者 5xx 作为视图名再去别离查找动静或者动态页面。

要自定义异样视图解析,也很容易,因为 DefaultErrorViewResolver 是在 ErrorMvcAutoConfiguration 类中提供的实例,即开发者没有提供相干实例时,会应用默认的 DefaultErrorViewResolver,开发者提供了本人的 ErrorViewResolver 实例后,默认的配置就会生效,因而,自定义异样视图,只须要提供 一个 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);
 }
}

实际上,开发者也能够在这里定义异样数据(间接在 resolveErrorView 办法从新定义一个 model,将参数中的 model 数据拷贝过来并批改,留神参数中的 model 类型为 UnmodifiableMap,即不能够间接批改),而不须要自定义 MyErrorAttributes。定义实现后,提供一个名为 123 的视图,如下图:

如此之后,谬误试图就算定义胜利了。

总结

实际上也能够自定义异样控制器 BasicErrorController,不过我感觉这样太大动干戈了,没必要,后面几种形式曾经能够满足咱们的大部分开发需要了。如果是前后端拆散架构,异样解决还有其余一些解决计划,这个当前和大家聊。

篇幅无限,其余内容就不在这里一一展现了,这份 Spring Boot 实战教程已整顿成一份 PDF 文档,共有 200 多页。

关注公众号:程序零世界,回复 666 获取这份整顿好的 Spring Boot 实战教程。

最初

欢送大家一起交换,喜爱文章记得点 ge 赞哟,感激反对!

退出移动版