Spring Boot相关
拦截器
-
首先创建自定义的拦截器,实现
HandlerInterceptor
接口,然后重写其下的三个方法(preHandle
,postHandle
,afterCompletion
)package com.fmxu.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * @author Dell * @projectName springbootdemo * @description: 登陆检查 * @date 2021/3/31/14:55 */ /* * 1、配置好拦截器需要拦截哪些请求 * 2、把这些配置放在容器中 * * */ public class LoginInterceptor implements HandlerInterceptor { //目标方法执行之前 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //登陆检查逻辑 HttpSession session = request.getSession(); Object loginUser = session.getAttribute("loginUser"); //登陆就放行 if(loginUser!=null){ return true; } //否则拦截. 跳转到登录页 response.sendRedirect("/"); return false; } //目标方法执行之后 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
-
然后创建自定义的配置类,实现
WebMvcConfigurer
接口,重写addInterceptors
方法package com.fmxu.config; import com.fmxu.interceptor.LoginInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @author Dell * @projectName springbootdemo * @description: * @date 2021/3/31/14:53 */ @Configuration public class MyConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") //拦截所有资源 .excludePathPatterns("/","/login"); //不拦截的请求路径 } }
拦截器原理
- 根据当前请求,
HandlerExecutionChain
找到可以处理请求的handler以及handler的所有拦截器 - 先顺序执行所有拦截器的
prehandle
方法- 如果当前拦截器的
preHandle
方法返回的是true,则执行下一个拦截器的prehandle
- 如果当前拦截器返回的为false,则直接调用
triggerAfterCompletion
方法倒序执行已经放行的拦截器的afterCompletion
方法。
- 如果当前拦截器的
- 如果任何一个拦截器返回false,直接跳出不执行目标方法。
- 所有拦截器都返回True,执行目标方法。
- 倒序执行所有拦截器的
postHandle
方法。
- 根据当前请求,
文件上传
-
简单模拟一下
package com.fmxu.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; /** * @author Dell * @projectName springbootdemo * @description: * @date 2021/3/31/16:00 */ //模拟单文件上传和多文件上传 @Controller public class UploadController { @PostMapping("/upload") public String upload(@RequestPart MultipartFile image,@RequestPart MultipartFile[] photos) throws IOException { if(!image.isEmpty()){ //获取文件的原始名 String originalFilename = image.getOriginalFilename(); image.transferTo(new File("D:\\cache\\"+originalFilename)); } if(photos.length>0){ for (MultipartFile photo : photos) { if(!photo.isEmpty()){ String originalFilename = photo.getOriginalFilename(); photo.transferTo(new File("D:\\cache\\"+originalFilename)); } } } return "main"; } }
一般文件上传有大小限制。
我们可以在
application.yml
主配置文件中设置文件上传的大小。spring: servlet: multipart: max-file-size: 10MB max-request-size: 100MB
原理
文件上传自动配置类-
MultipartAutoConfiguration-MultipartProperties
- 自动配置好了
StandardServletMultipartResolver
[文件上传解析器] - 原理步骤
- 请求进来使用文件上传解析器判断
isMultipart
并封装(使用resolveMultipart
并返回MultipartHttpServletRequest
)文件上传请求 - 参数解析器来解析并将请求中的文件内容封装成
MultipartFile
- 将request中文件信息封装为一个Map.
MultiValue<String,MultipartFile>
- 请求进来使用文件上传解析器判断
- 自动配置好了
异常处理
-
错误处理
默认规则:
- 默认情况下,Spring Boot提供/error处理所有错误的映射
- 对于机器客户端,它将生成
JSON
响应,其中包含错误,HTTP状态码和异常消息的详细信息。对于浏览器客户端,响应一个whitelabel
错误视图,以HTML格式呈现相同的数据。 - 要对其进行自定义,添加View解析为error
- 要完全替换默认行为,可以实现
ErrorController
并注册该类型的Bean定义,或者添加ErrorAttributes
类型的组件以使用现有机制替换其内容。 - 在static目录下添加error目录,并在其下面添加
4xx,5xx
页面会被自动解析。
-
异常处理自动配置原理
-
ErrorMvcAutoConfiguration
自动配置异常处理规则 -
容器中的组件:
-
类型:
DefaultErrorAttributes
-> id :errorAttributes
-
类型:
BasicErrorAttributes
-> id :basicErrorAttributes
默认处理/error路径的请求。 页面响应
new ModelAndView("error",model)
容器中有View组件 -> id是error (也即是默认错误响应页)
容器中放入
BeanNameViewResolver
(视图解析器)组件,按照返回的视图名作为组件的id去容器找View对象。
-
-
-
异常处理步骤流程
-
执行目标方法,目标方法运行期间有任何异常都会被catch,而且标识当前请求结束,并且抛出
dispatchException
异常 -
进入视图解析流程(页面渲染)
-
processHandlerException
处理handler发生的异常,处理完返回ModelAndView
-
遍历所有的
handlerExceptionResolvers
,看谁能处理当前异常[HandlerExceptionResolver
处理器异常解析器] -
系统默认的异常解析器:
- `DefaultErrorAttributes` - `ExceptionHandlerExceptionResolver` - `ResponseStatusExceptionResolver` - `DefaultHandlerExceptionResolver`
DefaultErrorAttributes
先来处理异常,把异常信息保存到request域,并返回null
;- 默认没有任何解析器能处理异常,所以异常会被抛出
- 如果没有任何解析器能处理异常最终底层会发送/error请求,会被底层的
BasicErrorController
处理 - 解析错误视图,遍历所有的
ErrorViewResolver
看谁能解析。 - 默认的
DefaultErrorViewResolver
,作用是把响应状态码作为错误页的地址,error/500.html
- 末班引擎最终响应这个页面
error/500.html
析器能处理异常最终底层会发送/error请求,会被底层的BasicErrorController
处理 - 解析错误视图,遍历所有的
ErrorViewResolver
看谁能解析。 - 默认的
DefaultErrorViewResolver
,作用是把响应状态码作为错误页的地址,error/500.html
- 末班引擎最终响应这个页面
error/500.html
- 如果没有任何解析器能处理异常最终底层会发送/error请求,会被底层的
-
-