SpringBoot笔记

SpringBoot笔记最全 SpringBoot 笔记 springboot 笔记

文章目录


1️⃣ 简介

一. 什么是 IoC 容器?
  1. 简介

    Inversion of Control 控制反转,

    又称为依赖注入 DI ——Dependency Injection。

  2. 解决痛点

    大型程序之间的高耦合性与冗余性,共享组件、统一销毁。

  3. 底层原理

    XML解析、工厂模式、反射。

    IOC容器底层就是对象工厂

  4. 意义

    传统的应用程序中,控制权在程序本身,程序的控制流程完全由开发者控制。在IoC模式下,控制权发生了反转,即从应用程序转移到了IoC容器,所有组件不再由应用程序自己创建和配置,而是由IoC容器负责,这样,应用程序只需要直接使用已经创建好并且配置好的组件。为了能让组件在IoC容器中被“装配”出来,需要某种“注入”机制,其将组件的创建+配置与组件的使用相分离,并且,由IoC容器负责管理组件的生命周期。

    总结:Ioc意味着将你设计好的对象交给容器控制,而不是按照传统在对象内部直接控制

  5. 小点:

    • 在 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面向切面编程
  1. 简介:

    ​ SpringBoot支持面向切面编程,其可以在不改动原代码的动态添加代码、动态删去代码。这在日志记录、安全检查和事务等方面很有用。AOP技术本质上就是一个动态代理,让我们可以把一些常用功能如权限检查、日志、事务从业务方法中剥离出来。

  2. 题外话:

    ​ Spring的 AOP实现基于 JVM的动态代理,所以我们有时候也会这样子形容——AOP代理、AOP代理对象,意即AOP代理了本来的类对象。

  3. 在 Java平台上对于AOP的织入,一共有三种方式:

    • 编译器:由编译器把切面编译进字节码,使用aspect关键字。
    • 类加载器:利用一个特殊的类加载器,在目标类被装载到JVM时,对目标类的字节码文件进行重新加强。
    • 运行期:目标对象和切面都是普通的Java类,通过JVM的动态代理对象功能或者第三方库实现运行期间动态织入。(最简单的方式)
  4. 原理解释:

    ​ Spring对接口类型使用JDK动态代理,对普通类使用CGLIB创建子类,在之后使用的也是它的子类,但对于用户来说是无感的。如果一个Bean的class是final,Spring将无法为其创建子类。

    // 原类为 UserTest,打印出来可以看到被 Spring enhance
    // 并非原类,为其子类。
    class com.thinkstu.test.UserTest$$EnhancerBySpringCGLIB$$217a2220
    
  5. AOP:Aspect-Orinented Programing 面向切面编程。

  6. OOP:Object-Oriented Programming面向对象编程,封装、继承、多态。

  7. 常用术语:

    image-20220418104139654

  8. AOP的使用:

    • 导包
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    
    • 切入:新定义类,并 @Aspect总开关注解,切入点注解。

      • @Around:环绕通知是所有通知里功能最为强大的注解,可以实现前直通知、后直通知、异常通知以及返回通知的功能。

      • @Pointcut解释:

        @Pointcut("execution(* com.thinkstu.controller.*.*(..))")

        image-20220418112638442

    @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
  1. 说明

    原生接口。当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中。

    通过 HttpServletRequest我们可以获得很多信息。

  2. 部分功能

    • headers:必须获得全部的 key,而后才能遍历出所有的 value。

    • getRemoteAddr:返回发出请求的客户机的IP地址。

    • getParameter(“username”):获取请求参数

image-20220424112644747
  1. 提示:

    获取全部请求信息应该使用 RequestEntity,而不是HttpServletRequest。

    单纯简单获取请求体应该使用 @RequestHeader注解,而不是HttpServletRequest。

    主要感觉 HttpServletRequest有点难用。

五. HttpServletResponse

​ 原生方式控制返回,但是一般不这样。

  1. 两种响应方式
image-20220424183056918
六. Cookie 与 Session
  1. Cookie与 Session的区别:Session比Cookie安全

    Cookie是客户端技术,存储在客户端。Session是服务器端技术,存储在服务端。

  2. 使用原因

    ​ HTTP 是无状态协议,它不能以状态来区分和管理请求和响应,也就是说服务器单从网络连接上无从知道客户身份。于是我们可以给客户端颁发通行证,如此服务端便能识别客户的身份,这就是 Cookie的工作原理。

七. Cookie
  1. 概念

​ Cookie是服务器存储在本地机器上的一小段文本。是客户端保存用户信息的一种机制,用来记录用户的一些信息,并随着每次请求发送到服务器。

​ Cookie会根据响应报文里的一个叫做Set-Cookie的首部字段信息,通知客户端保存Cookie。当下次客户端再向服务端发起请求时,客户端会自动在请求报文中加入Cookie值之后发送出去。然后服务器端会根据记录,得到之前的最后状态信息。

  1. set-cookie字段解释

image-20220424135520916

  • 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 的内容。
  1. Max-age与 Expires的区别

    Expires和max-age都可以用来指定文档的过期时间,但是二者有一些细微差别。

    Expires表示绝对时间,HTTP 1.0开始使用。Max-age表示相对时间,HTTP 1.1开始使用。

  2. 限制情况

    单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能超过3K。

八. Session
  1. 思想

    ​ 当用户第一次访问网站时,网站会为用户生成唯一的 Session ID值,而后 Session会自动跟随响应报文 set-Cookie返回给客户端,所以可以说 Session的设置在一定程度上依赖于 Cookie。可以把Session ID 想象成一种用以区分不同用户的唯一Id。

    image-20220308224127780
  2. 强依赖 Cookie与弱依赖

    ​ 当我们完全禁掉浏览器的cookie的时候,服务端的session可能不能正常使用。这取决于当前环境中 Session对 Cookie的依赖程度,通过规避写法可以避免强依赖。比如当禁用 Cookie时,PHP会自动把Session ID附着在URL中,继续正常使用。

九. 转发与重定向
  1. 转发:forward,客户端只发送了一次请求,该请求沿着“转发链”执行,所以可以通过request来共享数据。
  2. 重定向:redirect,客户端发送了两次请求,相当于客户端自己重新发送了一次请求,这是两次不一样的请求,不能通过request共享数据。
十. Spring项目转SpringBoot
  1. 思想:SpringBoot是为了简化 Spring项目而生的,其两者在很大程度上兼容。
  2. 大致步骤
    • 直接拷贝业务代码、pom包(这里删去Spring的依赖)
    • 按 XML编写配置类 或者直接导入配置类:@Import、@ImportSource
十一. Spring生命周期

这是一个大工程。

​ 在 Spring中,由于其生命周期过于复杂,所以 Spring没有按惯例为所有阶段单独定义方法。

​ 其使用事件监听器,我们只需要监听被干预的阶段即可(继承接口实现)。

​ 优点表现:统一了管理事件流程,并用泛型区分阶段。

  1. 简单实现

