目录
演化过程:JavaWeb 使用原始独立开发的 MVC 三层架构开发网站,为了简化我们的开发流程使用了 SSM 框架,但是配置也开始复杂起来,并且我们的 war 包需要配置 Tomcat 运行使用,把 Spring 技术做出简化的 SpringBoot,它内嵌了 Tomcat 方便的实现了微服务架构。当我们的服务越来越多的时候,SpringCloud 它来了。
1、第一个SpringBoot程序
环境准备:
- jdk 1.8
- maven 3.6.1
- springboot:最新版
- IDEA
项目创建方式一:使用Spring Initializr 的 Web页面创建项目 官方:提供了一个快速生成的网站!
1、打开 https://start.spring.io/
2、填写项目信息
3、点击”Generate Project“按钮生成项目;下载此项目
4、解压项目包,并用IDEA以Maven项目导入,一路下一步即可,直到项目导入完毕。
5、如果是第一次使用,可能速度会比较慢,包比较多、需要耐心等待一切就绪。
项目创建方式二:使用 IDEA 直接创建项目
1、创建一个新项目
2、选择spring initalizr , 可以看到默认就是去官网的快速构建工具那里实现
3、填写项目信息
4、选择初始化的组件(初学勾选 Web 即可)
5、填写项目路径
6、等待项目构建成功
IDEA集成了这个网站
- 可以直接在官网直接下载后,导入IDEA开发(告诉官网在哪儿)
- 直接使用idea创建一个SpringBoot项目(一般还是在IDEA中进行创建开发)
2、运行原理初探
自动装配:
2.1、pom.xml
运行主要依赖一个父依赖,主要是管理项目的资源过滤及插件!
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
点进去将会看到还有个父依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
- 这里才是真正管理SpringBoot应用里面所有依赖版本的地方,SpringBoot的版本控制中心;
- spring-boot-dependencies : 核心依赖在父工程中!
- 我们在写或者引入一些SpringBoot的依赖的时候,默认是不需要指定版本,就因为有这些版本仓库;但是如果导入的包没有在依赖中管理着就需要手动配置版本了。
2.2、启动器 spring-boot-starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
- 启动器 : 说白了就是SpringBoot的启动场景;spring-boot-starter-XXX:就是spring-boot的场景启动器
- 比如spring-boot-start-web,它就会帮我们自动导入web环境所有的依赖!
- SpringBoot会将所有的功能场景,都变成一个个的启动类。
- 我们要使用什么功能,就只需要找到相应的启动器,在项目中引入这些starter即可,所有相关的依赖都会导入进来 , 我们要用什么功能就导入什么样的场景启动器即可。starter。我们未来也可以自己定义starter;
2.3、主启动类
//@SpringBootApplication : 标注这个类是一个SpringBoot的应用 : 启动类下的所有资源被导入
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
//将SpringBoot应用启动
SpringApplication.run(Springboot01HelloworldApplication.class, args);
}
}
2.4、注解
@SpringBootConfiguration : SpringBoot的配置
@Configuration : Spring配置类
@Component : 说明这也是一个Spring的组件
@EnableAutoConfiguration : 自动配置
@AutoConfigurationPackage : 自动配置包
@Import({AutoConfigurationPackages.Registrar.class}) : 自动装配`包注册`
@Import({AutoConfigurationImportS、elector.class}) : 自动配置导入选择
//获取所有的配置
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
- @SpringBootApplication
标注在某个类上说明这个类就是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;
- @ComponentScan
在spring中很重要,它对应了xml配置中的元素。
作用:自动扫描并加载符合条件的组件或者bean,将这个bean定义加载到IOC容器中。
- @SpringBootConfiguration
SpringBoot的配置类,标注在某个类上,表示这是一个SpringBoot的配置类;
点进这个注解后
这里的 @Configuration,说明这是一个配置类 ,配置类就是对应Spring的xml 配置文件;
里面的 @Component 这就说明,启动类本身也是Spring中的一个组件而已,负责启动应用!
- @EnableAutoConfiguration
开启自动配置功能
以前我们需要配置的东西,而现在SpringBoot可以自动帮我们配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能,这样自动配置才能生效;
获取候选的配置
@AutoConfigurationPackage:自动配置包
- spring.factories
META-INF/spring.factories : 自动配置的核心文件,这就是自动配置的根源所在!
所以,自动配置真正实现是从classpath中搜寻所有的META-INF/spring.factories配置文件 ,并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration的JavaConfig形式的IOC容器配置类 , 然后将这些都汇总成为一个实例并加载到IOC容器中。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
Properties proerties = PropertiesLoaderUtils.loadProperties(resource);
//所有的资源加载到配置类中!
结论:SpringBoot所有的自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功!
- SpringBoot在启动的时候,从类路径下
/META-INF/spring.factories
获取指定的值; - 将这些自动配置的类导入容器,自动配置类就会生效,帮我们进行自动配置;
- 以前我们需要自动配置的东西,现在SpringBoot帮我们做了;
- 整合JavaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure-2.2.0.RELEASE.jar这个包下;
- 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器;
- 容器中也会存在非常多的xxxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要的所有的组件;并自动配置,@Configuration,JavaConfig;
- 有了自动配置类,免去了我们手动编写配置文件的工作!
JavaConfig @Configuration @Bean
Docker : 进程
关于SpringBoot,谈谈你的理解
- 自动装配
- run()
2.5、run方法流程分析
3、SpringBoot配置
3.1、yaml配置文件
SpringBoot使用一个全局的配置文件 , 配置文件名称是固定的
- application.properties
-
- 语法结构 :key=value
- application.yml
-
- 语法结构 :key:空格 value
配置文件的作用 :修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了;
yaml基础语法
说明:语法要求严格
-
- 空格不能省略。
- 以缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的。
- 属性和值的大小写都是十分敏感的。
注意:
- “ ” 双引号,不会转义字符串里面的特殊字符 , 特殊字符会作为本身想表示的意思;比如 :name: "kuang \n shen" 输出 :kuang 换行 shen
- '' 单引号,会转义特殊字符 , 特殊字符最终会变成和普通字符一样输出比如 :name: ‘kuang \n shen’ 输出 :kuang \n shen
# properties 只能保存键值对!
# k=v
# 对空格的要求十分高
# 普通的key-value
# 注入到我们的配置类中
name: chatter
# 对象
student:
name: chatter
age: 3
# 行内写法
student: {name: code,age: 4}
# 数组
pets:
- cat
- dog
- pig
pets: [cat,dog,pig]、
yaml可以直接给实体类赋值
/*
@ConfigurationProperties作用:
将配置文件中配置的每一个属性的值,映射到这个组件中;
告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应
*/
@Component //注册bean
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
}
person:
name: chatter #S{random.uuid} 随机uuid
age: ${random.int} # 随机int
happy: false
birth: 2019/3/9
maps: {k1: v1,k2: v2}
hello: haayy
lists:
- code
- music
- girl
dog:
name: ${person.hello:hello}_旺财
age: 3
SpringBoot配置注解处理器找不到,需要导入依赖
<!-- 导入配置文件处理器,配置文件进行绑定就会有提示,需要重启 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
解决properties文件的中文乱码问题
总结:
- @ConfigurationProperties只需要写一次即可,@Value则需要每个字段都添加
- 松散绑定:比如我的yml中写的last-name,这个和lastName是一样的,-后面跟着的字母默认是大写的。这就是松散绑定。
- .yaml和.yml基本一致的,优先建议.yaml
- JSR303数据校验,这个就是我们可以在字段是增加一层过滤器验证,可以保证数据的合法性
- 复杂类型的封装,yaml中可以封装对象,使用value就不会支持
- 配置yml和配置properties都可以获取到值 , 强烈推荐 yml;如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下 @value;如果说,我们专门编写了一个JavaBean来和配置文件进行一一映射,就直接@configurationProperties,不要犹豫!
3.2、JSR303数据校验
Springboot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。我们这里来写个注解让我们的name只能支持Email格式;
@Component //注册bean
@ConfigurationProperties(prefix = "person")
@Validated //数据校验
public class Person {
@Email(message="邮箱格式错误") //name必须是邮箱格式
private String name;
}
使用数据校验,可以保证数据的正确性;
3.2.1、常见参数
@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 对象是否符合正则表达式的规则
.......等等
除此以外,我们还可以自定义一些数据校验规则
3.3、多环境配置及配置文件优先顺序
profile是Spring对不同环境提供不同配置功能的支持,可以通过激活不同的环境版本,实现快速切换环境;
yaml文件的优先级顺序
多环境文件的配置的切换
- 方式一:application.properties
#springboot的多环境配置:可以选择激活哪一个配置文件
spring.profiles.active=dev
- 方式二:application.yaml
server:
port: 8081
#选择要激活哪个环境块
spring:
profiles:
active: dev
---
server:
port: 8082
spring:
profiles: dev #配置环境的名称
---
server:
port: 8083
spring:
profiles: test
注意:如果yml和properties同时都配置了端口,并且没有激活其他环境 , 默认会使用properties配置文件的!
3.4、自动配置原理再理解
#配置文件到底能写什么? ----联系---- spring.factories;
#在我们这配置文件中能配置的东西,都存在一个固有的规律
# xxxAutoConfiguration:默认值 xxxProperties 和 配置文件绑定 我们就可以使用自定义的配置了!
#可以通过debug: true来查看,哪些自动配置类生效,哪些没有生效!
#debug: true
一句话总结 :根据当前不同的条件判断,决定这个配置类是否生效!
- 一但这个配置类生效;这个配置类就会给容器中添加各种组件;
- 这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;
- 所有在配置文件中能配置的属性都是在xxxxProperties类中封装着;
- 配置文件能配置什么就可以参照某个功能对应的这个属性类
精髓
1、SpringBoot启动会加载大量的自动配置类
2、我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;
3、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;
xxxxAutoConfigurartion:自动配置类;给容器中添加组件
xxxxProperties:封装配置文件中相关属性;
了解:@Conditional
了解完自动装配的原理后,我们来关注一个细节问题,自动配置类必须在一定的条件下才能生效;
@Conditional派生注解(Spring注解版原生的@Conditional作用)
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;
我们可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;
4、SpringBoot Web开发
jar:webapp
自动装配
SpringBoot到底帮我们配置了什么?我们能不能进行修改?能修改什么东西?能不能扩展?
- xxxxAutoConfiguration:向容器中自动配置组件
- xxxxProperties:自动配置类,装配配置文件中自定义的一些内容!
要解决的问题:
- 导入静态资源……
- 首页
- jsp,模块引擎Thymeleaf
- 装配扩展SpringMVC
- 增删改查
- 拦截器
- 国际化!
4.1、Web开发静态资源处理
SpringBoot最大的特点就是自动装配
如果我们是一个web应用,我们的main下会有一个webapp,我们以前都是将所有的页面导在这里面的,对吧!但是我们现在的pom呢,打包方式是为jar的方式,那么这种方式SpringBoot能不能来给我们写页面呢?当然是可以的,但是SpringBoot对于静态资源放置的位置,是有规定的!
我们先来聊聊这个静态资源映射规则:
SpringBoot中,SpringMVC的web配置都在 WebMvcAutoConfiguration 这个配置类里面;
我们可以去看看 WebMvcAutoConfigurationAdapter 中有很多配置方法;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
// 已禁用默认资源处理
logger.debug("Default resource handling disabled");
return;
}
// 缓存控制
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
// webjars 配置
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
// 静态资源配置
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
读一下源代码:比如所有的 /webjars/** , 都需要去 classpath:/META-INF/resources/webjars/ 找对应的资源;
什么是webjars呢?
Webjars本质就是以jar包的方式引入我们的静态资源 , 我们以前要导入一个静态资源文件,直接导入即可。
使用SpringBoot需要使用Webjars,我们可以去搜索一下:
网站:https://www.webjars.org
要使用jQuery,我们只要要引入jQuery对应版本的pom依赖即可!
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.4.1</version>
</dependency>
访问:只要是静态资源,SpringBoot就会去对应的路径寻找资源,我们这里访问:http://localhost:8080/webjars/jquery/3.4.1/jquery.js
第二种静态资源映射规则
以下四个目录存放的静态资源可以被我们识别:
"classpath:/META-INF/resources/"
"classpath:/resources/"
"classpath:/static/"
"classpath:/public/"
我们可以在resources根目录下新建对应的文件夹,都可以存放我们的静态文件;
比如我们访问 http://localhost:8080/1.js , 他就会去这些文件夹中寻找对应的静态资源文件;
自定义静态资源路径
我们也可以自己通过配置文件来指定一下,哪些文件夹是需要我们放静态资源文件的,在application.properties中配置;
spring.resources.static-locations=classpath:/coding/,classpath:/kuang/
一旦自己定义了静态文件夹的路径,原来的自动配置就都会失效了!
总结:
- 在SpringBoot,我们可以使用以下方式处理静态资源
-
- webjars localhost:8080/webjars/
- public,static,/**,resources localhost:8080/
- 优先级:resources > static(默认)> static
4.2、首页如何定制
访问 http://localhost:8080/ ,就会找静态资源文件夹下的 index.html
在我们上面的3个目录中任意一个;然后访问测试 http://localhost:8080/
网站图标说明
与其他静态资源一样,Spring Boot在配置的静态内容位置中查找 favicon.ico。如果存在这样的文件,它将自动用作应用程序的favicon。
注意:有的版本没有
1、关闭SpringBoot默认图标
#关闭默认图标 spring.mvc.favicon.enabled=false
2、自己放一个图标在静态资源目录下,我放在 public 目录下
3、清除浏览器缓存!刷新网页,发现图标已经变成自己的了!
4.3、Thymeleaf模板引擎
前端交给我们的页面,是html页面。如果是我们以前开发,我们需要把他们转成jsp页面,jsp好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示,及交互等。
jsp支持非常强大的功能,包括能写Java代码,但是呢,我们现在的这种情况,SpringBoot这个项目首先是以jar的方式,不是war,像第二,我们用的还是嵌入式的Tomcat,所以呢,他现在默认是不支持jsp的。
那不支持jsp,如果我们直接用纯静态页面的方式,那给我们开发会带来非常大的麻烦,那怎么办呢?
SpringBoot推荐你可以来使用模板引擎:
模板引擎,我们其实大家听到很多,其实jsp就是一个模板引擎,还有用的比较多的freemarker,包括SpringBoot给我们推荐的Thymeleaf,模板引擎有非常多,但再多的模板引擎,他们的思想都是一样的,什么样一个思想呢我们来看一下这张图:
模板引擎的作用就是我们来写一个页面模板,比如有些值呢,是动态的,我们写一些表达式。而这些值,从哪来呢,就是我们在后台封装一些数据。然后把这个模板和这个数据交给我们模板引擎,模板引擎按照我们这个数据帮你把这表达式解析、填充到我们指定的位置,然后把这个数据最终生成一个我们想要的内容给我们写出去,这就是我们这个模板引擎,不管是jsp还是其他模板引擎,都是这个思想。
引入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依赖:可以适当点进源码看下本来的包!
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
我们去找一下Thymeleaf的自动配置类:ThymeleafProperties
@ConfigurationProperties(
prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
private Charset encoding;
}
我们可以在其中看到默认的前缀和后缀!
我们只需要把我们的html页面放在类路径下的templates下,thymeleaf就可以帮我们自动渲染了。
使用thymeleaf什么都不需要配置,只需要将他放在指定的文件夹下即可
要学习语法,还是参考官网文档最为准确,我们找到对应的版本看一下;
Thymeleaf 官网:https://www.thymeleaf.org/ , 简单看一下官网!我们去下载Thymeleaf的官方文档!
我们要使用thymeleaf,需要在html文件中导入命名空间的约束,方便提示。
我们可以去官方文档的#3中看一下命名空间拿来过来:
xmlns:th="http://www.thymeleaf.org"
@RequestMapping("/t2")
public String test2(Map<String,Object> map){
//存入数据
map.put("msg","<h1>Hello</h1>");
map.put("users", Arrays.asList("qinjiang","kuangshen"));
//classpath:/templates/test.html
return "test";
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>狂神说</title>
</head>
<body>
<h1>测试页面</h1>
<div th:text="${msg}"></div>
<!--不转义-->
<div th:utext="${msg}"></div>
<!--遍历数据-->
<!--th:each每次遍历都会生成当前这个标签:官网#9-->
<h4 th:each="user :${users}" th:text="${user}"></h4>
<h4>
<!--行内写法:官网#12-->
<span th:each="user:${users}">[[${user}]]</span>
</h4>
</body>
</html>
在SpringBoot中,有非常多的xxxx Configuration 帮助我们进行扩展配置,只要看见了这个东西,我们就要注意了!
5、员工系统设计
5.1、员工管理系统
- 首页配置:注意点:
-
- 所有页面的静态资源都需要使用thymeleaf接管;
- url的href用@{}2.
- 页面国际化,注意点:
-
- 我们需要配置i18n文件
- 如果需要在项目中进行按钮自动切换(页面底部切换语言),我们需要自定义一个组件
LocaleResolver
- 记得将自己写的组件配置到spring容器中
@Bean
- 要将File Encodings设置为UTF-8,不然全乱了。
- application.properties 中配置
- html 页面中的修改需要国际化显示内容进行使用 #{} 表示,例如:th:text="#{login.tip}"
其中按钮使用 th:value
- 登录+拦截器
- 员工列表展示
-
- 提取公共页面
-
-
th:fragment="sidebar"
th:replace="~{common/commons::topbar}
- 如果要传递参数,可以直接使用()传参,接收判断即可!
-
-
- 列表循环展示
- 添加员工
-
- 按钮提交
- 跳转到添加页面
- 添加员工成功
- 返回首页
注意:SpringBoot 默认的时间格式是 yyyy/MM/dd
更改默认格式使用
# 时间日期格式
spring.mvc.date-format=yyyy-MM-dd
- 修改、删除、404
5.2、聊聊如何写一个网站
前端
- 模板:别人下号的,我们拿来改成自己需要的
- 框架:组件:自己手动组合拼接。Bootstrap,Layui,semantic-ui,element-ui
-
- 栅格系统
- 导航栏
- 侧边栏
- 表单
网站总体的设计
- 前端搞定:页面长什么样子:数据
- 设计数据库 (数据库这集难点!)
- 前端让它能够自动运行,独立化工程
- 数据接口如何对接:json,对象 all in one!
- 前后端联调测试!
自己需要掌握的
- 有一套自己熟悉的后台模板:工作必要! 推荐:x-admin
- 前端界面:至少自己能够通过前端框架,组合出来一个网站页面
-
- index
- about
- blog
- post
- user
- 让这个网站能够独立运行!(一个月)
5.3、回顾
上周:
- SpringBoot是什么?
- 微服务
- HelloWorld-
- 探究远吗~自动装配原理~
- 配置yaml
- 多文档环境切换
- 静态资源映射
- Thymeleaf th:xxx
- SpringBoot 如何扩展 MVC javaconfig~
- 如何修改SpringBoot的默认配置~
- CRUD
- 国际化
- 拦截器
- 定制首页,错误页~
这周:
- JDSC
- Mybatis :重点
- Druid :重点
- Shiro:安全 :重点
- Spring Security :安全 :重点
- 异步任务~,邮件发送,定时任务
- Swagger
- Dubbo + Zookeeper
6、整合
6.1、整合 JDBC
6.1.1、创建测试项目和测试数据
1、我去新建一个项目测试:springboot-data-jdbc ; 引入相应的模块!基础模块
2、项目建好之后,发现自动帮我们导入了如下 JDBC 和 MySQL 的启动器,我们还需要导入 web 的启动器以用来编辑 controller :
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--JDBC-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--MySQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
3、编写yaml配置文件连接数据库:
spring:
datasource:
#?serverTimezone=UTC解决时区的报错
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: yjx123
注意:我们需要关闭默认的 properties 文件,否则会出现错误。
4、配置完这一些东西后,我们就可以直接去使用了,因为SpringBoot已经默认帮我们进行了自动配置;去测试类测试一下:查看默认的数据源并检验数据库是否连接成功。
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@SpringBootTest
class DemoApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
//查看一下默认的数据源 :class com.zaxxer.hikari.HikariDataSource :dbcp.springboot
System.out.println(dataSource.getClass());
//获得数据库连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
//xxxx Template : SpringBoot已经配置好的模板bean,拿来即用 CRUD
//jdbc
//redis
//关闭
connection.close();
}
}
结果:我们可以看到他默认给我们配置的数据源为 : class com.zaxxer.hikari.HikariDataSource , 我们并没有手动配置
我们来全局搜索一下,找到数据源的所有自动配置都在 :DataSourceAutoConfiguration文件:
@Import(
{Hikari.class, Tomcat.class, Dbcp2.class, Generic.class, DataSourceJmxConfiguration.class}
)
protected static class PooledDataSourceConfiguration {
protected PooledDataSourceConfiguration() {
}
}
这里导入的类都在 DataSourceConfiguration 配置类下,可以看出 Spring Boot 2.2.5 默认使用HikariDataSource 数据源,而以前版本,如 Spring Boot 1.5 默认使用 org.apache.tomcat.jdbc.pool.DataSource 作为数据源;
HikariDataSource 号称 Java WEB 当前速度最快的数据源,相比于传统的 C3P0 、DBCP、Tomcat jdbc 等连接池更加优秀;
可以使用 spring.datasource.type 指定自定义的数据源类型,值为 要使用的连接池实现的完全限定名。
关于数据源我们并不做介绍,有了数据库连接,显然就可以 CRUD 操作数据库了。但是我们需要先了解一个对象 JdbcTemplate
6.1.2、JDBCTemplate
1、有了数据源(com.zaxxer.hikari.HikariDataSource),然后可以拿到数据库连接(java.sql.Connection),有了连接,就可以使用原生的 JDBC 语句来操作数据库;
2、即使不使用第三方的数据库操作框架,如 MyBatis等,Spring 本身也对原生的JDBC 做了轻量级的封装,即JdbcTemplate。
3、数据库操作的所有 CRUD 方法都在 JdbcTemplate 中。
4、Spring Boot 不仅提供了默认的数据源,同时默认已经配置好了 JdbcTemplate 放在了容器中,程序员只需自己注入即可使用
5、JdbcTemplate 的自动配置是依赖 org.springframework.boot.autoconfigure.jdbc 包下的 JdbcTemplateConfiguration 类
JdbcTemplate主要提供以下几类方法:
- execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
- update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
- query方法及queryForXXX方法:用于执行查询相关语句;
- call方法:用于执行存储过程、函数相关语句。
6.1.3、编写 Controller 测试
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
public class JdbcController {
@Autowired
JdbcTemplate jdbcTemplate;
//查询数据库的所有信息
//没有实体类,数据库中的东西,怎么获取? Map
@GetMapping("/userList")
public List<Map<String,Object>> userList(){
String sql = "select * from user";
List<Map<String, Object>> list_maps = jdbcTemplate.queryForList(sql);
return list_maps;
}
@GetMapping("/addUser")
public String addUser(){
String sql = "insert into mybatis.user(id,name,pwd) values (5,'小王','123456')";
jdbcTemplate.update(sql);
return "addUser-ok";
}
@GetMapping("/updateUser/{id}")
public String updateUser(@PathVariable("id") int id){
String sql = "update mybatis.user set name=?,pwd=? where id=" + id;
//封装
Object[] objects = new Object[2];
objects[0] = "小明";
objects[1] = "hhhhhhh";
jdbcTemplate.update(sql,objects);
return "updateUser-ok";
}
@GetMapping("/deleteUser/{id}")
public String deleteUser(@PathVariable("id") int id){
String sql = "delete from mybatis.user where id = ?";
jdbcTemplate.update(sql,id);
return "deleteUser-ok";
}
}
通过 http://localhost:8080/deleteUser/5 等请求测试结果
6.2、整合 Druid
6.2.1、Druid简介
Java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池。
Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。
Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池。
Druid 已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
Spring Boot 2.0 以上默认使用 Hikari 数据源,可以说 Hikari 与 Driud 都是当前 Java Web 上最优秀的数据源,我们来重点介绍 Spring Boot 如何集成 Druid 数据源,如何实现数据库监控。
Github地址:https://github.com/alibaba/druid/
com.alibaba.druid.pool.DruidDataSource 基本配置参数如下:
配置 | 缺省值 | 说明 |
name | 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 | |
jdbcUrl | 连接数据库的url,不同数据库不一样。例如: | |
username | 连接数据库的用户名 | |
password | 连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里:https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter | |
driverClassName | 根据url自动识别 | 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下) |
initialSize | 0 | 初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 |
maxActive | 8 | 最大连接池数量 |
maxIdle | 8 | 已经不再使用,配置了也没效果 |
minIdle | 最小连接池数量 | |
maxWait | 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 | |
poolPreparedStatements | false | 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。 |
maxOpenPreparedStatements | -1 | 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100 |
validationQuery | 用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。 | |
testOnBorrow | true | 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 |
testOnReturn | false | 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 |
testWhileIdle | false | 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 |
timeBetweenEvictionRunsMillis | 有两个含义: | |
numTestsPerEvictionRun | 不再使用,一个DruidDataSource只支持一个EvictionRun | |
minEvictableIdleTimeMillis | ||
connectionInitSqls | 物理连接初始化的时候执行的sql | |
exceptionSorter | 根据dbType自动识别 | 当数据库抛出一些不可恢复的异常时,抛弃连接 |
filters | 属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: | |
proxyFilters | 类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系 |
6.2.2、配置数据源
- 添加上 Druid 数据源依赖。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
- 切换数据源;之前已经说过 Spring Boot 2.0 以上默认使用 com.zaxxer.hikari.HikariDataSource 数据源,但可以 通过 spring.datasource.type 指定数据源。
spring:
datasource:
#?serverTimezone=UTC解决时区的报错
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: yjx123
type: com.alibaba.druid.pool.DruidDataSource
- 数据源切换之后,在测试类中注入 DataSource,然后获取到它,输出一看便知是否成功切换;
- 切换成功!既然切换成功,就可以设置数据源连接初始化大小、最大连接数、等待时间、最小连接数 等设置项;可以查看源码
spring:
datasource:
#?serverTimezone=UTC解决时区的报错
url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: yjx123
type: com.alibaba.druid.pool.DruidDataSource
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
- 导入Log4j 的依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
- 现在需要程序员自己为 DruidDataSource 绑定全局配置文件中的参数,再添加到容器中,而不再使用 Spring Boot 的自动生成了;我们需要 自己添加 DruidDataSource 组件到容器中,并绑定属性;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DruidConfig {
/*
将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建
绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource从而让它们生效
@ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中
前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
}
- 去测试类中测试一下;看是否成功!
@Test
void contextLoads() throws SQLException {
//查看一下默认的数据源 :class com.zaxxer.hikari.HikariDataSource :dbcp.springboot
System.out.println(dataSource.getClass());
//获得数据库连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
//xxxx Template : SpringBoot已经配置好的模板bean,拿来即用 CRUD
//jdbc
//redis
//关闭
DruidDataSource druidDataSource = (DruidDataSource) dataSource;
System.out.println("druidDataSource 数据最大连接数:" + druidDataSource.getMaxActive());
System.out.println("druidDataSource 数据源初始化连接数:" + druidDataSource.getInitialSize());
connection.close();
}
输出结果 :可见配置参数已经生效!
6.2.3、配置 Druid 数据源监控
Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看,类似安装 路由器 时,人家也提供了一个默认的 web 页面。
所以第一步需要设置 Druid 的后台管理页面,比如 登录账号、密码 等;配置后台管理;
// 后台监控 : 相当于: web.xml ServletRegistrationBean
// 因为SpringBoot内置了 servlet 容器,所以没有 web.xml,替代方法:ServletRegistrationBean
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
//后台需要有人登录,账号密码配置
HashMap<String ,String> initParameters = new HashMap<>();
//增加配置
//登录的 key 是固定的 loginUsername、loginPassword
initParameters.put("loginUsername","admin");
initParameters.put("loginPassword","admin");
//允许谁可以访问
initParameters.put("allow","");
//禁止谁能访问 initParameters.put("kuangshen","192.168.11.123");
bean.setInitParameters(initParameters);//设置初始化参数
return bean;
}
配置完毕后,我们可以选择访问 :http://localhost:8080/druid/login.html
进入之后
配置 Druid web 监控 filter 过滤器
//filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
bean.setFilter(new WebStatFilter());
//可以过滤哪些请求呢?
HashMap<String,String> initParameters = new HashMap<>();
//这些东西不能进行统计
initParameters.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParameters);
return bean;
}
平时在工作中,按需求进行配置即可,主要用作监控!
6.3、整合 Mybatis
官方文档:http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
Maven仓库地址:https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter/2.1.1
总体步骤:
-
- 导入包
- 配置文件
- mybatis 配置
- 编写 sql
- service 层调用 dao 层
- controller 调用 service 层
- 新建一个 SpringBoot 项目
- 导入 MyBatis 所需要的依赖
<!--mybatis-spring-boot-starter:整合 有文档-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
- 配置数据库连接信息(不变)
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=yjx123
- 测试数据库是否连接成功!
- 创建实体类,导入 Lombok!
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
- 创建mapper目录以及对应的 Mapper 接口
//这个注解表示了这是一个 mybatis 的 Mapper类 : Dao
@Mapper
@Repository
public interface UserMapper {
List<User> queryUserList();
User queryUserById(int id);
int addUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
- 在 resources 下建 mybatis.mapper 包,在包下面编写 Mapper 接口对应的映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.mapper.UserMapper">
<select id="queryUserList" resultType="User">
select * from user;
</select>
<select id="queryUserById" resultType="User">
select * from user where id = #{id};
</select>
<insert id="addUser" parameterType="User">
insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
</insert>
<update id="updateUser" parameterType="User">
update user set name=#{name},pwd=#{pwd} where id = #{id}
</update>
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
</mapper>
- 整合 Mybatis
# 整合 mybatis
mybatis.type-aliases-package=com.kuang.pojo
# classpath 相当于 resources,mybatis前面不能加/,否则到项目目录扫描
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
- 编写 Controller 并测试
@RestController
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping("/queryUserList")
public List<User> queryUserList(){
List<User> userList = userMapper.queryUserList();
for (User user : userList){
System.out.println(user);
}
return userList;
}
@GetMapping("/queryUserById/{id}")
public User queryUserById(@PathVariable("id") int id){
User user = userMapper.queryUserById(id);
return user;
}
@GetMapping("/addUser")
public String addUser(){
userMapper.addUser(new User(5, "羊大", "12345"));
return "addUser OK";
}
@GetMapping("/updateUser")
public String updateUser(){
userMapper.updateUser(new User(5,"大脑","123"));
return "updateUser OK";
}
@GetMapping("/deleteUser/{id}")
public String deleteUser(@PathVariable("id") int id){
userMapper.deleteUser(id);
return "Ok";
}
}
- 启动项目访问进行测试
7、SpringSecurity
在 web 开发中,安全第一位!过滤器,拦截器~
做网站:安全应该在什么时候考虑?(设计之初~)
- 漏洞,隐私泄露~
- 架构一旦确定~
shiro、SpringSecurity:很像~除了类不一样,名字不一样;
认证,授权(vip1、vip2、vip3)
- 功能权限
- 访问权限
- 菜单权限
- ……拦截器,过滤器:大量的原生代码~冗余
MVC - SPRING - SPRINGBOOT - 框架思想
Aop:横切 - 配置类
7.1、简介
Spring Security 是针对 Spring 项目的安全框架,也是 SpringBoot 底层安全模块默认的技术选型,它可以实现强大的 Web 安全控制,对于安全控制,我们仅需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理!
记住几个类:
- WebSecurityConfigurerAdapter:自定义 Security 策略
- AuthenticationManagerBuilder:自定义认证策略
- @EnableWebSecurity:开启 WebSecurity 模式,@EnableXXX开启某个功能
Spring Security 的两个主要目标是“认证”和“授权”(访问控制)。
“认证”(Authentication)
“授权”(Authorization)
这个概念是通用的,而不是只在 Spring Security 中存在。
参考官网:Spring Security,查看我们自己项目中的版本,找到对应的帮助文档:Spring Security Reference
7.2、环境搭建
- 新建一个 SpringBoot 项目,选中 Spring Web 模块
- 导入 Thymeleaf 模板包
<!--thymeleaf模板-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
- 导入静态资源
- 关闭模板引擎
# 关闭模板引擎
spring.thymeleaf.cache=false
- 编写 Controller
@Controller
public class RouterController {
@RequestMapping({"/","/index"})
public String index(){
return "index";
}
@RequestMapping("/toLogin")
public String toLogin(){
return "views/login.html";
}
@RequestMapping("/level1/{id}")
public String level1(@PathVariable("id") int id){
return "views/level1/" + id;
}
@RequestMapping("/level2/{id}")
public String level2(@PathVariable("id") int id){
return "views/level2/" + id;
}
@RequestMapping("/level3/{id}")
public String level3(@PathVariable("id") int id){
return "views/level3/" + id;
}
}
7.3、用户认证和授权
- 导入依赖
<!--security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 编写配置类
package com.kuang.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
//AOP: 拦截器!
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//链式编程
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人可以访问, 功能也只有对应有权限的人才能访问
//请求授权的规则~
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
//没有权限默认会到登录页面,需要开启登录的页面
//login
http.formLogin();
}
//认证,SpringBoot 2.1.x 可以直接使用~
//密码编码:PasswordEncoder
//在Spring Security 5.0+ 新增了很多的加密方式~
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//这些数据征程应该从数据库中读
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("kuangshen").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
}
}
7.4、注销及权限控制
- 在配置类中开启注销功能
@Override
protected void configure(HttpSecurity http) throws Exception {
//首页所有人可以访问, 功能也只有对应有权限的人才能访问
//请求授权的规则~
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
//没有权限默认会到登录页面,需要开启登录的页面
//login
http.formLogin();
//注销:开启了注销功能,跳到首页
http.logout().logoutUrl("/");
//或者: http.logout().logoutSuccessUrl("/");
}
- index 前端页面进行注销跳转
<!--注销-->
<a class="item" th:href="@{/logout}">
<i class="sign-out icon"></i> 注销
</a>
- 在 Thymeleaf 里面可以写一些 Spring Security 的操作,导入整合包
<!--security-thymeleaf整合包-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
- index.html 页面导入命名空间
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
- Thymeleaf 进行使用 SpringSecurity
<!--登录注销-->
<div class="right menu">
<!--如果未登录-->
<div sec:authorize="!isAuthenticated()">
<a class="item" th:href="@{/toLogin}">
<i class="address card icon"></i> 登录
</a>
</div>
<!--如果已登录:用户名,注销-->
<div sec:authorize="isAuthenticated()">
<a class="item">
用户名:<span sec:authentication="name"></span>
<!--角色:<span sec:authentication="principal.getAuthorities()"></span>-->
</a>
</div>
<div sec:authorize="isAuthenticated()">
<a class="item" th:href="@{/logout}">
<i class="sign-out icon"></i> 注销
</a>
</div>
</div>
注意:对于 SpringBoot 版本只支持2.0.9及以下的2.0.x。
- SpringBoot 默认开启了防止网站攻击的功能,所以登录可能出现登录失败的原因
//防止网站攻击: get ,post
http.csrf().disable();//关闭csrf功能,登录失败可能存在的原因~
这样就可以在主界面显示登录后的用户名和注销图示,未登录不显示。
为了让各个 level 界面能够分配给不同的 vip 权限显示,可以在前端界面再进行使用 SpringSecurity 的设置