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场景启动器
- 见到很多 spring-boot-starter-* : *就某种场景
- 只要引入starter,这个场景的所有常规需要的依赖我们都自动引入
- 更多SpringBoot所有支持的场景
- 见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
<scope>compile</scope>
</dependency>
无需关注版本号,自动版本仲裁
- 引入依赖默认都可以不写版本
- 引入非版本仲裁的jar,要写版本号。
可以修改默认版本号
<mysql.version>5.1.43</mysql.version>
自动配置
容器功能
组件添加
@configuration
true模式会每次都检查容器是否有这个bean对象 效率较慢,有则使用容器中存在的Bean对象
@conditional
@ImportResource(原生配置文件导入)
@ConfigurationProperties(属性绑定)
自动配置原理
分析@SpringBootApplication注解,里面有三个核心注解
@AutoConfigurationPackage注解解释了主启动类所在的包底下的所有类被自动扫描
这里主要体现了按需加载,虽然所有自动配置启动时默认加载,但是都是按照条件进行判断是否按需加载:例如
总结(www.bilibili.com/video/BV19K…)
url请求映射
请求处理-常用参数注解
@PathVariable 路径变量
@RequestHeader 获取请求头
@RequestParam 获取请求参数(指问号后的参数,url?a=1&b=2)
@CookieValue 获取Cookie值
@RequestAttribute 获取request域属性
@RequestBody 获取请求体[POST]
@MatrixVariable 矩阵变量
@ModelAttribute
请求处理-@MatrixVariable与UrlPathHelper
语法: 请求路径:/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注入的几种方式
-
@Value
-
@ConfigurationProperties(prefix = "person") 读取配置文件
-
@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;
}
拦截器
实现步骤
- 编写一个拦截器实现
HandlerInterceptor接口 - 拦截器注册到容器中(实现
WebMvcConfigurer的addInterceptors()) - 指定拦截规则(注意,如果是拦截所有,静态资源也会被拦截】
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()。
异步任务
方法上加@Async 启动类加@EnableAsync