image-20220415151529764

  1. 生命周期示意图

    CSDN链接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3QSKrg0v-1651739102961)(https://tva1.sinaimg.cn/large/e6c9d24egy1h1m6y2cq40j20u00ufq76.jpg)]

十二. 什么是 pom
  1. POM:Project Object Model,项目对象模型
  2. 简介:**pom既是一个XML文件,也是 Maven 工程的基本工作单元。**其包含了项目的基本信息,用于描述项目如何构建、声明项目依赖等。在运行项目时,Maven会在当前目录中查找并读取 POM,然后获取所需的配置信息、执行目标。
  3. POM 中可以指定以下配置:
    • 项目依赖
    • 插件
    • 执行目标
    • 项目构建 profile
    • 项目版本
    • 项目开发者列表
    • 相关邮件列表信息
  4. **注意:**所有 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>
  1. pom包细究

    ​ 总体结构(四部分),此为阿里云下载的 SpringBoot程序结构,官方与此稍有不同。

  2. 项目的总体信息

  3. maven依赖库

  4. maven依赖库设置

  5. 构建插件

image-20220408111315873

十三. 为什么会返回JSON格式数据
  1. 原因:
    • 使用了 @ResponseBody注解
    • 导入了 Jackson JSON数据格式解析器
  2. 使用其他 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
  1. 简介:

    CORS,Cross-Origin Resource Sharing,是由 W3C制定的一种跨域资源共享技术标准,其目的是为了解决前端的跨域请求。它允许浏览器向跨源服务器,发出 XMLHttpRequest请求,从而克服了 AJAX只能同源使用的限制。

  2. 特征:

    • 其特征是浏览器在发送请求时会携带 Origin标识,因为“ 跨域 ”。
    image-20220417212305213
    • 服务器如果支持跨域请求,则会检查 client所携带的 Origin正确性,作出相应回应。如果 oringin指定的域名在许可范围内,服务器返回的相应数据则会多出几个头信息字段。
    image-20220428103243412

2️⃣ Spring基础知识

Spring全称: Spring Framework

一. 注解开发说明

Annotation:基于注解的方式 @Component。当我们给类注解时,默认 Bean的命名空间为小写开头的全类名,如 UserMapper则为 userMapper,当然我们也可以指定 Bean命名空间。

二. 配置 Bean

​ 其实总的来说,配置 Bean的方式有很多种,在SpringBoot的学习过程中我知道起码有七种。但是在日常的使用中普遍的也就两种:@Component注解或者 @Bean注解。

  1. 说明

    注解的方式需要事先开启包扫描 @ComponentScan注解。

  2. IDEA使用技巧

    当显示这个小图标表示注解已生效,点击可跳转至 @Autowired被注入的地方。

image-20220307174621434
  1. 注意:

    当 Bean被创建时,会首先默认调用其无参构造方法。

    当为饿汉模式时,运行即调用;当为懒汉模式时,使用时才调用。

  2. 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)

多实例的创建:

  1. @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。

  1. 简介:
    • @Conditional注解可以放在方法和类上。
    • 放在方法上和 @Bean一起使用,表示如果 @Conditional注解的参数类 matches方法为true这创建这个 Bean实例,否则不创建。
    • 放在类上结合 @Configuration、@ComponentScan判断被注解的类是否需要创建
    • 可以同时拥有多个 @Conditional,变式多样。
  2. 简单使用
// 如果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) ,当不存在此类时,条件为真。)

image-20220413105450924
八. 为Bean内的变量赋值

​ Spring在注入一对象时,对象里的变量是如何被赋值的呢?

​ Spring会调用这些变量的 set___ ( ) 方法从而为这些变量赋值,我们可以控制此流程。

九. Spring事务管理
  1. 四大特性:原子性、隔离性、一致性、持久性
  2. 底层原理:AOP面向切面编程
  3. 未完待续。
十. JdbcTemplate解释
  1. JDBC是Java操作数据库的一套规范。
  2. JdbcTemplate:**JDBC的模板 **,Spring封装的 JDBC对象。
  3. MyBatis是一个基于 Java的、封装了 JDBC的持久层框架。
十一. P命名空间

​ 即存在于 XML配置文件中的扩展写法(了解即可)。

实现步骤:

  1. 复制标准格式,改成名称 P。

    image-20220312214910599

  2. 直接使用

    image-20220312215146228

十二. 关闭ApplicationContext

​ 利用ApplicationContext获取的对象,最后需要手动的去关闭它。

两种方法:

  1. try-catch语句
  2. 强转 + close( ):原生的ApplicationContext中无close方法,所以这里需要强转再 close。
image-20220313093612166
十三. 完全注解开发
  1. 要求:创建配置类Configuration,代替XML配置文件
  2. 举个不太恰当的例子
image-20220313152549439
十四. 获取 Bean

​ Spring中拥有两种方式(并非方法)。

  1. 按 ID名字获取

    在SpringBoot中,根据 @Autowired + @Qulifier 获取

  2. 按类型获取

app.getBean("ByID");
app.getBean(___.class);
十五. 导入其他配置项

​ 两种注解。

  1. @Import:导入其他配置类。
@Import(ConfigUser.class)
  1. @ImportResource:导入 XML文件。
十六. Bean的分类

JavaBean分为两类:

  • 一类称为实体类 Bean:专门存储业务数据的,如 Student、User 等
  • 一类称为业务类 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。

3️⃣ Spring MVC基础知识

一. MVC简介
  1. 全称:Model View Controller
  2. 说明:MVC是模型(model) - 视图(view) - 控制器(controller)的缩写,其是一种软件设计规范,是一种业务逻辑、数据、界面显示,三者相互分离的方法。
  3. 优点:数据层、逻辑层、界面层相互分离,其中逻辑层来负责整体的调用,降低了程序整体的耦合性,从而可以三个人同时开发互不冲突。同时由于拥有清晰的结构性,也便于后期的维护。
二. 衍生的 Bean注解

​ 这些衍生出来的注解都是同一种东西的不同表现形式,作用完全一样、只是为了给程序员作区分使用。

注解@ 标识为
Component 一般组件
Controller 控制器
Service 事件处理器
Repository 持久层处理器
三. 路径叠加
  1. 其实说的是 @RequestMapping叠加的情况,此时路径也会直接进行叠加。
  2. @RequestMapping是 SpringMVC提供的注解,其包括 @GetMapping、@PostMapping等。
  3. 以下访问路径实为:/role/get
image-20220422222506577
四. RESTful风格
  1. 全称:Representational State Transfer,表现形态转换。

  2. 分类(Spring共支持8种)

    GET(查询)、POST(新增、保存)、PUT(修改)、DELETE(删除)

  3. 说明:

    • 当使用 RESTful风格时,就无路径参数符号 ? 拼接参数。
    • 当然,RESTful风格只是一种规范,流行于前后端分离开发。
  4. 路径占位符

