3.include->引入的东西会在link标签里面内嵌link标签
<link th:include="~{}">
4.标签改为div,div是万能的。
<div th:replace="~{}"></div>
(4.2)、配置拦截器
SpringMvc的拦截器配置
1.Filter: 是Servlet定义的原生组件。好处:脱离Spring也能够使用 2.Interceptor: 是Spring定义的接口。可以使用Spring的自动装配功能
第一种拦截机制
package com.jsxs.servlet; import lombok.extern.slf4j.Slf4j; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; /** * @Author Jsxs * @Date 2023/7/8 17:58 * @PackageName:com.jsxs.servlet * @ClassName: MyFilter * @Description: TODO 配置过滤器 * @Version 1.0 */ @Slf4j //@WebFilter(urlPatterns = {"/css/*","/imag/*"}) //设置拦截我们CSS和imag的所有文件 public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { log.info("MyFilter初始化完成....."); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { log.info("MyFilter工作中....."); chain.doFilter(request,response); } @Override public void destroy() { log.info("MyFilter初始化销毁....."); } }
第二种拦截机制
在这里进行拦截的操作
package com.jsxs.config; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 登入成功之后存在登入后的session if (request.getSession().getAttribute("LoginUser")!=null){ return true; }else { request.setAttribute("msg","没有权限请先进行登入"); request.getRequestDispatcher("/index.html").forward(request,response); return false; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } }
在这里设定规则
/** * 1、编写一个拦截器实现HandlerInterceptor接口 * 2、拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors) * 3、指定拦截规则【如果是拦截所有,静态资源也会被拦截】 */ @Configuration public class AdminWebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") //所有请求都被拦截包括静态资源 .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行的请求 } }
拦截器原理:
- 根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器】
- 先来
顺序
执行所有拦截器的preHandle
方法
- 如果当前拦截器prehandler返回为
true(通行)
。则执行下一个拦截器的preHandle - 如果当前拦截器返回为
false(不通行)
。直接倒序
执行所有已经执行了的拦截器的 afterCompletion;
- 如果任何一个拦截器返回false。
直接跳出不执行目标方法
所有拦截器都返回True。执行目标方法
倒序执行
所有拦截器的postHandle方法。- 前面的步骤有任何异常都会直接倒序触发
afterCompletion
- 页面成功渲染完成以后,也会倒序触发 afterCompletion
如图:
(4.3)、文件上传(表单)
1. 需要指定 enctype 2. 单个文件上传 什么也不加 3. 多个文件上传 需要加上: multiple 属性 <form method="post" action="/upload" enctype="multipart/form-data"> 单文件 <input type="file" name="file"><br> 多文件 <input type="file" name="file" multiple><br> <input type="submit" value="提交"> </form>
1.一定要加上参数注解 @RequestPart /** * MultipartFile 自动封装上传过来的文件,以后文件上传用这个类型和注解 * @param email * @param username * @param headerImg * @param photos * @return */ @PostMapping("/upload") public String upload(@RequestParam("email") String email, @RequestParam("username") String username, @RequestPart("headerImg") MultipartFile headerImg, @RequestPart("photos") MultipartFile[] photos) throws IOException { log.info("上传的信息:email={},username={},headerImg={},photos={}", email,username,headerImg.getSize(),photos.length); if(!headerImg.isEmpty()){ //保存到文件服务器,OSS服务器 String originalFilename = headerImg.getOriginalFilename(); //获取上传的文件名 headerImg.transferTo(new File("H:\\cache\\"+originalFilename)); //这个方法直接传输了,内部封装了InputStrean和OutStream流(需要指定路径+文件名即可) } if(photos.length > 0){ for (MultipartFile photo : photos) { if(!photo.isEmpty()){ String originalFilename = photo.getOriginalFilename(); photo.transferTo(new File("H:\\cache\\"+originalFilename)); //遍历传输各个文件 } } } return "main"; }
原理
MultipartAutoConfiguration 类 MultipartProperties 类
- 自动配置原理
文件上传自动配置类-MultipartAutoConfiguration-MultipartProperties
- 自动配置好了
StandardServletMultipartResolver
【文件上传解析器】 - 原理步骤
- 1、请求进来使用文件上传解析器判断(
isMultipart
)并封装(resolveMultipart,返回MultipartHttpServletRequest)文件上传请求` - 2、参数解析器来解析请求中的文件内容封装成`MultipartFile
- 3、将request中文件信息封装为一个
Map
;MultiValueMap<String, MultipartFile>
FileCopyUtils。实现文件流的拷贝
6.异常处理
(1).错误处理
(5.1)、默认规则
- 默认情况下,Spring Boot提供
/error
处理所有错误的映射 - 对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,响应一个“ whitelabel”错误视图,以HTML格式呈现相同的数据
要对其进行自定义,添加View解析为error
- 要完全替换默认行为,可以实现 ErrorController 并注册该类型的Bean定义,或添加ErrorAttributes类型的组件以使用现有机制但替换其内容。
静态资源或templates目录下放 error/下的4xx,5xx页面会被自动解析
(5.2)、定制错误处理逻辑 (==三种方法 ==)
- 自定义错误页 (第一种)
- error/404.html error/5xx.html;
有精确的错误状态码页面就匹配精确,没有就找 4xx.htm
l;如果都没有就触发白页
在自定义的4xx页面或者5xx页面的某个提示标签中可以这么写 th:text="${status}" ->在配置的错误页面中会获得返回的状态码 th:text="${message}" ->在配置的错误页面中会获得返回的信息
@ControllerAdvice+@ExceptionHandler
处理全局异常;底层是 ExceptionHandlerExceptionResolver 支持的 (第二种⭐)
- @ResponseStatus+自定义异常 ;底层是 ResponseStatusExceptionResolver ,把responsestatus注解的信息底层调用 response.sendError(statusCode, resolvedReason);tomcat发送的/error (第三种)
先定义: 编写有参构造和无参构造,并不是继承父类的方法
后使用
- Spring底层的异常,如 参数类型转换异常;DefaultHandlerExceptionResolver 处理框架底层的异常。
- response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
- ErrorViewResolver 实现自定义处理异常;
- response.sendError 。error请求就会转给controller
- 你的异常没有任何人能处理。tomcat底层 response.sendError。error请求就会转给controller
- basicErrorController 要去的页面地址是 ErrorViewResolver ;
(5.3)、异常处理自动配置原理
ErrorMvcAutoConfiguration
自动配置异常处理规则
- 容器中的组件:类型:
DefaultErrorAttributes
-> id:errorAttributes
- public class DefaultErrorAttributes implements ErrorAttributes, HandlerExceptionResolver
- DefaultErrorAttributes:定义错误页面中可以包含哪些数据。
容器中的组件:类型:BasicErrorController --> id:basicErrorController(json+白页 适配响应)
- 处理默认 /error 路径的请求;页面响应 new ModelAndView(“error”, model);
- 容器中有组件 View->id是error;(响应默认错误页)
- 容器中放组件 BeanNameViewResolver(视图解析器);按照返回的视图名作为组件的id去容器中找View对象。
- 容器中的组件:类型:DefaultErrorViewResolver -> id:conventionErrorViewResolver
- 如果发生错误,会以HTTP的状态码 作为视图页地址(viewName),找到真正的页面
- error/404、5xx.html