写在前面

鉴于有人留言说想要学习SpringBoot相关的知识,我这里打算写一个SpringBoot系列的相关博文,目标呢是想让看了这一系列博文的同学呢,能够对SpringBoot略窥门径,这一系列的博文初步都定下来包括SpringBoot介绍、入门、配置、日志相关、web开发、数据访问、结合docker、缓存、消息队列、检索、任务安全、分布式等等一系列的博文,工作量很大,是个漫长的过程,每一步我都尽量详细,配上截图说明,也希望对看的同学真的有用。
单纯就是想分享技术博文,还想说一句就是,如果觉得有用,请点个关注、给个赞吧,也算对我来说是个宽慰,毕竟也得掉不少头发,嘿嘿嘿

系列文章传送条

详细SpringBoot教程之入门(一)
详细SpringBoot教程之入门(二)
详细SpringBoot教程之配置文件(一)
详细SpringBoot教程之配置文件(二)
详细SpringBoot教程之日志框架
详细SpringBoot教程之Web开发(一)
详细SpringBoot教程之Web开发(二)
详细SpringBoot教程之Web开发(三)
详细SpringBoot教程之数据访问
详细SpringBoot教程之启动配置原理
详细SpringBoot教程之缓存开发

错误处理机制

SpringBoot默认的错误处理机制

我们接上一篇博文的项目,我们现在把拦截器关掉,直接在主配置文件注释掉注入就可以直接关掉了,像这样
在这里插入图片描述
然后我们现在通过浏览器随便访问一个不存在的连接,会出现下面这样的错误提示,应该不陌生吧,之前肯定是遇到过的。
在这里插入图片描述
我们可以查看一下浏览器发送请求的请求头,如下:
在这里插入图片描述

当然SpringBoot还另外规定了客户端访问无效链接的错误机制,如果我们通过客户端访问会返回一个默认的json数据,像下面这样

1
2
3
4
5
6
7
{
"timestamp": 1519637719324,
"status": 404,
"error": "Not Found",
"message": "No message avaliable",
"path": "/dbc/aaa",
}

默认错误处理机制原理

老样子,我们想要错误处理机制也有自己的自动配置类(之前说过,SpringBoot功能是通过配置文件来进行控制的,而配置文件一般是通过xxxAutoConfiguration这样的自动配置类来实现的),所以SpringBoot的默认的错误处理机制可以参照自动配置类,也就是ErrorMvcAutoConfiguration。

ErrorMvcAutoConfiguration通过给给容器中添加了以下组件,来控制错误处理机制

  • DefaultErrorAttributes:帮我们在页面共享信息;
  • BasicErrorController:处理默认/error请求
  • ErrorPageCustomizer:系统出现错误以后来到error请求进行处理;
  • DefaultErrorViewResolver:用来控制错误时,启用模板引擎视图,还是默认;

也就是默认的错误处理流程是,一但系统出现4xx或者5xx之类的错误,ErrorPageCustomizer就会生效(定制错误的响应规则),接着就会来到/error请求,然后就可以通过BasicErrorController来进行处理,进行相应时,响应页面去哪个页面是由DefaultErrorViewResolver解析得到的;

如何定制错误响应

如何定制错误页面

如果有模板引擎的情况下(我们项目中使用的是Thymeleaf模板引擎),可以通过error/状态码的形式来进行控制,也就是说,我们可以将错误页面命名为“错误状态码.html”,然后放在模板引擎文件夹(即templates目录下)里面的error文件夹下,没有error文件夹就创建一个,发生此状态码的错误就会来到 对应的页面,因为SpringBoot规则中已经默认规定好了。

更准确的将我们可以使用4xx和5xx作为错误页面的文件名,进而来匹配该种类型的所有错误,匹配的时候遵循精确优先(优先寻找精确的状态码.html),像下面这样
在这里插入图片描述
我们在默认的错误页面中可以获得如下信息:、

  • timestamp:时间戳
  • tstatus:状态码
  • terror:错误提示
  • texception:异常对象
  • tmessage:异常消息
  • terrors:JSR303数据校验的错误都在这里

这里要说明一下的是,如果我们项目中没有使用模板引擎(或者模板引擎找不到这个错误页面),就会去静态资源文件夹下找。如果静态资源文件夹中也没有错误页面,就是默认来到SpringBoot默认的错误提示页面。

如何定制错误的json

可以自定义异常处理和返回定制json数据,像下面这样,我们可以专门定义一个配置类用来解决错误定制的,我这里命名为MyExceptionHandler,然后通过@ExceptionHandler来定制响应的相关错误,进而返回定制数据
在这里插入图片描述
不过这样处理会有个问题,就是我们确实是定制了返回的json数据,但是本来SpringBoot会根据我们用什么访问请求,然后响应什么,比如我们用浏览器访问,响应html页面,客户端响应json数据,现在这样写,返回的都是接送数据了,所以我们需要换种方式,通过将相应转发到/error进行自适应响应效果处理,像下面这样
在这里插入图片描述

