javase:OOP
MySQL:持久化
html+css+js+jquery+框架:视图,框架不熟练,css不好
javaweb:独立开发MVC三层架构的网站:原始
ssm:框架:简化了我们的开发流程,配置也开始较为复杂;
在此之前项目打包都是war包,程序在Tomcat中运行
spring再简化:springBoot-jar包,内嵌Tomcat;微服务架构!
服务越来越多:springCloud
XXXXAutoConfiguration:自动配置类:给容器添加组件,这些组件要赋值就需要绑定一个XXXXProperties类
**XXXXProperties:里面封装配置文件中相关属性;**通过这个文件,可以找到你需要东西的配置类,可以更加了解这个功能
例如:thymeleafProperties里面有thymeleaf模板引擎的基础配置
言归正传,什么是SpringBoot呢,就是一个javaweb的开发框架,和SpringMVC类似,对比其他javaweb框架的好处,官方说是简化开发,约定大于配置, you can “just run”,能迅速的开发web应用,几行代码开发一个http接口。
Spring Boot 基于 Spring 开发,Spirng Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用 也就是说,它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。Spring Boot 以约定大于配置的核心思想,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring 配置。同时它集成了大量常用的第三方库配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot 应用中这些第三方库几乎可以零配置的开箱即用。
简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架 。
Spring Boot的主要优点:
使用idea创建:
其中:
这个类是程序的主入口,不能修改,不能删除!!!
就是这个SpringBootAppliaction注解标识的类
以后的项目文件/包,要创建在这个类的同级目录下,否则项目会报错
这个properties文件是springBoot的核心配置文件
这个test是springboot的单元测试模块
1,项目的类/包需要写在程序主入口的同级目录下。然后其他代码该这么写怎么写
2,controller层,service层注解开发不用配注解约束,和依赖了!!!
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.3version>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>Spring-Boot01artifactId>
<version>0.0.1-SNAPSHOTversion>
<name>Spring-Boot01name>
<description>Spring-Boot01description>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
1,修改端口号
在springboot核心配置文件中
server.port = 端口
2,自定义banner
就是开机的那个样式可以改
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hqmoKrr6-1668094039498)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220908205342196.png)]
在网上通过https://www.bootschool.net/ascii这个找
然后创建banner.txt(名字不可变)文件,放进去即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rnRyG4Sy-1668094039498)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220908205311677.png)]
1、见到很多 spring-boot-starter-* : 就某种场景(功能,json,链接mysql。。。。。)
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入(配置,需要的包,等等)*
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
自动配好Tomcat
引入Tomcat依赖。
配置Tomcat(官网找的启动器)
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
<version>2.3.4.RELEASEversion>
<scope>compilescope>
dependency>
自动配好SpringMVC 视图解析器,处理器映射器,注解开发,dispartatservlet,乱码。。。。
自动引入SpringMVC全套组件
自动配好SpringMVC常用组件(功能)
自动配好Web常见功能,如:字符编码问题
SpringBoot帮我们配置好了所有web开发的常见场景
默认的包结构
主程序所在包及其下面的所有子包里面的组件都会被默认扫描进来
无需以前的包扫描配置
想要改变扫描路径,@SpringBootApplication(scanBasePackages=“包的全路径”)
或者@ComponentScan 指定扫描路径
@SpringBootApplication
等同于
//这三句放一起
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.guo.boot")
配置拥有默认值
默认配置最终都是映射到某个类上,如:MultipartProperties
配置文件的值最终会绑定某个类上,这个类会在容器中创建对象
按需加载所有自动配置项
非常多的starter
引入了哪些场景这个场景的自动配置才会开启
SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面
1**.@Configuration** 给类添加这个注解后相当于原来的向bean注入的bean.xml文件
相当于就是springboot所有配置类的一个拓展配置类
基本使用
代码示例:
配置类:代替原来的xml配置文件
@Bean(“组件名:默认为方法名”)放在方法上,
#########Configuration使用示例#########################
/**
* 1、配置类里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
* 2、配置类本身也是组件
* 3、proxyBeanMethods:代理bean的方法
* Full(proxyBeanMethods = true)、【保证每个@Bean方法被调用多少次返回的组件都是单实例的】
* Lite(proxyBeanMethods = false)【每个@Bean方法被调用多少次返回的组件都是新创建的】
* 组件依赖必须使用Full模式默认,proxyBeanMethods = true。
其他默认是否Lite模式:proxyBeanMethods = flase
*/
@Configuration(proxyBeanMethods = true) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
/**
* Full:外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
* @return
*/
@Bean //给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值,就是组件在容器中的实例
public User user01(){
User zhangsan = new User("zhangsan", 18);
//user组件依赖了Pet组件
zhangsan.setPet(tomcatPet());
return zhangsan;
}
@Bean("tom")
public Pet tomcatPet(){
return new Pet("tomcat");
}
}
################################@Configuration测试代码如下########################################
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.atguigu.boot")
public class MainApplication {
public static void main(String[] args) {
//1、返回我们IOC容器
ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);
//2、查看容器里面的组件
String[] names = run.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
//3、从容器中获取组件
Pet tom01 = run.getBean("tom", Pet.class);
Pet tom02 = run.getBean("tom", Pet.class);
System.out.println("组件:"+(tom01 == tom02));
//4、com.atguigu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$51f1e1ca@1654a892
MyConfig bean = run.getBean(MyConfig.class);//原来的调xml中的对象
System.out.println(bean);
//如果@Configuration(proxyBeanMethods = true)代理对象调用方法。SpringBoot总会检查这个组件是否在容器中有。
//保持组件单实例
User user = bean.user01();
User user1 = bean.user01();
System.out.println(user == user1);
User user01 = run.getBean("user01", User.class);
Pet tom = run.getBean("tom", Pet.class);
System.out.println("用户的宠物:"+(user01.getPet() == tom));
}
}
2、@Bean、@Component、@Controller、@Service、@Repository
3、@ComponentScan、@Import
@Import会给容器中自动创建这两个类型的组件
* @Import({User.class, DBHelper.class})
*给容器中自动创建出这两个类型的组件、默认组件的名字就是全类名
*/
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //告诉SpringBoot这是一个配置类 == 配置文件
public class MyConfig {
}
@Conditional(条件装配注解)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OHkE51gG-1668094039499)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220908222330186.png)]
Spring-boot-dependencies:核心依赖在父工程中
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.3version>
<relativePath/>
parent>
我们在写或者引入springboot依赖的时候,不需要指定版本,因为有这些版本仓库
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<resource>
<directory>${basedir}/src/main/resourcesdirectory>
<filtering>truefiltering>
<includes>
<include>**/application*.ymlinclude>
<include>**/application*.yamlinclude>
<include>**/application*.propertiesinclude>//暗示文件要以application开头,.yml,yaml这些结尾
includes>
resource>
<resource>
<directory>${basedir}/src/main/resourcesdirectory>
<excludes>
<exclude>**/application*.ymlexclude>
<exclude>**/application*.yamlexclude>
<exclude>**/application*.propertiesexclude>
excludes>
resource>
启动器在哪里找?
官方文档
1、见到很多 spring-boot-starter-* : 就某种场景(功能,json,链接mysql。。。。。)
2、只要引入starter,这个场景的所有常规需要的依赖我们都自动引入(配置,需要的包,等等)*
3、SpringBoot所有支持的场景
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
4、见到的 *-spring-boot-starter: 第三方为我们提供的简化开发的场景启动器。
5、所有场景启动器最底层的依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
<version>2.3.4.RELEASEversion>
<scope>compilescope>
dependency>
太难了,暂时放弃
结论:
springboot所有的自动配置都是在启动的时候扫描并加载,扫描了spring.properties配置文件,所有的自动配置类都在这里面,但是不定生效,因为要判断条件是否成立,只要导入了对应的start,就有对应的启动器,有了启动器我们自动装配就会生效,然后就配置成功
步骤:
SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;
以前需要我们配置的文件,springboot帮我们配置了!
整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;
整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;
它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration)@Bean, 就是给容器中导入这个场景需要的所有组件 , 并配置好这些组件 @Configuration;
有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;
一句话总结 :根据当前不同的条件判断,决定这个配置类是否生效!
一但这个配置类生效;这个配置类就会给容器中添加各种组件;
这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
这样就可以形成我们的配置文件可以动态的修改springboot的内容。
所有在配置文件中能配置的属性都是在xxxxProperties类中封装着;
配置文件能配置什么就可以参照某个功能对应的这个属性类
通俗理解:把我们原先需要在bean中手打的属性(property)封装成了一个类,然后通过yaml文件进行自动注入,而我们也可以在application.yaml文件中对这些property进行赋值。
1.SpringBoot启动时会加载大量的自动配置类
2.我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中
3.我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在其中,我们就不需要再去手动配置了,如果不存在我们再手动配置)
4.给容器中自动配置类添加组件的时候,会从properties类中获取某些属性,我们只需要在配置文件中指定这些属性即可;
XXXXAutoConfiguration:自动配置类:给容器添加组件,这些组件要赋值就需要绑定一个XXXXProperties类
**XXXXProperties:里面封装配置文件中相关属性;**通过这个文件,可以找到你需要东西的配置类,可以更加了解这个功能
怎么去修改这些属性呢:说白了就是SpringBoot配置,---->.yaml、.properties这些文件
我们怎么知道哪些自动配置类生效?
我们可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;
#开启springboot的调试类
debug=true
SpringBoot使用一个全局的配置文件 , 配置文件名称是固定的:必须为application.yaml||properties
为什么?因为在源码乱码可以看见扫描的代码
application.properties(核心配置文件)(官方不推荐使用的方式)可以先删除
语法结构 :key=value
server.port=8081
**application.yaml(yaml文件,也是核心配置文件)**推荐使用
语法结构 :key:空格value
server: 对象:
port: 8081 等价于server.port=8081 属性:空格 数据
说明:语法要求严格!
里面还可以使用el表达式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Q6Ptk4O-1668094039499)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220909200250408.png)]
1、空格不能省略
2、以缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的。
#同级
name:
age:
index:
#父子级
name:
age:
index: 等价于name.age name.index
name:
age:
index: 等价于name.age.index
3、属性和值的大小写都是十分敏感的。
字面量:普通的值 [ 数字,布尔值,字符串 ]
字面量直接写在后面就可以 , 字符串默认不用加上双引号或者单引号;
注意:
“ ” 双引号,不会转义字符串里面的特殊字符 , 特殊字符会作为本身想表示的意思;
比如 :name: “kuang \n shen” 输出 :kuang 换行 shen
‘’ 单引号,会转义特殊字符 , 特殊字符最终会变成和普通字符一样输出
比如 :name: ‘kuang \n shen’ 输出 :kuang \n shen
对象、Map格式
key:
value1:
value2:
在下一行来写对象的属性和值得关系,注意缩进;比如:
student:
name: qinjiang
age: 3
行内写法
student: {name: qinjiang,age: 3}
数组( List、set )
用 - 空格 值表示数组中的一个元素,比如:
pets:
- cat
- dog
- pig
行内写法
pets: [cat,dog,pig]
package com.example.springboot01.pojo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 测试yaml赋值,格式要对应
* 使用 @ConfigurationProperties(prefix = "yaml中的对象名") 。
* ConfigurationProperties作用:
* 将配置文件中配置的每一个属性的值,映射到这个组件中;
* 告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
* 参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应
*/
@Component//注册bean,类似原来的xml注册bean
@ConfigurationProperties(prefix = "user")//使用后会报红,但不影响使用
public class User {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;//实体类属性
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", happy=" + happy +
", birth=" + birth +
", maps=" + maps +
", lists=" + lists +
", dog=" + dog +
'}';
}
public User(String name, Integer age, Boolean happy, Date birth, Map<String, Object> maps, List<Object> lists, Dog dog) {
this.name = name;
this.age = age;
this.happy = happy;
this.birth = birth;
this.maps = maps;
this.lists = lists;
this.dog = dog;
}
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Boolean getHappy() {
return happy;
}
public void setHappy(Boolean happy) {
this.happy = happy;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<Object> getLists() {
return lists;
}
public void setLists(List<Object> lists) {
this.lists = lists;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
user:
name: 李四
age: 18
happy: true
brith: 2022/1/1
maps: {aaa: aaa,bbb: bbb}//对象,map集合这样赋值
lists: [111,222,333]//list,set集合,数组可以这样赋值
dog: //实体类属性
name: 阿猫
age: 12
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F9yJptUE-1668094039499)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220909200942900.png)]
@SpringBootTest
class SpringBoot01ApplicationTests {
@Autowired
User user;
@Test
void contextLoads() {
System.out.println(user);
}
}
这个注解非常重要,他可以将yaml中的数据与对应的类进行绑定
例如实体类对象赋值。
配置类(代替原来的配置文件)例如SQL数据源的编写
解决@ConfigurationProperties(prefix = “yaml中的对象名”) 。爆红
导入约束
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BD40hwcr-1668094039500)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220909200143736.png)]
做对比
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oU8yYQjs-1668094039500)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220909195809014.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pebDHXmO-1668094039500)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220909195936995.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7yqph2NN-1668094039500)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220909200015637.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L701Y5iy-1668094039501)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220909201231907.png)]
1、@ConfigurationProperties只需要写一次即可 , @Value则需要每个字段都添加
2、松散绑定:这个什么意思呢? 比如我的yaml中写的last-name,这个和lastName是一样的, - 后面跟着的字母默认是大写的。这就是松散绑定。可以测试一下
3、JSR303数据校验 , 这个就是我们可以在字段是增加一层过滤器验证 , 可以保证数据的合法性
4、复杂类型封装,yaml中可以封装对象 , 使用value就不支持。
结论
配置yaml和配置properties都可以获取到值 , 但是强烈推荐 yaml;
如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下 @value;
如果说,我们专门编写了一个JavaBean来和配置文件进行一一映射,就直接@configurationProperties。
1,开启@validated注解
@Component //注册bean
@ConfigurationProperties(prefix = "person")//绑定yaml
@Validated //数据校验
public class Person {
@Email(message="邮箱格式错误") //name必须是邮箱格式,message提示错误信息
private String name;
}
如果没有@Email注解,需要在pom.xml文件中添加依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
dependency>
使用数据校验,可以保证数据的正确性
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;
空检查
@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty 检查约束元素是否为NULL或者是EMPTY.
Booelan检查
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false
长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=, max=) string is between min and max included.
日期检查
@Past 验证 Date 和 Calendar 对象是否在当前时间之前
@Future 验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern 验证 String 对象是否符合正则表达式的规则
.......等等
除此以外,我们还可以自定义一些数据校验规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XYyBrRpE-1668094039501)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220910163121247.png)]
1,这些类的名字,位置不能变
2,[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4INvBYmK-1668094039501)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220910163204202.png)]
1.是指项目下面的config文件下面的application文件(优先级最高)
2.是指项目下面的application文件(优先级第二)
3.是指resources资源目录下的config文件下面的application文件(优先级第三)
4.是指resources资源目录下的application文件(默认,优先级最低)
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
我们在最低级的配置文件中设置一个项目访问路径的配置来测试互补问题;
#配置项目的访问路径
server.servlet.context-path=/guo
#根目录
profile是Spring对不同环境提供不同配置功能的支持,可以通过激活不同的环境版本,实现快速切换环境;
我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml , 用来指定多个环境版本;
例如:
application-test.properties 代表测试环境配置
application-dev.properties 代表开发环境配置
但是Springboot并不会直接启动这些配置文件,它默认使用application.properties主配置文件;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AqjzSTsL-1668094039502)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220910165046103.png)]
切换配置环境的方法
#比如在配置文件中指定使用dev环境,我们可以通过设置不同的端口号进行测试;#我们启动SpringBoot,就可以看到已经切换到dev下的配置了;
spring.profiles.active=dev//dev是文件application-后面的名字
和properties配置文件中一样,但是使用yml去实现不需要创建多个配置文件,更加方便了 !
通过—来分割模块
#在yaml中用"---"来分隔文件,划分为几个部分,彼此之间不影响。类似一张纸分成几张
server:
port: 8081
spring:
profiles:
active: test #选择要激活那个环境块
---
server:
port: 8083
spring:
profiles: dev #配置环境的名称
---
server:
port: 8084
spring:
profiles: test #配置环境的名称
注意:如果yml和properties同时都配置了端口,并且没有激活其他环境 , 默认会使用properties配置文件的!
相关springboot类:WebMvcAutoConfiguration
要解决的问题:
静态资源:html,js,css
方式一:放在classPath/static/目录下(一般放图片)
方式二:放在classPath/public/目录下(一般放公共资源)
方式三:放在classPath/resources/目录下(一般放上传文件)
classPath:就是项目的resources资源目录下
//目录访问优先级:resources>static>public
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dqnL55z3-1668094039502)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220910203035567.png)]
请求路径直接写文件名即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bWul06yT-1668094039502)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220910203250578.png)]
方式二:放在webjars目录下
Webjars本质就是以jar包的方式引入我们的静态资源 , 我们以前要导入一个静态资源文件,直接导入即可。
使用SpringBoot需要使用Webjars,我们可以去搜索一下:
网站:https://www.webjars.org
要使用jQuery,我们只要要引入jQuery对应版本的pom依赖即可!
localhost:8080/webjars/
这个目录需要导入
<dependency>
<groupId>org.webjarsgroupId>
<artifactId>jqueryartifactId>
<version>3.4.1version>
dependency>
在导入资源里面去找这个目录(不推荐)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P1rjTVIM-1668094039502)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220910203959522.png)]
方式三:自定义静态资源路径
我们也可以自己通过配置文件来指定一下,哪些文件夹是需要我们放静态资源文件的,在application.properties中配置;
spring.resources.static-locations=classpath:/coding/,classpath:/kuang/
一旦自己定义了静态文件夹的路径,原来的自动配置就都会失效了!
这里提一个注意事项:在templates这个目录下的文件,只能通过controller发送请求跳转去访问。不能直接访问类似原来的WEB-INF目录。
并且需要在模板中导入模板引擎才可以使用
导入模板引擎的方法
1,在创建项目时templates选择一个模板引擎(一般是thymeleaf)
源码:
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
FormattingConversionService mvcConversionService,
ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(), // getWelcomePage 获得欢迎页
this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
return welcomePageHandlerMapping;
}
-----------------------------------------------------------------------------------
private Optional<Resource> getWelcomePage() {
String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
// ::是java8 中新引入的运算符
// Class::function的时候function是属于Class的,应该是静态方法。
// this::function的funtion是属于这个对象的。
// 简而言之,就是一种语法而已,是一种简写
return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
}
// 欢迎页就是一个location下的的 index.html 而已
private Resource getIndexHtml(String location) {
return this.resourceLoader.getResource(location + "index.html");
}
在指定的三个资源目录下写一个index.html。这个页面会被自动识别为首页
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UR8RgquZ-1668094039503)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220910210403876.png)]
老版:
将图片命名为favicon.ico放在前面那三个目录下
#关闭默认图标
spring.mvc.favicon.enabled=false
新版直接弄一个.ico的图片放在static目录下即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ROi4vQSd-1668094039503)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220910210216958.png)]
jsp支持非常强大的功能,包括能写Java代码,但是呢,我们现在的这种情况,SpringBoot这个项目首先是以jar的方式,不是war,像第二,我们用的还是嵌入式的Tomcat,所以呢,他现在默认是不支持jsp的。
模板引擎,我们其实大家听到很多,其实jsp就是一个模板引擎,还有用的比较多的freemarker,包括SpringBoot给我们推荐的Thymeleaf,模板引擎有非常多,但再多的模板引擎,他们的思想都是一样的
怎么引入呢,对于springboot来说,什么事情不都是一个start的事情嘛,我们去在项目中引入一下。给大家三个网址:
Thymeleaf 官网:https://www.thymeleaf.org/
Thymeleaf 在Github 的主页:https://github.com/thymeleaf/thymeleaf
Spring官方文档:找到我们对应的版本
https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter
找到对应的pom依赖:可以适当点进源码看下本来的包!
源码的themeleafProperties:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7FxqgkGQ-1668094039503)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220910213642706.png)]
默认可以识别templates文件下面的.html文件
1,导入themeleaf
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
2,写controller
@Controller
public class testControler {
@RequestMapping("/hello")
public String Hello(Model model){
model.addAttribute("msg","hello,springBoot");
return "Hello";
}
}
3,写html
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">//这个是themeleaf模板的依赖,导入之后,就可以通过th:指令去控制所有标签的属性(只要你知道属性名)类似vue指令
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div th:text="${msg}">div>//通过指令取数据,直接取取不到
body>
html>
4,测试
测试运行的是main类,不是测试类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sxf3txGZ-1668094039504)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220910220426920.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E3uEo2SN-1668094039504)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220911153252034.png)]
我们可以使用任意的 th:。。。 来替换Html中原生属性的值
Simple expressions:(表达式语法)
Variable Expressions: ${...}:获取变量值;OGNL;
1)、获取对象的属性、调用方法
2)、使用内置的基本对象:#18
#ctx : the context object.
#vars: the context variables.
#locale : the context locale.
#request : (only in Web Contexts) the HttpServletRequest object.
#response : (only in Web Contexts) the HttpServletResponse object.
#session : (only in Web Contexts) the HttpSession object.
#servletContext : (only in Web Contexts) the ServletContext object.
3)、内置的一些工具对象:
#execInfo : information about the template being processed.
#uris : methods for escaping parts of URLs/URIs
#conversions : methods for executing the configured conversion service (if any).
#dates : methods for java.util.Date objects: formatting, component extraction, etc.
#calendars : analogous to #dates , but for java.util.Calendar objects.
#numbers : methods for formatting numeric objects.
#strings : methods for String objects: contains, startsWith, prepending/appending, etc.
#objects : methods for objects in general.
#bools : methods for boolean evaluation.
#arrays : methods for arrays.
#lists : methods for lists.
#sets : methods for sets.
#maps : methods for maps.
#aggregates : methods for creating aggregates on arrays or collections.
==================================================================================
Selection Variable Expressions: *{...}:选择表达式:和${}在功能上是一样;
Message Expressions: #{...}:获取国际化内容
Link URL Expressions: @{...}:定义URL;
Fragment Expressions: ~{...}:片段引用表达式
Literals(字面量)
Text literals: 'one text' , 'Another one!' ,…
Number literals: 0 , 34 , 3.0 , 12.3 ,…
Boolean literals: true , false
Null literal: null
Literal tokens: one , sometext , main ,…
Text operations:(文本操作)
String concatenation: +
Literal substitutions: |The name is ${name}|
Arithmetic operations:(数学运算)
Binary operators: + , - , * , / , %
Minus sign (unary operator): -
Boolean operations:(布尔运算)
Binary operators: and , or
Boolean negation (unary operator): ! , not
Comparisons and equality:(比较运算)
Comparators: > , < , >= , <= ( gt , lt , ge , le )
Equality operators: == , != ( eq , ne )
Conditional operators:条件运算(三元运算符)
If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)
Special tokens:
No-Operation: _
1、 我们编写一个Controller,放一些数据
@RequestMapping("/t2")
public String test2(Map<String,Object> map){
//存入数据
map.put("msg","Hello
");
map.put("users", Arrays.asList("qinjiang","kuangshen"));
//classpath:/templates/test.html
return "test";
}
2,测试页面取出数据.
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>狂神说title>
head>
<body>
<h1>测试页面h1>
<div >
<div th:utext="${msg}">div>
<h4 th:each="user :${users}" th:text="${user}">h4>
<h4>
<span th:each="user:${users}">[[${user}]]span>
h4>
body>
html>
1,写一个类实现webmvcconfigurer接口,然后在头上配置@configuration注解,表示这是一个配置类,且交由容器控制
2,所有实现了viewResolver接口的类,都可以看做是一个视图解析器
3.1写一个类继承viewResolver接口,从写里面的一个方法
3,2在继承了webmvcconfigurer接口的类中写一个返回值为viewResolver的方法
3,3该方法头上加一个@bean注解,交由springboot管理即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V1J6L4MG-1668094039504)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220911170032052.png)]
4,如何修改请求跳转的页面?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UkU9RNIv-1668094039504)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220911173306689.png)]
addviewController(“/请求”).setViewName(“跳转的页面”)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VhIxiB30-1668094039505)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220911173432389.png)]
这一步没做。。。。。
主看
1,1 将静态资源(html,css,js导入static目录,一般是前端给我们的),功能性页面导入templates目录(一般是后端程序员写一下页面)
1,2 模拟数据,写实体类,数据,SQL类似的java语句
1,3配置欢迎页(利用额外配置配置)
@Configuration
public class MVCconfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
}
所有的静态资源都需要先让thymeleaf接管
<html lang="en" xmlns:th="www.thymeleaf.org">
修改链接
本地的项目链接(本地页面)
需要通过thymeleaf的th指令绑定
只要需要动态的修改属性的值,都需要th指令去替换
例:
<link th:href="@{/css/dashboard.css}" rel="stylesheet">
上面的链接是本地项目的
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign outa>
这个链接不是本地的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KzQCUTt9-1668094039505)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220911212047991.png)]
如果修改没有,则清除缓存
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TfjTRyPs-1668094039505)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220911211800337.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UubS1qUn-1668094039506)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220911212653490.png)]
server:
port: 8080
servlet:
context-path: /caishan
//设置项目的虚拟访问路径
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QdAtajWo-1668094039506)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915180935246.png)]
配置这个后,就不能直接访问/去访问项目,必须加上前缀
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FivwRS95-1668094039506)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915180949746.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-65R1hBA4-1668094039506)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915204749290.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SalOO0Mw-1668094039507)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915181820817.png)]
就是可以中英文互换,怎么互换呢
通过propertise文件,实现中英文的互换,每一个汉字都要互换到!!!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zitTzyMQ-1668094039509)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915191824056.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LP3Lr3sh-1668094039510)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915191522602.png)]
如果没有可视化界面(就是一次性可以改多个)下载这个插件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AUESY2U2-1668094039510)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915192236562.png)]
然后就有了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pozTP56Z-1668094039511)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915192346087.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KnlCsm45-1668094039512)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915192820929.png)]
效果:==========================================================================
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CVre6f7W-1668094039514)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915193116089.png)]
yaml中配置
#绑定国际化配置文件
spring:
messages:
basename: i18n.login #这里绑定主的文件就行了
使用:
国际化数据通过“#{key值}”获取
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign inh1>
效果:===============================================
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qSaqOTMP-1668094039515)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220915193828023.png)]
<a class="btn btn-sm" th:href="@{/(lang='zh_CN')}">中文a>
<a class="btn btn-sm" th:href="@{/(lang='en_US')}">Englisha>
th:href:跳转生效
在thymeleaf中传递参数用()阔起来
Locale对象:解析需要转换的语言类型
public class MyLocalResoverl implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {//核心跳转方法
String lang=request.getParameter("lang");//获取前端参数传递的语言类型
Locale locale=Locale.getDefault();//获取浏览器默认的语言模式
if(lang!=null){
String[] strings= lang.split("_");
locale=new Locale(strings[0],strings[1]);//将语言参数传递给地区化视图
}
return locale;
}
}
在核心配置类中配置
@Bean
public LocaleResolver localeResolver(){
return new MyLocalResoverl();
}
1,可以点击跳转语言的前提:在每一个需要转换语言的地方th:绑定另外一种语言的字段(这个字段是自己配置好的)
2,发送对应的语言类型编码,Local接收后会在那个properties组中找到对应的语言,去切换绑定的语言类型
<form class="form-signin" th:action="@{/dash}">//发送的请求要让thymeleaf管理
<p th:text="${msg}" th:if="${not #strings.isEmpty(msg)}">p>
//显示登录失败的信息
//th:if="${not #strings.isEmpty(msg)}"如果msg不为空则实现该标签
@Controller
public class LoginController {
@RequestMapping("/dash")
public String dashboard(Model model,String pwd,String name){
System.out.println(pwd);
if ("123456".equals(pwd)){//用equals,不要用!=,无法实现
model.addAttribute("msg","用户名或密码有误");
return "index";
}
return "dashboard";
}
}
和springMVC设置拦截器方式一样
public class Heander implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object user=request.getSession().getAttribute("userKey");
if(user==null){
request.setAttribute("msg","暂无权限");
request.getRequestDispatcher("/").forward(request,response);//请求转发
return false;
}
return true;
}
}
addInterceptors方法(配置拦截器的)
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new Heander()).addPathPatterns("/**").excludePathPatterns("/","/dash","/css/*","/js/*","/img/*");
}
/**
addInterceptor(new Heander()):配置指定的拦截器,Heander就是那个拦截器类
addPathPatterns("/**"):拦截那些请求,这里是所有请求
excludePathPatterns("/","/dash","/css/*","/js/*","/img/*"):排除那些请求不拦截
*/
th:fragment="自定义名"
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="titil">//
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${session.userKey}]]a>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign outa>
li>
ul>
nav>
调用
<div th:replace="~{提前标签页面路径::哪一个自定义名(aaa)}">div>//replace导入复用标签(div覆盖)
<div th:include="~{提前标签页面路径::哪一个自定义名(aaa)}">div>//include导入复用标签(div存在)
<div th:replace="~{../comments/comments.html :: titil}">div>
1,传递参数
<div th:replace="~{../comments/comments.html :: sidebar(activity='document')}">div>
//传递一个activity的参数
<a th:class="${activity=='document'?'nav-linkactive':'nav-link'}"th:href="@{/main.html}">
//如果这个参数是指定值,则,类型添加高亮属性active,否则普通属性
思路:实现定义表单的表头,然后添加表单内容,通过th:each遍历后台传递的数据,然后将每一条数据装到对应的位置。
dates.format(date,‘日期格式’):springboot自带方法,定义日期格式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nN0Pybnd-1668094039516)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220916192735533.png)]
tr:表头 th:表头字段
tbody:表单体 tr:表单数据 td 每一个元素内容
添加功能写法没有什么太多的变化,写一个添加功能的页面,填写数据,然后封装传递给后台执行SQL操作
表单下拉框:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4o8tcfZh-1668094039517)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220916203435848.png)]
select标签:下拉选择框
option标签:每个具体的选项 text:显示的内容 value:隐藏的内容(一般为主键)
下拉框一般会隐晦的包含这个选项的主键
传递该条数据的主键到修改页面,这里采用的是restful风格,报错但不影响使用
restful风格的传参,和接收参数没忘吧?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gRmdKqQz-1668094039518)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220916205812467.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HtMBKccL-1668094039519)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220916210019257.png)]
让下拉框默认选中我们数据的内容
selected属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DJIT3N6Z-1668094039519)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220916210630889.png)]
springBoot中非常简单
原来思路:写一个controller获取全部请求,然后跳转到404页面
现在:在templates资源目录下,创建error目录,然后将报错页面放进去,出错会自动跳到这个页面
注意:404错误就404开头页面,500错误就500开头错误
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oIBr7Mzm-1668094039520)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220916213353832.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wKzwDw0t-1668094039520)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\image-20220916220020158.png)]
首先明确一个点:在springBoot里面,核心配置文件是类,组件也是类
1,首先写一个类继承WebMvcConfigurer接口,还要添加@Configuration接口表示这是一个配置类
表示这是一个webMvc的spring容器(代替原来的xml)(核心配置文件)
@Configuration
public class MVCconfig implements WebMvcConfigurer {
}
2,写组件,这些组件都是继承了一些特定的接口,然后完全理解,仿造写一个自定义组件
**LocaleResolver接口:**配置国际化的路由跳转
public class MyLocalResoverl implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {//核心跳转方法
String lang=request.getParameter("lang");//获取前端参数传递的语言类型
Locale locale=Locale.getDefault();//获取浏览器默认的语言模式
if(lang!=null){
String[] strings= lang.split("_");
locale=new Locale(strings[0],strings[1]);//将语言参数传递给地区化视图
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
3,在核心配置,类中写一个方法,这个方法的返回值就是这个接口,然后return 这个类的对象,这个方法再添加一个@Bean注解,表示被容器注册
@Bean
public LocaleResolver localeResolver(){
return new MyLocalResoverl();
}
用于请求路由转发
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
//映射,访问“/”可以跳转到index.html页面
//这个功能可以用来隐藏实际的页面名字//在这里相当于请求转发
//url显示“/” 但是实际访问得是index.html页面
}
用于配置拦截器的
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new Heander()).addPathPatterns("/**").excludePathPatterns("/","/dash","/css/*","/js/*","/img/*");
}
/**
addInterceptor(new Heander()):配置指定的拦截器,Heander就是那个拦截器类
addPathPatterns("/**"):拦截那些请求,这里是所有请求
excludePathPatterns("/","/dash","/css/*","/js/*","/img/*"):排除那些请求不拦截
*/
只有两步!!加两个注解
为何要使用异步任务?
所谓异步,在某些功能实现时可能要花费一定的时间,但是为了不影响客户端的体验,选择异步执行
案例
//sservice层
@Service
public class AsyncService {
public void hello(){
try {
Thread.sleep(3000);//启用多线程停留3秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("数据正在传输...");
}
}
==========================================================================
//controller层
@RestController
public class AsyncController {
@Autowired
AsyncService asyncService;
@RequestMapping("/async")
public String async(){
asyncService.hello();
return "ok";
}
}
这样在执行/async请求时,网站会延时三秒再显示ok,后台数据也会三秒后显示数据正在传输
现在想要做到前端快速响应我们的页面,后台去慢慢的传输数据,就要用到springboot自带的功能
第一步:
@Async//核心在需要异步的方法上添加这个注解
public void hello(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("数据正在传输...");
}
第二步:
@EnableAsync//在springboot的主类上添加这个注解,开启异步任务
@SpringBootApplication
public class SwaggerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SwaggerDemoApplication.class, args);
}
}
重启即可
邮件发送,在我们的日常开发中,也非常的多,Springboot也帮我们做了支持
步骤:
1,导入相关包
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>
dependency>
2,写配置文件
spring.mail.username=你的邮箱
spring.mail.password=你的邮箱授权码
spring.mail.host=smtp.163.com #什么邮箱就什么smtp.xxx.com
# qq需要配置ssl,其他邮箱不需要
spring.mail.properties.mail.smtp.ssl.enable=true
#这个是properties的配置文件,yaml会改吧
3,去邮箱开启功能
邮箱的账号设置中,在这里你可以得到授权码
4,编写代码
@SpringBootTest
class SpringBoot01ApplicationTests {
//使用邮箱的内置实现类,可以通过源码查看
@Autowired
JavaMailSenderImpl mailSender;
@Test
void contextLoads() {
//发送简单邮件,创建simpleMailMessage对象
SimpleMailMessage message = new SimpleMailMessage();//发送的邮件方式
message.setSubject("这是一个测试邮件发送标题");//邮件标题
message.setText("这是一个测试邮件发送内容");//邮件内容
message.setTo("[email protected]");//接收方
message.setFrom("[email protected]");//发送方
mailSender.send(message);//通过内置方法发送
}
@Test
public void contextLoads2() throws MessagingException {
//发送复杂的邮件,创建MimeMessage对象
MimeMessage mimeMessage = mailSender.createMimeMessage();
//组装,第一个参数传递复杂邮件对象,第二个参数选择是否开启多文件发送
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);//通过helper类去封装复杂邮件对象
helper.setSubject("testTitle");
//第二个参数选择是否解析HTML
helper.setText("test",true);
//发送附件,第一个参数为附件名字,第二个参数为文件的绝对地址(通过属性查看)
helper.addAttachment("1.jpg",new File("C:\\Users\\HP\\Desktop\\1.gif"));
helper.addAttachment("2.jpg",new File("C:\\Users\\HP\\Desktop\\1.gif"));
helper.setTo("[email protected]");
helper.setFrom("[email protected]");
mailSender.send(mimeMessage);//发送还是发送这个复杂对象
}
}
查看邮箱,邮件接收成功!
我们只需要使用Thymeleaf进行前后端结合即可开发自己网站邮件收发功能了!
可以指定一个方法在某个指定的时间触发,项目开发中经常需要执行一些定时任务,比如需要在每天凌晨的时候,分析一次前一天的日志信息,Spring为我们提供了异步执行任务调度的方式,提供了两个接口。
TaskExecutor接口
TaskScheduler接口
两个注解:
@EnableScheduling
@Scheduled
cron表达式:
这个是核心点因为@Scheduled指定执行的时间需要这个
http://www.bejson.com/othertools/cron/4、常用的表达式
(1)0/2 * * * * ? 表示每2秒 执行任务
(1)0 0/2 * * * ? 表示每2分钟 执行任务
(1)0 0 2 1 * ? 表示在每月的1日的凌晨2点调整任务
(2)0 15 10 ? * MON-FRI 表示周一到周五每天上午10:15执行作业
(3)0 15 10 ? 6L 2002-2006 表示2002-2006年的每个月的最后一个星期五上午10:15执行作
(4)0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
(5)0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时
(6)0 0 12 ? * WED 表示每个星期三中午12点
(7)0 0 12 * * ? 每天中午12点触发
(8)0 15 10 ? * * 每天上午10:15触发
(9)0 15 10 * * ? 每天上午10:15触发
(10)0 15 10 * * ? 每天上午10:15触发
(11)0 15 10 * * ? 2005 2005年的每天上午10:15触发
(12)0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发
(13)0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
(14)0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
(15)0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
(16)0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发
(17)0 15 10 ? * MON-FRI 周一至周五的上午10:15触发
(18)0 15 10 15 * ? 每月15日上午10:15触发
(19)0 15 10 L * ? 每月最后一日的上午10:15触发
(20)0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发
(21)0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发
(22)0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发
实现步骤:
1,创建一个类写一个方法
@Service
public class ScheduledService {
//秒 分 时 日 月 周几
//0 * * * * MON-FRI
//注意cron表达式的用法
@Scheduled(cron = "0 0/2 * * * ?")//表示每2分钟 执行任务
//在方法上添加这个Scheduled注解,指定执行的时间,里面传递的是cron表达式,可以百度在线生成
public void hello(){
System.out.println("hello.....");
}
}
2,在主类上开启定时任务
@EnableScheduling //开启基于注解的定时任务
@SpringBootApplication
public class SpringbootTaskApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootTaskApplication.class, args);
}
}
分布式架构会遇到的四个核心问题:
1.这么多的服务,客户端该如何去访问?
2.这么多的服务,服务器之间如何进行通信?
3.这么多的服务,该如何管理和治理?
4.服务挂了,怎么办?
解决方案:
SpringCloud,是一套生态,就是来解决以上分布式架构的四个问题
想使用SpringCloud,必须要掌握Springboot,因为它是基于SpirngBoot的
1.SpringCloud NetFlix,出了一套解决方案
2.Apcahe Dubbo zookeeper 第二套解决方案
API:没有,要么找第三方,要么自己实现
Dubbo是一个高性能的基于java实现的RPC通信框架
服务注册与发现,zookeeper,没有熔断机制,接住了Hystrix
3.SpringCloud Alibaba 一站式解决方案!
架构 > 解偶
开发框架 spring
IOC AOP
Ioc :控制反转
约泡:泡温泉,泡茶. … ,泡友
附近的人,打招呼。加微信.聊天,天天聊,-一>约泡
浴场(容器):温泉,茶庄,泡友
直接进温泉.就有人恻尔一起了!
原来我们都是自己一步步操作,现在交给容器了!我们需要什么就去拿就可以了
Aop :切面(本质,动态代理)
为了解决什么?不影响业务本来的情况下,实现动态增加功能,大量应用在日志,事务 … 等等方面
spring 是一个轻量级的java开源框架,容器目的:解决企业开发的复杂性问题 spring 是春天,觉得他是春天,也十分复杂,配置文件!
SpringBoot
SpringBoot 并不是新东西,就是spring的升级版!
新一代JavaEE的开发标准,开箱即用!一>拿过来就可以用!
它自动帮我们配置了非常多的东西,我们拿来即用!
特性:约定大于配置!
随着公司体系越来越大,用户越来越多!
微服务架构-一>新架构
模块化.功能化!
用户,支付,签到,娱乐 … ;
人多余多:一台服务器解决不了;在增加服务器!横向
假设A服务器占用 98 %资源, B 服务器只占用了 10 %。--负载均衡
将原来的整体项目.分成模块化.用户就是,个单独的项目.签到也是一个单独的项目,项目和项目之前需要通信,如何通信
用户非常多,而签到十分少!给用户多一点服务器,给签到少一点服务器
微服务架构问题?
分布式架构会遇到的四个核心问题?
1.这么多服务,客户端该如何去访问?
2.这么多服务.服务之间如何进行通信?
3.这么多服务.如何治理呢?
4.服务挂了.怎么办?
解决方案:
spring cloud,是一套生态,就是来解决以上分布式架构的 4个问题想使用 Spring cloud ,必须要掌握 SpringBoot,
因为 Spring cloud 是基于 springBoot。
1.Spring cloud NetFlix 出来了一套解决方案!一站式解决方案.我们都可以直接去这里拿?
Api 网关, zuul 组件
Feign 一> Httpclient --- HTTP的通信方式 同步并阻塞
服务注册与发现Eureka
熔断机制, Hystrix
2018年年底, NetFlix 宣布无限朋停止维护。生态不再维护,就会脱节.
2.Apache Dubbo zookeeper ,第二套解决系统.
API:没有!要么找第三方组件.要么自己实现
Dubbo 是一个高性能基于Java 实现的 Rpc 通信框架! 2.6.x
服务注册与发现, zookeeper :动物园管理者( Hadoop ,Hive )
没有:借助了 Hystrix
不完兽, Doubbo 当前 Doubbo 3.0 将提倡具备当代特性(如响应式编程)的相关支持同时汲取阿里内部HSF的设计长处来实现两者融合
当前预览版的很多地方还在探讨中,希望大家能够积极反馏,我们都会虚心学习并参考。
3. springcloud Alibaba 一站式解决方案!
目前.又提出了一种方案:
服务网格:下一代微服务标准, Server Mesh
代表解决方案: Istio 。(你们未来可能需要掌握!)
万变不离其宗.一通百通!
1. API 网关,服务路由
2. HTTP , RpC 框架,异步调用
3. 服务注册与发现,高可用
4. 熔断机制,服务降级
如果,你们基于这四个问题,开发一套解决方案,也叫 Spri ngcloud !
为什么要解决这个问题?本质二网络是不可靠的!程序猿,不要停下学习的脚步!