@GetMapping("/{name}/{pass}")
void login(@PathVariable("name") String name){
   
    System.out.println("login");
}
  1. 功能清单范例
功能 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作用的则是请求参数。

  1. value

    指定请求的实际地址。

  2. method

    指定请求的method类型, GET、POST、PUT、DELETE等。

  3. produces

    指定返回内容的类型,只有当 request请求头中 Accept属性包含该 produces指定的类型才能返回数据成功,例如:accept:text/xml。

  4. cousumes

    指定request请求提交的内容类型(Content-Type),例如application/json, text/html等。

  5. headers

    指定request请求中必须包含某些指定的请求头header的值,才能让该方法处理请求。

    例如:Host=127.0.0.1

    “header”:要求请求映射所匹配的请求必须携带header请求头信息

    “!header”:要求请求映射所匹配的请求必须不能携带header请求头信息

    “header=value”:要求请求映射所匹配的请求必须携带header请求头信息且header=value

    “header!=value”:要求请求映射所匹配的请求必须携带header请求头信息且header!=value

  6. 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风格时的情况。

  1. 一般使用(参数同名时)

    形参参数名应与浏览器传过来的参数名一样,并不使用 @PathVariable路径参数注解。

    在该例中,浏览器会跳转至 /static/uuu.html页面(MVC自动解析跳转)。

image-20220424103916945

  1. 可变长参数

    最后环节,使用数组接收可变长参数。

image-20220424101821095

  1. @RequestParam参数

    当形参参数名与浏览器传过来的参数不一致时,使用注解来指定。

    required:是否必须

    name:名字

    defaultValue:当不存在时,则使用默认值。(结合 required = false 使用)

image-20220424102418810

八. 域共享对象
  1. 实例:在 url的跳转中实现数据的共享。

  2. 要求:既要实现完整功能,又要范围最小。

  3. 5种方式

    • 原生 Servlet:request.setAttribute( key , value ) + EL表达式。
    • ModelAndView
    • ModelMap
    • HttpSession对象
    • Application对象

    image-20220424144648690

    image-20220424144725636

九. ModelAndView
  1. 说明

    ModelAndView 统一实现了 Model对象和 View对象的功能。

    Model 主要用于向请求域共享数据,其本身是 Map的子类,拥有相应功能。

    View 主要用于设置视图实现页面跳转。

  2. 注意

    ​ 当未配置其他解析器或者为使用 @ResponseBody注解时,默认使用的是SpringMVC解析器,而SpringMVC解析器会返回 ModelAndView对象。

  3. 实现原理

    ​ 当控制器处理完请求后,通常控制器会将包含视图名称以及一些模型属性的 ModelAndView对象返回给 DispatcherServlet。因此,在控制器中会构造一个 ModelAndView对象

  4. 数据共享:直接使用方法。

addObject(String attributeName, Object attributeValue)
  1. 页面跳转
@GetMapping
ModelAndView get() {
   
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("uuu.html");
    return modelAndView;
}
十. 请求响应扩展
  1. 简介

    正式名称:HttpMessageConverter 报文信息转换器

    将请求报文转换为Java对象,或将Java对象转换为响应报文。

四种类型:

  1. @RequestBody

    ​ 该注解加在Controller 的处理方法的形参上,作用是将json格式的数据转为java对象

    ​ 作用于 Post请求,获取请求体。

    @RequestBody String requestBody
    @RequestBody User user_date
    
  2. RequestEntity对象

    ​ 获取的是整个请求头+请求体,getBody( ) 获取请求体,getHeaders( )获取请求头。

    ​ **需要理解的是,HttpServletRequest是 Servlet技术,而 RequestEntity是 SpringMVC技术。**使用 RequestEntity而不使用 HttpServletRequest。

    用法:只要控制器方法的形参中设置该类型,其就会自动赋值。

    public String test(RequestEntity reqEntity){
         
      //
    }
    
  3. @ResponseBody

    ​ 该注解使用在Controller 方法上的 。将方法的返回值通过适当的转换器(如 Jackson)转换为指定的格式之后,写入到 response 对象的 body 区,通常用来给客户端返回 JSON 数据或者是 XML 数据。

    当方法上面没有写 ResponseBody 时,底层会将方法的返回值封装为 ModelAndView 对象(原此);需要注意的是,在使用此注解之后不会再走试图处理器,而是直接将数据写入到输入流中,他的效果等同于通过 response 对象输出指定格式的数据。

  4. 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视图,渲染数据后最终响应给浏览器。

十二. 文件下载
  1. 本质:文件复制。
  2. SpringMVC文件下载流程:
    • 先通过输入流( 例如InputStream )将文件读取到Java程序中。
    • 建立 byte[ ] 数组,将输入流读取到的所有数据都存储到byte [ ] 数组。
    • 向客户端响应byte[ ]数组或者类似 **ResponseEntity<byte[ ]>**的响应类型。
  3. 文件下载必须要设置的请求头(设置类型)
 headers.add("Content-Disposition", "attachment;filename=1.jpg");
  1. 使用 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;
}
  1. 实践:

    ​ 以上代码我在 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;

image-20220504161208936

十三. 文件上传
  1. 本质:文件复制。

  2. 上传功能必需请求头:

    multipart/form-data,即标明为以二进制方式上传数据,而不是key-value。

<form method="post" enctype="multipart/form-data" action="/upload">
    图片:<input type="file">
    <input type="submit">
</form>
  1. 上传操作要导入额外的依赖包 Apache Commons FileUpload
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
  1. 范例代码
@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";
}
  1. 简单实践

    该案例会将文件上传至与当前项目总文件夹 平齐的文件夹。

@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";
}}
十四. 拦截、过滤、分发器总结
  1. 英文名称

    • 拦截器 interceptor:拦截Controller,分为前后拦截器。
    • 过滤器 Filter
    • 分发器 DispatcherServlet
  2. 示意图:

image-20220311151447026
十五. @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属性的一个别名
十六. 视图解析器
  1. 简介:

    SpringMVC视图的种类很多,默认有转发视图和重定向视图。

    但这必须不能存在@ResponseBody注解。

    存在@ResponseBody注解时,就关乎SpringBoot下页面的跳转问题,具体使用 ModelAndView。

  2. 关注点:Themleaf好像已经很少使用。

  3. 转发视图

    ​ SpringMVC中默认的转发视图是 InternalResourceView

    ​ 当控制器方法中所设置的视图名称以"forward:"为前缀时,会创建InternalResourceView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"forward:"去掉,剩余部分作为最终路径通过转发的方式实现跳转

@RequestMapping("/testForward")
public String testForward(){
   
    return "forward:/testHello";
}
  1. 重定向视图

    ​ 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的执行流程

  1. 用户向服务器发送请求,请求经过Filter后被 SpringMVC 前端控制器 DispatcherServlet捕获。
  1. 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中

  2. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。

  3. 此时将开始执行拦截器的postHandle(…)方法【逆向】。

  4. 根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model和View,来渲染视图。

  5. 渲染视图完毕执行拦截器的afterCompletion(…)方法【逆向】。

  6. 将渲染结果返回给客户端。

