文章目录


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
查询全部数据/employeeGET
删除/employee/2DELETE
跳转到添加数据页面/toAddGET
执行保存/employeePOST
跳转到更新数据页面/employee/2GET
执行更新/employeePUT
五. @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. 两种方法:

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

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