基础 介绍 Spring家族有一套完全,之前学习的Spring5(Spring Framework),SpringMVC,都是Spring家族的组件,用于解决某一问题的,可以这么说
Spring家族还有很多的组件,在以前,整合起来会非常的麻烦,要写很多的配置文件,有了SpringBoot就会方便去整合,有了它,可以快速去构建出生产级别的Spring应用
背景 微服务
微服务是一种架构风格
一个应用拆分成一组小型服务
每个服务运行在自己的进程里,可独立部署和升级
服务之间使用轻量级HTTP进行交互
服务围绕业务功能进行拆分
可以由全自动部署机制独立部署
去中心化,服务自治。服务可以使用不同的语言,不同的存储技术
分布式 分布式-有了微服务的架构,就必然会有分布式的概念
分布式的难点:
远程调用
服务发现
负载均衡
服务容错
配置管理
服务监控
链路追踪
日志管理
任务调度
…
分布式难点的解决:
云原生 应用写出来就会有上云的问题,上云的过程中又会出现很多问题
难点:
服务自愈
弹性伸缩
服务隔离
自动化部署
灰度发布
流量自理
…
解决:
优点
创建独立的Spring应用
内嵌web服务器
自动starter依赖,简化构建配置
自动配置Spring以及第三方功能
提供生产级别的监控,健康检查以及外部化配置
无代码生成,无需编写XML
对于很多的东西(拿不到源码的Java文件),不需要再去写配置Bean,直接在配置文件就可以解决
缺点 迭代快,需要时刻关注变化
封装太深,内部原理复杂,难以精通
使用 多看文档。
https://docs.spring.io/spring-boot/docs/current/reference/html/
初使用 Maven版 父级依赖
1 2 3 4 5 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.6.3</version > </parent >
引入场景依赖
这个引入的是SpringBoot的依赖
这个依赖会把与这个场景相关的依赖全部引入进来,不需要我们自己手动去找依赖!
1 2 3 4 5 6 <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies >
编写启动程序
SpringBoot内置了有web服务器,所以说我们不用手动配置Tomcat服务器,直接写个程序启动就行了如下操作
@SpringBootApplication
标识这个类是主程序类,用它去启动SpringBoot程序
这个类里main方法就是用来启动的,写法如下
1 2 3 4 5 6 @SpringBootApplication public class MainApplication { public static void main (String[] args) { SpringApplication.run(MainApplication.class,args); } }
编写配置文件
在resource目录里(资源目录)新建一个application.properties
,这一个配置文件可以将web服务器等配置进行修改,具体看官方文档
如果没需求,这个文件可以不写
下面demo就是修改服务访问端口的配置
编写服务
服务就是控制层
@RestController
是@Controller
和@ResponseBody
的复合注解,标识这是控制层,同时标识这个类下的方法都会给页面一个响应
有@ResponseBody
这个注解,方法返回的字符串就会直接响应在浏览器内容中
1 2 3 4 5 6 7 8 @RestController public class HelloController { @RequestMapping("/hello") public String handle01 () { return "Hello,SpringBoot2" ; } }
简化部署
何为简化部署?
就是我们不用手动去打jar包(不加配置打出来的jar包是不能够直接运行的)
SpringBoot为我们提供了maven插件,可以让我们直接打成jar包,然后在终端中直接运行
1 2 3 4 5 6 7 8 <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build >
启动服务
启动服务就是将启动程序启动,启动后在浏览器里输入localhost:8888/hello
,就会出现Hello,SpringBoot2
的页面。
启动服务可以在IDEA里面启动,也可以在终端中运行jar包
特点 依赖管理 修改依赖
初使用里面的pom文件里面有个parent标签,那是SpringBoot帮我们在做依赖管理,我们可以依次往上翻,找到真正的父级项目依赖管理
在spring-boot-dependencies.pom
文件里可以看到SpringBoot帮我们把会用到的依赖都引入了,还有默认版本号
如果我们需要自定义依赖版本号,那么就在自己项目的父类项目里按一下方式写
1 2 3 <properties > <mysql.verson > 8.0.23</mysql.verson > <properties >
修改场景启动器
初使用项目中,我们看到只引入了spring-boot-starter-web
依赖,这个就叫做场景启动器,就是web的依赖,会将web需要的依赖全部导入。
具体翻源码spring-boot-starter-*
*-spring-boot-starter
类似这种的就是第三方的场景启动器
自动配置
自动配好Tomcat服务器
自动配好SpringMVC常用组件
自动配好Web常用功能
默认包结构
主程序所在的包以及其下面所有子包里的所有被默认扫描
各个配置文件拥有默认值
application.properties
文件中的默认配置都会绑定一个类,这个类会在容器中创建对象
按需加载所有自动配置项
自动配置的依赖在场景启动器的依赖中,名为spring-boot-autoconfigur.jar
这个jar包里有很多的自动配置项,有缓存,aop等等
但是SpringBoot会根据你引入的 场景启动器去开启需要的,不需要的则会爆红(具体如何实现的后续会讲)
容器功能 组件添加 @Configuration
在SpringBoot中,我们要为容器添加bean组件,可以使用纯XML的方式,也可以写配置类,在配置类里引入bean
@Configuration
标识在类上,告诉SpringBoot这是一个配置类
在配置类里对方法使用@Bean
注解,这样就可以为容器注册bean组件
这个方法也是有讲究的,看下面的注释
详情翻阅Spring笔记
1 2 3 4 5 6 7 8 9 10 11 12 13 @Configuration public class MyConfig { @Bean public User user01 () { return new User ("zhangsan" , 18 ); } }
full-lite
上面的操作注册的组件(bean)是单例模式的,就是单实例对象。
但我们有时候不需要单实例模式,这样就只需要下面的操作
默认是true,会创建动态代理
1 2 3 4 5 6 7 @Configuration(proxyBeanMethods = false) public class MyConfig { @Bean public User user01 () { return new User ("zhangsan" , 18 ); } }
@ComponentScan @Import
在容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
这种使用方式下就不用
用在@Configuration
注解下面
1 @Import({User.class, DBHelper.class})
@Conditional
@Conditional
及其子注解是用于条件注册组件的
XML配置文件引入
我们有时候会遇到写了很多的配置文件,想迁移到配置类里里面,但是太繁琐,这个时候我们就在配置类哪里使用注解将beans.xml
引入
使用下面这个注解,就会把XML文件中配置的bean组件注册到容器中
1 @ImportResource("classpath:beans.xml")
配置绑定(Properties)
配置绑定就是将配置文件里面的信息注入到某个类里
以下两种实现方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Component @ConfigurationProperties(prefix = "mycar") public class Car {@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(Car.class) public class MyConfig {} mycar.brand=BYD mycar.price=100000
开发小技巧 Lombok
Lombok好用,帮我们简化开发,我们的pojo类,可以只写字段,而使用Lombok提供的注解简化
使用注解后就可以不写构造器,set/get方法,toString方法等等,Lombok会在程序编译的时候为我们补上
记得导包和安装IDEA的lombok插件
注解不止下面几种,还有别的,比如@Slf4j
,用了这个我们就不用在主程序去打印了,直接在类哪里使用log.info()
1 2 3 4 5 6 7 8 9 10 11 @Data @ToString @NoArgsConstructor @AllArgsConstructor @Component @ConfigurationProperties(prefix = "mycar") public class Car { private String brand; private int price; }
Spring Initailizer 前面哪个项目是使用maven手动去设置的SpringBoot项目,我们可以继续简化开发,使用Spring的初始化程序去创建项目
相当于就是热部署,想用速度快些,添加依赖,Command+F9
配置文件 SpringBoot开发的时候,配置文件有两种
一种是:properties
二种是:yaml
yaml yaml是一种标记语言,类似markdown,html等,非常适合用来做以数据为中心的配置文件
基本语法
key:value,kv之间有空格
大小写敏感
使用缩进表示层级关系,缩进不允许使用tab,只允许空格
缩进的空格数不做要求,对齐即可
#表示注释
‘’和”” 表示的字符串内容 会被 转义/不转义
数据类型 字面量
字面量:单个的、不可再分的值。date、boolean、string、number、null
对象
字面量:单个的、不可再分的值。date、boolean、string、number、null
1 2 3 4 5 6 行内写法: k: {k1:v1 ,k2:v2 ,k3:v3 }k: k1: v1 k2: v2 k3: v3
数组
数组:一组按次序排列的值。array、list、queue
1 2 3 4 5 6 行内写法: k: [v1 ,v2 ,v3 ]k: - v1 - v2 - v3
示例 需要注意的是List就是数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 @ConfigurationProperties(prefix = "person") @Component @ToString @Data public class Person { private String userName; private Boolean boss; private Date birth; private Integer age; private Pet pet; private String[] interests; private List<String> animal; private Map<String, Object> score; private Set<Double> salarys; private Map<String, List<Pet>> allPets; } @Component @ToString @Data public class Pet { private String name; private Double weight; } person: user-name: "Jsckot" boss: true birth: 2001 /11 /28 20 :12 :33 age: 20 pet: name: "tomcat" weight: 23.4 interests: ["篮球" ,"游泳" ] animal: - Jerry - Mario score: english: first: 20 second: 40 third: 50 math: {23 ,45 ,65 } chinese: {first: 34 ,second: 43 ,third: 65 } salarys: [1234 ,6789 ,9877 ,7777 ] all-pets: sick: - {name: tom} - {name: jerry,weight: 47 } health: [{name: Mario,weight: 47.9 }]
yml简化开发 我们在使用yml以及properties两种文件类型做配置绑定的时候,IDEA不会提醒我们去写类的字段,这时候我们可以使用SpringBoot提供的依赖去辅助我们开发
tip:这个依赖只是用于方便我们的开发,项目运行并不需要这个,所以我们可以将这个依赖在编译的时候移除是,以免JVM需要加载过多无用的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > <optional > true</optional > </dependency > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > <configuration > <excludes > <exclude > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > </exclude > <exclude > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > </exclude > </excludes > </configuration > </plugin > </plugins > </build >
WEB开发 WEB开发中,SpringBoot为我们做了很多的自动配置,具体翻看文档
简单功能 静态资源访问
类路径下的/static
or/publuc
or/resources
or/META-INF/resources
只要文件在类的这些目录下,项目启动后就可以通过域名:端口/静态资源名
进行访问
原理:静态映射/**
请求进来先看Controller能否处理,不能处理的则又交给静态资源处理器,就会去指定目录寻找,找不到就404
静态资源访问前缀
这个功能挺有用的,上面的操作是默认的,没有前缀,直接使用域名:端口/静态资源名
我们可以进行操作,使其可以按这种路径访问域名:端口/访问前缀/静态资源名
1 2 3 spring: mvc: static-path-pattern: /res/**
自定义资源路径
1 2 3 4 spring: web: resources: static-locations: [classpath:/haha/ ]
webjars
1 2 3 4 5 <dependency > <groupId > org.webjars</groupId > <artifactId > jquery</artifactId > <version > 3.5.1</version > </dependency >
欢迎页
自定义Favicon
Faviocn就是网站在浏览器中访问的时候,浏览器上面的小图
直接将文件改为favicon.ico
,然后放在静态资源目录下即可
请求处理 请求映射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 spring: mvc: hiddenmethod: filter: enabled: true @RestController public class HelloController { @RequestMapping(value = "/user" ,method = RequestMethod.GET) public String getUser() { return "GET-张三" ; } @RequestMapping(value = "/user" ,method = RequestMethod.POST) public String saveUser() { return "POST-张三" ; } @RequestMapping(value = "/user" ,method = RequestMethod.PUT) public String putUser() { return "PUT-张三" ; } @RequestMapping(value = "/user" ,method = RequestMethod.DELETE) public String deleteUser() { return "DELETE-张三" ; } } /**上面的操作**/ @RestController public class HelloController { @GetMapping("/user") public String getUser() { return "GET-张三" ; } @PostMapping("/user") public String saveUser() { return "POST-张三" ; } @PutMapping("/user") public String putUser() { return "PUT-张三" ; } @DeleteMapping("/user") public String deleteUser() { return "DELETE-张三" ; } }
改变默认_method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.Jsckot.thirdweb.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.filter.HiddenHttpMethodFilter;@Configuration(proxyBeanMethods = false) public class WebConfig { @Bean public HiddenHttpMethodFilter hiddenHttpMethodFilter () { HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter (); methodFilter.setMethodParam("_m" ); return methodFilter; } }
普通参数与基本注解
SpringBoot的web层是基于SpringMVC实现的,在Controller的请求方法的参数中,可以传很多的参数来获取信息
下面介绍的就是一些常用的信息
基本注解
@PathVariable
–路径变量–就是请求路径里的变量 - user/{id}
@RequestHeader
–获取请求头信息
@RequestParam
–获取请求参数–就是?携带的信息
@CookieValue
–获取cookies
@RequestBody
–获取请求体信息[post请求的数据]
@RequestAttribute
–获取request域信息
@MatrixVariable
–矩阵变量
获取的信息都是健值对形式的,可以使用上面的注解将全部的信息或者某一个key的信息获取
获取全部就是将获取的信息放在Map中,健值对嘛
获取特定的信息就是 将这个key放注解的参数里传给具体的变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @RestController public class ParameterTestController { @GetMapping("/car/{id}/owner/{username}") public Map<String,Object> getCar (@PathVariable("id") Integer id, @PathVariable("username") String name, @PathVariable Map<String,Object> pv, @RequestHeader("User-Agent") String userAgent, @RequestHeader Map<String,String> headers) { Map<String,Object> map = new HashMap <>(); map.put("id" ,id); map.put("name" ,name); map.put("pv" ,pv); map.put("User-Agent" ,userAgent); map.put("header" ,headers); return map; } }
ServletAPI
参数也可以传ServletAPI参数,比如HttpServlet等等
复杂参数
自定义对象参数-POJO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <form action ="/saveuser" method ="post" > 姓名: <input name ="userName" value ="zhangsan" /> <br /> 年龄: <input name ="age" value ="18" /> <br /> 生日: <input name ="birth" value ="2019/12/10" /> <br /> 宠物: <input name ="pet" value ="啊猫,3" /> <input type ="submit" value ="保存" /> </form > // 下面的代码可以不写,如果需要自定义handle再来写 @Bean public WebMvcConfigurer webMvcConfigurer() { // 这是Lamada表达式的写法 return new WebMvcConfigurer() { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new Converter<String, Pet>() { @Override public Pet convert(String source) { if (!StringUtils.isEmpty(source)) { Pet pet = new Pet(); String[] split = source.split(","); pet.setName(split[0]); pet.setAge(split[1 ]); } return null; } }); } }; }
响应处理 响应JSON
准备工作
web场景依赖+jackson.jar
映射方法上标注@ResponseBody
注解
返回的就是JSON类型
上面的测试中,返回的都是XML
响应XML
将jackson-dataformat-xml.jar的依赖导入进来
映射方法上标注@ResponseBody
注解
内容协商
1 2 3 4 5 6 7 8 // 开启内容协商 spring: contentnegotiation: favor-parameter: true <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
自定义内容协商处理
可以使用WebMvcConfig去定制化SpringMVC功能,需要的时候自己去看文档
视图解析与模板引擎
Thymeleaf使用
导入Thymeleaf的依赖-SpringBoot会为我们配置好Thymeleaf以及模板引擎,视图解析器
在html页面中引入Thymeleaf的名称空间-可以直接修改IDEA的配置信息
1 2 3 4 5 6 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-thymeleaf</artifactId > </dependency > <!DOCTYPE html > <html lang ="en" xmlns:th ="http://www.thymeleaf.org" >
FreeMaker 也是一种模板引擎,可以了解一下
解决表单重复提交
在使用请求映射的情况下会出现表单重复提交样子,比如这个demo
因为它是映射的main.html
这个文件,如果已经映射了再刷新就会再次发起请求
1 2 3 4 @PostMapping("/login") public String main (String username,String passward) { return "main" ; }
解决方案如下:
访问/login这个请求映射的时候,满足情况的话会带着请求参数直接重定向到具体的页面,而不是请求本身。
这个点去了解一下请求与重定向等等
1 2 3 4 5 6 7 8 9 10 11 @PostMapping("/login") public String main (String username,String passward) { return "redirect:/main.html" ; } @GetMapping("/main.html") public String mainPage () { return "main" ; }
抽取公共部分
将公共部分抽取后放到一个html页面中,然后使用th:formtarget
命名,再在原页面中引入即可
拦截器
拦截器和原生Servlet里面的 Filter功能类似,都是用于拦截的
HandlerInterceptor接口
HandlerInterceptor接口
是拦截器接口,有三个默认方法,用于实现拦截。
操作
新建一个类实现拦截器接口,实现拦截的方法
将拦截器类注入到容器中,在容器中配置拦截以及放行的路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 @Configuration public class AdminWebConfig implements WebMvcConfigurer { @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor ()) .addPathPatterns("/**" ) .excludePathPatterns("/" ,"/login" ,"/css/**" ,"fonts/**" ,"/images/**" ,"/js/**" ,"/aa/**" ); } } 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 ; } request.setAttribute("msg" ,"请先登录" ); request.getRequestDispatcher("/" ).forward(request,response); 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 { } }
文件上传
SpringBoot将文件上传封装到了Multipart里面了,原理后续专门看,很方便
操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <form role ="form" th:action ="@{/upload}" method ="post" enctype ="multipart/form-data" > /** *使用注解将前端上传的文件标识 */ @PostMapping("/upload") public String upload(@RequestParam("email") String email, @RequestParam("username") String username, @RequestPart("headerImg") MultipartFile headerImg, @RequestPart("photos") MultipartFile[] photos) throws Exception{ log.info("{}---{}---{}---{}---{}",email,username,headerImg.getSize(),photos.length); if (!headerImg.isEmpty()) { //获取原文件名 String originalFilename = headerImg.getOriginalFilename(); //使用Multipart的transferTo方法将文件写入目标目录 headerImg.transferTo(new File("/Users/Jsckot/Desktop/upload/"+originalFilename)); } if (photos.length > 0) { for (MultipartFile photo : photos) { if (!photo.isEmpty()) { String originalFilename = photo.getOriginalFilename(); photo.transferTo(new File("/Users/Jsckot/Desktop/upload//"+originalFilename)); } } } return "redirect:/main.html"; }
异常处理(TODO) 默认情况下SpringBoot提供/error
处理所有请求的映射
对于机器客户端,它将响应json
对于浏览器,会响应一个页面
1 2 3 4 5 6 { "timestamp" : "2022-02-18T08:35:42.807+00:00" , "status" : 999 , "error" : "None" , "message" : "No message available" }
自定义页面处理
自定义处理就是可以在resource/templates目录下创建一个error目录,里面放对应的页面,SpringBoot会帮我们自动解析,当遇到访问为5xx或者404的时候就会自动访问页面
我们也可以通过json将报错栈放到页面上
5xx表示响应状态码为5开头就会自定响应这个页面
1 2 3 4 5 6 7 <section class="error-wrapper text-center" > <h1><img alt="" src="images/500-error.png" ></h1> <h2>OOOPS!!!</h2> <h3 th:text="${message}" >Something went wrong.</h3> <p class="nrml-txt" th:text="${trace}" >Why not try refreshing you page? Or you can <a href="#" >contact our support</a> if the problem persists.</p> <a class="back-btn" th:href="@{/main.html}" > Back To Home</a> </section>
定制异常处理 处理全局异常
@ControllerAdvice
和@ExceptionHandler
注解配合使用进行全局异常捕获
@ControllerAdvice
继承了@Component
@ExceptionHandler
注解用于自定全局异常类型
返回的是视图地址
这个操作是全局的,全局内遇到后会自动进行响应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Slf4j @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler({ArithmeticException.class,NullPointerException.class}) public String handlerArithException (Exception e) { return "login" ; } }
@ResponseStatus+自定义异常
自定义异常,然后再在程序中抛出这个异常
reason属性会被封装在message里面
1 2 3 4 5 6 7 8 9 10 @ResponseStatus(value = HttpStatus.FORBIDDEN,reason = "用户数量太多") public class UserTooManyException extends RuntimeException { public UserTooManyException () { } public UserTooManyException (String message) { super (message); } }
自定义异常解析器
这是自定义异常解析器,用的不多,配合Order注解可以实现优先级的分配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Order(value = Ordered.HIGHEST_PRECEDENCE) @Component public class CustomerHandlerExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { try { response.sendError(511 ,"我喜欢的错误" ); } catch (IOException e) { e.printStackTrace(); } return new ModelAndView (); } }
原生组件
原生组件比如Servlet,Filter,Listener等等,注入容器有两种方式
原生注解➕包扫描
原生注解就是@WebServlet
,再在启动器上面加一个Servlet的包扫描注解
这样的话就可以通过/myservlet
路径进行访问,这个访问是不受Spring拦截器的拦截的,直接访问
1 2 3 4 5 6 7 8 9 10 11 12 @Slf4j @WebServlet(urlPatterns = "/myservlet") public class MyServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { log.info("11111" ); resp.getWriter().write("666666" ); } } @ServletComponentScan(basePackages = "com.Jsckot.webtest.servlet") @SpringBootApplication public class ForthTestApplication {
RegistrationBean注解
使用RegistBean的话,就必须先写好上面的MyServlet的自定义类
1 2 3 4 5 6 7 8 @Configuration public class MyRegistConfig { @Bean public ServletRegistrationBean myServlet () { MyServlet myServlet = new MyServlet (); return new ServletRegistrationBean (myServlet); } }
定制Servlet容器
数据访问
数据源的自动配置 JDBC场景
导入JDBC依赖
导入数据库驱动-因为SpringBoot也不知道我们需要使用哪个-而且也有版本仲裁
配置文件写好数据源信息
再使用JdbcTemplate进行单元测试
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-jdbc</artifactId > </dependency > spring: datasource: url: jdbc:mysql://localhost:3306/ssmbuild?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC username: root password: xxxxxxxxx driver-class-name: com.mysql.cj.jdbc.Driver
使用Druid数据库连接池
自定义方式
导入Druid的依赖
新建一个配置类
配置连接信息
连接信息的话和上面一样,写在SpringBoot的配置文件中
将配置信息导入到数据库连接池的配置信息中
配置Druid监控页面等-根据官方文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.0.29</version > </dependency > spring: datasource: url: jdbc:mysql://localhost:3306/ssmbuild?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC username: root password: xxxxxxx driver-class-name: com.mysql.cj.jdbc.Driver filters: stat,wall @Configuration public class MyDataSourceConfig { //配置连接池信息 @ConfigurationProperties("spring.datasource") @Bean public DataSource dataSource() throws SQLException { DruidDataSource druidDataSource = new DruidDataSource(); return druidDataSource ; } /** * 配置监控页 * @return */ @Bean public ServletRegistrationBean statViewServlet() { //配置监控页路径 StatViewServlet statViewServlet = new StatViewServlet(); ServletRegistrationBean<StatViewServlet > registrationBean = new ServletRegistrationBean<> (statViewServlet,"/druid/*"); //配置监控页访问账号密码 registrationBean.addInitParameter("loginUsername","admin"); registrationBean.addInitParameter("loginPassword","123456"); return registrationBean; } /** * WebStatFilter -用于采集Web-Jdbc关联监控的属性 * 拦截排除的连接,将拦截到的展示在监控平台 * @return */ @Bean public FilterRegistrationBean WebStatFilter() { WebStatFilter webStatFilter = new WebStatFilter(); FilterRegistrationBean<WebStatFilter > registrationBean = new FilterRegistrationBean<> (webStatFilter); registrationBean.setUrlPatterns(Arrays.asList("/*")); registrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); return registrationBean; } }
starter方式
引入starter-spring-boot-druid
SpringBoot配置文件中写配置
SpringBoot会为我们自动配置,不用手写AutoConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <dependency > <groupId > com.alibaba</groupId > <artifactId > druid-spring-boot-starter</artifactId > <version > 1.1.17</version > </dependency > spring: datasource: url: jdbc:mysql://localhost:3306/ssmbuild?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC username: root password: xxxxxxs driver-class-name: com.mysql.cj.jdbc.Driver druid: aop-patterns: com.Jsckot.webtest.* #监控SpringBean filters: stat,wall #sql监控和防火墙 stat-view-servlet: enabled: true #开启监控页 login-username: admin #监控账号 login-password: 123456 #监控密码 reset-enable: false #不允许重置 web-stat-filter: enabled: true #开启url拦截 url-pattern: /* #拦截的请求 exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*' #不拦截的请求 filter: stat: 对上面filters里面的进行详细配置 slow-sql-millis: 1000 log-slow-sql: true enabled: true wall: enabled: true config: delete-allow: false #不允许删表
整合MyBatis
引入mybatis-spring-boot-starter
1 2 3 4 5 <dependency > <groupId > org.mybatis.spring.boot</groupId > <artifactId > mybatis-spring-boot</artifactId > <version > 2.2.3-SNAPSHOT</version > </dependency >
配置方式
全局配置文件-自己写好,放在/resource/mybatis
SqlSessionFactory:【SpringBoot已自动配好,不用再手动进行配置bean操作】
SqlSession:【自动配置了SqlSessionTemplate,里面自动组合了SqlSession】
Mapper:只要我们写的Mybatis的接口标注了@Mapper
注解就会被自动扫描进来
超级方便,再自己写好接口和映射文件即可,可以搭配IDEA插件MyBatisX
进行使用
操作
导入mybatis的starter
编写mapper接口–(一定要标注@Mapper
注解)
编写sql映射文件并绑定mapper接口
在application.yml
中指xml全局配置文件的位置和mapper映射文件
mybatis-config.xml
全局配置文件可以不写,直接使用 mybatis-configuration
(application.yml)进行配置
1 2 3 4 mybatis: config-location: classpath:mybatis/mybatis-config.xml mapper-locations: classpath:mybatis/mapper/*.xml
注解方式
注解模式就是使用注解,不写mapper映射文件,不过只适合简单的sql语句
混合模式
混合模式就是将配置方式和注解方式 混合使用,简单的sql语句就使用注解,复杂的sql语句就使用配置方式
整合MyBatis-Plus
引入MyBatis-Plus的starter-【可以不用引入MyBatis的】
MyBatis-Plus的mapper映射文件目录,可以不写,因为有默认值 classpath:/mapper/**/*.xml
,以后我们就把mapper映射文件放到这里
写Mapper接口-将接口继承BaseMapper类
,这样的话就能满足基本的CRUD操作
MyBatis-Plus的注解也可以完成很多的步骤!!比如TableField
…学习MyBatisPlus后再来复习
1 2 3 4 5 <dependency > <groupId > com.baomidou</groupId > <artifactId > mybatis-plus-boot-starter</artifactId > <version > 3.5.1</version > </dependency >
单元测试
SpringBoot2.2.0版本开始引入JUnit5作为单元测试默认库
和以前的有很大不同
SpringBoot2.4及以上移除了JUnit4
准备工作
引入JUnit的starter依赖
使用注解@Test
,jupiter包下的
编写方法
JUnit具有Spring的功能
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > </dependency >
常见注解
@DisplayName注解
1 2 3 4 5 6 7 8 9 @DisplayName("JUnit5功能测试1") public class Junit5Test { @DisplayName("测试displayname注解") @Test void testDisplayName () { System.out.println(1 ); } }
@BeforeEach注解 这个注解是用于提示的,每个测试开始前都会提示这句话
1 2 3 4 @BeforeEach void testBeforeEach () { System.out.println("测试即将开始..." ); }
@AfterEach注解 和上面的一致
1 2 3 4 @AfterEach void testAfterEach () { System.out.println("测试已经结束..." ); }
··· 断言机制 断言是测试方法中的核心部分,用来对测试需要满足的条件进行验证
分为以下几个品类
检查业务逻辑返回的数据是否合理
所有测试运行结束以后会有一个详细的测试报告
前置条件 和断言类似,可以说是假设。
它不会停止测试,而是抛出这里的异常进行下面的
具体翻看文档
嵌套测试 翻文档
参数化测试 翻文档
指标监控