十八. Thymeleaf说明
  1. 简介:

    • 在目前的企级应用开发中前后端分离是趋势,但视图层技术仍有一席之地。
    • Spring Boot 官方推荐使用的模板引擎是 Thymeleaf,Spring Boot 提供了 Thymeleaf自动配置解决方案,因而Spring Boot 中使用 Thymeleaf非常方便。
    • 如果开发者使用的是前后端分离技术,那么开发过程不需要整合视图层技术。
  2. 默认配置说明

    路径:classpath/template/____,后缀 html。

    image-20220411165830387

  3. 实现步骤:

    • 导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
  1. 实现说明:

    在 cotroller中使用后,会默认返回 ModelAndView对象。

    SpringMVC返回的也是 ModelAndView对象,两者同为视图解析器。


4️⃣ SpringBoot小知识点

  1. **static与 template目录:**static中的资源不受保护,可以直接通过 url定位来访问,而templates中的资源是受保护的。

  2. SpringBoot工程在IDEA下需要联网进行。

  3. SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程。

  4. SpringBoot只是简化Spring与SpringMVC的简化开发,MybatisPlus也是在简化Mybatis,本质还是SSM框架。

  5. Spring Boot 不支持同时在配置中启动 HTTP HTTPS 。

  6. 一些专业名词

    • 数据源:DruidDataSource
    • 持久化技术:Mybatis、MybatisPlus
    • 数据库:MySQL
  7. 三种内嵌的数据源

    数据源默认存在的,并不一定需要 Druid。

    1. HikariCP(SpringBoot默认数据源)
    2. Tomcat的 DataSource
    3. Common的 DBCP
  8. 三种内嵌数据库(了解)

    不过到真正上线的时候还是要切换到正式数据库,而且体验并不是很好,弃用。

    1. H2
    2. HSQL
    3. Derby
  9. MyBatis是一个基于 Java的、封装了 JDBC的持久层框架,其底层使用 JDBC来编写。

  10. JS等前端库可通过 pom导入。

    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>vue</artifactId>
        <version>2.6.14</version>
    </dependency>
    
  11. Controller路径命名规则:

    常用复数形式表示,如 users、employees等。

  12. 配置文件放在哪?

    在Maven的结构下,配置文件均放在resource目录里。

  13. yml配置信息如何记?

只需要你记得其中几个关键字,然后在 IDEA中敲一敲就能知道个大概。
  1. 未知编程思想

    当遇到陌生方法调用时,只需观察其形参与返回值,在大多数情况下便可了解其用法。

  2. html表单说明

    html中的 form表单只能发送 Get或者 Post请求,并不能发送其他请求。

  3. Tomcat思想:万物皆对象。

  4. JSON数据格式说明:一共只有两种格式。

- 对象:{ }
- 数组:[ ]
  1. 宝塔小坑

    • 阿里云与宝塔均存在端口拦截机制,需要在两边都打开才能访问。
    • 即使我在宝塔里部署 SpringBoot项目时设置了随机端口映射,宝塔也不会默认开启端口。
  2. 关于 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


image-20220408122451017
二. delete、put请求说明

部分浏览器只支持发送 get和 post请求,那么在 SpringBoot中该如何发送 put和 delete请求呢?

​ SpringMVC 提供了 HiddenHttpMethodFilter 帮助我们将 POST 请求转换为 DELETE 或 PUT 请求,SpringBoot中默认存在此配置类。

使用要求:

  • 浏览器的请求方式必须为post
  • 浏览器必须传输请求参数_method

​ 满足以上条件,HiddenHttpMethodFilter 过滤器就会将当前请求的请求方式转换为请求参数_method的值,因此请求参数_method的值才是最终的请求方式。

三. jar包与 war包的区别
  1. 简介:

    ​ jar包和war包都可以看成压缩文件,都可以用解压软件打开,jar包和war包都是为了项目的部署和发布,通常在打包部署的时候,会在里面加上部署的相关信息。

  2. 简单区别:

    • JAR(Java Archive,Java 归档文件),是一个完整的项目结构,以流行的 ZIP 文件格式为基础,jar包本质上就是 zip包,只是额外附加了一些固定的描述文件。
    • war包不是一个完整的项目结构,需要按照传统的方式去进行部署。war包是 Sun提出的一种 web应用程序格式,与 jar类似,是很多文件的压缩包。
  3. 根本区别:

    ​ JAR文件的目的是把类和相关的资源封装到压缩的归档文件中,而对于WAR文件来说,一个WAR文件代表了一个Web应用程序,它可以包含 Servlet、HTML页面、Java类、图像文件,以及组成Web应用程序的其他资源,而不仅仅是类的归档文件。

image-20220420212742409

四. start 与 parent的区别
  1. 说明:Start与 parent均在 pom文件中。
  2. Start指定对应包。
  3. 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说明
  1. 简介:

    位于主启动程序上,负责配置主程序

    其实是一个 SpringBoot Configuration( SpringBoot Configuration下面是 @Configuration)。

@SpringBootApplication
public class Test01Application {
   

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

}
image-20220409092628263
六. #{ }与 ${ }说明
  1. 简介:

    • #{ }用来获取 Bean类的变量值。
    • ${ }用来获取 yml文件中的变量值。
  2. 范例:

    加载名为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;

image-20220425175934960
八. 临时配置说明
  1. 临时配置既可以在命令行中修改,也可以在代码中提前写好。
java -jar xxx.java
--server.port 8080

image-20220410173207725

  1. 禁止临时配置

有时我们会为了安全,禁止其他人在运行我们的程序时添加临时属性。

方式:阻止main主程序中的args参数传到SpringApplication。

image-20220410173410067

九. yml格式说明
  1. 说明:重数据、轻格式。
  2. 基本语法格式:
    • 属性 与 属性值之间用冒号 : 分隔,属性值之前要加空格

    • 大小写敏感,禁止同名,#表注释。

    • 多属性值(数组)之间用**小横杆-**分隔

    • 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格。

    • 属性值支持转义字符,但必须用双引号括起来。如:name: "/t name /n"

  3. 简单书写实例
#表示对象,多实例(数组)用 - 符号分隔
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}]
  1. yml格式中互相引用
name: duck
users: ${
   name}
  1. 特殊写法
version: @project.version@

表示获取该程序的version属性,@ @包裹、输入会有提示。

十. 松散绑定说明
  1. 简介:

    松散绑定是 Spring为了兼容各种编程爱好者而制定的规则。

    我们并不需要使用,但是要了解、知道它的存在,其有时会导致程序出现 error。

  2. 注意点:

    • 部分支持、部分不支持,使用驼峰命名法永远没有错。
    • @ConfigurationProperties支持松散绑定,@Value不支持。
  3. 范例:

