简单功能分析
静态资源访问
- 静态资源目录,类路径下:
/static
,/public
,resources
,/META-INF/resources
- 原理
- 静态资源映射规则为
/**
,请求进来先让Controller处理,Controller没有则在静态资源中找
- 静态资源映射规则为
- 通过
spring.mvc.static-path-pattern
可以给静态资源请求路径加上前缀- 场景:使登录拦截器跳过静态资源前缀的请求
spring.resources.static-locations
改变代码中静态资源读取的路径- webjars
- 像
jquery
这样的前台代码可以通过依赖jar包的方式引用,访问地址http://localhost:8080/webjars/***
- 像
欢迎页支持
网页小图标支持
- 将名称为
favicon.ico
的小图标放到静态资源根目录下
静态资源配置原理
- SpringMVC功能的自动配置类
WebMvcAutoConfiguration
- 静态内部类
WebMvcAutoConfigurationAdapter
- 只有一个有参构造器,那么参数会在容器中找,找不到就使用配置文件构造
- 添加资源处理器的方法
addResourceHandlers
- 静态资源映射规则是否生效
spring.resources.addMappings
- 静态资源缓存时间
spring.resources.cache.period
- 配置
/webjars/**
映射规则 - 配置静态资源访问路径规则
spring.mvc.static-path-pattern
- 静态资源映射规则是否生效
- 静态内部类
EnableWebMvcConfiguration
- 欢迎页配置规则
welcomePageHandlerMapping
- 欢迎页配置规则
- 静态内部类
请求参数处理
- 请求映射
- @xxxMapping
- Rest风格支持(使用HTTP请求方式动词来表示对资源的操作)
- 以前:/getUser、/deleteUser、/editUser、/saveUser
- 现在:/user GET方式、DELETE方式、PUT方式、POST方式
- 核心Filter
HiddenHttpMethodFilter
WebMvcAutoConfiguration
的方法hiddenHttpMethodFilter
配置了开启rest风格- 默认关闭,需要手动开启
doFilterInternal
方法配置了表单请求
方式下REST风格的支持- 请求方式必须是
POST
- 请求中带上
_method
参数区分方式 - 使用包装者模式,构造一个
HttpMethodRequestWrapper
- 该类实现原生
HttpServletRequest
- 重写了
getMethod
方法,返回_method
- 该类实现原生
- 过滤器放行包装对象
- 请求方式必须是
- 若非表单提交,直接根据不同请求方式映射到对应方法
- 请求映射原理
- 所有请求都会进入
DispatcherServlet
- 核心方法
doGet
、doPost
–>processRequest
–>doService
–>doDispatch
getHandler
获取处理器handlerMappings
处理器映射器集合RequestMappingHandlerMapping
mappingRegistry
中存放了请求路径对应的处理器
- 所有请求都会进入
普通参数与基本注解
- 注解
@PathVariable
、@RequestHeader
、@ModelAttribute
、@RequestParam
、@MatrixVariable
、@CookieValue
、@RequestBody
- 通过文档注释可以发现,有些注解可以用于修饰
Map<String,String>
- 矩阵变量
- 如
/car/cell;low=34;brand=byd,yd
,queryString分号后面的参数就是矩阵变量 - SpringBoot默认关闭
@MatrixVariable
,需要自己定制配置开启矩阵变量- 原因:
WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#configurePathMatch
,该方法配置了UrlPathHelper
,变量removeSemicolonContent
默认为true
,移除queryString中的分号以及后面的参数 - 定制方式1:不用
@EnableWebMvc
注解,使用@Configuration
+继承WebMvcConfigurer
,重写configurePathMatch
方法 - 定制方式2:直接注入
WebMvcConfigurer
对象,重写configurePathMatch
方法
- 原因:
- 如
- 矩阵变量
- Servlet API
WebRequest
、ServletRequest
、MultiparRequest
、HttpSession
、javax.servlet.http.PushBuilder
、Principal
、InputStream
、Reader
、HttpMethod
、Locale
、TimeZone
、ZoneId
- 复杂参数
Map
、Errors/BindingResult
、Model
、RedirectAttributes
、ServletResponse
、SessionStatus
、UriComponentsBuilder
、ServletUriComponentsBuilder
- 自定义对象参数
- 可以自动类型转换与格式化,可以级联封装
- 参数处理原理
DispatcherServlet#getHandler
找到能处理请求的HandlergetHandlerAdapter
为当前Handler找到一个适配器HandlerAdapterRequestMappingHandlerAdapter
- 内部方法处理细节
RequestMappingHandlerAdapter#handleInternal
–>invokeHandlerMethod
- 设置参数解析器
- 设置返回值处理器
invokeAndHandle
invokeForRequest
真正执行Controller方法getMethodArgumentValues
获取所有参数HandlerMethodArgumentResolverComposite#supportsParameter
当前所有解析器是否支持该参数HandlerMethodArgumentResolverComposite#resolveArgument
解析该参数
- 使用反射调用目标方法
定制参数转换器
- 重写
WebMvcConfigurer#addFormatters
,添加Converter
返回值处理
HandlerMethodReturnValueHandlerComposite#handleReturnValue
返回值处理- 找到返回值处理器
RequestResponseBodyMethodProcessor
AbstractMessageConverterMethodProcessor#writeWithMessageConverters
- 响应内容协商
- 找到支持该响应类型的转换器,将返回值写出去
- 找到返回值处理器
内容协商
- springboot会根据客户端请求头的
Accept
找到优先适配的转换器对返回值进行转换 - 添加依赖对应依赖,丰富服务器内容协商种类,例如
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
spring.mvc.contentnegotiation.favor-parameter
为true
可以开启基于请求参数的内容协商,根据参数format
判断响应格式- 场景:应用于浏览器端无法修改请求头的情况下
- 原理
ContentNegotiationManager#strategies
内容协商管理器中多了一种参数策略ParameterContentNegotiationStrategy
自定义HttpMessageConverter
WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#configureMessageConverters
中会添加系统默认的转换器HttpMessageConverters#getConverters
–>HttpMessageConverters()
–>getDefaultConverters()
–>WebMvcConfigurationSupport#getMessageConverters
–>addDefaultHttpMessageConverters()
- 自定义
- 实现
HttpMessageConverter
WebMvcConfigurer#configureMessageConverters
配置类中加入自定义转换器
- 实现
视图解析
DispatcherServlet#doDispatch
AbstractHandlerMethodAdapter#handle
获取视图DispatcherServlet#render
–>View#render
解析式图
异常处理自动配置原理
ErrorMvcAutoConfiguration
DefaultErrorAttributes errorAttributes()
,定义错误页面可以包含哪些数据BasicErrorController basicErrorController()
,默认处理/error
请求,根据内容协商响应错误视图(白页或json)View defaultErrorView()
默认错误视图BeanNameViewResolver beanNameViewResolver()
,按beanName在容器中寻找bean的视图解析器DefaultErrorViewResolver conventionErrorViewResolver()
默认错误视图解析器DefaultErrorViewResolver#resolve
错误视图解析
异常处理
DispatcherServlet#processHandlerException
processHandlerException
处理异常,若所有解析器都不能处理异常则抛出- 如果没有解析器能处理异常,则spring会再发一个请求
/error
定制错误处理逻辑
- 自定义错误页
- 404错误跳转页
404.html
,所有500异常跳转页5xx.html
@ControllerAdvice
+@ExceptionHandler
处理全局异常,底层是ExceptionHandlerExceptionResolver
支持的@ResponseStatus
+ 自定义异常,底层是ResponseStatusExceptionResolver
支持,把ResponseStatus
注解信息组装成错误信息,调用response.sendError(statusCode,resolveReason)
- Spring底层的异常,如:参数类型转换异常
- 自定义实现
HandlerExceptionResolver
处理异常 ErrorViewResolver
实现自定义处理异常
- 404错误跳转页
Web原生组件注入(Servlet,Filter,Listener)
- 方式一
@ServletComponentScan
扫描注解- 继承
HttpServlet
, 添加@WebServlet
- 继承
Filter
, 添加@WebFilter
- 继承
ServletContextListener
, 添加@WebListener
- 方式二
- 注入
ServletRegistrationBean
组件 - 注入
FilterRegistrationBean
组件 - 注入
ServletListenerRegistrationBean
组件
- 注入
- 为何注入的Servlet不会被SpringMVC的拦截器拦截到
- SpringMVC注入了一个
DispatcherServlet
,默认映射路径为/
,如果我们注入的Servlet映射路劲为/my
,当请求发到tomcat的时候,tomcat会按精确匹配优先
原则转发到我们注入的Servlet,因此不走SpringMVC流程,也就不会被SpringMVC中的拦截器拦截到
- SpringMVC注入了一个
@EnableWebMvc
全面接管SpringMVC配置,慎用
- 原理
WebMvcAutoConfiguration
自动配置类有个条件@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@EnableWebMvc
注解导入了一个组件@Import(DelegatingWebMvcConfiguration.class)
DelegatingWebMvcConfiguration
继承于WebMvcConfigurationSupport
, 因此WebMvcAutoConfiguration
自动配置类不生效
数据访问
- 导入
spring-boot-starter-jdbc
- 依赖
- 数据源
com.zaxxer:HikariCP
- JDBC
org.springframework:spring-jdbc
- 事务
org.springframework:spring-tx
- 导入驱动,如
mysql-connector-java
- 自动配置的类
DataSourceAutoConfiguration
: 数据源的自动配置DataSourceTransactionManagerAutoConfiguration
: 事务管理器的自动配置JdbcTemplateAutoConfiguration
: JdbcTemplate的自动配置,可以来对数据库进行crudJndiDataSourceAutoConfiguration
: jndi的自动配置XADataSourceAutoConfiguration
: 分布式事务相关的