springboot 基础

246 阅读4分钟

springboot 特点

依赖管理

父项目做依赖管理

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.3.4.RELEASE</version>
</parent>

上面项目的父项目如下:
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-dependencies</artifactId>
	<version>2.3.4.RELEASE</version>
</parent>

它几乎声明了所有开发中常用的依赖的版本号,自动版本仲裁机制

开发导入starter场景启动器

  1. 见到很多 spring-boot-starter-* : *就某种场景
  2. 只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
  3. 更多SpringBoot所有支持的场景
  4. 见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
所有场景启动器最底层的依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter</artifactId>
	<version>2.3.4.RELEASE</version>
	<scope>compile</scope>
</dependency>

无需关注版本号,自动版本仲裁

  1. 引入依赖默认都可以不写版本
  2. 引入非版本仲裁的jar,要写版本号。

可以修改默认版本号

<mysql.version>5.1.43</mysql.version>

自动配置

image.png

image.png

image.png

容器功能

组件添加

@configuration

true模式会每次都检查容器是否有这个bean对象 效率较慢,有则使用容器中存在的Bean对象

image.png

@conditional

image.png

image.png

@ImportResource(原生配置文件导入)

image.png

image.png

@ConfigurationProperties(属性绑定)

image.png

image.png

自动配置原理

分析@SpringBootApplication注解,里面有三个核心注解

image.png

image.png

image.png

@AutoConfigurationPackage注解解释了主启动类所在的包底下的所有类被自动扫描 image.png

这里主要体现了按需加载,虽然所有自动配置启动时默认加载,但是都是按照条件进行判断是否按需加载:例如 image.png

image.png

总结www.bilibili.com/video/BV19K…image.png

url请求映射

image.png

请求处理-常用参数注解

@PathVariable 路径变量
@RequestHeader 获取请求头
@RequestParam 获取请求参数(指问号后的参数,url?a=1&b=2)
@CookieValue 获取Cookie值
@RequestAttribute 获取request域属性
@RequestBody 获取请求体[POST]
@MatrixVariable 矩阵变量
@ModelAttribute
请求处理-@MatrixVariableUrlPathHelper
语法: 请求路径:/cars/sell;low=34;brand=byd,audi,yd

SpringBoot默认是禁用了矩阵变量的功能

手动开启:原理。对于路径的处理。UrlPathHelper的removeSemicolonContent设置为false,让其支持矩阵变量的。
矩阵变量必须有url路径变量才能被解析

手动开启矩阵变量:

实现WebMvcConfigurer接口:
@Configuration(proxyBeanMethods = false)
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {

        UrlPathHelper urlPathHelper = new UrlPathHelper();
        // 不移除;后面的内容。矩阵变量功能就可以生效
        urlPathHelper.setRemoveSemicolonContent(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}

创建返回WebMvcConfigurerBean:
@Configuration(proxyBeanMethods = false)
public class WebConfig{
    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
                        @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper = new UrlPathHelper();
                // 不移除;后面的内容。矩阵变量功能就可以生效
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }
        }
    }
}

@MatrixVariable的用例

@RestController
public class ParameterTestController {

    ///cars/sell;low=34;brand=byd,audi,yd
    @GetMapping("/cars/{path}")
    public Map carsSell(@MatrixVariable("low") Integer low,
                        @MatrixVariable("brand") List<String> brand,
                        @PathVariable("path") String path){
        Map<String,Object> map = new HashMap<>();

        map.put("low",low);
        map.put("brand",brand);
        map.put("path",path);
        return map;
    }

    // /boss/1;age=20/2;age=10

    @GetMapping("/boss/{bossId}/{empId}")
    public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
                    @MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
        Map<String,Object> map = new HashMap<>();

        map.put("bossAge",bossAge);
        map.put("empAge",empAge);
        return map;

    }

}

bean注入的几种方式

  1. @Value

  2. @ConfigurationProperties(prefix = "person") 读取配置文件

  3. @PropertySource(value = "classpath:a.properties") ,与@Value("${}")连用

参数校验

多参数校验放在类中


@Data
public class User {
    @NotBlank(message = "eqeqe")
    @NotNull(message = "sssss")
    String name;
    Integer age;
    @Size(min = 1,message = "lsit最小为一")
    @Valid
    List list;

}


@RestController
public class HelloController {
    @PostMapping("/test")
    public String test(@Validated @RequestBody User user) {
        return user.toString();
    }

}


单个参数校验、(类上要加@Validated)

@RestController
@Validated
public class HelloController {
    @PostMapping("/test")
    public String test(@NotNull String id) {
        return null;
    }
}

注意点-要加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

嵌套校验(对应参数加@Valid)

public class User {
    @NotBlank(message = "eqeqe")
    @NotNull(message = "sssss")
    String name;
    Integer age;
    @Size(min = 1,message = "lsit最小为一")
    @Valid
    List list;
 
}

拦截器

实现步骤

  1. 编写一个拦截器实现HandlerInterceptor接口
  2. 拦截器注册到容器中(实现WebMvcConfigureraddInterceptors()
  3. 指定拦截规则(注意,如果是拦截所有,静态资源也会被拦截】
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 目标方法执行之前
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String requestURI = request.getRequestURI();
        log.info("preHandle拦截的请求路径是{}",requestURI);

        //登录检查逻辑
        HttpSession session = request.getSession();

        Object loginUser = session.getAttribute("loginUser");

        if(loginUser != null){
            //放行
            return true;
        }

        //拦截住。未登录。跳转到登录页
        request.setAttribute("msg","请先登录");
//        re.sendRedirect("/");
        request.getRequestDispatcher("/").forward(request,response);
        return false;
    }

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

    /**
     * 页面渲染以后
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion执行异常{}",ex);
    }
}


@Configuration
public class AdminWebConfig implements WebMvcConfigurer{
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())//拦截器注册到容器中
                .addPathPatterns("/**")  //所有请求都被拦截包括静态资源
                .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**",
                        "/js/**","/aa/**"); //放行的请求
}

原理

根据当前请求,找到HandlerExecutionChain(可以处理请求的handler以及handler的所有 拦截器)

先来顺序执行 所有拦截器的 preHandle()方法。

如果当前拦截器preHandle()返回为true。则执行下一个拦截器的preHandle()

如果当前拦截器返回为false。直接倒序执行所有已经执行了的拦截器的 afterCompletion();。

如果任何一个拦截器返回false,直接跳出不执行目标方法。

所有拦截器都返回true,才执行目标方法。

倒序执行所有拦截器的postHandle()方法。

前面的步骤有任何异常都会直接倒序触发 afterCompletion()。

页面成功渲染完成以后,也会倒序触发 afterCompletion()。

image.png

异步任务

方法上加@Async 启动类加@EnableAsync