​ yml中写的是 dataSource,但是在代码中以下形式都能绑定上数据。

@ConfigurationProperties(prefix = "datasource")
@ConfigurationProperties(prefix = "Data_Source")
@ConfigurationProperties(prefix = "Data-Source")		// 羊肉串模式
//等等

6️⃣ SpringBoot常用操作

一. 页面跳转

​ 在 SpringBoot条件下,利用 ModelAndView实现。

image-20220424145936663
二. 注解方式获取请求头

@RequestHeader,Spring中常用方式,非原生的方式。

经过观察,其注解的参数与 @RequestParam一样。

image-20220424132818315
三. 注解方式获取Cookie

@CookieValue,Spring中常用方式,非原生的方式。

@CookieValue注解一共有三个属性:value、required、defaultValue,用法同@RequestParam

四. 编码格式修改

​ SpringBoot默认的编码格式是 UTF-8 (写在底层源码中)。

有三种方式可以定制编码格式。

  1. yml配置

    直接查找 endoding就可以显现所有的内容。

server:
  servlet:
    encoding:
      charset: UTF-8
  1. Filter 过滤器配置

    原理:Filter是浏览器发送的请求接触到的第一层服务器端应用。 (代码省略)

image-20220425094815065

  1. 配置类 配置

image-20220425094849863

五. 发送邮件
  1. 三个邮件协议

    • SMTP:simple mail transfer protocol 简单邮件传输协议,发送邮件
    • POP3:post office protocol -Version 3 第3代邮局协议,接受邮件
    • IMAP:Internet mail access protocol 互联网消息协议,用来替代IMAP,接受邮件

    POP3与IMAP的不同点:**首先要得知,**我在这里所说的采用邮件协议为,全部在第三方软件中采用。采用POP3时,邮件删除等操作不会同步,即使你在第三方邮件系统删除了某封邮件,但是在原邮件系统中并不会执行删除操作。而采用IMAP就是为了改进这一点,实现了同步的操作。

  2. 简单实现三步走:

    • 导包:spring-boot-starter-mail。
    • 配置信息(服务器host、账号、授权码等)
    • 代码实现(自动注入JavaMailSender类)
  3. 范例:

    发送简单邮件

<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);
    }

  1. 邮件中的SSL加密

    ​ 发送邮件或者接受邮件时我们可以配置SSL加密,具体要去邮件提供商那边获取。

    ​ 例如对于腾讯,SSL端口为465或者587,首先开启 SSL然后再配置端口。

image-20220420154608848

image-20220420154903017

六. Scheduled定时任务
  1. 简介:Spring注解整合的方式只适用于较简单的情况,复杂业务使用 Quartz
  2. 实现步骤:
    • 启动类上开启
    • 方法上调用
@EnableScheduling
@Component
public class Test {
   
    @Scheduled(cron = "0/5 * * * * ?")
    void print(){
   
        System.out.println("+----+--------+");
    }
}
  1. yml额外配置:task拥有两组配置,我们选择 sheduling
task:
  scheduling:
    pool:
      size: 10		#线程池数量,默认只为1。
    shutdown:
      await-termination: false				#关闭时是否等待所有完成
      await-termination-period: 10s		#最大等待时间
  1. @Scheduled 注解可以利用 @Value形式从 yml中取值
@Scheduled(cron = "0/${a.b.c:10} * * * * ?")
七. Cron格式编写指南
  1. 简介:

    • 逻辑反人类
    • 在线验证网站:链接
  2. 简单编写思想

    调整的时间顺序,思维应该顺着从小到大

  3. 编写规则

    秒数:

    • 范围 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监控
  1. 简介:

    分布式监控程序,非 SpringBoot官方开发,使用时需导入与之对应的官方版本号,否则报错。

  2. 注意事项:

    子节点要开放什么内容全部由子节点规定,Server无权干涉。(安全性)

  3. 实现流程:

    • 导包 admin + SpringBoot Web

    • yml配置主从客户端

      配置Server,主程序上开启 @EnableAdminServer注解, yml中配置端口。

      配置Client,yml中配置主服务器即可。

  4. 简单实现

    配置 Server:

    1. 创建 SpringBoot程序时选择 ops中的 Server与 SpringBoot Web项目
    2. 配置 yml端口,这里我设置为80
    3. 主程序上配置开启Server
    server: 
    	port: 80
    
    @EnableAdminServer
    

    配置 Client:

    1. 创建SpringBoot程序时选择 ops中的Server与 SpringBoot Web项目(此处勾选 web纯粹是为了能使 SpringBoot项目持续运行,实际生产中可以勾选别的,达到效果就可以)
    2. 配置 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
    
  5. 界面预览

    打开 Server主页地址,可以看到许多的数据image-20220417145049492

  6. 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");
        }
    }
    
  7. 自定义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);
            }
        }
    }
    

    image-20220417154331611

  8. 结合邮件系统:邮件信息报警系统

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MBjnpfJ6-1651739102964)(https://tva1.sinaimg.cn/large/e6c9d24egy1h1o6xhb71xj21cm0man1y.jpg)]

九. 消息中间件
  1. 基础概念:
    • MQ:Message Queue,消息队列。
    • JMS:Java Message Service;一个规范,等同于JDBC,提供了与消息服务相关的API接口
    • AMQP: advanced message queue protocal,高级消息传输协议,一种协议,不一定要遵守。其解决了JMS中的数据格式不唯一的缺点,统一使用byte[ ]。
    • Kafka:大数据技术,可以用作消息中间件,但是主要功能不是此。其是一种高吞吐量的分布式发布订阅消息系统,提供实时消息功能。
  2. JMS规范简介
  • JMS消息模型

    • Peer-to-peer:P2P,点对点模型,一对一。
    • publish-subscribe:发布订阅模型,消息可以被多个消费者消费,生产者与消费者完全独立,不需要告知对方自身的存在。
  • JMS消息种类

    TextMessage、MapMessage、ByteMessage、StreamMessage、ObjectMessage、Message

  • 实现JMS的技术

    ActiveMQ、Redis、RabbitMQ、RocketMQ(没有完全实现)

  1. AMQP协议简介
  • 优点:

    具有跨平台性,服务器、供应商、生产者消费者可以使用不同的语言来实现。

  • AMQP消息模型:

    direct exchange、fanout exchange、topic exchange、headers exchange、system exchange

  • AMQP消息种类:byte[ ]

  • AMQP实现:

    RabbitMQ、RockerMQ、StormMQ等

  1. 四种消息中间件简介

    ActiveMQ:Apache产品,社区已经不活跃。

    RabbitMQ:使用频率较高,速度中等,数据直接写在磁盘中,不易丢失。

    RocketMQ:阿里巴巴开源的消息中间件,Java语言开发,各方面也表现的比较优越,几乎同时解决了Kafka和RabbitMQ它们两个的缺点,速度介于两者之间,数据不易丢失。

    Kafka:速度快,但数据写在内存中、易丢失。

  2. 实现暂略。

十. 自定义错误页
  1. 简介:

    • Spring Boot 中的错误默认由 BasicErrorController 类来处理
    • 如果开发者不需要向用户展示详细的错误信息,那么可以把错误信息定义成静态页面
    • resources/static 中创建 error目录,然后导入错误展示页面。
  2. 原理:

    ​ 当触发错误页面时,BasicErrorController类被调用。(其将会返回 JSON或 html格式的错误数据,具体由用户请求方式而定)

    • JSON格式的 error得到解决,html格式的 error传到下一步。
    • 触发 DefaultErrorViewResolver类,开始在 error目录查找 4__ 、5__格式的错误页面。
    • **(还是找不到时触发)**回到 errorHtml ( )方法,使用 error 作为默认的错误页面视图名,如果名 error的视图也找不到,就会展示默认错误页面。

image-20220417194231322

  1. 简单实现

获取错误的静态页面,置于 /resource/static/error 目录中。

  • 两种形式:

    xx形式 与 具体的数字形式。4xx.html、5xx.html的优先级低于具体的数字权限,如404、503等,所以它们是可以同时的存在的。

image-20220417193233675

  1. 复杂实现(自由度很高)

image-20220417202515646

@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日志使用
  1. 简介:

    • Lombok包中提供的注解。
    • 针对类使用、打印类的日志。
    • 在开发中,应该尽量使用日志而不是打印 Print。
  2. 简单实现:

  • 注解实现
@Slf4j
@RestController
@RequestMapping("/users")
public class UsersController {
   
    @GetMapping()
    String getById(HttpServletResponse response) throws IOException {
   
        log.error("fashion");
        return "啊啊啊啊";
    }
}
  • 原生创建
 Logger log= LoggerFactory.getLogger(UsersController.class);
  1. 效果:

image-20220411095052956

**从左至右:**日志记录时间、级别、PID、所属线程、类对象、信息。

十二. 静态资源访问
  1. 简介

    • 在SpringMVC 中,对于所有的静态资源都需要开发者手动配置资源过滤
    • Spring Boot简化了静态资源过滤配置
    • SpringBoot静态资源自动化配置类: WebMvcAuto Configuration。
  2. 位置说明

    SpringBoot默认会过滤所有的静态资源,一共有5个位置

    开发者可以将静态资源放在这5个位置中的任意一个,优先级依次降低

classpath:/META-INF/resource/
classpath:/resource/
classpath:/static/
classpath:/public/
/
  1. 冲突说明

​ 如果将文件夹中存在同名文件,则只有第一个会生效。

image-20220412092421622
十三. 路径映射
  1. 简介

    ​ 正常情况,如果我们有静态网页会放在/static里,然后访问的时候需要添加 .html后缀。如果不想添加.html后缀,则需要在 Controller中加一层转发的操作。

    ​ 但是我们有更简单的方法,而且节省资源。

  2. 效果:

    访问 http://localhost/aaa

    相当于 http://localhost/aaa.html

  3. 简单实现:

    首先将文件置于/static下。

image-20220418100628341

​ 然后编写 @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");
    }
}
十四. 服务器日志
  1. 简介:

    在服务器中使用日志。

    在正式业务上线后不能使用开发工具进行调试,我们需要日志系统。

  2. 说明:

    保存到服务器上的日志数据,我们可以使用 IDEA打开(拥有格式)。

  3. 简单使用

