文章目录
- 1️⃣ 简介
- 一. 什么是 IoC 容器?
- 二. AOP面向切面编程
- 三. SSM整合
- 四. HttpServletRequest
- 五. HttpServletResponse
- 六. Cookie 与 Session
- 七. Cookie
- 八. Session
- 九. 转发与重定向
- 十. Spring项目转SpringBoot
- 十一. Spring生命周期
- 十二. 什么是 pom
- 十三. 为什么会返回JSON格式数据
- 十四. 跨域请求 CORS
- 2️⃣ Spring基础知识
- 一. 注解开发说明
- 二. 配置 Bean
- 三. 配置第三方 Bean
- 四. 单例与多实例
- 五. @Autowired说明
- 六. Bean的生命周期
- 七. 条件装配:Bean加载控制
- 八. 为Bean内的变量赋值
- 九. Spring事务管理
- 十. JdbcTemplate解释
- 十一. P命名空间
- 十二. 关闭ApplicationContext
- 十三. 完全注解开发
- 十四. 获取 Bean
- 十五. 导入其他配置项
- 十六. Bean的分类
- 3️⃣ Spring MVC基础知识
- 一. MVC简介
- 二. 衍生的 Bean注解
- 三. 路径叠加
- 四. RESTful风格
- 五. @RequestMapping详解
- 六. 路径 ant风格
- 七. 非 RESTful风格说明
- 八. 域共享对象
- 九. ModelAndView
- 十. 请求响应扩展
- 十一. MVC工作流程
- 十二. 文件下载
- 十三. 文件上传
- 十四. 拦截、过滤、分发器总结
- 十五. @RequestParam、@PathVariable区别
- 十六. 视图解析器
- 十七. SpringMVC执行流程
- 十八. Thymeleaf说明
- 4️⃣ SpringBoot小知识点
- 5️⃣ SpringBoot基础知识
- 一. 初始项目结构
- 二. delete、put请求说明
- 三. jar包与 war包的区别
- 四. start 与 parent的区别
- 五. @SpringBootApplication说明
- 六. #{ }与 ${ }说明
- 七. @ControllerAdvice说明
- 八. 临时配置说明
- 九. yml格式说明
- 十. 松散绑定说明
- 6️⃣ SpringBoot常用操作
- 一. 页面跳转
- 二. 注解方式获取请求头
- 三. 注解方式获取Cookie
- 四. 编码格式修改
- 五. 发送邮件
- 六. Scheduled定时任务
- 七. Cron格式编写指南
- 八. SpringBootAdmin监控
- 九. 消息中间件
- 十. 自定义错误页
- 十一. Slf4j日志使用
- 十二. 静态资源访问
- 十三. 路径映射
- 十四. 服务器日志
- 十五. 多环境开发 Profile
- 十六. 优先执行的代码
- 十七. 异常处理器
- 十八. 配置日志等级
- 十九. 兼容xml配置文件
- 二十. 读取标准 yml配置
- 二十一. 读取第三方 yml配置
- 二十二. 拦截器
- 二十三. 页面跳转
- 7️⃣ SpringBoot常用技巧
- 一. 获取UUID的正确姿势
- 二. 全路径名
- 三. 页面重定向
- 四. 表格的画法
- 五. yml中相互引用
- 六. 随时获取 ApplicationContext
- 七. 网站图标 favicon
- 八. 跳过测试模块
- 九. 排除自动配置
- 十. 查看 pom组件版本
- 十一. 正确的项目创建流程
- 十二. 离线创建SpringBoot程序
- 十三. 快速制作程序模板
- 十四. Tomcat替换成Jetty
- 十五. 修改Banner
- 十六. 测试中开启服务器配置
- 十七. 测试中开启事务
- 十八. 测试中的临时属性
- 十九. @JsonIgnore
- 二十. 项目打包构建
- 二十一. IDEA隐藏文件
- 二十二. jdk8单位类
- 8️⃣ SpringBoot不常用操作
- 1. 修改配置文件名
- 2. maven控制yml环境
- 3. JDBC使用
- 4. 热部署
- 5. 开启 Bean校验
- 6. 代码中编写测试
- 7. 测试用例中设置随机数据
- 9️⃣ 整合第三方
- 一. 整合Mybatis
- 二. 整合MybatisPlus
- 三. 整合Druid
- 🔟 Spring Security
- 一. 简介
- 二. 使用步骤
- 三. 自定义登录页面与返回值
- 四. 注销登录
- 五. 加盐 Salt
- 六. 使用注解进行配置
- 七. 持久层存储:数据库
- 八. 令牌技术:token
- 九. WebSocket
- 十. Swagger2
1️⃣ 简介
一. 什么是 IoC 容器?
-
简介
Inversion of Control 控制反转,
又称为依赖注入 DI ——Dependency Injection。
-
解决痛点
大型程序之间的高耦合性与冗余性,共享组件、统一销毁。
-
底层原理
XML解析、工厂模式、反射。
IOC容器底层就是对象工厂。
-
意义
传统的应用程序中,控制权在程序本身,程序的控制流程完全由开发者控制。在IoC模式下,控制权发生了反转,即从应用程序转移到了IoC容器,所有组件不再由应用程序自己创建和配置,而是由IoC容器负责,这样,应用程序只需要直接使用已经创建好并且配置好的组件。为了能让组件在IoC容器中被“装配”出来,需要某种“注入”机制,其将组件的创建+配置与组件的使用相分离,并且,由IoC容器负责管理组件的生命周期。
总结:Ioc意味着将你设计好的对象交给容器控制,而不是按照传统在对象内部直接控制
-
小点:
- 在 Spring IoC程序中,我们把所有的组件统称为 Java Bean。
- Spring容器是通过读取XML文件后使用反射完成的,其实所有的配置文件差不多都是这样,Java的反射机制。
- Spring容器就是 ApplicationContext,它是一个接口,有很多实现类,这里我们选择 ClassPathXmlApplicationContext,表示它会自动从classpath中查找指定的XML配置文件。
- Spring还提供了另外一种IoC容器:懒加载对象 BeanFactory。使用方法和 ApplicationContext一样,但是懒加载主要是第一次获取时才会加载指定的 Bean对象,而 ApplicationContext则会在创建时一次性加载所有的 Bean对象。
// 从 ApplicationContext里面获取 Bean UserMapper mapper=context.gerBean(UserMapper.class);
二. AOP面向切面编程
-
简介:
SpringBoot支持面向切面编程,其可以在不改动原代码的动态添加代码、动态删去代码。这在日志记录、安全检查和事务等方面很有用。AOP技术本质上就是一个动态代理,让我们可以把一些常用功能如权限检查、日志、事务从业务方法中剥离出来。
-
题外话:
Spring的 AOP实现基于 JVM的动态代理,所以我们有时候也会这样子形容——AOP代理、AOP代理对象,意即AOP代理了本来的类对象。
-
在 Java平台上对于AOP的织入,一共有三种方式:
- 编译器:由编译器把切面编译进字节码,使用aspect关键字。
- 类加载器:利用一个特殊的类加载器,在目标类被装载到JVM时,对目标类的字节码文件进行重新加强。
- 运行期:目标对象和切面都是普通的Java类,通过JVM的动态代理对象功能或者第三方库实现运行期间动态织入。(最简单的方式)
-
原理解释:
Spring对接口类型使用JDK动态代理,对普通类使用CGLIB创建子类,在之后使用的也是它的子类,但对于用户来说是无感的。如果一个Bean的class是final,Spring将无法为其创建子类。
// 原类为 UserTest,打印出来可以看到被 Spring enhance // 并非原类,为其子类。 class com.thinkstu.test.UserTest$$EnhancerBySpringCGLIB$$217a2220
-
AOP:Aspect-Orinented Programing 面向切面编程。
-
OOP:Object-Oriented Programming面向对象编程,封装、继承、多态。
-
常用术语:
-
AOP的使用:
- 导包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
-
切入:新定义类,并 @Aspect总开关注解,切入点注解。
-
@Around:环绕通知是所有通知里功能最为强大的注解,可以实现前直通知、后直通知、异常通知以及返回通知的功能。
-
@Pointcut解释:
@Pointcut("execution(* com.thinkstu.controller.*.*(..))")
-
@Aspect //表示AOP @Component public class UsersAspect { @Pointcut("execution(* com.thinkstu.controller.*.*(..))") public void cut() { } @Before(value = "cut()") public void before(JoinPoint joinPoint) { // 返回方法名 String name = joinPoint.getSignature().getName(); System.out.println("before开始执行----" + name); } @After(value = "cut()") public void after(JoinPoint joinPoint) { System.out.println("after开始执行----"); } @AfterReturning(value = "cut()", returning = "result") public void getResult(JoinPoint joinPoint, Object result) { // 方法返回值 System.out.println("after开始执行----" + result); } @AfterThrowing(value = "cut()", throwing = "ex") public void afterThrowing(Exception ex) { System.out.println("发生异常------afterThrowing" + ex); } @Around(value = "cut()") public void around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("around优先执行的语句----------"); pjp.proceed(); System.out.println("around中方法已执行----------"); } }
三. SSM整合
SSM整合指 Spring、SpringMVC、Mybatis的整合。
四. HttpServletRequest
-
说明
原生接口。当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中。
通过 HttpServletRequest我们可以获得很多信息。
-
部分功能
-
headers:必须获得全部的 key,而后才能遍历出所有的 value。
-
getRemoteAddr:返回发出请求的客户机的IP地址。
-
getParameter(“username”):获取请求参数
-
-
提示:
获取全部请求信息应该使用 RequestEntity,而不是HttpServletRequest。
单纯简单获取请求体应该使用 @RequestHeader注解,而不是HttpServletRequest。
主要感觉 HttpServletRequest有点难用。
五. HttpServletResponse
原生方式控制返回,但是一般不这样。
- 两种响应方式
六. Cookie 与 Session
-
Cookie与 Session的区别:Session比Cookie安全
Cookie是客户端技术,存储在客户端。Session是服务器端技术,存储在服务端。
-
使用原因
HTTP 是无状态协议,它不能以状态来区分和管理请求和响应,也就是说服务器单从网络连接上无从知道客户身份。于是我们可以给客户端颁发通行证,如此服务端便能识别客户的身份,这就是 Cookie的工作原理。
七. Cookie
- 概念
Cookie是服务器存储在本地机器上的一小段文本。是客户端保存用户信息的一种机制,用来记录用户的一些信息,并随着每次请求发送到服务器。
Cookie会根据响应报文里的一个叫做Set-Cookie的首部字段信息,通知客户端保存Cookie。当下次客户端再向服务端发起请求时,客户端会自动在请求报文中加入Cookie值之后发送出去。然后服务器端会根据记录,得到之前的最后状态信息。
- set-cookie字段解释
- logcookie = 3qjj:设置 Cookie的 key、value值。
- Expires:设置 cookie有效期,当省略 expires属性时,Cookie在本次浏览器窗口关闭后失效。如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。
- Max-age:如果你创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie:存储在浏览器的内存中,用户退出浏览器之后被删除。如果 你希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该 cookie。
- path:限制指定Cookie 的发送范围的文件目录,不过另有办法可避开这项限制。
- domain:domain属性指定一级域名。比如,指定 domain是 thinkstu.com,那么只有从一级域名是 thinkstu.com网址发送过来的请求才有效。
- secure:设置只有在HTTPS安全连接时,才可以发送Cookie。
- HttpOnly:使 JavaScript 脚本无法获得 Cookie。通过上述设置,通常从 Web 页面内还可以对Cookie 进行读取操作,但使用 JavaScript 的 document.cookie无法读取附加 HttpOnly 属性后的Cookie 的内容。
-
Max-age与 Expires的区别
Expires和max-age都可以用来指定文档的过期时间,但是二者有一些细微差别。
Expires表示绝对时间,HTTP 1.0开始使用。Max-age表示相对时间,HTTP 1.1开始使用。
-
限制情况
单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能超过3K。
八. Session
-
思想
当用户第一次访问网站时,网站会为用户生成唯一的 Session ID值,而后 Session会自动跟随响应报文 set-Cookie返回给客户端,所以可以说 Session的设置在一定程度上依赖于 Cookie。可以把Session ID 想象成一种用以区分不同用户的唯一Id。
-
强依赖 Cookie与弱依赖
当我们完全禁掉浏览器的cookie的时候,服务端的session可能不能正常使用。这取决于当前环境中 Session对 Cookie的依赖程度,通过规避写法可以避免强依赖。比如当禁用 Cookie时,PHP会自动把Session ID附着在URL中,继续正常使用。
九. 转发与重定向
- 转发:forward,客户端只发送了一次请求,该请求沿着“转发链”执行,所以可以通过request来共享数据。
- 重定向:redirect,客户端发送了两次请求,相当于客户端自己重新发送了一次请求,这是两次不一样的请求,不能通过request共享数据。
十. Spring项目转SpringBoot
- 思想:SpringBoot是为了简化 Spring项目而生的,其两者在很大程度上兼容。
- 大致步骤
- 直接拷贝业务代码、pom包(这里删去Spring的依赖)
- 按 XML编写配置类 或者直接导入配置类:@Import、@ImportSource
十一. Spring生命周期
这是一个大工程。
在 Spring中,由于其生命周期过于复杂,所以 Spring没有按惯例为所有阶段单独定义方法。
其使用事件监听器,我们只需要监听被干预的阶段即可(继承接口实现)。
优点表现:统一了管理事件流程,并用泛型区分阶段。
- 简单实现
-
生命周期示意图
CSDN链接
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3QSKrg0v-1651739102961)(https://tva1.sinaimg.cn/large/e6c9d24egy1h1m6y2cq40j20u00ufq76.jpg)]
十二. 什么是 pom
- POM:Project Object Model,项目对象模型
- 简介:**pom既是一个XML文件,也是 Maven 工程的基本工作单元。**其包含了项目的基本信息,用于描述项目如何构建、声明项目依赖等。在运行项目时,Maven会在当前目录中查找并读取 POM,然后获取所需的配置信息、执行目标。
- POM 中可以指定以下配置:
- 项目依赖
- 插件
- 执行目标
- 项目构建 profile
- 项目版本
- 项目开发者列表
- 相关邮件列表信息
- **注意:**所有 POM 文件都需要 project 元素和三个必需字段 groupId、artifactId、version。
<project xmlns = "http://maven.apache.org/POM/4.0.0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.companyname.project-group</groupId>
<artifactId>project</artifactId>
<version>1.0</version>
</project>
-
pom包细究:
总体结构(四部分),此为阿里云下载的 SpringBoot程序结构,官方与此稍有不同。
-
项目的总体信息
-
maven依赖库
-
maven依赖库设置
-
构建插件
十三. 为什么会返回JSON格式数据
- 原因:
- 使用了 @ResponseBody注解
- 导入了 Jackson JSON数据格式解析器
- 使用其他 JSON数据格式解析器:如:GSON、fastJSON
- 排除 Jackson依赖并导入其他依赖
- 配置新环境
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--导入新依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.80</version>
</dependency>
(Spring官方对 fastJSON的支持度很低,自行配置编码格式等内容)
@Configuration
class MyFastJsonConfig {
@Bean
FastJsonHttpMessageConverter fastJsonHttpMessageConverter(){
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setCharset(Charset.forName("UTF-8"));
config.setDateFormat("yyyy-MM-dd");
config.setSerializerFeatures(
SerializerFeature.WriteClassName,
SerializerFeature.WriteMapNullValue,
SerializerFeature.PrettyFormat,
SerializerFeature.WriteNullListAsEmpty,
SerializerFeature.WriteNullStringAsEmpty
);
converter.setFastJsonConfig(config);
return converter;
}
}
server:
port: 80
servlet:
encoding:
force-response: true
十四. 跨域请求 CORS
-
简介:
CORS,Cross-Origin Resource Sharing,是由 W3C制定的一种跨域资源共享技术标准,其目的是为了解决前端的跨域请求。它允许浏览器向跨源服务器,发出 XMLHttpRequest请求,从而克服了 AJAX只能同源使用的限制。
-
特征:
- 其特征是浏览器在发送请求时会携带 Origin标识,因为“ 跨域 ”。
- 服务器如果支持跨域请求,则会检查 client所携带的 Origin正确性,作出相应回应。如果 oringin指定的域名在许可范围内,服务器返回的相应数据则会多出几个头信息字段。
2️⃣ Spring基础知识
Spring全称: Spring Framework
一. 注解开发说明
Annotation:基于注解的方式 @Component。当我们给类注解时,默认 Bean的命名空间为小写开头的全类名,如 UserMapper则为 userMapper,当然我们也可以指定 Bean命名空间。
二. 配置 Bean
其实总的来说,配置 Bean的方式有很多种,在SpringBoot的学习过程中我知道起码有七种。但是在日常的使用中普遍的也就两种:@Component注解或者 @Bean注解。
-
说明
注解的方式需要事先开启包扫描 @ComponentScan注解。
-
IDEA使用技巧
当显示这个小图标表示注解已生效,点击可跳转至 @Autowired被注入的地方。
-
注意:
当 Bean被创建时,会首先默认调用其无参构造方法。
当为饿汉模式时,运行即调用;当为懒汉模式时,使用时才调用。
-
SpringBoot如何设置在创建时调用有参构造方法?
@Configuration + @Bean
三. 配置第三方 Bean
采用配置类 @Configuration + @Bean的方式。第三个类可以指在所导入的 jar包中的类,它原来不是 Bean或者我们需要去配置它,但是我们并不能直接的去改写它,因为继承太过于麻烦、而且有时 jar中的类会被定义为 final无法继承。
@Configuration
public class CustomConfig {
@Bean
RedisTemplate getRedisTemplate(){
return new RedisTemplate();
}
}
四. 单例与多实例
当我们创建 Bean时,默认会为我们创建单例 Singleton的实例:即容器初始化时创建 Bean,容器关闭前销毁 Bean。
Spring默认类型是 singleton,几乎90%以上的业务使用单实例就可以。
Singleton的优点是效率高;缺点是可能会引发单线程下的线程安全问题。
Prototype的优点是不会触发单线程安全问题;缺点是每次连接请求都会创建 bean实例,请求数越多性能越低。而且因为创建的实例导致频繁垃圾回收,GC的时长也相应增加。(garbage cycle)
多实例的创建:
- @Scope: 硬编码格式。
@Scope(value = "prototype")
@Scope(value = "singleton")
@Scope(value = "request") //一次http请求内有效
@Scope(value = "session") //一个用户会话内有效
@Scope(value = "globalSession") //全局会话内有效
五. @Autowired说明
自动注入本身属性: require = true
实现功能:在注入时忽略报错,有则加载、无则使用默认值。
// 此处并不一定会加载 222,而是该 Bean不存在时才会加载 222,注意这种写法。
@Autowired(required = false)
User user = new User(222);
属性 | 说明 |
---|---|
@Autowired | 根据属性类型自动装配 |
@Qualifier | 结合@ Autowired根据属性名称自动装配 |
@Resource | 可以根据属性类型或属性名称进行注入 |
@Value | 普通类型属性注入 |
(但是 Spring官方不推荐使用 @Resource,因为注解并非 Spring官方开发,而是属于 Javax——Java扩展包之中的内容)
简单使用:
配置同类型不同名的 Bean对象。
@Configuration
public class CustomConfig {
@Bean
@Primary // 默认 Bean
UserService get_01() {
return new UserServiceImpl();
}
@Bean("other") // 需指定名称才能导入
UserService get_02() {
return new UserServiceImpl();
}
}
利用 @Autowired + @Qualifier 进行指定Bean的注入。
@Autowired
@Qualifier("other")
UserService service;
六. Bean的生命周期
Bean也含有生命周期,利用注解(于方法上)我们可以对其进行控制,分别在其创建后、销毁前。
@PostConstruct与 @PreDestroy
@PostConstruct
void initial(){
System.out.println("创建后");
}
@PreDestroy
void destroy(){
System.out.println("销毁前");
}
七. 条件装配:Bean加载控制
即 @Conditional(OnSmtpEnvCondition.class)的形式。
使用条件注解,使我们能够更加灵活的装载 Bean。
- 简介:
- @Conditional注解可以放在方法和类上。
- 放在方法上和 @Bean一起使用,表示如果 @Conditional注解的参数类 matches方法为true这创建这个 Bean实例,否则不创建。
- 放在类上结合 @Configuration、@ComponentScan判断被注解的类是否需要创建
- 可以同时拥有多个 @Conditional,变式多样。
- 简单使用
// 如果Spring中不存在 UsersController Bean,就加载配置
@Configuration
@ConditionalOnMissingBean(Cat.class)
public class Test {
@Bean
public Dog getMsg(){
return new Dog();
}
}
@ConditionalOnBean(name = "com.test.controller.UsersController")
@Component("jerry")
public class Cat {
}
( 比如 @ConditionalOnMissingClass(com.pojo.yyoo) ,当不存在此类时,条件为真。)
八. 为Bean内的变量赋值
Spring在注入一对象时,对象里的变量是如何被赋值的呢?
Spring会调用这些变量的 set___ ( ) 方法从而为这些变量赋值,我们可以控制此流程。
九. Spring事务管理
- 四大特性:原子性、隔离性、一致性、持久性。
- 底层原理:AOP面向切面编程
- 未完待续。
十. JdbcTemplate解释
- JDBC是Java操作数据库的一套规范。
- JdbcTemplate:**JDBC的模板 **,Spring封装的 JDBC对象。
- MyBatis是一个基于 Java的、封装了 JDBC的持久层框架。
十一. P命名空间
即存在于 XML配置文件中的扩展写法(了解即可)。
实现步骤:
-
复制标准格式,改成名称 P。
-
直接使用
十二. 关闭ApplicationContext
利用ApplicationContext获取的对象,最后需要手动的去关闭它。
两种方法:
- try-catch语句
- 强转 + close( ):原生的ApplicationContext中无close方法,所以这里需要强转再 close。
十三. 完全注解开发
- 要求:创建配置类Configuration,代替XML配置文件
- 举个不太恰当的例子
十四. 获取 Bean
Spring中拥有两种方式(并非方法)。
-
按 ID名字获取
在SpringBoot中,根据 @Autowired + @Qulifier 获取
-
按类型获取
app.getBean("ByID");
app.getBean(___.class);
十五. 导入其他配置项
两种注解。
- @Import:导入其他配置类。
@Import(ConfigUser.class)
- @ImportResource:导入 XML文件。
十六. Bean的分类
JavaBean分为两类:
- 一类称为实体类 Bean:专门存储业务数据的,如 Student、User 等
- 一类称为业务类 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。
3️⃣ Spring MVC基础知识
一. MVC简介
- 全称:Model View Controller
- 说明:MVC是模型(model) - 视图(view) - 控制器(controller)的缩写,其是一种软件设计规范,是一种业务逻辑、数据、界面显示,三者相互分离的方法。
- 优点:数据层、逻辑层、界面层相互分离,其中逻辑层来负责整体的调用,降低了程序整体的耦合性,从而可以三个人同时开发互不冲突。同时由于拥有清晰的结构性,也便于后期的维护。
二. 衍生的 Bean注解
这些衍生出来的注解都是同一种东西的不同表现形式,作用完全一样、只是为了给程序员作区分使用。
注解@ | 标识为 |
---|---|
Component | 一般组件 |
Controller | 控制器 |
Service | 事件处理器 |
Repository | 持久层处理器 |
三. 路径叠加
- 其实说的是 @RequestMapping叠加的情况,此时路径也会直接进行叠加。
- @RequestMapping是 SpringMVC提供的注解,其包括 @GetMapping、@PostMapping等。
- 以下访问路径实为:/role/get
四. RESTful风格
-
全称:Representational State Transfer,表现形态转换。
-
分类(Spring共支持8种)
GET(查询)、POST(新增、保存)、PUT(修改)、DELETE(删除)
-
说明:
- 当使用 RESTful风格时,就无路径参数符号 ? 拼接参数。
- 当然,RESTful风格只是一种规范,流行于前后端分离开发。
-
路径占位符
@GetMapping("/{name}/{pass}")
void login(@PathVariable("name") String name){
System.out.println("login");
}
- 功能清单范例
功能 | URL 地址 | 请求方式 |
---|---|---|
访问首页 | / | GET |
查询全部数据 | /employee | GET |
删除 | /employee/2 | DELETE |
跳转到添加数据页面 | /toAdd | GET |
执行保存 | /employee | POST |
跳转到更新数据页面 | /employee/2 | GET |
执行更新 | /employee | PUT |
五. @RequestMapping详解
该注解属性有六种,分别为 value、method、produces、consumes、header、params。
其中注意 headers作用的是请求头,而 params作用的则是请求参数。
-
value
指定请求的实际地址。
-
method
指定请求的method类型, GET、POST、PUT、DELETE等。
-
produces
指定返回内容的类型,只有当 request请求头中 Accept属性包含该 produces指定的类型才能返回数据成功,例如:accept:text/xml。
-
cousumes
指定request请求提交的内容类型(Content-Type),例如application/json, text/html等。
-
headers
指定request请求中必须包含某些指定的请求头header的值,才能让该方法处理请求。
例如:Host=127.0.0.1
“header”:要求请求映射所匹配的请求必须携带header请求头信息
“!header”:要求请求映射所匹配的请求必须不能携带header请求头信息
“header=value”:要求请求映射所匹配的请求必须携带header请求头信息且header=value
“header!=value”:要求请求映射所匹配的请求必须携带header请求头信息且header!=value
-
params
指定request请求地址中必须包含某些参数值,方法才处理,否则拒绝处理。
----params = “key1”==:表示请求必须包含名为key1的请求参数;
----params = “!key1”:表示请求不能包含名为key1的请求参数;
----params = “key1 != value1”:表示请求必须包含名为key1的请求参数,但是其值不能是value1;
----params = {“key1 = value1”, “key2”}:==表示请求必须包含名为key1和key2两个请求参数,且key1的值必须为value1;
params = {"username","password!=123456"}
六. 路径 ant风格
SpringMVC支持 ant风格的路径,即支持 ant风格的通配符,三种。
符号 | 表意 |
---|---|
? | 单个字符 |
* | 0个或多个字符 |
** | 一层或者多层目录 |
七. 非 RESTful风格说明
本节将展示当我们不采用 RESTful风格时的情况。
-
一般使用(参数同名时)
形参参数名应与浏览器传过来的参数名一样,并不使用 @PathVariable路径参数注解。
在该例中,浏览器会跳转至 /static/uuu.html页面(MVC自动解析跳转)。
-
可变长参数
最后环节,使用数组接收可变长参数。
-
@RequestParam参数
当形参参数名与浏览器传过来的参数不一致时,使用注解来指定。
required:是否必须
name:名字
defaultValue:当不存在时,则使用默认值。(结合 required = false 使用)
八. 域共享对象
-
实例:在 url的跳转中实现数据的共享。
-
要求:既要实现完整功能,又要范围最小。
-
5种方式
- 原生 Servlet:request.setAttribute( key , value ) + EL表达式。
- ModelAndView
- ModelMap
- HttpSession对象
- Application对象
九. ModelAndView
-
说明
ModelAndView 统一实现了 Model对象和 View对象的功能。
Model 主要用于向请求域共享数据,其本身是 Map的子类,拥有相应功能。
View 主要用于设置视图实现页面跳转。
-
注意
当未配置其他解析器或者为使用 @ResponseBody注解时,默认使用的是SpringMVC解析器,而SpringMVC解析器会返回 ModelAndView对象。
-
实现原理
当控制器处理完请求后,通常控制器会将包含视图名称以及一些模型属性的 ModelAndView对象返回给 DispatcherServlet。因此,在控制器中会构造一个
ModelAndView
对象 -
数据共享:直接使用方法。
addObject(String attributeName, Object attributeValue)
- 页面跳转
@GetMapping
ModelAndView get() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("uuu.html");
return modelAndView;
}
十. 请求响应扩展
-
简介
正式名称:HttpMessageConverter 报文信息转换器。
将请求报文转换为Java对象,或将Java对象转换为响应报文。
四种类型:
-
@RequestBody
该注解加在Controller 的处理方法的形参上,作用是将json格式的数据转为java对象。
作用于 Post请求,获取请求体。
@RequestBody String requestBody @RequestBody User user_date
-
RequestEntity对象
获取的是整个请求头+请求体,getBody( ) 获取请求体,getHeaders( )获取请求头。
**需要理解的是,HttpServletRequest是 Servlet技术,而 RequestEntity是 SpringMVC技术。**使用 RequestEntity而不使用 HttpServletRequest。
用法:只要控制器方法的形参中设置该类型,其就会自动赋值。
public String test(RequestEntity reqEntity){ // }
-
@ResponseBody
该注解使用在Controller 方法上的 。将方法的返回值通过适当的转换器(如 Jackson)转换为指定的格式之后,写入到 response 对象的 body 区,通常用来给客户端返回 JSON 数据或者是 XML 数据。
当方法上面没有写 ResponseBody 时,底层会将方法的返回值封装为 ModelAndView 对象(原此);需要注意的是,在使用此注解之后不会再走试图处理器,而是直接将数据写入到输入流中,他的效果等同于通过 response 对象输出指定格式的数据。
-
ResponseEntity对象
可以定义返回的 HttpStatus(状态码)和 HttpHeaders(响应头) 和响应体 body,当形参出现此时,ModelAndView失效、@ResponseBody注解也失效。
@RequestMapping("/downExcel") @ResponseBody public String downExcel(HttpServletResponse response) { // response逻辑操作 OutputStream os = response.getOutputStream(); return "" }
十一. MVC工作流程
用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器。
十二. 文件下载
- 本质:文件复制。
- SpringMVC文件下载流程:
- 先通过输入流( 例如InputStream )将文件读取到Java程序中。
- 建立 byte[ ] 数组,将输入流读取到的所有数据都存储到byte [ ] 数组。
- 向客户端响应byte[ ]数组或者类似 **ResponseEntity<byte[ ]>**的响应类型。
- 文件下载必须要设置的请求头(设置类型)
headers.add("Content-Disposition", "attachment;filename=1.jpg");
- 使用 ResponseEntity实现下载文件的功能(未跑通)
@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/static/img/1.jpg");
InputStream is = new FileInputStream(realPath);
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=1.jpg");
HttpStatus statusCode = HttpStatus.OK;
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
//关闭输入流
is.close();
return responseEntity;
}
-
实践:
以上代码我在 IDEA与服务器上并未跑通,于是我尝试了别的方法。
需要说明的是:所有资源都放在
/resource/static/
里。
- IDEA跑通,服务器跑通。
@RestController
@RequestMapping("/download")
public class DownloadController {
@GetMapping("{fileName}")
ResponseEntity down(@PathVariable("fileName") String fileName) throws Exception {
InputStream file = ClassUtils.getDefaultClassLoader()
.getResourceAsStream("static/" + fileName);
byte[] data = new byte[file.available()];
file.read(data);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition",
"attachment;filename=" + fileName);
ResponseEntity responseEntity =
new ResponseEntity<>(data, headers, HttpStatus.OK);
return responseEntity;
}}
-
IDEA跑通,服务器未跑通。
在路径两处多了感叹号
!
,暂时不明白原因是什么。
String realPath =
ResourceUtils.getURL("classpath:static/").getPath()+ fileName;
十三. 文件上传
-
本质:文件复制。
-
上传功能必需请求头:
multipart/form-data,即标明为以二进制方式上传数据,而不是key-value。
<form method="post" enctype="multipart/form-data" action="/upload">
图片:<input type="file">
<input type="submit">
</form>
- 上传操作要导入额外的依赖包 Apache Commons FileUpload
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
- 范例代码
@RequestMapping("/testUp")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
//获取上传的文件的文件名
String fileName = photo.getOriginalFilename();
//处理文件重名问题,UUID
String hzName = fileName.substring(fileName.lastIndexOf("."));
fileName = UUID.randomUUID().toString() + hzName;
//获取服务器中photo目录的路径
ServletContext servletContext = session.getServletContext();
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
if(!file.exists()){
file.mkdir();
}
String finalPath = photoPath + File.separator + fileName;
//实现上传功能
photo.transferTo(new File(finalPath));
return "success";
}
-
简单实践
该案例会将文件上传至与当前项目总文件夹 平齐的文件夹。
@RestController
@RequestMapping("/upload")
public class UploadController {
@PostMapping
String upload(MultipartFile file, HttpSession session) throws IOException {
String filename = file.getOriginalFilename();
String fileType = filename.substring(filename.lastIndexOf("."));
filename = filename.substring(0,filename.indexOf("."))+ "-"
+ UUID.randomUUID().toString()+fileType;
String realPath = ResourceUtils.getURL("images").getPath();
File io_file=new File(realPath);
if (!io_file.exists()){
io_file.mkdirs();
}
file.transferTo(new File(finalPath));
return "success";
}}
十四. 拦截、过滤、分发器总结
-
英文名称
- 拦截器 interceptor:拦截Controller,分为前后拦截器。
- 过滤器 Filter
- 分发器 DispatcherServlet
-
示意图:
十五. @RequestParam、@PathVariable区别
@RequestParam,@PathVariable 之间的区别。
@RequestParam 和 @PathVariable 注解都是用于从 request中接收请求,两个都可以接收参数。关键点不同的是 @RequestParam 是从request里面拿取值,而 @PathVariable 是从一个 URI模板里面来填充。
- 用@RequestParam:/login?name=uu&pass=123
- defaultValue 如果本次请求没有携带这个参数,或者参数为空,那么就会启用默认值
- name 绑定本次参数的名称,要跟URL上面的一样
- required 这个参数是不是必须的
- value 跟name一样的作用,是name属性的一个别名**(震惊)**
- 用@PathVariable:/login/uu/123
- name-要绑定到的路径变量的名称
- required-指示路径变量是否为必需
- value 跟name一样的作用,是name属性的一个别名
十六. 视图解析器
-
简介:
SpringMVC视图的种类很多,默认有转发视图和重定向视图。
但这必须不能存在@ResponseBody注解。
存在@ResponseBody注解时,就关乎SpringBoot下页面的跳转问题,具体使用 ModelAndView。
-
关注点:Themleaf好像已经很少使用。
-
转发视图
SpringMVC中默认的转发视图是 InternalResourceView。
当控制器方法中所设置的视图名称以"forward:"为前缀时,会创建InternalResourceView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"forward:"去掉,剩余部分作为最终路径通过转发的方式实现跳转
@RequestMapping("/testForward")
public String testForward(){
return "forward:/testHello";
}
-
重定向视图
SpringMVC中默认的重定向视图是 RedirectView。
当控制器方法中所设置的视图名称以"redirect:"为前缀时,创建RedirectView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"redirect:"去掉,剩余部分作为最终路径通过重定向的方式实现跳转
@RequestMapping("/testRedirect")
public String testRedirect(){
return "redirect:/testHello";
}
十七. SpringMVC执行流程
**前置知识:**SpringMVC常用组件
- DispatcherServlet:前端控制器,不需要工程师开发,由框架提供
作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求
- HandlerMapping:处理器映射器,不需要工程师开发,由框架提供
作用:根据请求的url、method等信息查找Handler,即控制器方法
- Handler:处理器,需要工程师开发
作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理
- HandlerAdapter:处理器适配器,不需要工程师开发,由框架提供
作用:通过HandlerAdapter对处理器(控制器方法)进行执行
- ViewResolver:视图解析器,不需要工程师开发,由框架提供
作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、RedirectView
- View:视图
作用:将模型数据通过页面展示给用户
SpringMVC的执行流程:
- 用户向服务器发送请求,请求经过Filter后被 SpringMVC 前端控制器 DispatcherServlet捕获。
-
DispatcherServlet对请求 URL进行解析,得到请求资源标识符 URI,判断请求 URI对应的映射:
不存在
-
判断是否配置了mvc:default-servlet-handler
没配置:则控制台报映射查找不到,客户端展示404错误
有配置:则访问目标资源(一般为静态资源,如:JS,CSS,HTML),找不到客户端也会展示404错误
存在(此处的 Handler为 Controller的同一对象不同说法)
-
根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以 HandlerExecutionChain执行链对象的形式返回。
-
DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapter。
-
如果成功获得 HandlerAdapter,此时将开始执行拦截器的 preHandler(…)方法【正向】
-
提取 Request中的模型数据,填充Handler入参,开始执行 Handler方法,处理请求。在填充 Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
a) HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
b) 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
c) 数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
d) 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
-
-
Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。
-
此时将开始执行拦截器的postHandle(…)方法【逆向】。
-
根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model和View,来渲染视图。
-
渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。
-
将渲染结果返回给客户端。
十八. Thymeleaf说明
-
简介:
- 在目前的企级应用开发中前后端分离是趋势,但视图层技术仍有一席之地。
- Spring Boot 官方推荐使用的模板引擎是 Thymeleaf,Spring Boot 提供了 Thymeleaf自动配置解决方案,因而Spring Boot 中使用 Thymeleaf非常方便。
- 如果开发者使用的是前后端分离技术,那么开发过程不需要整合视图层技术。
-
默认配置说明
路径:classpath/template/____,后缀 html。
-
实现步骤:
- 导pom start包
- yml配置属性
- controller中使用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
spring:
thymeleaf:
prefix: classpath:/template/
encoding: UTF-8
suffix: .html
-
实现说明:
在 cotroller中使用后,会默认返回 ModelAndView对象。
SpringMVC返回的也是 ModelAndView对象,两者同为视图解析器。
4️⃣ SpringBoot小知识点
-
**static与 template目录:**static中的资源不受保护,可以直接通过 url定位来访问,而templates中的资源是受保护的。
-
SpringBoot工程在IDEA下需要联网进行。
-
SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程。
-
SpringBoot只是简化Spring与SpringMVC的简化开发,MybatisPlus也是在简化Mybatis,本质还是SSM框架。
-
Spring Boot 不支持同时在配置中启动 HTTP HTTPS 。
-
一些专业名词
- 数据源:DruidDataSource
- 持久化技术:Mybatis、MybatisPlus
- 数据库:MySQL
-
三种内嵌的数据源
数据源默认存在的,并不一定需要 Druid。
- HikariCP(SpringBoot默认数据源)
- Tomcat的 DataSource
- Common的 DBCP
-
三种内嵌数据库(了解)
不过到真正上线的时候还是要切换到正式数据库,而且体验并不是很好,弃用。
- H2
- HSQL
- Derby
-
MyBatis是一个基于 Java的、封装了 JDBC的持久层框架,其底层使用 JDBC来编写。
-
JS等前端库可通过 pom导入。
<dependency> <groupId>org.webjars</groupId> <artifactId>vue</artifactId> <version>2.6.14</version> </dependency>
-
Controller路径命名规则:
常用复数形式表示,如 users、employees等。
-
配置文件放在哪?
在Maven的结构下,配置文件均放在resource目录里。
-
yml配置信息如何记?
只需要你记得其中几个关键字,然后在 IDEA中敲一敲就能知道个大概。
-
未知编程思想
当遇到陌生方法调用时,只需观察其形参与返回值,在大多数情况下便可了解其用法。
-
html表单说明
html中的 form表单只能发送 Get或者 Post请求,并不能发送其他请求。
-
Tomcat思想:万物皆对象。
-
JSON数据格式说明:一共只有两种格式。
- 对象:{ }
- 数组:[ ]
-
宝塔小坑
- 阿里云与宝塔均存在端口拦截机制,需要在两边都打开才能访问。
- 即使我在宝塔里部署 SpringBoot项目时设置了随机端口映射,宝塔也不会默认开启端口。
-
关于 long类型
**long类型**本身描述的时间单位为**毫秒ms**,熟记。
5️⃣ SpringBoot基础知识
一. 初始项目结构
├── HELP.md
├── README.md
├── catcat.iml
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── thinkstu
│ │ └── catcat
│ │ └── CatcatApplication.java
│ └── resources
│ ├── application.properties
│ ├── static
│ └── templates
└── test
└── java
└── com
└── thinkstu
└── catcat
└── CatcatApplicationTests.java
二. delete、put请求说明
部分浏览器只支持发送 get和 post请求,那么在 SpringBoot中该如何发送 put和 delete请求呢?
SpringMVC 提供了 HiddenHttpMethodFilter 帮助我们将 POST 请求转换为 DELETE 或 PUT 请求,SpringBoot中默认存在此配置类。
使用要求:
- 浏览器的请求方式必须为post
- 浏览器必须传输请求参数_method
满足以上条件,HiddenHttpMethodFilter 过滤器就会将当前请求的请求方式转换为请求参数_method的值,因此请求参数_method的值才是最终的请求方式。
三. jar包与 war包的区别
-
简介:
jar包和war包都可以看成压缩文件,都可以用解压软件打开,jar包和war包都是为了项目的部署和发布,通常在打包部署的时候,会在里面加上部署的相关信息。
-
简单区别:
- JAR(Java Archive,Java 归档文件),是一个完整的项目结构,以流行的 ZIP 文件格式为基础,jar包本质上就是 zip包,只是额外附加了一些固定的描述文件。
- war包不是一个完整的项目结构,需要按照传统的方式去进行部署。war包是 Sun提出的一种 web应用程序格式,与 jar类似,是很多文件的压缩包。
-
根本区别:
JAR文件的目的是把类和相关的资源封装到压缩的归档文件中,而对于WAR文件来说,一个WAR文件代表了一个Web应用程序,它可以包含 Servlet、HTML页面、Java类、图像文件,以及组成Web应用程序的其他资源,而不仅仅是类的归档文件。
四. start 与 parent的区别
- 说明:Start与 parent均在 pom文件中。
- Start指定对应包。
- parent指定具体版本。
<!-- Start示例 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!-- 对应parent -->
<jetty.version>9.4.35.v20201120</jetty.version>
五. @SpringBootApplication说明
-
简介:
位于主启动程序上,负责配置主程序。
其实是一个 SpringBoot Configuration( SpringBoot Configuration下面是 @Configuration)。
@SpringBootApplication
public class Test01Application {
public static void main(String[] args) {
SpringApplication.run(Test01Application.class, args);
}
}
六. #{ }与 ${ }说明
-
简介:
- #{ }用来获取 Bean类的变量值。
- ${ }用来获取 yml文件中的变量值。
-
范例:
加载名为users的这个Bean的cycle属性值
@Scheduled(cron = "0/#{users.cycle} * * * * ?")
@Data
@Component("users")
public class Users{
Integer cycle=10;
}
七. @ControllerAdvice说明
@ControllerAdvice :全局数据处理,是@Controller 的加强版。
@ControllerAdvice 主要用来处理全局数据,一般搭配@ExceptionHandler、@ModelAttribute 及@InitBinder 使用。而RESTControllerAdvice就是Restful风格的ControllerAdvice;
八. 临时配置说明
- 临时配置既可以在命令行中修改,也可以在代码中提前写好。
java -jar xxx.java
--server.port 8080
- 禁止临时配置
有时我们会为了安全,禁止其他人在运行我们的程序时添加临时属性。
方式:阻止main主程序中的args参数传到SpringApplication。
九. yml格式说明
- 说明:重数据、轻格式。
- 基本语法格式:
-
属性 与 属性值之间用冒号 : 分隔,属性值之前要加空格
-
大小写敏感,禁止同名,#表注释。
-
多属性值(数组)之间用**小横杆-**分隔
-
使用缩进表示层级关系,同层级左侧对齐,只允许使用空格。
-
属性值支持转义字符,但必须用双引号括起来。如:
name: "/t name /n"
-
- 简单书写实例
#表示对象,多实例(数组)用 - 符号分隔
users:
-
name: zhangsan
age: 22
city: 北京
-
name: wangwu
age: 23
city: 海南
#或者
users:
- name: zhangsan
age: 22
city: 北京
- name: wangwu
age: 23
city: 海南
#或者 (注:外层中括号表数组,里层大括号表具体对象)
users: users2: [{name: zhangsan,age: 22},{name: wangwu,age: 23}]
- yml格式中互相引用
name: duck
users: ${name}
- 特殊写法
version: @project.version@
表示获取该程序的version属性,@ @包裹、输入会有提示。
十. 松散绑定说明
-
简介:
松散绑定是 Spring为了兼容各种编程爱好者而制定的规则。
我们并不需要使用,但是要了解、知道它的存在,其有时会导致程序出现 error。
-
注意点:
- 部分支持、部分不支持,使用驼峰命名法永远没有错。
- @ConfigurationProperties支持松散绑定,@Value不支持。
-
范例:
yml中写的是 dataSource,但是在代码中以下形式都能绑定上数据。
@ConfigurationProperties(prefix = "datasource")
@ConfigurationProperties(prefix = "Data_Source")
@ConfigurationProperties(prefix = "Data-Source") // 羊肉串模式
//等等
6️⃣ SpringBoot常用操作
一. 页面跳转
在 SpringBoot条件下,利用 ModelAndView实现。
二. 注解方式获取请求头
@RequestHeader,Spring中常用方式,非原生的方式。
经过观察,其注解的参数与 @RequestParam一样。
三. 注解方式获取Cookie
@CookieValue,Spring中常用方式,非原生的方式。
@CookieValue注解一共有三个属性:value、required、defaultValue,用法同@RequestParam
四. 编码格式修改
SpringBoot默认的编码格式是 UTF-8 (写在底层源码中)。
有三种方式可以定制编码格式。
-
yml配置
直接查找 endoding就可以显现所有的内容。
server:
servlet:
encoding:
charset: UTF-8
-
Filter 过滤器配置
原理:Filter是浏览器发送的请求接触到的第一层服务器端应用。 (代码省略)
- 配置类 配置
五. 发送邮件
-
三个邮件协议
- SMTP:simple mail transfer protocol 简单邮件传输协议,发送邮件
- POP3:post office protocol -Version 3 第3代邮局协议,接受邮件
- IMAP:Internet mail access protocol 互联网消息协议,用来替代IMAP,接受邮件
POP3与IMAP的不同点:**首先要得知,**我在这里所说的采用邮件协议为,全部在第三方软件中采用。采用POP3时,邮件删除等操作不会同步,即使你在第三方邮件系统删除了某封邮件,但是在原邮件系统中并不会执行删除操作。而采用IMAP就是为了改进这一点,实现了同步的操作。
-
简单实现三步走:
- 导包:spring-boot-starter-mail。
- 配置信息(服务器host、账号、授权码等)
- 代码实现(自动注入JavaMailSender类)
-
范例:
发送简单邮件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
spring:
mail:
host: smtp.qq.com
username: you_email@qq.com
password: "Authorized code"
default-encoding: UTF-8
@Autowired
JavaMailSender sender;
@Test
void sendEmail(){
SimpleMailMessage msg = new SimpleMailMessage();
String from="Your email@qq.com";
msg.setFrom(from+"(自定义发送昵称)"); //小括号里有内容~
msg.setTo("To email@qq.com");
msg.setSubject("标题");
msg.setText("内容");
sender.send(msg);
}
**发送复杂邮件:**html格式、附件等
- 将 SimpleMailMessage替换成 MimeMessage
- 借助于 MimeMessageHelper创建邮件内容
@Autowired
JavaMailSender sender;
@org.junit.jupiter.api.Test
void sendEmail() throws MessagingException {
MimeMessage msg= sender.createMimeMessage();
MimeMessageHelper msgHelper=new MimeMessageHelper(msg,true);
msgHelper.setFrom("Your email@qq.com(哇哇哇)");
msgHelper.setTo("To email@qq.com");
msgHelper.setText("<a href='http://baidu.com'>链接</a>",true);
String file="src/main/resources/application.yml";
msgHelper.addAttachment("application.yml", new File(file));
sender.send(msg);
}
-
邮件中的SSL加密
发送邮件或者接受邮件时我们可以配置SSL加密,具体要去邮件提供商那边获取。
例如对于腾讯,SSL端口为465或者587,首先开启 SSL然后再配置端口。
六. Scheduled定时任务
- 简介:Spring注解整合的方式只适用于较简单的情况,复杂业务使用 Quartz
- 实现步骤:
- 启动类上开启
- 方法上调用
@EnableScheduling
@Component
public class Test {
@Scheduled(cron = "0/5 * * * * ?")
void print(){
System.out.println("+----+--------+");
}
}
- yml额外配置:task拥有两组配置,我们选择 sheduling。
task:
scheduling:
pool:
size: 10 #线程池数量,默认只为1。
shutdown:
await-termination: false #关闭时是否等待所有完成
await-termination-period: 10s #最大等待时间
- @Scheduled 注解可以利用 @Value形式从 yml中取值
@Scheduled(cron = "0/${a.b.c:10} * * * * ?")
七. Cron格式编写指南
-
简介:
- 逻辑反人类
- 在线验证网站:链接
-
简单编写思想
调整的时间顺序,思维应该顺着从小到大
-
编写规则
秒数:
- 范围 0~59 ,不允许为空值,若值不合法,调度器将抛出 SchedulerException异常
- ***** 表每隔1秒钟触发;
- , 表在指定的秒数触发,比如"0,15,45"代表0秒、15秒和45秒时触发任务
- - 表在指定范围内触发,比如"25-45"代表从25秒开始触发到45秒结束触发,每隔1秒触发1次
- / 表触发步进(step),**"/“前面的值代表初始值(”“等同"0”),后面的值代表偏移量。**比如"0/20"或者"/20"代表从0秒钟开始,每隔20秒钟触发1次,即0秒触发1次,20秒触发1次,40秒触发1次;"5/20"代表5秒触发1次,25秒触发1次,45秒触发1次;"10-45/20"代表在[10,45]内步进20秒命中的时间点触发,即10秒触发1次,30秒触发1次。
纯数字系列:
基于系统时间,比如 5即代表当系统时间走到某分钟05秒时触发。
每分钟0秒触发格式为 0 * * * * ? 或者 0 0/1 * * * ? 。
最后的问号代表什么:
其实最后一位代表星期几。为避免与前面冲突,故使用 ? 来表示任意。
八. SpringBootAdmin监控
-
简介:
分布式监控程序,非 SpringBoot官方开发,使用时需导入与之对应的官方版本号,否则报错。
-
注意事项:
子节点要开放什么内容全部由子节点规定,Server无权干涉。(安全性)
-
实现流程:
-
导包 admin + SpringBoot Web
-
yml配置主从客户端
配置Server,主程序上开启 @EnableAdminServer注解, yml中配置端口。
配置Client,yml中配置主服务器即可。
-
-
简单实现
配置 Server:
- 创建 SpringBoot程序时选择 ops中的 Server与 SpringBoot Web项目
- 配置 yml端口,这里我设置为80
- 主程序上配置开启Server
server: port: 80
@EnableAdminServer
配置 Client:
- 创建SpringBoot程序时选择 ops中的Server与 SpringBoot Web项目(此处勾选 web纯粹是为了能使 SpringBoot项目持续运行,实际生产中可以勾选别的,达到效果就可以)
- 配置 yml:Server地址、开放的数据内容等
server: port: 8080 spring: boot: admin: client: url: http://localhost #server路径地址 management: endpoints: web: exposure: include: "*" #开放所有,即13个端点 endpoint: health: show-details: always #展示细节,true。默认false
-
界面预览
打开 Server主页地址,可以看到许多的数据
-
info信息配置
- info端点:在 Server中展示 client业务信息的端点,比如程序名、作者,初始值为空。
# yml文件中添加以下配置 management: info: env: enabled: true #使能够info info: author: ThinkStu des: "good program" #具体信息,纯手工编写yml
- 上述配置的另一种实现方案:创建 Bean并继承 InfoContributor 后编写配置。
@Component public class AppinfoContributor implements InfoContributor { @Override public void contribute(Info.Builder builder) { builder.withDetail("msg","good"); } }
-
自定义Health健康状况
比如 client程序中存在 Redis,那么就会显示redis的健康状况。
四种状态:
up在线、down离线、unkown未知、outofservice失去服务。
我们可以利用四种状态在编码中写一些自定义程序,然后为这些程序添加 health监控。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yX3TLkw1-1651739102964)(https://tva1.sinaimg.cn/large/e6c9d24egy1h1o6xhkv8sj21xs0u0tcc.jpg)]
@Component public class HealthConfig extends AbstractHealthIndicator { @Override protected void doHealthCheck(Health.Builder builder){ boolean check=true; if (check){ builder.withDetail("runtime","xxx"); builder.status(Status.UP); }else{ builder.withDetail("error","系统运行失败"); builder.status(Status.DOWN); } } }
-
结合邮件系统:邮件信息报警系统
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MBjnpfJ6-1651739102964)(https://tva1.sinaimg.cn/large/e6c9d24egy1h1o6xhb71xj21cm0man1y.jpg)]
九. 消息中间件
- 基础概念:
- MQ:Message Queue,消息队列。
- JMS:Java Message Service;一个规范,等同于JDBC,提供了与消息服务相关的API接口
- AMQP: advanced message queue protocal,高级消息传输协议,一种协议,不一定要遵守。其解决了JMS中的数据格式不唯一的缺点,统一使用byte[ ]。
- Kafka:大数据技术,可以用作消息中间件,但是主要功能不是此。其是一种高吞吐量的分布式发布订阅消息系统,提供实时消息功能。
- JMS规范简介
-
JMS消息模型
- Peer-to-peer:P2P,点对点模型,一对一。
- publish-subscribe:发布订阅模型,消息可以被多个消费者消费,生产者与消费者完全独立,不需要告知对方自身的存在。
-
JMS消息种类
TextMessage、MapMessage、ByteMessage、StreamMessage、ObjectMessage、Message
-
实现JMS的技术
ActiveMQ、Redis、RabbitMQ、RocketMQ(没有完全实现)
- AMQP协议简介
-
优点:
具有跨平台性,服务器、供应商、生产者消费者可以使用不同的语言来实现。
-
AMQP消息模型:
direct exchange、fanout exchange、topic exchange、headers exchange、system exchange
-
AMQP消息种类:byte[ ]
-
AMQP实现:
RabbitMQ、RockerMQ、StormMQ等
-
四种消息中间件简介
ActiveMQ:Apache产品,社区已经不活跃。
RabbitMQ:使用频率较高,速度中等,数据直接写在磁盘中,不易丢失。
RocketMQ:阿里巴巴开源的消息中间件,Java语言开发,各方面也表现的比较优越,几乎同时解决了Kafka和RabbitMQ它们两个的缺点,速度介于两者之间,数据不易丢失。
Kafka:速度快,但数据写在内存中、易丢失。
-
实现暂略。
十. 自定义错误页
-
简介:
- Spring Boot 中的错误默认由 BasicErrorController 类来处理
- 如果开发者不需要向用户展示详细的错误信息,那么可以把错误信息定义成静态页面。
- 在
resources/static
中创建 error目录,然后导入错误展示页面。
-
原理:
当触发错误页面时,BasicErrorController类被调用。(其将会返回 JSON或 html格式的错误数据,具体由用户请求方式而定)
- JSON格式的 error得到解决,html格式的 error传到下一步。
- 触发 DefaultErrorViewResolver类,开始在 error目录查找 4__ 、5__格式的错误页面。
- **(还是找不到时触发)**回到 errorHtml ( )方法,使用 error 作为默认的错误页面视图名,如果名 error的视图也找不到,就会展示默认错误页面。
- 简单实现
获取错误的静态页面,置于 /resource/static/error 目录中。
-
两种形式:
xx形式 与 具体的数字形式。4xx.html、5xx.html的优先级低于具体的数字权限,如404、503等,所以它们是可以同时的存在的。
- 复杂实现(自由度很高)
@Component
public class MyException extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
Map<String ,Object> map=super.getErrorAttributes(webRequest, options);
map.remove("error");
map.put("msg","错误请求");
return map;
}
}
十一. Slf4j日志使用
-
简介:
- Lombok包中提供的注解。
- 针对类使用、打印类的日志。
- 在开发中,应该尽量使用日志而不是打印 Print。
-
简单实现:
- 注解实现
@Slf4j
@RestController
@RequestMapping("/users")
public class UsersController {
@GetMapping()
String getById(HttpServletResponse response) throws IOException {
log.error("fashion");
return "啊啊啊啊";
}
}
- 原生创建
Logger log= LoggerFactory.getLogger(UsersController.class);
- 效果:
**从左至右:**日志记录时间、级别、PID、所属线程、类对象、信息。
十二. 静态资源访问
-
简介
- 在SpringMVC 中,对于所有的静态资源都需要开发者手动配置资源过滤
- Spring Boot简化了静态资源过滤配置
- SpringBoot静态资源自动化配置类: WebMvcAuto Configuration。
-
位置说明
SpringBoot默认会过滤所有的静态资源,一共有5个位置。
开发者可以将静态资源放在这5个位置中的任意一个,优先级依次降低。
classpath:/META-INF/resource/
classpath:/resource/
classpath:/static/
classpath:/public/
/
- 冲突说明
如果将文件夹中存在同名文件,则只有第一个会生效。
十三. 路径映射
-
简介
正常情况,如果我们有静态网页会放在
/static
里,然后访问的时候需要添加 .html后缀。如果不想添加.html后缀,则需要在 Controller中加一层转发的操作。 但是我们有更简单的方法,而且节省资源。
-
效果:
访问 http://localhost/aaa
相当于 http://localhost/aaa.html
-
简单实现:
首先将文件置于
/static
下。
然后编写 @Configuration、配置 WebMvcConfigurer接口,实现跳转。
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/uuu").setViewName("/uuu.html");
registry.addViewController("/ooo").setViewName("/ooo.html");
}
}
十四. 服务器日志
-
简介:
在服务器中使用日志。
在正式业务上线后不能使用开发工具进行调试,我们需要日志系统。
-
说明:
保存到服务器上的日志数据,我们可以使用 IDEA打开(拥有格式)。
-
简单使用
logging:
file:
max-history: 10
max-size: 10MB
name: server.log
pattern:
rolling-file-name: server.%d{yyyy-MM-dd}.%i.log
十五. 多环境开发 Profile
-
简介:
SpringBoot约定在不同环境下配置文件的名称规则为
- application-{profile} .properties
- application-{profile}.yml
profile占位符表示当前环境的名称。
-
作用:
解决在多环境开发下配置文件混乱的问题。
-
版本限制说明:
- SpringBoot 2.4之前是 include
- SpringBoot 2.4之后是 group
- 阿里云现在的是2.3.7版本
-
简单实现
- 在主 yml配置文件以外,编写多份 yml文件
- application-dev
- application-devDB
- application-MVC
- 在主 yml配置文件中选择性的引入其他配置文件。
十六. 优先执行的代码
-
简介:
有一些特殊任务需要在系统启动时执行(例如配置文件加载、数据库初始化等),SpringBoot对此提供了两种基本一样的方案:CommandLineRunner类、ApplicationRunner类。
-
两种简单实现:
CommandLineRunner:Spring Boot 项目在启动时会遍历所有 CommandLineRunner的实现类,并调用其中的 run 方法,如果整个系统中有多个 CommandLineRunner 的实现类,那么可以使用 @Order注解对这些实现类的调用顺序进行排序。Order值越小越优先执行,可为负数,负数最小。
@Component
@Order(-100)
public class StartPrint implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("优先启动~");
}
}
ApplicationRunner:几乎同上。两者 Order通用,计算执行顺序的时候需要同时参考两者。
@Component
@Order(-1000)
public class Start03 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("33333");
}
}
十七. 异常处理器
-
简介:
异常,指的是当正常访问时服务器时发生的异常,并非指 404之类的异常。
-
简单实现
( utils包下的异常处理类)
// 拦截所有异常
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(Exception.class)
R allException(Exception ex) {
ex.printStackTrace();
return new R("服务器发生未知故障,请稍后重试...");
}
}
十八. 配置日志等级
-
简介:
在 yml中配置当前日志的打印等级,一共有两种形式。
- 按包名划分
- 按分组划分
-
简单实现:
按包名划分
logging:
level:
root: error # root是根路径 / 的正式写法
com.test.controller: info
分组划分,先分组再划定等级。
logging:
group:
ebank_name: com.test.controller,com.test.mapper
level:
root: error
ebank: info
十九. 兼容xml配置文件
-
简介:
有时候我们需要改写一些比较老的程序,或者作 xml文件配置。
虽然 SpringBoot不推荐使用 xml进行配置,但是如果开发者需要使用 xml配置,那么只需在 resources目录下提供配置文件、然后在主程序上导入即可。
-
说明:
- @ImportResource:导入 XML配置文件。
- @Import:导入其他配置类。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yWRboVy5-1651739102965)(https://tva1.sinaimg.cn/large/e6c9d24egy1h1sq40ejyaj214a0aoabn.jpg)]
二十. 读取标准 yml配置
-
简介:
yml 中编写了众多属性,那么该入伙获取呢?
-
获取方式分类:
- 单个读取
- 全部读取
- 选择读取
-
单个读取:@Value注解
@Value("${users[0].name}")
String name;
@Value("${a.b.c:10}") // 读取不到则加载默认值
String num;
- 全部读取:利用被 Spring封装的 Enviroment对象,该对象中包含了所有的 yml文件属性。
@Autowired
Environment env;
@Test
void contextLoads() {
env.getProperty("users[0].name");
}
-
选择读取:既可以为 Spring原生 Bean注入属性,也可以为第三方 Bean注入属性。
实现步骤:
-
yml存在数据
-
创建属性获取 Bean( @Component + @Data + @ConfigurationProperties 注解)。
在这一步 Spring可能会提示缺少相应包,按提示导入即可。
-
注入该 Bean并使用
-
@Data
@Component
@ConfigurationProperties("users2")
public class UsersConfiguration {
String name;
String age;
}
// 使用
@Autowired
UsersConfiguration userConfig;
二十一. 读取第三方 yml配置
-
简介:
我怀疑此种方式存在Bug,单级可以识别,一旦遇到多级就不能识别我的文件。还应该注意的是,方法不止这一种,但这种比较直接。
-
简单实现:
@PropertySource属性引入第三方文件(得加上类全路径名)
-
@Data
@Configuration
@PropertySource(value = "classpath:users.yml")
public class CustomConfig {
@Value("${users}")
Object name;
}
二十二. 拦截器
所有的拦截器都必须实现 HandlerInterceptor接口。
**拦截器( Interceptor)**同 Filter 过滤器一样,都是面向切面编程 AOP 的具体实现。
-
必须实现的三个方法。
- preHandle:控制器方法执行之前执行 preHandle(),其 boolean类型的返回值表示是否拦截或放行,返回 true为放行,即调用控制器方法;返回 false表示拦截,即不调用控制器方法。当它返回 false 时,表示请求结束,
- postHandle: 方法在当前请求处理完成之后,也就是 Controller 方法调用之后执行。但是它会在 DispatcherServlet 进行视图返回渲染之前被调用,我们可以在这个方法中对 Controller 处理之后的 ModelAndView 对象进行操作。
- afterComplation:该方法在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行,主要用来进行资源清理。
- 执行顺序:preHandle ----> Controller ----> postHandle ----> afterComplation
-
多个拦截器的执行顺序
- 拦截器的执行顺序为链条。
- ==注意:==当某个拦截器方法返回值为 false时,后续的 Interceptor和 Controller都不会再执行,所以一般需要手写为 true。
-
实现步骤:
- 继承自 HandlerInterceptor,重写方法
- @Configuration中 注册拦截器:将拦截器 Bean交由 SpringMVC拦截器类 WebMvcConfigurer管理。
在这一步才能配置拦截的路径,还可以配置排除的路径 excludePathPatterns。
二十三. 页面跳转
原理:利用 ModelAndView对象。
@GetMapping
ModelAndView get() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/uuu.html");
return modelAndView;
}
7️⃣ SpringBoot常用技巧
一. 获取UUID的正确姿势
二. 全路径名
在 xml或者 yml文件中进行配置时,可以使用全路径名缩写形式:classpath:
classpath:UserMapper.class
# 相当于全路径+UserMapper.class
三. 页面重定向
简单的页面重定向,页面跳转与重定向并不一样。
@GetMapping()
String getById(HttpServletResponse response) throws IOException {
response.sendRedirect("/cancel.html");
return null;
}
四. 表格的画法
我是实在想不到,竟然还会有表格画法这种教程。
节点用+号码表示,线条用-号表示,空格表示表中的待填项。
System.out.println("+----+--------+");
System.out.println("+ | |");
System.out.println("+ | |");
System.out.println("+----+--------+");
五. yml中相互引用
dollar + 大括号
username: kk
your_name: ${username}
六. 随时获取 ApplicationContext
-
为什么能够实现?
理解 SpringBoot底层工作源码,采取官方接口 ___Aware。
-
简单实现:
只要继承 ApplicationContextAware并实现 set方法即可。
public class Demo01 implements ApplicationContextAware { ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext=applicationContext; } }
七. 网站图标 favicon
-
简介
favicon,网站图标。
虽然在 html代码中也可以添加,不过在此添加较为方便。
-
简单实现
- 将普通图片转为 ico图标文件,链接
- 重命名为 favicon.ico ,置于
/resource/static/
下。
八. 跳过测试模块
-
问题简介:
SpringBoot程序在打包的时候会默认先执行测试类 Test里面的方法。
这是因为存在 Maven生命周期,后执行的必须先执行前面的所有内容。
解决:maven设置跳过测试
九. 排除自动配置
-
简介:
手动排除 SpringBoot的自动配置。
-
两种实现方法:
- 主程序上配置
- yml中配置
十. 查看 pom组件版本
-
简介:
查看在 pom文件中导入的具体软件版本(全部)。
可以分为两种,Spring官方 与 阿里云镜像 所创建的 SpringBoot程序并不一样。
-
Spring官方
两层点击:spring-boot-starter-parent — spring-boot-dependencies
-
阿里云
在 dependencyManagement下的与中,点击查看。
十一. 正确的项目创建流程
-
简介:
有利于项目与项目之间的解耦合,促进开发。
-
操作流程:
- 创建空项目工程
- 在空的项目工程中 添加 所需要的其他组件 module。
十二. 离线创建SpringBoot程序
-
简介:
在没有网络的计算机上创建 SpringBoot程序,过程离线。
但事先需要在官网上把相应文件创建并下载。
-
步骤:
- 官网创建、下载
- 将项目导入离线设备
十三. 快速制作程序模板
-
简介:
制作模板程序,可以在学习的过程中大量复制某份程序。
制作模板步骤:
-
选择模板
-
删除项目结构的无用文件
-
删除pom文件两行、改一行(结束)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bh5Q4N9S-1651739102967)(https://tva1.sinaimg.cn/large/e6c9d24egy1h1p9wf9t2xj2144092q53.jpg)]
使用步骤:
通常都是在项目中直接将上面的模板当成组件module导入。
- 再复制出一份模板。
- 在pom文件中把改成新组件名。
- IDEA中导入,注意此次选择的是import module而不是new module。
- 设置使用的JDK版本。(结束)
十四. Tomcat替换成Jetty
-
简介:
排除 Tomcat依赖,可以换成其他任意服务器程序。
-
步骤:
- pom中排除 Tomcat依赖
- pom中新增 Jetty依赖
<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-jetty</artifactId>
</dependency>
十五. 修改Banner
-
简介:
修改控制台打印出来的 Banner广告位。
-
两种方法:
-
纯文字:/resource 中编写 banner.txt文件,Banner在线生成网站
-
文字或者图片:yml中配置
-
#关闭banner
spring:
main:
banner-mode: off
#修改banner为指定图片
spring:
banner:
image:
location: WechatIMG96.jpeg
十六. 测试中开启服务器配置
-
简介:
我们在执行测试的时候,SpringBoot默认不开启服务器、节省资源。但是现在由于业务需求,需要对其测试,采用 WebEnvironment Web环境。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class Test03 {
@Test
void test03(){
}
}
webEnviroment参数说明:
- SpringBootTest.WebEnvironment.NONE:默认值,不启动服务器
- SpringBootTest.WebEnvironment.DEFINED_PORT:使用定义的端口
- SpringBootTest.WebEnvironment.RANDOM_PORT:使用随机的端口
- SpringBootTest.WebEnvironment.MOCK:欺骗idea
十七. 测试中开启事务
-
简介:
在测试中经常会有写入数据库操作,但我只想知道是否执行成功,不想污染数据库。
-
步骤:
- SpringBoot程序中已经导入 mysql + mybatis的包,没有则无法开启事务
- 开启 @Transational 注解
@SpringBootTest
@Transactional
public class Test04 {
@Test
void test04(){
}
}
十八. 测试中的临时属性
-
简介:
想要在测试用例中添加一些临时属性,在 @SpringBootTest 中使用参数属性注入即可。
@SpringBootTest(properties = {"a=b","server.port=99999"})
public class Test02 {
@Value("${a}")
String msg1;
@Value("${server.port}")
String msg2;
@Test
void test02( ){
System.out.println(msg1);
System.out.println(msg2);
}
}
十九. @JsonIgnore
-
简介:
使用 Jackson作为项目的序列化工具时,可以作用在属性、方法或者类上面,用来规避不想要的序列化功能。
@JsonIgnore
private String username;
二十. 项目打包构建
-
简介:
我们在 SpringBoot项目中能够打包是因为配置了 maven插件,该插件由 SpringBoot parent 中提供。但是其他公司可能不采用 SpringBoot parent 作为parent,此时就需要配置。
-
示意图:避免重复打包
二十一. IDEA隐藏文件
-
简介:
隐藏不想看见的文件,避免冗余。
set up — Edit — File Type.
-
注意事项
在 IDEA 2022.01版本中,我遭遇了隐藏文件时产生的 Bug,需注意。
二十二. jdk8单位类
-
简介:
JDK8 提供了两个单位类,用来规范单位的表达形式。
分别为:
- 时间单位:Duration
- 容量大小单位:DataSize
//使用
1. Duration duration1=Duration.of(3, ChronoUnit.HOURS);
2. Duration duration2=Duration.ofHours(3);
3. @DurationUnit(ChronoUnit.HOURS)
Duration duration3;
//DataSize同理,例如:
DataSize dataSize=DataSize.ofGigabytes(2);
8️⃣ SpringBoot不常用操作
1. 修改配置文件名
修改配置文件名,然后在程序运行时再指定配置文件名
虽然感觉这种方式比较愚蠢,但是暂时收录
2. maven控制yml环境
maven是比 Spring更底层的存在,Spring建立在 maven的基础之上。
我们可以使用 maven来控制并改变 Spring运行的时的 yml文件配置。
3. JDBC使用
优势阐述:
Mybatis之类是基于JDBC开发的,可以说 jdbc是更加底层的存在。
安全性与底层效率要较其他框架高,银行相关行业比较热衷此。
步骤:
- 导pom包
- 自动注入,直接使用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
@Autowired
JdbcTemplate jdbcTemplate;
4. 热部署
说明:
- 只能够在开发环境中使用,并不是生产环境,也就是只能在 IDEA中使用
- 部署比直接运行run速度要快,因为部署是 restart而不是 reload整个工程。
- 消耗的资源很多,不实用,谨慎开启。
开启流程:到pom包、idea设置中开启。
5. 开启 Bean校验
- 利用validation(接口)与hibernate(实现类)结合实现。
- **具体功能:**可对自定义的 Bean在运行时进行数据的校验,比如最大值 max、最小值 min、范围 range等的校验,通过了才能继续编译。
- **具体使用:**对于我,暂时还未想到。
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Alpha3</version>
</dependency>
6. 代码中编写测试
有时候我们需要在代码中编写测试用例,而不使用 postman这类工具。
- 简单测试:
get请求访问页面,先开启webEnviroment、AutoConfigureMockMVC,然后注入MOckMVC,最后执行操作
- 后续放弃。
7. 测试用例中设置随机数据
只是想在测试的时候加载一些随机数据,应该把以下内容用Profile思想来编写:即多份yml文件。
- 编写yml数据,里面是dollar大括号加上随机函数
random
testData:
name: ${random.uuid}
age: ${random.int(6,100)}
id: ${random.value} #MD5加密,32位
- 代码中配置(注入即可,之前使用过)
@Data
@Component
@ConfigurationProperties( "testdata")
public class TestDataConfig {
String name;
Integer age;
String id;
}
- 使用:直接 @Autowired 即可使用
9️⃣ 整合第三方
此章节需要日积月累。
一. 整合Mybatis
- 导包或者勾选包
- 配置 yml
- 编写 Mapper接口
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/adult?serverTimezone=UTC
username: root
password: "$Now2022"
@Mapper
public interface UsersMapper {
@Select("select * from users where id = #{id}")
List<Users> getById(Integer id);
}
@Autowired
UsersMapper mapper;
- 开启 Mybatis运行日志
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
二. 整合MybatisPlus
- 将Mybatis包换成MybatisPlus包
- Mapper接口继承BaseMapper< T >
- 修改ID自增长策略,逐渐增长而不是雪花算法增长
- 整合业务层 Iservice与 ServiceImpl
- 开启 Mybatis运行日志(非 MybatisPlus功能)
@Mapper
public interface UsersMapper extends BaseMapper<Users> {
@Select("select * from users;")
List<Users> getAll();
}
public class UsersServiceImpl extends ServiceImpl<UsersMapper,Users> implements UsersService , IService<Users> { }
mybatis-plus:
global-config:
db-config:
id-type: auto
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
三. 整合Druid
- 导 pom包
- Yml配置文件加上一行
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/adult?serverTimezone=UTC
username: root
password: "$Now2022"
🔟 Spring Security
一门登录技术, 学会不易。
一. 简介
-
Spring Security是基于内存级别的认证,不是数据库。
-
SpringBoot为 SpringSecurity提供了很好的支持。
-
导包之后,SpringSecurity为我们提供了一个默认页面登录页面(未登录时拦截了所有的请求!),默认账号为user,密码见控制台。如果对初始的账号密码不满意,可以在yml中修改。
spring: security: user: name: admin password: admin roles: ADMIN #此处是区分大小写的,需特别注意
二. 使用步骤
-
导包
-
yml简单配置
-
代码中正式配置
配置说明:
-
访问
/admin/**
需要 ADMIN角色权限 -
访问
/user/ **
需要 CAT或者 USER角色权限。 -
访问其他任意资源都要先登录。
-
默认登录页面是 /login。
-
permitAll作用于 /login ,表示和登录相关的接口都不需要认证即可访问。
-
csrf( ).disable( )表示关闭 csrf,防止服务器被 csrf攻击。
(csrf攻击:Cross Site Request Forgery,跨站请求伪造。)
-
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**")
.hasRole("ADMIN")
.antMatchers("/user/**")
.access("hasAnyRole('CAT','USER')")
.anyRequest().authenticated()
.and().formLogin()
.loginProcessingUrl("/login")
.permitAll().and().csrf().disable();
}
}
- Basic认证:添加 Basic认证能够让 Postman可访问。
.and().httpBasic()
三. 自定义登录页面与返回值
-
简介:
目前为止我们使用的还都是 Spring Security默认提供的登录页面。
在前后端分离的开发中,我们需要自定义登录页面与返回的 JSON格式数据
-
思想:
- 虽然新登录地址是
/login_new
,但是最终的数据提交地址还是/login
。 - 对于传输过程中的参数 usename与 password可以自定义而不必固定。
- 可以设置登录成功、失败返回的数据。
- 虽然新登录地址是
-
简单实现(配置):
.and()
.formLogin()
.loginPage("/login_page")
.loginProcessingUrl("/login")
.usernameParameter("name")
.passwordParameter("pass")
.successHandler((req, resp, auth) -> {
Object principal = auth.getPrincipal();
System.out.println(principal + "-------principle"); resp.setContentType("application/json;charset=utf-8");
PrintWriter writer = resp.getWriter();
Map<String, Object> map = new HashMap<>(16);
map.put("status", "200");
map.put("msg", principal);
ObjectMapper om = new ObjectMapper();
writer.write(om.writeValueAsString(map));
writer.flush();
writer.close();
})
.failureHandler((req, resp, exception) -> { resp.setContentType("application/json;charset=utf-8");
PrintWriter writer = resp.getWriter();
resp.setStatus(401);
Map<String, Object> map = new HashMap<>(16);
if (exception instanceof LockedException){
map.put("msg","账户冻结");
}else if (exception instanceof BadCredentialsException){
map.put("msg","账号密码错误,请重新输入");
}else {
map.put("msg","登录失败");
}
ObjectMapper om = new ObjectMapper();
writer.write(om.writeValueAsString(map));
writer.flush();
writer.close();
})
.permitAll()
.and()
.csrf()
.disable();
四. 注销登录
-
简介:
默认访问
/logout
即可注销。 但是在这里我遇到问题,可能是这种方式已经失效。
- 简单实现:
.and()
.logout()
.logoutUrl("/logout")
.clearAuthentication(true)
.invalidateHttpSession(true)
.addLogoutHandler((req, resp, authentication) -> {
})
.logoutSuccessHandler((req, resp, authentication) -> {
try {
resp.sendRedirect("/login_page");
} catch (IOException e) {
e.printStackTrace();
}
})
五. 加盐 Salt
-
简介:
所谓加盐就是一种加密形式,其既可以是随机数、也可以是用户名。
加盐之后原本密码相同的用户所生成的最终密码也不会相同,可以有效防止跑库破解密码。
-
传统加盐方式:需要在数据库中记录用户的盐值。
-
Spring Security加盐:
Spring Security提供了多种加盐方案。
官方推荐使用BCryptPasswordEncoder,其使用了 BCrypt 强哈希函数,开发者在使用时可以选择提供 strength 和 SecureRandom 实例 ,strengh越大,密钥的迭代次数越多,迭代次数为2的strength次方。(strength 取值在4~31 之间,默认为 10)
@Configuration public class PasswordEncoderConfig { @Bean PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(10); } }
-
简单使用:
- 写 service
- 注册时将 encrypt传到数据库(代码编写)
六. 使用注解进行配置
-
简介:
上面都是使用 Java类来进行Spring Security配置,现在采用注解的形式。
配置内容:访问路径(或者方法)需要授权。
-
使用步骤:
- 开启注解形式
- 类或者方法上面使用
七. 持久层存储:数据库
-
简介:
将 Spring Security基于内存级别的登录验证信息存储到数据库。
-
遗憾:暂时未能成功实现。
-
实现步骤:
- 创建数据库对应表:首先得创建三张数据库用户表
- 代码中实现注册与登录等相关业务
-
建表语句范例:
drop table if exists user;
drop table if exists role;
drop table if exists user_role;
create table user(
id int primary key auto_increment,
username varchar(32),
password varbinary(255),
enabled tinyint(1),
locker tinyint(1)
);
create table role(
id int,
name varchar(32),
nameZh varchar(32)
);
create table user_role(
id int(11),
uid int(11),
rid int(11)
)
八. 令牌技术:token
-
简介:
本节基于 OAuth2框架,该框架的使用与实现账号密码登录不冲突。
-
遗憾:暂时未能成功实现。
-
令牌技术说明:
令牌技术的优势在于可以只授权部分权限给第三方,从而避免了密码直接泄露的可能性。第三方拿着令牌可以访问一些基础资源,如:头像、用户名等。很多第三方也只支持 token而不支持 Cookie(如:微信小程序)。
-
交互流程(三次):
-
OAuth授权模式说明:
OAuth具有多种授权模式,其各有千秋、按需选择。
九. WebSocket
- 简介:一种 HTTP即时通信技术,目前流行。
- 暂无。
十. Swagger2
-
简介:
一种可以将 代码编写 和 需求文档编写 融为一体的技术(暂时无该需要)。
-
简单实现