携带定制数据

前面我们讲过,出现错误以后,会来到/error请求,会被BasicErrorController处理,响应出去可以获取的数据是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)规定的方法)

所以,我们可以通过编写一个ErrorController的实现类或者是编写AbstractErrorController的子类,然后放在容器中,我们要知道,页面上能用的数据,或者是json返回能用的数据都是通过errorAttributes.getErrorAttributes得到,也就是说容器中DefaultErrorAttributes.getErrorAttributes()来默认进行数据处理的,我们定制自定义ErrorAttributes,如下
在这里插入图片描述
这样,我们的错误响应是自适应的,可以通过定制ErrorAttributes改变需要返回的内容,就不在只有原先的默认属性了,形象的将,我们返回的信息就会是如下

  • timestamp:时间戳
  • tstatus:状态码
  • terror:错误提示
  • texception:异常对象
  • tmessage:异常消息
  • terrors:JSR303数据校验的错误都在这里
  • author: dbc

配置嵌入式Servlet容器

SpringBoot默认使用Tomcat作为嵌入式的Servlet容器,这我们都是知道的
在这里插入图片描述
那么这个时候我们如果想要换成其他的Servlet容器,我们应该怎么做呢?那么接下来我们就来讲解怎么搞

如何定制和修改Servlet容器的相关配置

修改和server有关的配置(ServerProperties即也是使用WebServerFactoryCustomizer),在主配置文件中可以通过这样的形式来设置
在这里插入图片描述
除了在主配置文件中进行相关的设置之外,我们还可以通过注册WebServerFactoryCustomizer组件来在类中自定义配置,也就是嵌入式的Servlet容器的定制器,来修改Servlet容器的配置
在这里插入图片描述

注册Servlet三大组件

Servlet三大组件分别是Servlet、Filter、Listener,如果我们原先熟悉SpringMVC开发的应该知道,我们在Webapp下面的web.xml中,经常需要配置这三大组件用来过滤监听相关的请求,而在SpringBoot中,由于SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器来启动SpringBoot的web应用,所以并没有没有web.xml文件。但是我们依旧可以通过SpringBoot特有的相关注册Bean进行注册,分别是

  • ServletRegistrationBean
1
2
3
4
5
6
7
//注册三大组件
@Bean
public ServletRegistrationBean myServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet");
return registrationBean;
}

  • FilterRegistrationBean
1
2
3
4
5
6
7
@Bean
public FilterRegistrationBean myFilter(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new MyFilter());
registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));
return registrationBean;
}
  • ServletListenerRegistrationBean
1
2
3
4
5
@Bean
public ServletListenerRegistrationBean myListener(){
ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>(new MyListener());
return registrationBean;
}

SpringBoot帮我们自动配置SpringMVC的时候,会自动的注册SpringMVC的前端控制器,即DIspatcherServlet,我们通过查阅DispatcherServletAutoConfiguration发现,会默认拦截,“/”的所有请求,包括静态资源,但是不拦截jsp请求,/*会拦截jsp,可以通过server.servletPath来修改SpringMVC前端控制器默认拦截的请求路径

更换其他嵌入式Servlet容器

我们知道,SpringBoot是默认支持Tomcat的,也就是在pom.xml中通过如下依赖引入的
在这里插入图片描述
所以,我们不能整个去除web依赖,因为里面还有其他除了Tomcat的依赖,所以我们在web下直接排除Tomcat的依赖就可以了,然后添加其他的嵌入式Servlet容器的依赖,不同的嵌入式Servlet依赖如下

Jetty

在这里插入图片描述

Undertow

在这里插入图片描述

使用外置的Servlet容器

在我们之前学习的SpringBoot应用,是通过嵌入式Servlet容器,应用打成可执行的jar,这样做的优点显而易见,就是简单、便携,但是缺点就是默认不支持JSP、优化定制比较复杂(使用定制器ServerProperties、自定义WebServerFactoryCustomizer,自己编写嵌入式Servlet容器的创建工厂ConfigurableWebServerFactory);
但是不着急,我们可以使用外置的Servlet容器,也就是外面安装Tomcat,然后应用war包的方式打包。

步骤

  • 必须创建一个war项目,利用idea创建好目录结构
    在这里插入图片描述

  • 将嵌入式的Tomcat指定为provided;

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
  • 必须编写一个SpringBootServletInitializer的子类,并调用configure方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    //传入SpringBoot应用的主程序
    return application.sources(SpringBoot04WebJspApplication.class);
    }

    }
  • 启动服务器就可以使用;

我这里说一下jar包和war包启动的区别

  • jar包:执行SpringBoot主类的main方法,启动ioc容器,创建嵌入式的Servlet容器;
  • war包:启动服务器,服务器启动SpringBoot应用通过SpringBootServletInitializer,启动ioc容器;