logging:
  file:
    max-history: 10
    max-size: 10MB
    name: server.log
  pattern:
    rolling-file-name: server.%d{
   yyyy-MM-dd}.%i.log
十五. 多环境开发 Profile
  1. 简介:

    SpringBoot约定在不同环境下配置文件的名称规则为

    • application-{profile} .properties
    • application-{profile}.yml

    profile占位符表示当前环境的名称。

  2. 作用:

    解决在多环境开发下配置文件混乱的问题。

  3. 版本限制说明:

    • SpringBoot 2.4之include
    • SpringBoot 2.4之group
    • 阿里云现在的是2.3.7版本
  4. 简单实现

  • 在主 yml配置文件以外,编写多份 yml文件
    • application-dev
    • application-devDB
    • application-MVC
  • 在主 yml配置文件中选择性的引入其他配置文件。

image-20220411085603392

十六. 优先执行的代码
  1. 简介:

    ​ 有一些特殊任务需要在系统启动时执行(例如配置文件加载、数据库初始化等),SpringBoot对此提供了两种基本一样的方案:CommandLineRunner类、ApplicationRunner类。

  2. 两种简单实现:

    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");
    }
}
十七. 异常处理器
  1. 简介:

    异常,指的是当正常访问时服务器时发生的异常,并非指 404之类的异常。

  2. 简单实现

    ( utils包下的异常处理类)

// 拦截所有异常
@RestControllerAdvice
public class ProjectExceptionAdvice {
   
    @ExceptionHandler(Exception.class)
    R allException(Exception ex) {
   
        ex.printStackTrace();
        return new R("服务器发生未知故障,请稍后重试...");
    }
}
十八. 配置日志等级
  1. 简介:

    在 yml中配置当前日志的打印等级,一共有两种形式。

    • 按包名划分
    • 按分组划分
  2. 简单实现:

按包名划分

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配置文件
  1. 简介:

    ​ 有时候我们需要改写一些比较老的程序,或者作 xml文件配置。

    ​ 虽然 SpringBoot不推荐使用 xml进行配置,但是如果开发者需要使用 xml配置,那么只需在 resources目录下提供配置文件、然后在主程序上导入即可。

  2. 说明:

    • @ImportResource:导入 XML配置文件。
    • @Import:导入其他配置类。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yWRboVy5-1651739102965)(https://tva1.sinaimg.cn/large/e6c9d24egy1h1sq40ejyaj214a0aoabn.jpg)]

二十. 读取标准 yml配置
  1. 简介:

    ​ yml 中编写了众多属性,那么该入伙获取呢?

  2. 获取方式分类:

    • 单个读取
    • 全部读取
    • 选择读取
  3. 单个读取:@Value注解

@Value("${users[0].name}")
String name;

@Value("${a.b.c:10}")		// 读取不到则加载默认值
String num;
  1. 全部读取:利用被 Spring封装的 Enviroment对象,该对象中包含了所有的 yml文件属性。
@Autowired
Environment env;

@Test
void contextLoads() {
   
    env.getProperty("users[0].name");
}
  1. 选择读取:既可以为 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配置
  1. 简介:

    ​ 我怀疑此种方式存在Bug,单级可以识别,一旦遇到多级就不能识别我的文件。还应该注意的是,方法不止这一种,但这种比较直接。

    1. 简单实现:

      @PropertySource属性引入第三方文件(得加上类全路径名)

@Data
@Configuration
@PropertySource(value = "classpath:users.yml")
public class CustomConfig {
   
    @Value("${users}")
    Object name;
}
二十二. 拦截器

​ 所有的拦截器都必须实现 HandlerInterceptor接口。

​ **拦截器( Interceptor)**同 Filter 过滤器一样,都是面向切面编程 AOP 的具体实现。

  1. 必须实现的三个方法。

    • preHandle:控制器方法执行之前执行 preHandle(),其 boolean类型的返回值表示是否拦截或放行,返回 true为放行,即调用控制器方法;返回 false表示拦截,即不调用控制器方法。当它返回 false 时,表示请求结束,
    • postHandle: 方法在当前请求处理完成之后,也就是 Controller 方法调用之后执行。但是它会在 DispatcherServlet 进行视图返回渲染之前被调用,我们可以在这个方法中对 Controller 处理之后的 ModelAndView 对象进行操作。
    • afterComplation:该方法在整个请求结束之后,也就是在 DispatcherServlet 渲染了对应的视图之后执行,主要用来进行资源清理。
    • 执行顺序:preHandle ----> Controller ----> postHandle ----> afterComplation
  2. 多个拦截器的执行顺序

    • 拦截器的执行顺序为链条
    • ==注意:==当某个拦截器方法返回值为 false时,后续的 Interceptor和 Controller都不会再执行,所以一般需要手写为 true。
  3. 实现步骤:

    • 继承自 HandlerInterceptor,重写方法
    • @Configuration中 注册拦截器:将拦截器 Bean交由 SpringMVC拦截器类 WebMvcConfigurer管理。

image-20220415104318246

在这一步才能配置拦截的路径,还可以配置排除的路径 excludePathPatterns。

image-20220415104439489
二十三. 页面跳转

原理:利用 ModelAndView对象。

@GetMapping
ModelAndView get() {
   
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("/uuu.html");
    return modelAndView;
}

7️⃣ SpringBoot常用技巧

一. 获取UUID的正确姿势
image-20220311150135474
二. 全路径名

​ 在 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("+----+--------+");
image-20220415083309304
五. yml中相互引用

​ dollar + 大括号

username: kk

your_name: ${
   username}
六. 随时获取 ApplicationContext
  1. 为什么能够实现?

    ​ 理解 SpringBoot底层工作源码,采取官方接口 ___Aware

  2. 简单实现:

    只要继承 ApplicationContextAware并实现 set方法即可。

    public class Demo01 implements ApplicationContextAware {
         
        ApplicationContext applicationContext;
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
         
            this.applicationContext=applicationContext;
        }
    }
    

    image-20220413140440652

七. 网站图标 favicon
  1. 简介

    favicon,网站图标。

    虽然在 html代码中也可以添加,不过在此添加较为方便。

  2. 简单实现

    • 将普通图片转为 ico图标文件,链接
    • 重命名为 favicon.ico ,置于 /resource/static/ 下。
八. 跳过测试模块
  1. 问题简介

    SpringBoot程序在打包的时候会默认先执行测试类 Test里面的方法。

    这是因为存在 Maven生命周期,后执行的必须先执行前面的所有内容。

解决:maven设置跳过测试

image-20220410171602553
九. 排除自动配置
  1. 简介:

    手动排除 SpringBoot的自动配置。

  2. 两种实现方法:

  • 主程序上配置

image-20220418114544307

  • yml中配置

image-20220418114629102

十. 查看 pom组件版本
  1. 简介:

    查看在 pom文件中导入的具体软件版本(全部)。

    可以分为两种,Spring官方 与 阿里云镜像 所创建的 SpringBoot程序并不一样。

  2. Spring官方

    两层点击:spring-boot-starter-parentspring-boot-dependencies

    image-20220428110600494

    image-20220428110637762

  3. 阿里云

    dependencyManagement下的与中,点击查看。

    image-20220408094701319

十一. 正确的项目创建流程
  1. 简介:

    有利于项目与项目之间的解耦合,促进开发。

  2. 操作流程:

    • 创建空项目工程
    • 在空的项目工程中 添加 所需要的其他组件 module。
image-20220409082841997
十二. 离线创建SpringBoot程序
  1. 简介:

    在没有网络的计算机上创建 SpringBoot程序,过程离线。

    但事先需要在官网上把相应文件创建并下载。

  2. 步骤:

    • 官网创建、下载
    • 将项目导入离线设备

image-20220409083517253

十三. 快速制作程序模板
  1. 简介:

    制作模板程序,可以在学习的过程中大量复制某份程序。

