SpringBoot 组件使用

1 拦截器

1.1 HandlerInterceptor

public interface HandlerInterceptor {
    //页面处理之前
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
	//页面处理以后
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
	//post完成以后
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

1.2 实现登陆拦截和静态资源放行

1. 编写一个拦截器实现HandlerInterceptor
2. 拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors)
3. 指定拦截规则
  • 编写拦截器
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 方法方法执行以前
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @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;
    }

    /**
     *  目标方法执行完成以后
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**
     * 页面渲染以后
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

  • 拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors)
//注册到容器中
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
	//指定拦截规则
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/","/login","/css/**","/js/**","/fonts/**");
    }
}

1.3 拦截器原理

  1. 根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有拦截器】
  2. 先来按照顺序执行所有拦截器的preHandle方法
    • 如果当前拦截器prehandler返回为true,则执行下一个拦截器的prehandle
    • 如果当前拦截器返回false,直接倒序执行所有执行的所有拦截器的afterComletion
  3. 如何任何一个拦截器返回false。直接跳出不执行目标方法
  4. 所有拦截器都返回True,才执行完以后。
  5. 倒序执行所有拦截器的postHandle方法
  6. 前面的步骤有任何异常都会直接倒叙触发afterComletion
  7. 页面成功渲染完成以后,也会倒叙触发afterComletion

触发的也只是,已经执行过preHandle方法的拦截器的afterComletion

2 文件上传

2.1 后端测试代码

public class FormTestController {

  
    @PostMapping("/upload")
    public String upload(@RequestParam("email") String email,
                         @RequestParam("username") String username,
                         //单文件的上传
                         @RequestPart("headerImg") MultipartFile headerImg,
                         //多文件的上传
                         @RequestPart("photos") MultipartFile[] photos) throws IOException {

        if (!headerImg.isEmpty()){
        	//文件存储到本地固定目录
            headerImg.transferTo(new File("D:\\WdGame\\"+headerImg.getOriginalFilename()));

        }

        if (photos.length>0){

            for(MultipartFile photo : photos){

                if (!photo.isEmpty()){
                    photo.transferTo(new File("D:\\WdGame\\"+photo.getOriginalFilename()));
                }
            }
        }
        return "index";
    }
}

2.2 配置信息

spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB

2.3 自动配置原理

文件上传自动配置类 MultipartAutoConfiguration—>MultipartProperties

  • 自动配置好了 StandardServletMultipartResolver 【文件上传解析器】

  • 原理步骤

    • 请求今来使用文件上传解析器判断(isMultipart)并且封装(resolveMulipart,返回MultipartHttpServletRequest)文件上传请求
    • 参数解析器来解析请求中的文件内容封装成MultipartFile
    • 将request中的文件信息封装成一个map (接受参数,List)

    FileCopyUtils:实现文件流的拷贝

3 异常处理

3.1 错误处理

  • 默认情况下,SrpingBoot提供了/error处理所有得错误得映射
  • 对于己写客户端,他将胜场JSON相应,其中包含错误,HTTP状态和一场消息得详细信息,对于浏览客户端,响应一个"whitelabel"错误视图,以HTML格式呈现相同的数据
  • 要对其进行自定义,添加View解析为error
  • 要完全替换默认行为,可以实现ErrorController并注册该类型的Bean定义,或添加ErrorAttributes类型的组件已使用现有的机制代替其内容
  • error/下的4xx,5xx页面会被自动解析

3.2定制错误处理逻辑

  • 自定义错误页

    • error/404.html,error/5xx.html
  • @ControllerAdvice+@ExceptionHandler处理异常(推荐):返回值是String 也是ModelView,底层是ExceptionHandlerExceptionResolver

  • @ResponseStatus+自定义异常;底层是ResponseStatusExceptionResolver ,把responsertatus注解的信息封装成ModelAndView返回,底层用response.sendError(StatusCode,resolveReason);也就是tomcat返回的/error

  • Spring底层的异常,如参数类型转换异常;DefaultHandlerExceptionResolver处理框架底层的异常,最后也会落脚到response.sendError

  • ErrorViewResolver实现自定义处理异常

    • response.sendError。error请求就会转给controller
    • 你的异常没有任何人能处理,tomcat底层response.sendError。error请求就会转给controller
    • basicErrorController要去的页面地址是ErrorViewResolver
  • 实现HandlerExceptionResolver处理异常

3.3 异常处理自动配置原理

  • ErrorMvcAutoConfiguration 自动配置异常处理规则

    • 容器中的组件:类型:DefaultErrorAttributes->id:errorAttributes

      • public class DefaultErrorAttributes implements ErrorAttributes, HandlerExceptionResolver, Ordered 
        
      • DefaultErrorAttributes:定义错误页面中应该包含哪些数据

    • 容器中的组件: 类型:BasicErrorController->id:basicErrorController (json+白夜 适配响应)

      • 处理默认/error路径的请求;页面响应: new ModelView(“error”,model)
      • 容器中有组件View->id是error(响应默认错误页)
      • 容器中放组件BeanNameResolver(视图解析器);按照返回的视图名作为组件的id去容器中找View对象。
    • 容器中的组件:DefaultErrorViewResolver->id:conventionErrorViewResolver

      • 如果发生错误,会以HTTP的状态码作为视图页地址(ViewName),找到真正的页面
      • error/404,5xx.html页面

如果想要返回页面;就会找到error视图【staticView】(默认是一个白页)

3.4 异常处理流程

  1. 执行目标方法,目标方法运行期间又任何异常都会被catch,而且标志当前请求结束;并且用dispatchException

  2. 进行视图解析流程(页面渲染?)

    processDispatchResult(processeRequest,response,mapperHandler,mv,dispatchException)

  3. mv=precessHandlerException:处理handler发生的异常,处理完成返回ModelAndView

    1. 遍历所有的handlerExceptionResolvers 看谁能处理当前异常[HandlerExceptionResolver处理器异常解析器]

    2. 默认的异常解析器:DefaultErrorAttributes和HadnlerExceptionResolverCompsite

      • DefaultErrorAttributes先来处理异常。把异常信息保存到request域,并且返回null;

      • 默认没有任何人能处理异常,所以异常会被抛出

        1. 如果没有任何人能处理,最终底层就会发送/error请求,会被底层的BasicErrorController处理

        2. 解析错误视图,遍历所有的ErrorViewResokver看谁能解析

        3. 默认的DefaultErrorViewResolver 作用是把响应状态码作为错误页的地址拼接成,error/500.html

        4. 模板引擎最终响应这个页面 error/500.html

4 Web原生组件注入(Servlet,Filter,Listener)

4.1 使用Servlet API

@WebServlet(urlPatterns = "/my")
public class Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      
    }
}
//主类申明Servlet需要扫描的Servlet包
@ServletComponentScan(basePackages = "com.atguigu.admin")
@SpringBootApplication
public class Boot05WebAdminApplication {

    public static void main(String[] args) {
        SpringApplication.run(Boot05WebAdminApplication.class, args);
    }
}

@ServletComponentScan(basePackages = “com.atguigu.admin”):指定原生Servlet组件都放在哪里

@WebServlet(urlPatterns = “/my”):效果:直接影响,没有Spring的拦截器?

此时系统中存在两个Servlet

1.MyServlet—>/my Tomcat处理

2.DispatcherServlet—>SpringMVC所带有的 Spring流程

扩展:DispatchServlet是如果注册:

  • 容器中自动配置了DispatcherServlet属性绑定到WebMvcProperties;对应的配置文件的配置项是spring.mvc

  • 通过ServletRegistrationBean把DispatcherServlet配置进来

  • 默认映射的是/路径

  • 同样遵循精确有限原则

    /my请求提交锅来,由Tomcat处理

Tomcat-Servlet

多个Servlet都能处理到同一层路径,精确优先原则

4.2 使用Filter API

@WebFilter(urlPatterns = {"/css/*","/images/*"})
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    }

    @Override
    public void destroy() {

    }
}

4.3 Listener

//注解
@WebListener
public class MyServletContextListenter implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {

    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }
}

4.4 RegistrationBean

@Configuration
public class MyRegisticConfig {
    @Bean
    public ServletRegistrationBean myServlet(){
        Servlet myServlet = new Servlet();
        return  new ServletRegistrationBean(myServlet,"/my","/my02");
    }

    @Bean
    public FilterRegistrationBean myFilter(){
        MyFilter myFilter = new MyFilter();
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
        return filterRegistrationBean;
    }

    public ServletListenerRegistrationBean myListenter(){
        MyServletContextListenter myServletContextListenter = new MyServletContextListenter();
        return new ServletListenerRegistrationBean(myServletContextListenter);
    }
}

5. 嵌入式Servlet容器

5.1 切换嵌入式Servlet容器

  • 默认支持的WebServer

    • Tomcat,Jetty,or Undertow
    • ServletWebServerApplicationContext 容器启动寻找ServletWebServerFactory 并且创建服务器
  • 切换服务器

     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-tomcat</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-undertow</artifactId>
            </dependency>
    
  • 原理

    • SpriingBoot应用启动发现当前是Web应用。Web场景包-导入Tomcat

    • web应用会创建一个Web的IOC容器ServletWebServerApplicationContext

    • ServletWebServerApplicationContext 启动的时候 启动ServletWebServerFactory工厂

    • SpringBoot底层默认支持的很多的WebServer工厂:

      TomcatServletWebServerFactory,JettyServletWebServerFactory,or underServletWebServerFactory

    • 底层直接会有一个自动配置类。ServletWebServerFactoryAutoConfiguration

    • ServletWebServerFactoryAutoConfiguration导入了ServletWebServerFactoryAutoConfiguration(配置类)

    • ServletWebServerFactoryAutoConfiguration 配置类 根据动态判断系统中到底导入了那个Web服务器的包。(默认是导入web-starter,因此导入了tomcat包),容器中就有TomcatServletWebServerFactory。

    • TomcatServletWebServerFactory创建出tomcat服务器并且启动;TomcatWebServer的构造器拥有初始化方法initialize

    • 只能由一个服务器,否则就会抛出异常

    • 内嵌服务器,就是手动把启动服务器的代码调用(tomcat核心jar包存在)

5.2 定制Servlet容器

  • 实现WebServerFactoryCustomizer
  • 修改配置文件server.xxx
  • 直接自定义configuServletWebServerFactory

xxxxCustomizer:定制化器,可以改变xxxx的默认规则

5.3 定制化的常见方式

  • 修改配置文件

  • xxxxxCustomizer

  • 编写自定义的配置类 xxxConfiguration + @Bean替换,增加容器中默认组件;视图解析器

  • web应用实现WebMvcConfigurer即可定制化web功能(推荐)

  • @EnableWebMvc+WebMvcConfigurer-@Bean 可以全面接管SpringMVC,所有规则全部自己重新部署慎重使用;实现定制和扩展功能

    • 原理

      1. WebMVCAutoConfiguration的默认的SpringMVC的自动配置类,静态资源,欢迎页

      2. 一旦使用@EnableWebMvc,导入DelegatingWebMvcConfiguration.class

      3. DelegatingWebMvcConfiguration的作用

        • 把所有系统中的WebMvcConfiguration。所有功能的定制都是这些WebMvcConfiguration所有都生效
        • 自动配置了一些非常底层的组件。RequestMapping,HandlerMappinng 这些组件依赖的组件都是从容器中获取
      4. WebMvcAutoConfiguration里面的配置要能生效 必须

        @ConditionalOnMissingBean(WebMvcConfigutationSupport.class)

        DelegatingWebMvcConfiguration.class 继承 WebMvcConfigutationSupport.class

      5. EnableWebMvc导致了WebMvcAutoConfiguration

5.4 原理分析套路

场景starter-xxxxAutoConfiguration-导入xxx组件—绑定xxxProperties—绑定配置文件项

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>