制作模板步骤:

  • 选择模板

  • 删除项目结构的无用文件

    image-20220409110118672
  • 删除pom文件两行、一行(结束)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bh5Q4N9S-1651739102967)(https://tva1.sinaimg.cn/large/e6c9d24egy1h1p9wf9t2xj2144092q53.jpg)]

使用步骤:

通常都是在项目中直接将上面的模板当成组件module导入。

  • 再复制出一份模板。
  • 在pom文件中把改成新组件名。
  • IDEA中导入,注意此次选择的是import module而不是new module
  • 设置使用的JDK版本。(结束)
十四. Tomcat替换成Jetty
  1. 简介:

    排除 Tomcat依赖,可以换成其他任意服务器程序。

  2. 步骤:

    • 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
  1. 简介:

    修改控制台打印出来的 Banner广告位。

    image-20220409111635498
  2. 两种方法:

    • 纯文字:/resource 中编写 banner.txt文件,Banner在线生成网站

    • 文字或者图片:yml中配置

image-20220410213705186

#关闭banner
spring:
  main:
    banner-mode: off
    
#修改banner为指定图片
spring:
  banner:
    image:
      location: WechatIMG96.jpeg
十六. 测试中开启服务器配置
  1. 简介:

    ​ 我们在执行测试的时候,SpringBoot默认不开启服务器、节省资源。但是现在由于业务需求,需要对其测试,采用 WebEnvironment Web环境。

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class Test03 {
   
    @Test
    void test03(){
   
    }
}

webEnviroment参数说明:

  1. SpringBootTest.WebEnvironment.NONE:默认值,不启动服务器
  2. SpringBootTest.WebEnvironment.DEFINED_PORT:使用定义的端口
  3. SpringBootTest.WebEnvironment.RANDOM_PORT:使用随机的端口
  4. SpringBootTest.WebEnvironment.MOCK:欺骗idea
十七. 测试中开启事务
  1. 简介:

    ​ 在测试中经常会有写入数据库操作,但我只想知道是否执行成功,不想污染数据库。

  2. 步骤:

    • SpringBoot程序中已经导入 mysql + mybatis的包,没有则无法开启事务
    • 开启 @Transational 注解
@SpringBootTest
@Transactional
public class Test04 {
   
    @Test
    void test04(){
   

    }
}
十八. 测试中的临时属性
  1. 简介:

    ​ 想要在测试用例中添加一些临时属性,在 @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
  1. 简介:

    ​ 使用 Jackson作为项目的序列化工具时,可以作用在属性、方法或者类上面,用来规避不想要的序列化功能。

@JsonIgnore
private String username;
二十. 项目打包构建
  1. 简介:

    ​ 我们在 SpringBoot项目中能够打包是因为配置了 maven插件,该插件由 SpringBoot parent 中提供。但是其他公司可能不采用 SpringBoot parent 作为parent,此时就需要配置。

  2. 示意图:避免重复打包

image-20220420211214814

二十一. IDEA隐藏文件
  1. 简介:

    隐藏不想看见的文件,避免冗余。

    set up — Edit — File Type.

  2. 注意事项

    在 IDEA 2022.01版本中,我遭遇了隐藏文件时产生的 Bug,需注意。

image-20220409080650941image-20220409080619393

二十二. jdk8单位类
  1. 简介:

    ​ 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. 修改配置文件名

修改配置文件名,然后在程序运行时再指定配置文件名

虽然感觉这种方式比较愚蠢,但是暂时收录

image-20220410215017297

2. maven控制yml环境

maven是比 Spring更底层的存在,Spring建立在 maven的基础之上。

我们可以使用 maven来控制并改变 Spring运行的时的 yml文件配置。

3. JDBC使用

优势阐述:

​ Mybatis之类是基于JDBC开发的,可以说 jdbc是更加底层的存在。

​ 安全性与底层效率要较其他框架高,银行相关行业比较热衷此。

步骤:

  1. 导pom包
  2. 自动注入,直接使用
<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校验
  1. 利用validation(接口)与hibernate(实现类)结合实现。
  2. **具体功能:**可对自定义的 Bean在运行时进行数据的校验,比如最大值 max、最小值 min、范围 range等的校验,通过了才能继续编译。
  3. **具体使用:**对于我,暂时还未想到。
<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这类工具。

  1. 简单测试:

​ get请求访问页面,先开启webEnviroment、AutoConfigureMockMVC,然后注入MOckMVC,最后执行操作

image-20220412123634889

  1. 后续放弃。
7. 测试用例中设置随机数据

只是想在测试的时候加载一些随机数据,应该把以下内容用Profile思想来编写:即多份yml文件。

  1. 编写yml数据,里面是dollar大括号加上随机函数random
testData:
  name: ${
   random.uuid}
  age: ${
   random.int(6,100)}
  id: ${
   random.value}   #MD5加密,32位
  1. 代码中配置(注入即可,之前使用过)
@Data
@Component
@ConfigurationProperties( "testdata")
public class TestDataConfig {
   
    String name;
    Integer age;
    String id;
}
  1. 使用:直接 @Autowired 即可使用

9️⃣ 整合第三方

此章节需要日积月累。

一. 整合Mybatis
  1. 导包或者勾选包
  2. 配置 yml
  3. 编写 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;
  1. 开启 Mybatis运行日志
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
二. 整合MybatisPlus
  1. 将Mybatis包换成MybatisPlus包
  2. Mapper接口继承BaseMapper< T >
  3. 修改ID自增长策略,逐渐增长而不是雪花算法增长
  4. 整合业务层 Iservice与 ServiceImpl
  5. 开启 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
  1. 导 pom包
  2. 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

一门登录技术, 学会不易。

一. 简介
  1. Spring Security是基于内存级别的认证,不是数据库。

  2. SpringBoot为 SpringSecurity提供了很好的支持。

  3. 导包之后,SpringSecurity为我们提供了一个默认页面登录页面(未登录时拦截了所有的请求!),默认账号为user,密码见控制台。如果对初始的账号密码不满意,可以在yml中修改。

    spring:
      security:
        user:
          name: admin
          password: admin
          roles: ADMIN			#此处是区分大小写的,需特别注意
    
二. 使用步骤
  1. 导包

  2. yml简单配置

  3. 代码中正式配置

    配置说明:

    • 访问/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();
    }
}
  1. Basic认证:添加 Basic认证能够让 Postman可访问。
.and().httpBasic()
三. 自定义登录页面与返回值
  1. 简介:

    ​ 目前为止我们使用的还都是 Spring Security默认提供的登录页面。

    ​ 在前后端分离的开发中,我们需要自定义登录页面与返回的 JSON格式数据

  2. 思想:

    • 虽然新登录地址是/login_new,但是最终的数据提交地址还是/login
    • 对于传输过程中的参数 usename与 password可以自定义而不必固定。
    • 可以设置登录成功、失败返回的数据。
  3. 简单实现(配置):

.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();
四. 注销登录
  1. 简介:

    ​ 默认访问 /logout即可注销。

    ​ 但是在这里我遇到问题,可能是这种方式已经失效。

image-20220419115231670

  1. 简单实现:
.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
  1. 简介:

    ​ 所谓加盐就是一种加密形式,其既可以是随机数、也可以是用户名。

    ​ 加盐之后原本密码相同的用户所生成的最终密码也不会相同,可以有效防止跑库破解密码。

  2. 传统加盐方式:需要在数据库中记录用户的盐值。

  3. 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);
        }
    }
    
  4. 简单使用:

    • 写 service
    • 注册时将 encrypt传到数据库(代码编写)

    image-20220419121903303

六. 使用注解进行配置
  1. 简介:

    ​ 上面都是使用 Java类来进行Spring Security配置,现在采用注解的形式。

    ​ 配置内容:访问路径(或者方法)需要授权。

  2. 使用步骤:

    • 开启注解形式
    • 类或者方法上面使用

    image-20220419122621680

    image-20220419122633112image-20220419122642279

七. 持久层存储:数据库
  1. 简介:

    ​ 将 Spring Security基于内存级别的登录验证信息存储到数据库。

  2. 遗憾:暂时未能成功实现。

  3. 实现步骤:

    • 创建数据库对应表:首先得创建三张数据库用户表
    • 代码中实现注册与登录等相关业务
    image-20220419140409141
  4. 建表语句范例:

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
  1. 简介:

    ​ 本节基于 OAuth2框架,该框架的使用与实现账号密码登录不冲突。

  2. 遗憾:暂时未能成功实现。

  3. 令牌技术说明:

    ​ 令牌技术的优势在于可以只授权部分权限给第三方,从而避免了密码直接泄露的可能性。第三方拿着令牌可以访问一些基础资源,如:头像、用户名等。很多第三方也只支持 token而不支持 Cookie(如:微信小程序)。

    image-20220420144457977

  4. 交互流程(三次):

    image-20220420144021719
  5. OAuth授权模式说明

    ​ OAuth具有多种授权模式,其各有千秋、按需选择。

image-20220420144106615

image-20220420144119770

九. WebSocket
  1. 简介:一种 HTTP即时通信技术,目前流行。
  2. 暂无。
十. Swagger2
  1. 简介:

    ​ 一种可以将 代码编写 和 需求文档编写 融为一体的技术(暂时无该需要)。

  2. 简单实现

image-20220420164930804

image-20220420164955683

编程小号
上一篇 2025-09-01 09:30
下一篇 2025-06-27 16:30

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/77250.html